4 ms·
Sorry I was short. I mean operator precedence was not considered. In the first implementation, 'def =' has higher precedence than 'if'. Which leads to surprisin
by lolc 3y ago
Sorry I was short. I mean operator precedence was not considered. In the first implementation, 'def =' has higher precedence than 'if'. Which leads to surprising behaviour with tailing ifs. The if is evaluated to determine whether the method should be defined, instead of being part of the expression.
The fact that they released this and are now considering a change in precedence is a showcase of the haphazard development of the lang. If the feature were useful, somebody could have tried using it and noticed the issue before they released it. But it's just a clever hack that adds another way how methods can be written. Nobody sane will use it, but the golfers cheer it into the release.
- PH95VuimJjqBqy 3y agoI can't speak for ruby development, but I can tell you literally every RoR project I've ever taken on has me losing even more respect for the community as a whole. Somehow I always seem to find the ruby projects where everything stopped being supported years before.
- vidarh 3y ago"def =" isn't operator. It doesn't have a precedence. "=" is an operator, and has a precedence, and in ruby "def some_method ... if something" is an entirely valid expression, and not one you can arbitrarily ban for all def expressions because it is occasionally used (not a fan of using a trailing if here, it's rarely obvious). It's not haphazard. It was an intentional tradeoff knowing that introducing new rules into the parser that would address this would delay introducing the feature, and that it might make sense to defer changing it until the currently ongoing process of replacing the parser is complete, and deciding that it was useful enough this way in the meantime. That there are corner cases was well-known before it was released. If you're going to criticise how this was handled, at least understand the issue before you jump to conclusions. It's perfectly fine to disagree with the tradeoff, but that tradeoff was intentional.
- lolc 3y agoOh so they knew? My understanding is that it's already released, warts and all. Did I misread? So the tradeoff is that the parsing rules of that operator may change in the future? Who would even use it if it could change again?
- vidarh 3y ago> Oh so they knew? It was an obvious consequence of the grammar rule that was updated. > My understanding is that it's already released, warts and all. Did I misread? It was added on a experimental basis 3.5 years ago, and released in Ruby 3.0.0 in December 2020 (Ruby currently bumps the first decimal every Christmas day, current release series is 3.2, and 3.3.0 is due this Christmas. > So the tradeoff is that the parsing rules of that operator may change in the future? Who would even use it if it could change again? You can safely use it as long as you understand that anything that inside the method body might operate on a whole assignment expression will likely operate on the `def` if applied to an endless method which is almost certainly not what you want, in which case the solution is to either not use an endless def or use parentheses to make your intent clear. IF operating on the `def` expression is what you want, then you either need to avoid end-less def's or enclose the expression in parentheses or your code might break. That is, this is safe (but means different things), as long as "some_expression" is safe to put as the right hand side of an expression (which might take parentheses or not): def foo = (some_expression if bar) (def foo = some_expression) if bar def foo = some_expression This is not: def foo = some_expression if bar I
- lolc 3y agoThanks for the clarification. The whole thing is pretty far from the principle of least surprise for me. But so is operating on a def. Why would that be allowed if it is likely to change? Oh well, not that I needed more reasons not to use Ruby.
- vidarh 3y ago> But so is operating on a def. A "def" in Ruby is just syntactic sugar for calling the method `define_method(name) <block>`, and so there's no reason you shouldn't be able to operate on a def by Ruby thinking because it's just another form of expression and disallowing it would involve a special rule for a specific situation. You can do the same with classes, modules etc. ("class Foo; end if expression_evaluating_to_false" will not define Foo, same as if you'd wrapped it in "if false ... end). Even more so because a training "if" is just syntactic sugar for "if <condition> then <expression> end" and so given that Ruby made the choice that defining classes and modules and methods is allowed as expressions in conditional blocks, it'd be an odd exception to exclude them from training if's. The Ruby philosophy there is that this is what falls out of the generic rules, so it's allowed, and maybe someone finds a reasonable use for it, or not, but disallowing it for the sake of it doesn't really fit Ruby. > Why would that be allowed if it is likely to change? That isn't likely to change, and it's not a new thing - it's been part of Ruby from the start. Only the precedence is likely to change exactly to bring it closer to the principle of least surprise. You will still be able to write "def foo; end if some_condition" because expectations there (to Ruby programmers anyway) are clear, or "(def foo() = expression) if some_condition". If it happens, any precedence change will be based on what will cause the least surprise if people leave out the parentheses. Almost everything in Ruby can be thought of as a method call or expression - it's our inheritance from Smalltalk, which is perhaps the strongest influence on Ruby. E.g. a "if" or "case" expression also has a return value, just like "class" and "def". There's "special syntax" in terms of parsing, where Ruby's focus has always been "developer happiness" over purity, but extremely little special syntax in terms of semantics.