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

Assignment operator usability issues #897

Open
nicowilliams opened this issue Aug 11, 2015 · 5 comments
Open

Assignment operator usability issues #897

nicowilliams opened this issue Aug 11, 2015 · 5 comments

Comments

@nicowilliams
Copy link
Contributor

The assignment operators are somewhat tricky to use. This may be mostly a matter of documentation...

Issues:

  • users often miss the fact that the LHS expression is supposed to be a path expression matching paths in .
  • = and |= have different semantics besides |= passing the value at the LHS paths to the RHS expression. Compare jq -n '(.a, .b, .c) = (1,2,3)' to jq -n '(.a, .b, .c) |= (1,2,3)'.

The first issue is easy enough to handle in documentation.

The second issue is difficult to "fix" without risking breaking jq programs. Since |= is supposed to modify whatever value is found at the LHS, only one of the RHS expressions' outputs can be used as the final value -- there is just no question of making |= work like =. One reason that we can't make |= work like = is that while the RHS in the = case will produce the same outputs for all paths named in the LHS, the RHS in the |= absolutely can produce different sets of outputs for each path as the RHS gets a possibly-different input for each path in .. At best we could make = work like |=, but ='s behavior as to RHS generator expressions seems to be just too useful, and thus likely to be depended upon. This too, then, seems like a job for documentation.

Unless other issues crop up, we should close this one (perhaps after tweaking the docs).

@nicowilliams
Copy link
Contributor Author

This one is for @pkoppstein and @slapresta :)

@nicowilliams
Copy link
Contributor Author

There's also precedence issues... .a,.b=1 is not the same as (.a,.b)=1.

nicowilliams added a commit that referenced this issue Aug 11, 2015
@pkoppstein
Copy link
Contributor

@nicowilliams - Thanks for documenting and clarifying some of the issues.

You're right - the discrepancy between the semantics of = and += on the one hand, and of |= on the other, is the main thing that bothers me from a requirements perspective. But from a requirements perspective, the current behavior of = is also a bit weird and probably useless in certain cases. E.g. I think it's hard to justify (let alone find the use for) {} | ((.a,.b) = (1,2)) producing two copies of {"a":1, "b":2}. But let's set aside that case and focus on the relationship between = and |=.

So I think we're all agreed that the basic rule for |= ought to be:

V | (.a |= v) === V | (.a = (V | .a | v)  # (*)

when v and V are singletons.

The issue thus becomes: what if v is a (possibly empty) stream?

Currently, both .a = (1,2) and a += (1,2) have the normal stream semantics (i.e., producing two distinct objects as one would expect), and .a |= (1,2) is the odd man out as it has reduction semantics.

My main point is that it would be possible to define (.a |= STREAM) to have stream semantics based on (*). (E.g., (.a |= (1,2)) would produce the stream: (.a=1), (.a=2).)

Since reduction can readily be achieved by other means, it seems to me that consistency in favor of stream semantics should win, at least in this case (when the LHS is uncomplicated).

@nicowilliams
Copy link
Contributor Author

For now, since we don't say, empty in the RHS is undefined. Don't do it.

@nicowilliams
Copy link
Contributor Author

I don't think we can have the semantics you propose. How would you implement _modify(paths; update) to get the semantics you want? Remember, the paths expression can be a generator, and that's too useful and must stay.

nicowilliams added a commit that referenced this issue Aug 16, 2015
@dtolnay dtolnay added usability and removed support labels Aug 22, 2015
eiiches added a commit to eiiches/jackson-jq that referenced this issue Mar 30, 2019
Current |= operator in jq may return unexpected values when RHS is empty.

`[1,2,3] | ((.[] | select(. > 1)) |= empty)` => `[1,3]`

I don't say this is a bug. It's just an undefined behavior (*2). In
jackson-jq, rather than emulating the exact same behavior, I decided to
raise an error to notify users that this is an undefined behavior.

Users can still directly call _modify/2 to obtain the same result.

Related issues:
(*1) /jqlang/jq/issues/1751
(*2) /jqlang/jq/issues/897
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants