171 comments

[ 1.4 ms ] story [ 216 ms ] thread
[question]: Is the main benefit of "Rightward assignments" readability and does this provide more benefits?
Ruby currently supports "Rightward conditionals":

    user.delete() if deleteUser
It is probably thought that this feature would result in similar readability improvements.
I don't find that more readable at all. I prefer:

    if deleteUser
      user.delete()
    end
It's easier for me to read. It doesn't try to hide away logic. And if the line gets longer if the conditional gets more complex or I want to add an else I can without reformatting.
It's subjective, the point is that some people prefer it.
It works well for some cases. You end up with

return if a.nil? return if attempts < max_attempts

In this case "return if" becomes like a keyword and you can ignore it and focus on the rest of the expression. It also seems very readable for other simple values like `return false if ...`. But I agree, as soon as the code to the left of the `if` gets non-trivial it is harder to read.

Python has the same "rightward conditional" thing.

Any time I use it, I wish python had just gone with the normal ternary (? :) operator.

> Python has the same "rightward conditional" thing.

No, python writes the ternary operator with words, it doesn't have rightward conditionals.

The key difference is that the else clause is required in the Python ternary, where it's optional in a conditional.

Doesn't make it any less irritating.
I am also struggling to think of a situation where I would want to reach for this feature. The only examples I can muster are just minor improvements to readability, like you pointed out. I would love to see a solid example where this is a must have feature.
I think it would make sense for chained operations in a mental data flow sense.

    makejunk().filter().last(4) => fourthings
feels better than

    fourthings = makejunk().filter().last(4)
Not to me, and other people who use Ruby sparingly
I’m not sure. In shell, I think

  makejunk | grep foo | tail -4 > fourthings
is more popular than

  > fourthings makejunk | grep foo | tail -4
Having said that, I don’t understand why you would add this, but then, I don’t understand the popularity of ruby or other languages that think adding alternative ways to do things most of the time is a good thing.
In shell outside of file manipulation,

  fourthings=$(makejunk | grep foo | tail -4)
I think I would use this if I were writing a cpu emulator in Ruby (which I wouldn't). It mirrors assembly, but I'm not sure that's a good thing.
It depends upon the assembly language. Intel defines its opcodes as `dest,src` and Motorola did `src,dest`.
This hurts readability of code with lengthy expressions. Knowing the target of the assignment is usually more important than the particulars of the expression when you're skimming unfamiliar code. Having the variable pushed out to random locations on a ragged right side isn't helpful.
One of Ruby's philosophies is to provide multiple ways to express the same fundamental operation so that it can conform to your thoughts instead of forcing your thoughts to conform to it. You can still do it the old way where it makes sense. Whether this philosophy is helpful or harmful is another debate.
The fat rocket seems like an odd choice for an operator. It's already used for hashes - and you don't have to put set braces around hashes.
Until youre working on a team and your thoughts aren't the same as everyone else's thoughts.
Sure. Peer review, making sure that the code one person has written makes sense to the rest of the team, is a fundamental and incredibly important part of pretty much all team-based development projects.
(comment deleted)
that's why having a coding style guide is important and to lint it every commit.
That’s rubocop’s raison d’etre. I like that you can be completely free exploring with code in the style you like, and “button up” when it needs to become shipping/shared code.
That doesn't sound any more difficult to resolve than the fact that you are probably working on a team where different individuals prefer different programming languages.
(comment deleted)
If everyone thought like this there would only be one language that everyone used. Writing software is creative.
synonyms in ruby seem to be a mistake. Searching code for certain usage patterns ends up needing more complicated regular expressions taking into account all synonym variations.

If you've seen a method one way many times while learning, then see a synonym, you end up having to search up docs to make sure there isn't some subtle difference.

I find it really valuable to have different patterns of similar tokens to express different intent. My canonical example is early returns in JavaScript.

Function f () {

  if(errorCindition) return

  if(normalBehavior) {
    return 1
  }
  else {
    return 2
  }
}

(I know, my use of braces and lack of semi-colons will cause flame wars!)

The error condition looks different from the rest, so when I’m scanning quickly, I know where I am. My eyesight’s rubbish, so the shape of the code has a marked impact on me. I don’t have to read the whole thing to orient myself.

I thought it was nuts when I read the title, but reading the examples had a noticeable “easing” effect on my reading. So I’m very excited by this addition to Ruby. It could lead to some neat, expressive patterns.

shape of the code

This is an undervalued aspect of development. The tactile shape of a block of code conveys some aspects of intent, and overly aggressive linting tools destroy that intent.

There almost invariably is a subtle difference (very commonly, in precedence), and that's usually a key part of the motivation for the (near) synonym.
That makes it confusing when there isn't a difference (I think map and collect?).
Oh, I was thinking of (nearly) synonymous alternate syntax. It's true that Ruby has lots of true synonyms in method names.
> multiple ways to express the same fundamental operation

Sounds like the timtowtdi of perl. Funny, I've always called ruby "perl++".

Remember how perl is known to be readable?

Is this like 'unless'?

Unless is great if it's the first or second clause on the line. If it's the tenth, then it feels more like slapstick and I am the butt of the joke. Haha, just kidding, we aren't really going to call that function.

Similarly, rightward:

   someBigFunction(thatNeedsAnswersFrom(), otherFunctions(), true) => variableIAmDebugging
Three unnamed Laws of Computing that everyone ignores and at their peril:

- Nobody reads your unit tests in a PR

- People glaze over at the end of long lines of code

- Merges are hard

#2 and #3 combine to cause over half of the bad merges I have had to diagnose. Don't save the important bits for the end of a line. If I were still writing Ruby code, I'd be prepping to see more of them.

If your 10th clause is an unless then you're using it wrong. I agree that unless and the right hand assignment can be used incorrectly but that's not a reason to omit the feature :)
Where these conversations tend to break down is "you are using it wrong", which is technically correct but practically is a non sequitur.

I can't control other people. Neither can you. Unfortunately saying that and acting like it's true are two separate things, and so we are chronically making decisions based on an illusion of control that is unhealthy to the point of self-harm. It just sets you up for disappointment and/or antisocial behavior (eg delusions of grandeur)

We put safeties on missiles. We color code and cover emergency power cutoffs in server rooms. We've started putting finger preservation devices on table saws. But code? Well it's your fault for backing into the shutoff button.

"You're using it wrong" = "People will use it wrong." = "You're going to have to work with people who use it wrong" = "You are going to run out of places to hide their bodies and just have to accept it being used wrong."

The question isn't "can it be used right?". Every bad library ever written has been "used right" by at least the author, even if not all the time. The question is "can we live with how often it is going to be used wrong?"

(comment deleted)
> We put safeties on missiles

And we put linters on code.

Sometimes. Often we don't. Putting linters on code is doing it right. But unless the language is opinionated and requires the linter there will be people who don't use it.
There are no language features that can't "be used wrong". This argument proves too much!

Status Quo Bias is probably why we don't think of existing language features this way.

It's of course true that we're all likely to work with (or even be) incompetent people, but I really doubt individual language features has substantial impact on the damage they cause.

Rightward assignment is pretty strongly discouraged in the R community, due to the effect it has of burying the lede. That said, I always felt the same about Ruby’s inline if/unless (`puts "still working" unless done`) so maybe it will have a better reception in this community.
Interesting, that it became discouraged. Probably won’t make it into Ruby proper then. I don’t fault them for experiment.
Actually, this is a pretty good reason, and it's straight from the source (creator of S, the predecessor of R): https://stackoverflow.com/a/51548423/139922

> When you type a long expression only to remember at the end that it would be a good idea to save the result, a right-hand arrow allows you to perform an assignment without retyping the line.

(I don't do this personally, though. I just run the expression and then my next command is `x <- .Last.value`)

I use right assignment in this way all the time, you should try it Joe :)
> While the above pattern has become standardized, it feels somewhat unnatural as we read most of the spoken languages from left to right.

Is this true (the 'unnatural' part)? Reading left to right, `age = 42` can be read as "age is 42" which feels perfectly natural in English. `42 => age` would be read as "assign 42 to age"? This feels more awkward to me. I'm not sure I understand why anyone would want Rightward assignment.

