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.
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.
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.
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.
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.
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.
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.
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.
(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.
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.
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.
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?"
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.
> 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`)
> 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.
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 ;)
> 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 '='.)
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 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.
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...
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).
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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".
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.
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.
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 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.
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?
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:
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.
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 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...
171 comments
[ 1.4 ms ] story [ 216 ms ] threadreturn 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.
Any time I use it, I wish python had just gone with the normal ternary (? :) operator.
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.
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.
Function f () {
}(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.
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.
Sounds like the timtowtdi of perl. Funny, I've always called ruby "perl++".
Remember how perl is known to be readable?
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:
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.
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?"
And we put linters on code.
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.
> 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`)
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.
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 '='.)
`favorite_color = red' == "Favorite Color is Red"
Which feels more natural than: "Red is Favorite Color"
And I don't see why a statement can't describe a mutation.
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.
It feels a bit like a new method definition syntax that allows you to put the name after the `end` for... reasons.
set age 42
I'm not saying it's good or bad, I'm just saying that appears to be one of the reasons for it.
Having both options is nice!
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.
Eh, there is a reason why Golang has such a huge popularity.
Disclaimer: I'm not a core dev but saw a discussion amongst them about such use cases.
I still strongly believe that the `key: value` hash syntax was a massive mistake. That's a lost battle, but this is getting ridiculous.
[1]: https://github.com/ruby/irb/blob/master/lib/irb/context.rb#L...
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.
[1]: https://www.artima.com/intv/ruby.html
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.
"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
This is true of the indicative mood, but not the imperative.
Giving commands in the indicative mood is not typical.
Writing classes can be misguided.
http://www.lel.ed.ac.uk/grammar/passives.html
[1]: https://www.ef.com/ca/english-resources/english-grammar/pass...
"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.
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 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".
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.)
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.
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.
The `:=` has been in use in other langs like MySQL
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").
-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.
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.
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.
https://play.nim-lang.org/#ix=2x7r
https://tio.run/##K0gtyjH7/7@4NEkhMy8ts8Lq0Gpbu0O7NVQSdRRUgG...
1: https://raku.guide/#_feed_operator
my Int $age;
42 R= $age;
say $age;
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?
I expect it's the `
Haskell works the same way.
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.
Not quite. Imagine you have:
Is that 3 + a = b, or a = 3 + b? Precedence still comes into it. (I don't know nim's solution.)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.
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/
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.
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.
Like natural language (but unlike programming languages constructed with thought toward ease of automated parsing), Ruby syntax is quite context sensitive.
Quiz: what does the following Ruby code do?
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)