Here’s my 2 cents from someone seasoned in Ruby but fresh to Crystal.
If we really want to overload the & symbol for this then I strongly prefer that we require that a number is always suffixed, i.e., &1, &2, &3, &N.
The & can already find itself in some hairy readability situations today like aa.bb(&->cc.dd(T1, T2(TN))). When parsing this symbol thicket I don’t want to even remotely think that maybe, somehow, an ampersand in there can also refer to the first passed argument of a function.
Enforcing a number suffix would at least allow me to mentally parse code faster by instantly recognizing & + digit groups and shoving them aside in my brain instead of worrying about deciphering which particular use case of & is this.
Right now & has very clear purposes related to capturing and forwarding procs. Aliasing variable names is a very different and much simpler thing that I think deserves a more instantly recognizable visual shape.
I suggest we overload a less common symbol, like %N, 'N or ^N if feasible. Even @N would be okay IMO.
But definitely anything other than _1, _2, _N. There’s just something terribly unbalanced about it in my eyes :)
On the usefulness of this sort of aliasing I suspect this is less useful in Crystal due to what you can already accomplish with &->. In Ruby I do find myself needing it fairly often to avoid ballooning otherwise very short blocks. It’s definitely a sharp knife. Drink responsibly. Words over symbols
I second this. (I would even go a step further, and suggest some new symbol, chosen from some unicode set. But that is obviously currently not very useful to type)
Just throwing my two cents in. Personally I like the idea of keeping the current syntax when it comes to simple things like arr.map(&.to_s), but within an actual block a number suffix should be enforced to reduce ambiguity.
So
foo do
&0.first
&1.second
end
It feels like it would be a fairly minimal addition, and wouldn’t break existing code. It is certainly less explicit though.
The Safe Navigation Operator (&.) is the most highly unreadable syntax in this language, but Crystal devs love it. But but… we can’t have it inside methods though!
Not sure why you call &. a “Safe Navigation Operator” though, it’s not an operator, more like a shorthand notation for blocks.
And it’s not about safe/unsafe navigation, the behavior is defined by the method you’re calling and has nothing to do with the &. syntax
I think it depends on the context. It can be abused and look bad, but in other instances it is quite nice because the variable is clear and coming up with a name just makes things more indirect. To me this is a sharp tool. Helpful, but can be misused. I think that can be ok if
Here’s an example of a pattern often used in Lucky Operations:
password.value.try do |value|
copy_and_encrypt_password value, to: encrypted_password
end
The problem here is now “value” isn’t that clear, but I also can’t name it password. Basically “value” is a meaningly variable, but there isn’t really a better one
password.value.try do
copy_and_encrypt_password &1, to: encrypted_password
end
To me this is fantastic. &1 is password.value. Nice! No need for a meaningless variable name like “value” or an unnecessarily long one like “password_value”
It’s a small win, but since this pattern is used all over Lucky (and most of my Crystal) projects to handle nil this really does save a lot of little papercuts.
Definitely not necessary, but would be a nice little win for the people that would like it. But I understand we can’t get everything so I get it if this is not added :)
&. in Crystal is &: in Ruby. There is no such thing as a Safe Navigation Operator in Crystal. So the official name would be Short one-argument syntax I suppose.
why not just _0?
come to think about it I also thought about this issue just yesterday after seeing ruby code with _1, _2.
IIRC there were some problems with this proposal: nesting blocks creating ambiguous references. I think we can do it this way instead: requiring another _ to refer to outer block anonymous block variables:
hash.each { # hash is Hash(Int, Array(Int322)
_2.map { _0 + __1 } # _1 here mapping to `value`, _0 is element of array, __1 refers to outer `key`
}
yeah this looks silly but you get the idea, dirty codes should look dirty so you want to clean it up later.
edit: personally I like \ more, eg, \1, \2. the reason is regex is already using this convention + \ is easier to type.
For what? it is equivalent to _1.
The reason to introduce it in Ruby seems to be that the underscore syntax comes off as weird for some people and that way you get at least a nice accessor for the first parameter
Please no. That’s going over the top. If you have to count the number of leading underscores to understand the code, you’ll soon get lost. Better use named arguments for this.
Multiple nested blocks doesn’t fit the use case for this feature, being a simple inline block.
Hm, an interesting fresh idea! Readability wise I would certainly prefer this over _1, _2 etc.
I misunderstood the thread so I assumed that they want another keyword to capture all the block variables.
anyway, since crystal support automatic tuple unpack, this might cause real issues, plus sometime I want to capture all the block variables to pass it to other methods, too. having a capture all variable will be pretty convenience and also avoid a lot of confusion.
Please no. That’s going over the top.
that’s the point, for me _1, _2 mostly use for one time script so it should look dirty so you will have the urge to modify it when you decide to keep it longer.
Hm, an interesting fresh idea! Readability wise I would certainly prefer this over _1, _2 etc.
too bad \\1 will look even more silly, guess if we decide to use this then only one level would be allowed (also \1 looks less dirty so I will probably keep it in my code even after cleaning up)