Exactly how I feel. This is one of the reasons I'm not a huge fan of R, either
If you visualize variables as "boxes" with values in them, "put 42 in age" makes sense.
A math tutor of mine was actually pretty angry at computer science for writing things like `a=1; a=2; //so 1=2 ?` I guess he'd rather have the "assign 42 to age"... Except he'd probably read `42 => age` as "42 implies age", which would probably cause him more sleepless nights ;)
He’d probably like a := 42 which is in a lot of languages actually! Also Erlang and other fp’s do consider = equivalence.
I noticed a year or two ago when I'm pseudocoding I seem to default to "age <- 42" which I kinda like more...
I'm a big fan of immutability and using constantly so I agree with your tutor.
> math tutor ... angry

It's not the same language, so why should he expect the semantics to be the same?

> It's not the same language, so why should he expect the semantics to be the same?

It's a bit like discovering that inline C in your favourite non-C language isn't actually semantically correct C. If you're a mathematician, then you know, intimately and fluently, how math is spoken and written, so seeing something that looks exactly like "inline math", but isn't, is jarring.

(I don't get angry over it, but it is exactly counter to the extremely delicate and precise way mathematicians train ourselves to think about '='.)

I had the same issue. This is why I always comment my assignments.

    x = x + 1 // assign x to x+1
I can't tell if this is a multiple joke or not
(comment deleted)
`42 => age` would probably be "42 is age", or if it was `42 => person.age` you'd read it "42 is person's age".
Agreed, when I read that line I found myself saying it out loud wondering if it was a typo.

`favorite_color = red' == "Favorite Color is Red"

Which feels more natural than: "Red is Favorite Color"

But “age is 42” is a statement/Boolean, not a mutation. “Let age be 42” is more natural, but doesn’t sound well on reassignments (“let age now be 42”?)
I read assignment like "age gets 42".
I would say this as "set age to 42".
"age is 42" may be a statement while "is age 42" may produce a boolean.

And I don't see why a statement can't describe a mutation.

I read it as "42 is stored in age". The works particularly well for a long chain of methods that should end in storing the resulting value in a variable. I know this might seem to be the most conventional way that Ruby is written; it makes a single statement take 8 lines instead of 1, it transforms a value over the course of the statement instead of sending messages to tell an object to transform itself, and it ignores the concept of encapsulation by moving the interesting actions into the foreground rather than being hidden within an object.

Below is an _incredibly_ contrived example. Take note how the `=> final_value` syntax is useful. The alternative is to place a `final_value = ` at the _top_ of the statement. I'll admit: placing the assignment at the top of the method chain helps point out to the reader of the code that an assignment is happening. However, more useful I think is quickly recognizing the flow of data.

  "hello"
    .chars
    .size
    .*(10980643.4)
    .to_i
    .to_s(36)
    .upcase
    => final_value
  
  puts(final_value)
  # => WORLD
... and it's useful how? It obscures the assignment at the end of an arbitrarily long statement instead of giving the value a name right up front.

It feels a bit like a new method definition syntax that allows you to put the name after the `end` for... reasons.

wait i feel like that's actually kind of gorgeous. syntax highlighting as it exists today might not be good enough to really make that form stand out, though...
"42 gets crammed into age"
Is this really just syntactic sugar? None of the examples in the article seemed to show why code would be more readable (array assignment maybe, but the leftward seems just as readable).
Why? Why does ruby have an infinite amount of ways to do the same thing?
As someone else said in these comments, Ruby offers multiple ways to express things, so you have more options to "write how you think" as opposed to being pushed to "think how the language wants you to write".

I'm not saying it's good or bad, I'm just saying that appears to be one of the reasons for it.

This is actually one of the things I first liked about Ruby. Then it became one of the main reasons I started disliking Ruby.
It seems the opinionated, directive "there's only one way to do it" approach is winning over the hacking around, "wrapping around your mind" approach. Lisp and Perl have had their times under the sun, now it's all about Python and Go. Perhaps these things are cyclical.
I'm just happy that there's still a popular language around that lets me write how I think (or however _I_ think would make the code look the best), so I don't have to suffer through using languages that direct how I have to write every little thing.

Having both options is nice!

I'm using both Ruby and Go a lot (also Elixir, PHP, Bash and others).

I wouldn't even say that they solve different problems for me, it's more a matter of how I need the problem solved. If I need something that runs on other OSes than my Linux box preferably with as few dependencies as possible, Go. However, I can probably code it faster in Ruby, so if it only needs to run on my machine or if I know Ruby's available where it needs to be run, then I'll probably go with Ruby.

I think, instead of arguing which is better, the argument should be about whether they're useful. And for both Go and Ruby that's an "absolutely!" from me.

It's great if you're the only one who ever has to read or maintain your code.
I love Ruby and its 10th ways of writing code to achieve same thing...

Eh, there is a reason why Golang has such a huge popularity.

It's not like Ruby has an insignificant amount of users either...
Go is hugely popular? That's news to me.
To counter some of the complaints regarding readability, a major use case for this is simply hacking stuff together in the REPL. Sometimes you notice you want to have your result as a variable when you've just typed a line, and other solutions for this problem (Ctrl+A or ENTER plus foo = _) are not universal.

Disclaimer: I'm not a core dev but saw a discussion amongst them about such use cases.

This is the exact reason I've wanted this, for a long time. I even asked Matz about it a conference once, probably 10-ish years ago.
This is a completely unnecessary feature. `_` is always assigned to the value of the previous expression.

    >> 4 + 2
    => 6
    >> _
    => 6
    >> "abc" + "def"
    => "abcdef"
    >> _
    => "abcdef
Adding this kind of syntax for something that's already trivial to do is honestly kind of distressing for me as a Ruby developer who's been around since early 1.8.

I still strongly believe that the `key: value` hash syntax was a massive mistake. That's a lost battle, but this is getting ridiculous.

`_` being assigned the result of the last statement evaluated is an IRB feature [1], not a ruby feature - hence the note that it is not a universal solution.

[1]: https://github.com/ruby/irb/blob/master/lib/irb/context.rb#L...

So?

Why does this need to be in the language when both major REPLs already support it? Why must this be yet another alternative way to accomplish the same thing as the way that’s existed since the first days of the language?

There is no argument in favor of this addition. It doesn’t allow anything new, it provides a pointless alternative to the current way of doing things, and the one situation where it’s useful—REPLs—there’s already a feature that renders it completely unnecessary.

Then maybe it should be a feature that only exists in the REPL like _.
I've got "<up> <ctrl-a> q = " in muscle memory by now. I feel like I've got a hand tied behind my back when I'm in a place that doesn't support those keybindings, but I'm not sure finding rightward assigns peppered at the 128th stack depth is going to make me a happier developer.
This is just feature bloat. Why is this needed?
Because after a few thousand hours of ruby, when you can - most of the time - tell a variable form a function, or if a function is receiving a list of argument or a hash, you now need another challenge.
I'm also not a fan of spending this syntax card on this feature. The ... => ... syntax might be needed for something more useful in the future.
Here is a feature ticket. The usage in a data transformation pipeline feels right and appropriate as in comment #20 https://bugs.ruby-lang.org/issues/15921
I don't find that reason any more compelling than any other reason I've read. I still don't get why it's better than what already exists.
The example given in comment #20 provides a practical reason for it, in that in some cases it makes things more consistent visually. But mostly these reasons are subjective and some people will be more or less sensitive to them. A lot of programming language design and tool design in general is not completely rational or about functionality only.
I'm sorry but this "feature" is yet another design a hacker living in a bubble came up with. Most people think and program in English, or languages very close to English. In English I can read let x be 4ys and some change. I don't know how to read the arrow. 4ys and some change implies x? If this is a feature designed purely for speakers of SOV or OSV order languages like Japanese, that's fine, but the dominant language in technical discourse isn't one of those.
Comprehension follows perception
> I don't know how to read the arrow.

As a description (which is an easier translation of this idiom into English than an imperative) “is assigned to”.

Imperatively, English tends to prefer verb-object with implicit subject, so we ought to be using a Lisp family language (setq “foo” 42) maps better to English imperative structure than most popular languages that do imperative assignment.

Complete English sentences in present tense are infix, with the subject and object clearly stated. Implicit subjects only follow after the first sentence in a paragraph or a phrase. Case in point is the words you've read so far. "are", "follow" and "is" are verbs. This is why most programming languages are in infix notation. Lisp syntax stayed is a historical accident. [1] Arabic is a prefix languages, and people don't program in Arabic.

"is assigned to" is passive voice. I think we've all learned in writing classes we should avoid it as much as possible because stating the active voice is clearer.

[1]: http://www.paulgraham.com/icad.html

> Complete English sentences in present tense are infix. . Implicit subjects only follow after the first sentence in a paragraph or a phrase.

This is true of the indicative mood, but not the imperative.

Giving commands in the indicative mood is not typical.

Yes that's true. That's why most languages have infix operators and prefix function calls.
> I think we've all learned in writing classes we should avoid it as much as possible because stating the active voice is clearer.

Writing classes can be misguided.

http://www.lel.ed.ac.uk/grammar/passives.html

No, in that example, the TA is very misguided and clearly didn't understand what passive voice is. Passive voice only applies to verbs, and it's often used to invert the object and the subject, occasionally used to emphasis one over another[1]. Unfortunately in English, there are a lot of adjectives that look like verbs in passive voice, examples like "interested" and "motivated" are given in the link you provided. The Edinburgh professor is not wrong either, he just thought every university teaches in America teaches passive voice the wrong way. Not in my case.

[1]: https://www.ef.com/ca/english-resources/english-grammar/pass...

The student paper is one of many examples of people inveighing against the passive while 1) providing incorrect examples, and usually 2) using it. It's amusing, but it's not the whole point:

"The passive is of course perfectly respectable, and there is no reason to try to avoid it. (To say that it shouldn't be over-used, or it shouldn't be used where it is inappropriate, doesn't distinguish it from any other construction or expression.)"

See the tremendous list of Language Log links at the bottom which deal with the issue from a host of angles. I recommend reading some of them - Geoff Pullum, in particular, is usually delightful.

"You should use active voice whenever possible" is bad advice - both active and passive are (nearly?) always possible but often one is clearer - and that can very much be the passive.

"You should use active except when passive is better" is arguably correct but fails to actually provide guidance about when the passive actually is better - which isn't rare.

That the passive is often overused may be useful to note, if that's actually the case.

The sentence "The passive voice is overused." illustrates this tension well. When you omit the subject, (implicitly we all know who that sentence is referring to), passive voice is more concise, but it's not clearer. It's actually less clear because there's less information available. I think this is the distinction most commentator miss.

In programming languages we often find better, we prefer explicitness over implicitness if the language is already designed to be very concise. Case in point: Python.

The passive lets you omit the subject gramatically. In every case, you can include an informative or uninformative subject. If you are including an uninformative subject, the passive is probably clearer.

The clearest is not the most informative; the clearest provides the most important information and the least distracting information.

"Helicopters were used to control the blaze" is no less clear than "the blaze was controlled using helicopters". And, assuming the news item is about the trajectory of the fire, it is much more clear than "Pilot John Smith, having just moved to the area from Baltimore where he attended school with a 3.7 GPA, helped control the blaze with a fire department helicopter" despite that offering quite a bit more information.

To your explicit claim, I contend that "the passive voice is overused" would not be made clearer phrased "writers overuse the passive voice".

>R language also has a similar way of doing this 42 -> age.

Ah yes, the R language, a model of clarity, beauty and lightness in the world of programming languages. Truly an example to follow.

(And it's not like anyone ever uses that "feature" in the R world either.)

shrug

I've used it. The overloading of the equals sign is something that has never made sense for assignment. (Seriously, it's hard to intentionally come up with dumber notation than x = x+1.) I do use -> sometimes. It's more natural to do the evaluation and then figure out where you're going to store the result (particularly when you're programming).

This is minor as these things go. Definitely not a big deal one way or the other.

If assignment is what we are concerned about, we should introduce something like `x := x + 1`.
why `:=` and not `<-`?

The `<-` in R comes from the APL keyboard, and that glyph is an assignment in APL. It wasn't just some crazy invention from Ross & Robert or even John Chambers.

Left side assignment is still used to us, from maths and most other programming languages, so it keeps things familar.

The `:=` has been in use in other langs like MySQL

Is "x<-3" an assignment to x or a comparison of x to -3?

The same problem led early C (pre-K&R1) to change its compound assignment operators from "=op" to "op=". In early C, "x = -3" assigned the value -3 to x (as it does now), but "x=-3" meant "x = x - 3" (now written "x-=3").

I don't understand what point you are trying to make here. Do you not like the feature simply because R has a similar feature? Why not look at examples given here and by others and decide/comment on whether it adds clarity or expressiveness or not?
I am making two points:

-Arguing that adding a feature is ok because "R does it" is comically wrong when one is acquainted with all of R's warts and superfluous stuff

-Not even the R world uses that feature either, so we have actual empirical evidence that it's not that helpful to developers.

I wouldn't say an additional notes section at the end of article showing that is syntax is not unprecedented is an argument that the feature is ok because R does it. The author is simply giving additional context to allow readers to form their own opinion.

It's fine to not like the feature–I don't know enough about its usecase to feel one way of another–but your comment felt unnecessarily negative without adding much to the discussion.

Knowing that R users have access to these syntax and choose not to use it is interesting to consider, but that was overshadowed by your first statement.

R is a very...haphazard language. Not to say it isn't elegant in places, but I wouldn't describe it as a consistent, well planned language. I suspect it's not the rightward assignment OP has an issue with, but the fact that they're looking at R as an example to follow.
If you're interactively exploring data using the REPL it can be quite handy.

You do have the correct sentiment in that for actual code meant to be distributed to other human beings it's almost never a good idea to use it although I've seen use cases, particularly involving Tidyverse constructs, where it arguably makes sense.

Can you mix left assignments, right assignments, and assignments in expressions all in one statement? That will be great for obfuscating code.
It'll probably be implementation-defined...
Well, this is a nice coincidence, Nim also added support for rightward assignments today!

https://play.nim-lang.org/#ix=2x7r

Funny you should mention it, raku just got the same feature!

https://tio.run/##K0gtyjH7/7@4NEkhMy8ts8Lq0Gpbu0O7NVQSdRRUgG...

Doesn't Raku essentially already have this with feed operator? [1]

1: https://raku.guide/#_feed_operator

Not quite. For example:

  > my $x
  (Any)
  > 1 ==> $x
  (1)
  > 2 ==> $x
  (2)
  > 3 ==> $x
  (3)
  > $x
  [1 2 3]
If ==> were simply assignment, we would expect x's value to be 3.
There's no need for a new operator. The R metaoperator respects precedence, associativity, etc.

my Int $age;

42 R= $age;

say $age;

Alright, I did in fact chuckle, out loud.

But I gotta ask: does it have the correct precedence?

And sure, throwing some superficial math at the problem works. But is that a coincidence?

I guess what I'm asking is: how does Nim know that `=>` is infix? How does it derive the correct precedence? It looks like spooky magic, but Nim is pretty well-designed in my experience: what's going on here?

> how does Nim know that `=>` is infix?

I expect it's the `

Haskell works the same way.

Ah, and templates are a rewrite engine on the AST! That completely slipped my mind.

So the compiler itself just sees the `a = b`, the `b => a` is never visible, therefore precedence isn't germane to the template itself.

Neat.

> So the compiler itself just sees the `a = b`, the `b => a` is never visible, therefore precedence isn't germane to the template itself.

Not quite. Imagine you have:

  3 + b => a
Is that 3 + a = b, or a = 3 + b? Precedence still comes into it. (I don't know nim's solution.)
Hmm no I'm pretty sure in a template it's, ok I'm going to use different variable names for clarity:

3 + c => d

the left hand side (3 + c) is b, and the right hand side is (d) is a, and this will apply no matter what you put on those sides, so it's rewritten in its entirety before the actual compiler sees the code.

Unless you're talking about a scope violation/dirty macro situation? And yeah I don't know Nim's story around hygiene either, but: it's usually only a problem with Lisp macros, exactly because of the homoiconicity. I'd wager Nim templates have their own scope that won't shadow the rewrite.

Ruby's parser is notoriously complex; if I remember correctly, only a few members of the core team even know how to maintain it without introducing regressions.

The craziest part of this is that Ruby does not provide a full featured Ruby parser, so its entire static and dynamic analysis ecosystem depends on a (actually very high quality) 3rd party parser, begrudgingly maintained by someone who (AFAIK) doesn't even write Ruby anymore: https://github.com/whitequark/parser

When I see new language features like this, I think of how Ruby's entire tooling ecosystem depends on the dramatically underfunded (and therefore primarily goodwill) efforts of high output maintainers like whitequark and a few others. Ruby's highly dynamic and untyped nature means these tools are all the non-runtime guarantees you can get, basically. Epitome of digital infrastructure.

Consider asking your company to fund some of these people:

* https://github.com/whitequark (maintains parser)

* https://github.com/sponsors/bbatsov (maintains RuboCop)

* https://github.com/sponsors/mbj (maintains unparser and mutant)

---

As context, I know this stuff intimately because I used to contribute heavily to most static and dynamic analysis tools in the Ruby ecosystem (https://github.com/backus?tab=overview&from=2017-12-01&to=20...) and used to track new ruby changes really closely: https://cognitohq.com/new-features-in-ruby-2-4/

`parser` is indeed a fantastic gem. @whitequark is the initial author but today it is maintained by @iliabylich
Is Ripper dead? I attempted to do some minor work on Ripper and it was profoundly painful. My explanation for Ripper boiled down to a domain specific language in parse.y comments that gets translated into C via a very confusing Ruby script, which manually calls Ruby VM functions, that wait for it, are dynamically defined. This constructs a parse tree. If Ripper is still getting maintained, I'm seriously impressed.
Yeah. Been years since I even played with it, but even in 2016 I remember Ripper being completely unusable, failing to parse plenty of normal Ruby syntax. The Parser gem also maintains a separate parser for every Ruby version, so you can a program using Ruby 2.5 but tell it to parse code according to Ruby 2.2 syntax. It's also just way better built, tested, and has other nice features like tools for rewriting ASTs.
I helped out with parser as well for a while, though it was mostly documentation, triaging issues, that sort of thing. I think I still have push access to the Gem, as at the time the project had a bus factor of 1 (= whitequark).

Anyway, I remember just how frustrated whitequark would get every time CRuby decided to make some random syntax change. I have a lot of respect for the current maintainer(s) for putting up with the ever growing complexity of the Ruby syntax. I hope Ruby stops changing the syntax on a regular basis, but I doubt this will happen any time soon.

Yeah, I don't remember any of the Ruby tooling ecosystem maintainers having nice things to say about the various syntax changes they've added over the years. I don't blame them.

These changes are always justified with a hand wave and a reference to "developer happiness" and ergonomics. I think that justification is seen as insulting when all the static/dynamic analysis tools obviously actually deliver a lot of value to Ruby devs, and yet the basic tooling to support this ecosystem (robustly parsing, traversing, annotating, rewriting, and unparsing an AST) is not provided by the language.

When can we start writing ruby bottom up?
Left is right, bottom is up, and the world is upside down.
Uh.. I'm not sure I like this, in a language that already has a similar boolean operator (although I suppose that goes for all uses of such "arrow" operators). But still:

  a = 2
  b = 1
  b >= a # false
  b >= a => a # assign false to a?
  b => a # assign 1 to a?
It already has at least two different uses for the exact sigil "=>" (hash construction, identifying capture variable in a rescue clauses), which is probably more significant than that it has a kinda similar sigil used as a comparison operator.

Like natural language (but unlike programming languages constructed with thought toward ease of automated parsing), Ruby syntax is quite context sensitive.

I forgot one, or two:

  b <= a # true
  b <= a => b # assign true to b?
I'm not too thrilled about the hash-arrow - but I think it's a bit more obvious from context.
This is true to Ruby's Perl heritage. There is more than one way to do everything, even the most basic of operations.

Quiz: what does the following Ruby code do?

  a = b => c = d
Makes me reject the PR for lack of clarifying parentheses.
Do you really punish everybody else because you can't remember precedence rules?
(comment deleted)
Do you allow code into your codebase that isn't obvious on a first read?
I've always liked the good old Perlism

    [$a => $b]->[$b <= $a]
for the minimum. (I think this is from Effective Perl Programming, but I couldn't find it at a glance.)
So, a = b becomes equivalent to b => a.

However, you already construct hashes like hash = {:a => b}.

Perhaps we can also add reverse hash construction like hash = {b = a} for consistency (and additional madness)

I like it. The next step is piping result forward.

   1.2 + 2 | double | abs => result
I wish they pay more attention to real issues and potentials. e.g. The Refinement design is half-baked -- Can't refine module methods, can't DRYly reuse monkey patch code as refinements...