Extracted from #7429, which has been closed due to the fact that some of the members of the community can’t stand the fact someone that is having a different point of view (see the irony).
So,
foo do |x|
x.foo
x.bar
end
and
foo do
&.foo
&.bar
end
Let’s continue arguing and insulting each other the discussion then.
I had extra subjective pros:
- A developer would not need to think of the argument naming anymore
- Ampersand is highlighted, which allows the brain to quickly extract the call name (compare
x.foo
and&.foo
in the example above, listen to how your brain reads it) - A developer would still be free to choose between explicit block argument and
&.
whenever they want to - It would conform with the existing
foo &.bar
syntax, as it expands tofoo { |x| x.bar }
, which is essentially the same - It would not affect the
with yield
syntax
Let’s skip the fact that I could have chosen Go or C instead of Crystal if it was not about subjective perception. And that Crystal would be just a one of meh languages if it was not expressive.
Oh wait, some community members are directly against expressiveness. They imply on the need for the code to be as much explicit as possible. But we have foo &.bar
. And we have record
. And tons of other macros. And also getter
, setter
and property
. Why not defining def get_foo
and def set_foo
explicitly? getter
is too implicit! Vote for removing the getter
macro from the language!
My point is that expressiveness is the amount of code a developer needs to write to achieve the same result preserving the readability. foo &.bar
equals to foo { |x| x.bar }
, record
equals to struct Foo ...
. We omit repeatable code using some rules.
foo do |x|
x.foo
x.bar
end
Is a perfect use-case for omitting the code with a simple rule – &
= first block argument. It’s easy to remember, it’s easy to parse on the brain-side. Maybe even simpler than record
macro.