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

Make the body of a user-defined op a fully-fledged scope #5073

Closed
philrz opened this issue Mar 15, 2024 · 2 comments · Fixed by #5074 or #5082
Closed

Make the body of a user-defined op a fully-fledged scope #5073

philrz opened this issue Mar 15, 2024 · 2 comments · Fixed by #5074 or #5082
Assignees

Comments

@philrz
Copy link
Contributor

philrz commented Mar 15, 2024

tl;dr

In the Zed docs about statements several times we explain scopes as:

...the main scope at the start of a Zed program or a lateral scope defined by an over operator

However, there are valid reasons why a user might want to treat other ( )-enclosed code blocks (e.g, the body of a user-defined operator) like scopes.

Details

Repro is with Zed commit f1be6a4.

This topic was kicked off by a community user in a Slack thread. In their own words:

  1. Can i define a function inline?

There was some back & forth about what was implied by the word "inline" here (e.g., in language contexts it often refers to this kind of concept from C++, which indeed did not seem to be what this user had in mind). I ultimately read back this simplified example that the user confirmed captured the essence of what they had in mind.

This works:

$ cat works.zed 
func compute(num): (
  num * num
)

op square(val): (
  yield compute(val)
)

$ zq -version
Version: v1.14.0-17-gf1be6a4a

$ echo '2' | zq -I works.zed 'square(this)' -
4

However, this currently does not, as it produces a syntax error.

$ cat attempt.zed 
op square(val): (
  func compute(num): (
    num * num
  )
  yield compute(val)
)

$ echo '2' | zq -I attempt.zed 'square(this)' -
zq: error parsing Zed in attempt.zed at line 2, column 20:
  func compute(num): (
               === ^ ===

In terms of why the user might find the second approach desirable, they confirmed:

The main problem is not wanting to pollute the global namespace.

Indeed, other languages have this concept of being able to define functions, constants, etc., that are local to the innermost scope, so it's understandable why users might hope to see it in Zed.

That covers a specific case of a func inside of an op, but if we want to approach this in a general way, it seems there's other variations we might want to cover, e.g., #5075 tracks the equivalent for user-defined functions.

@philrz philrz changed the title Make more ( )-enclosed blocks act as fully-fledged scopes Make the body of a user-defined op a fully-fledged scope Mar 15, 2024
@philrz
Copy link
Contributor Author

philrz commented Mar 18, 2024

Verified in Zed commit 18b3c7f.

Our Zed program with the user-defined function defined within the scope of the user-defined operator now parses successfully and produces the expected result.

$ zq -version
Version: v1.14.0-19-g18b3c7f8

$ cat attempt.zed 
op square(val): (
  func compute(num): (
    num * num
  )
  yield compute(val)
)

$ echo '2' | zq -I attempt.zed 'square(this)' -
4

Thanks @mattnibs!

@philrz philrz linked a pull request Mar 20, 2024 that will close this issue
@iloveitaly
Copy link
Contributor

Amazing! Thank you for implementing this!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
3 participants