Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added default (elvis) operator #638

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

markmelville
Copy link
Contributor

@markmelville markmelville commented Jun 8, 2023

Implements request from #370.

I have never been sure about how the project owners feel about the addition of operators. Functions are one thing, but an operator is a first-class citizen, and eating one up has roadmap-altering consequences. Is there even a roadmap?

Of all the proposed syntaxes, I opted to use the elvis operator ?: since it's so close to its functional equivalent.
property ? property : 'default' becomes property ?: 'default'. (Just collapse the ? and the : of a ternary.)

Draft mode for now since:

  • I want to get general input about the direction and use of a new operator
  • Right now the implementation is pure javascript by using the javascript ternary, which may have different rules for what is "truthy" than the JSONata ternary. I suspect this should change to match JSONata's ternary logic.
  • I'm wondering if this operator should be a short-circuiting operator to prevent the overhead of the evaluation of a potentially expensive RHS that won't be used. Thoughts?
  • Documentation needs to be updated.

Thanks for looking!

@markmelville markmelville reopened this Jun 8, 2023
@markmelville
Copy link
Contributor Author

Ah. I meant to open this in draft mode, and I can't seem to change it now.

@@ -40,6 +40,7 @@ const parser = (() => {
'<=': 40,
'>=': 40,
'~>': 40,
'?:': 40,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

any input on what the binding power should be on this operator?

@andrew-coleman
Copy link
Member

Hi Mark, many thanks for taking the lead on this, I’m happy that we get this into the language. Re-reading the discussion, I think there are two separate operations that we could add:

  • Elvis operator, as you propose - A ?: B which is equivalent to the existing A ? A :B.
  • Coalescing operator A ?? B which will evaluate to B iff A does not exist (empty sequence). Equivalent to [A, B](0) (from XPath).

As far as implementation is concerned, it would probably be easiest to modify the parser to check whether the next token is : (or ?) before attempting to parse the ‘then’ expression https://github.com/jsonata-js/jsonata/blob/master/src/parser.js#L843
Then amend the evaluator to handle the different usages https://github.com/jsonata-js/jsonata/blob/master/src/jsonata.js#L1067

On the question of roadmap, I don’t have any committed plans at the moment, but I’m having thoughts in the following areas:

  • A simpler syntax for accessing property names in objects. I’m seeing lots of questions in Slack and StackOverflow (thank you Mark for answering many of them) along the lines of “How to I transform {“A”: “B”, …} into {“key”: A, “value”: B}". At the moment, the only answer is to use the $each function with a lambda function to generate the output. Which is a bit long winded for simple use cases. XPath has a name() function (https://www.w3.org/TR/xpath-functions-31/#func-name) which I didn’t implement in JSONata because unlike XML, values are just values; they’re not owned by a DOM node with a name. But I think I need to revisit how to implement something like this.
  • I’ve never liked the syntax for defining lambda functions. I don’t ever plan to make breaking changes, but it’s interesting to see that a proposal for XPath 4.0 has added support for arrow functions https://www.saxonica.com/qt4specs/XP/xpath-40-diff.html#id-inline-func. I might look at doing something similar.

Neither of these would affect your proposal though.

@jhorbulyk
Copy link
Contributor

I think there are two separate operations that we could add:

  • Elvis operator, as you propose - A ?: B which is equivalent to the existing A ? A :B.
  • Coalescing operator A ?? B which will evaluate to B iff A does not exist (empty sequence). Equivalent to A, B (from XPath).

I agree. The A?:B is nice in that it simplifies many expressions written as A ? A : B but it might slightly miss the actual use case of "we want to provide a default value when there is none". However, we can start with this operator and see where we end up.

@mattbaileyuk mattbaileyuk marked this pull request as draft August 10, 2023 11:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants