Got an idea while reading this forum thread -- make &. an alias to the_first_block_argument. within blocks. In my use-case, I have a Query(T)#join(reference, &block) method which yields another Query(U) instance:
query = Query(Post).new
.where(id: 42)
.join(:author) do |q|
q.select(:username)
q.select(:bio)
end
It would be much easier to write (and read) this code instead:
query = Query(Post).new
.where(id: 42)
.join(:author) do
&.select(:username)
&.select(:bio)
end
q.select and &.select in the example above, listen to how your brain reads it)&. whenever they want tofoo &.bar syntax, as it expands to foo { |x| x.bar }, which is essentially the samewith yield syntaxIf the incoming block argument is explicitly named, prohibit the &. usage:
def foo(&block)
yield "foo"
end
foo do |a|
&.upcase # Compile-time error, the block has explicit arguments
end
foo do
&.upcase # OK
end
def bar(&block)
yield "foo", "bar"
end
bar do |a, b|
&.upcase # Compile-time error, the block has explicit arguments
end
bar do |a|
&.upcase # Compile-time error, the block has explicit arguments
end
bar do
&.upcase # OK, omitting arguments except the first one
end
Nested blocks should work fine as well (should use explicit naming if need to distinguish):
query = Query(Post).new
.where(id: 42)
.join(:author) do
&.select(:username)
&.select(:bio)
&.join(:settings) do
&.select(:foo) # This &. is clearly belong to the nested block
end
end
It's just some sweet sugar which would improve the Quality Of a developers Life. WDYT?
It's just some sweet sugar which would improve the Quality Of a developers Life. WDYT?
By exchanging explicit block argument over implicit &? I don't see how, aside of shedding in most cases 3 characters (|x|) for the whole block...
foo do |x|
x.bar
x.baz
end
# vs
foo do
&.bar
&.baz
end
Sorry to interrupt, but can we continue discussing this in the forums? This is an issue tracker and this is not an issue (it's brainstorming).
@asterite it does not interfere with with yield replacement, it's a separate feature request.
What would happen in such case:
foo do
&.each(&.upcase)
end
?
If I understood correctly, &.each is from suggested syntax, and &.upcase is existing one.
So, if the first argument of foo is Enumerable, then &.upcase would apply to each member of this Enumerable or to Enumerable itself?
@AlexWayfer, consider this code:
["foo", "bar"].try &.each(&.upcase)
How do we know&.upcase would apply to each member of ["foo", "bar"] or to ["foo", "bar"] itself?
Yeah, @Sija, thanks, I see that you dislike it. A single "confused" emoji would be enough. I get it. Totally get it.
["foo", "bar"].try &.each(&.upcase)
OK, that's good example. If Crystal already can deal with it — I don't see a problem with this.
@vladfaust :D yeah, It's confusing for lil' gain and I do dislike it. If having symbols all over the place would be considered beautiful we all should be praising brainfuck ;)
So this proposal is about, instead of writing this:
foo do |x|
x.foo
x.bar
end
writing this:
foo do
&.foo
&.bar
end
In short:
x in this case) with &Conclusion: we only save writing the block argument.
I'm not sure that's a great advantage compared to not changing anything at all in the language, also considering that with ... yield has you typing less.
Sorry, closed accidentally (but I still think this should be closed and discussed in the forums, this is not an _issue_, it's a proposal).
Sorry, closed accidentally (but I still think this should be closed and discussed in the forums, this is not an _issue_, it's a proposal).
One of first lines in the CONTRIBUTING.md, current verstion:
The issue tracker is the heart of Crystal's work. Use it for bugs, questions, proposals and feature requests.
So…
@asterite, some additions to your conclusions:
q.select and &.select in the example above, listen to how your brain reads it. In fact, my brain doesn't pronounce & at all, it's like a picture, I just see it, while q is pronounced as _[k'u]_ -- this is subjective, I knowI think this feature worth at least thinking about.
Also with yield is kinda buggy when there is block forwarding included. That's why I sticked with explicit yield in my case.
Sorry, I don't see any benefit from this:
- A developer would not need to think of the argument naming anymore
That's not a pro. Naming is hard, agreed. But it's also important to explain what the code is doing. That's why it's hard.
- Ampersand is highlighted, which allows the brain to quickly extract the call name (compare
q.selectand&.selectin the example above, listen to how your brain reads it)
That's a completely random argument which solely depends on some specific behaviour of a syntax highlighter. I don't see a gain whatsoever. The focus thing doesn't even make sense.
- A developer would still be free to choose between explicit block argument and
&.whenever they want to
So what's the point in having two ways instead of one which everyone agrees on? Crystal's goal is to make it easier for developers to not have to think about circumstantial problems (like "which completely arbitrary alternative should I choose today?") but instead focus on meaningful decisions (like "what's the best name to convey the meaning of this variable?").
- It would conform with the existing
foo &.barsyntax, as it expands tofoo { |x| x.bar }, which is essentially the same
One syntax is a shortcut for the other. Using the shortcut in the expanded version is confusing.
- It would not affect the
with yieldsyntax
It would not affect my grandma's cat either.
@vladfaust "issues" you've highlighted are highly subjective, for one I have none of those. "beauty" argument is also pretty overused (especially by yourself) - some see beauty in say, Andy Warhol's "art", while personally I wouldn't pay a dime for any his pieces, so...
A developer would need to learn another - not-so-clear - construct and understand the distinction between .try &.each &.upcase and &.bar calls within a block - for what, shedding 3 characters altogether and satisfying you subjective sense of "beauty"?
Sorry but I think that topics like this are just waste of time and keyboards for the community... Also, that's what forum is for (on which btw, I haven't seen much praises for such idea).
I think the tones are becoming a bit more aggressive/sarcastic and it's not good. Because of that, I'm going to close this and lock the conversation. However, I strongly suggest continue discussing this in the forums. I think it's a bit related to the existing proposals (a way to omit mentioning the first block argument).
Most helpful comment
Yeah, @Sija, thanks, I see that you dislike it. A single "confused" emoji would be enough. I get it. Totally get it.