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

Clarification needed for let() function behaviour and sub-expressions #152

Closed
springcomp opened this issue Mar 3, 2023 · 1 comment
Closed

Comments

@springcomp
Copy link
Contributor

In light of this comment, is appears clarification is needed.

In fact, @jamesls was aware of potential confusions. and @mtdowling talked him out of moving the JEP forward.

[@jamesls] In this scenario we're evaluating foo.qux. foo evaluates to {"bar": "baz"}. So far so good. Next we evaluate the RHS of the sub expression, qux. We see the qux is not defined in the current object {"bar": "baz"} so we look in the scope object and see it's defined as "qux", so we use that value. I can see how some people might find that confusing. Maybe not.

[@mtdowling] We've spoken about this in person, but I wanted to leave feedback here to hopefully help drive this proposal forward. I stated this earlier, but I think that the current behavior of this JEP would be confusing.

I still think this feature brings more benefits as is as it brings confusions but I agree clarification is needed and changes may be made if necessary.

Sub Expressions

It appears the most common source for confusion is trying to use the scope when evaluating the RHS of a sub-expression.
The current implementations of the specification behave is unconditionnally simple:

  • When evaluating an identifier, first lookup the current context.
  • If not found in the context, lookup the call chain.

The confusion arises when trying such expressions:

  • search( let({bar: 'bar'}, &foo.bar ) , {"foo": "foo"} ) -> "bar"

Whereas intuition would dictate that expression to evaluate to null instead, as bar is not a property of the "foo" string.

Pipe Expressions

It’s worth mentioning that JEP-19 standardized a small difference between evaluating a sub-expression vs a pipe-expression.

Thoughts must be applied when clarifying this JEP-11 in this context.
For the record, assuming we closed the confusion with sub-expression, I would still be comfortable with the following evaluations:

  • search( let({bar: 'bar'}, &foo.bar ) , {"foo": "foo"} ) -> null
  • search( let({bar: 'bar'}, &foo | bar ) , {"foo": "foo"} ) -> "bar"
@springcomp springcomp changed the title Clarification need for let() function behaviour and sub-expressions Clarification needed for let() function behaviour and sub-expressions Mar 3, 2023
@springcomp
Copy link
Contributor Author

springcomp commented Mar 4, 2023

Here are some pointers for discussion.

I think the main – if not only – source of confusion comes from the arguably counter-intuitive behaviour when evaluating the RHS of a sub-expression. In that case, I would be happy to close that source of confusion. This would be quite easy (I think) to implement, as each new sub-expression would create a new fresh scope chain.

Here is how it could be implemented:

    case parsing.ASTSubexpression:
      left, err := intr.Execute(node.Children[0], value)
      if err != nil {
        return nil, err
      }
      if left == nil {
        return nil, nil
      }
-    return intr.Execute(node.Children[1], left)
+    return intr.WithScope(nil).Execute(node.Children[1], left)

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

No branches or pull requests

1 participant