-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
interpret call f(; x, y) as f(; x=x, y=y) #29333
Comments
This is implementable as a macro if you really need it and it doesn't enabling doing anything that couldn't be done while making the syntax much more confusing (even more so than the significance of It'll also give |
Of course, the whole point of introducing this as syntax is to avoid a macro.
|
I see Rust has something similar for their kwarg constuctors https://doc.rust-lang.org/book/2018-edition/ch05-01-defining-structs.html#using-the-field-init-shorthand-when-variables-and-fields-have-the-same-name. |
For start, And it did cause issues with macros in corner cases. |
My biggest concern over this is that really it shouldn't matter what name you've given to a variable, but in this case you have to be careful if you rename anything, because it can subtly change behavior when using keyword arguments. Instead of just being able to rename your variable, you have to comb through all potential uses of it in this context, and if you miss one you get an unsupported keyword argument error (if you're lucky) or a different result entirely (if you aren't). |
This argument is a bit late, you do already have to comb through potential uses, e.g. function f()
s = 0
let
a = 3
end
return s
end Renaming the variable |
This isn't a defence at all. It's all about the "subtleness" of the change and more precisely, the localness of the effect. Of course you can't rename a variable that override another one without any observable effect. You don't even need that Edit: The effect of renaming a variable in this PR though, is not local. It's observable from not just the scope you see, but also from the callee scope. A macro can serve as a clear marker of customized evaluation rule so it won't be too bad for the reader. The syntax proposed here, however, allows this to happen in a much more subtle way. |
This is already implemented here, commented out: Line 1746 in 8484f97
It's done during lowering, since f(; x) and f(; x=x) of course parse differently.
Given the precedent in Rust and other languages with some kind of object notation (e.g. C#, VB, JS) I think this is a reasonable feature. Some commentary from David Anthoff: #22194 (comment) |
I work extensively in Javascript/Typescript, where this is an extremely useful feature. It was originally prototyped in CoffeeScript (a compile-to-Javascript language with terser syntax) and then folded into Javascript proper in Javascript ES6. If anyone is curious to read the discussion thread where this feature was proposed for Rust, here it is: rust-lang/rfcs#1682 |
I don't believe you can call something useful if it doesn't allow you to do anything new. I certainly agree it's "convinient" in some cases but that's also a feature of all the other syntax sugars that makes writing the code slightly easier but reading the code much harder.
I don't know Rust very well to know for sure but the other examples certainly doesn't have macros similar to what julia have. (Even the rust one doesn't seem as flexible as julia's and it certainly put less work on the macro writers to deal with the syntax details.) So while rust has macro implementation as alternative, other languages mentioned doesn't. From the linked rust RFC, the alternative syntax is |
This is an absurd argument. If this was true we'd all just write assembly code. |
I think the concern about this feature is essentially this. Currently, if you want to rename a variable to a new unique name, all you have to do is find every instance of it, following the scope rules, and change all those instances. (If you want to rename a variable to something else, you have to worry about name collisions, but that's complicated, so let's ignore it.) With this feature, that's no longer true, you have to also expand any instance |
Yes, agreed. I think enough other (very widely used) languages have had this feature for long enough to safely conclude that it's not a disaster. |
Well, writing assembly code requires significant knowledge of the hardware, is not portable, does not provide features (restrictions) to allow concepts of interfaces so that different code (modules) could interact with each other knowing what other code would use it, etc. All of these are enabling new functionalities that's not doable with assembly code. If theses were doable with macros on top of assembly language, then yes I would totally agree that we don't need any other languages. It seems that this is not the case though, implementation of many of these requires significant restrictions to what the user is allowed to do.
No, not at all, that's not even my objection. I wrote #29333 (comment) only because I think that is a minor issue and the defence against it is not valid.
None of them has as flexible macro as ours. Only one of them has to make a choice in order to have that function at all (since others don't have macros as alternative). This significance of creating temporary variables is basically my biggest objection. I see the variable renaming as a readability and maintainability issue that's only a minor concern since it'll only give a harder life for people that want to use it, I'll be ok with it if that was the only issue. The significance of adding local variable, however, is not like that. All macro writers now have to be careful when splicing expressions and when creating local variables since they might change the semantics of the code they generate. |
In another word, I'll be ok with this if we disallow Edit: note that this does not imply I'll like this or want to use it in this case, neither does it mean I think this is a worthwhile trade off, just that the two features are in conflict. |
This is always true? |
Ref: #27649. |
The thing is, the context |
@HarrisonGrodin oh, wow, that's an exact dup. |
It's one thing if you do this and get an error (current behavior), it's much worse if you do this and get working code with completely different result (proposed behavior).
And no. Creating local variable in general should not change the semantics. |
Presumably |
I think I would like this more if the named context was required for any calls with keyword arguments, e.g. |
I leverage the fact that keyword arguments are not required to be at the end pretty strongly in my Hyperscript package — In HTML attributes are specified at the start, and this lets you write |
Another argument in favor of this feature: what else would it mean? Even if we decide later that we want a different way to express this, what else would this particular syntax mean besides this? |
FWIW, I have been experimenting with a pair of macros for a few months now --- one that allows deconstructing dispatch on named tuple arguments and turned out to be very brittle and useless (because of matching the exact ordered set of names), but the other is @eponymtuple(a, b, c = 3) which turns into (a = a, b = b, c = 3) I find it very useful to organize code in the following situations:
I can of course live with a macro, but adding this to |
Is there a chance that this feature gets released with 1.x in the near future? |
There's a chance of it; the main problem is this seems to be somewhat controversial, with many in favor but several opposed. |
My concerns over this as a general feature still stand, but I've definitely felt many cases lately where it would be quite convenient. |
The more I've thought about this, the more I'm in favor of |
I thought I had already commented this, but it looks like I never did; I'm also very much in favor of this. Having done a bunch of javascript/typescript lately, it's widely used and pretty handy; I've grown to really enjoy it. I also think it's a pretty "natural" feature; like, it's pretty easy to guess what it means just by looking at it (in a namedtuple or keyword arg context). |
I also wanted this feature several times in the past and would be in favor if this moves forward. Without this feature I often try to abbreviate variable names or even abbreviate the keyword name in order to not increase the line length of a function call. |
I'll start on a PR. I just realized one minor inconsistency is that |
Function definitions are already different from call sites anyway, so I'd agree that it isn't a showstopper, but it is a bit unfortunate. |
I don't really think that's so bad. Even if |
I thought the canonical way to do that was |
Not since #25830. |
- `x` implies `x=x` - `a.b` implies `b=a.b` closes #29333
- `x` implies `x=x` - `a.b` implies `b=a.b` closes #29333
Given that the feature suggested is possible to implement in a package with a macro (eg jw3126/EponymKeywordSyntax.jl), I am not sure it should be in As much as I find the feature useful, I think that making this transformation only when explicitly requested would be the best approach for now. |
- `x` implies `x=x` - `a.b` implies `b=a.b` closes #29333
- `x` implies `x=x` - `a.b` implies `b=a.b` closes JuliaLang#29333
- `x` implies `x=x` - `a.b` implies `b=a.b` closes JuliaLang#29333
- `x` implies `x=x` - `a.b` implies `b=a.b` closes #29333
Sorry if this is a dup but I couldn't find one.
I find it quite common that one calls functions with keyword arguments like
My proposal is to write this as
f(;x, y, this_was_a_bit_long)
and to parse that to the first example.
Since
f(; x, y)
is already a syntax error, I think this should be possible?
The text was updated successfully, but these errors were encountered: