9 ms·
I'd consider myself a writer more than a developer, but I've been working in Rails for over 15 years, and one of my absolute favourite things is "unless". Why?
by nickelcitymario 4y ago
I'd consider myself a writer more than a developer, but I've been working in Rails for over 15 years, and one of my absolute favourite things is "unless".
Why? Because it allows you to express yourself more elegantly.
The click-bait title is misleading. It's meant to ridicule "unless", but actually achieves the opposite.
If you were to write the title of the post as code, it would be:
unless !ruby_dev
read article
end
That would be a terrible use of "unless"! That should clearly say "if ruby_dev", not "unless !ruby_dev".
But what if you wanted to write an article meant for anyone other than ruby developers?
Which of the following is better?
if !ruby_dev
or
unless ruby_dev
Both work, but I consider the second option more elegant. Just as I wouldn't verbally say "if you're not a ruby developer" rather than "unless you're a ruby developer".
Honestly, I don't see the issue. It's a style matter. Just use it properly. All language can be abused if you try hard enough.
- welder 4y agoI treat the 'if' statement and the '!ruby_dev' conditional as separate entities. That allows thinking of the conditional alone in boolean logic terms, instead of having to consider the outside prefix statement too. Therefore, coming from a computer science background I don't like 'unless'.
- nickelcitymario 4y agoI could see that. Maybe it really is because I'm more of a writer than a computer scientist. (For context: I dropped out of comp sci and took a job as a web dev ~18 years ago. Never looked back. But have ended up learning more about copywriting and marketing than computer science along the way.)
- philote 4y agoI'm a computer scientist and not much of a writer yet I prefer the use of "unless" over a negated "if". Then again, at the start of my career I used quite a bit of Perl and it was created by a linguist.
- JasonFruit 4y agoYou've demonstrated that it is trivially replaced by 'if' and negation. I think that's almost the definition of inelegant.
- nickelcitymario 4y agoOnly if you definition of elegance is "please express yourself in as convoluted a way as possible, so as to minimize the number of words I need to know." The truth is there is a balance in all languages. Nearly every word was invented to prevent having to say a string of other words to mean the same thing. "Unless" is a single word to mean "If not". I consider that elegant. However, some languages take this too far, in my opinion. German famously has a word for nearly everything. I'm not sure that's elegant, in that it requires learning a far greater number of words. English has many words that I wouldn't consider elegant, simply because they're uncommon or convoluted. Never use a 10 dollar word when a 5 cent word will do. So, if, like me and the ruby community, you prefer to optimize for developer happiness, "unless" is an elegant choice. If you prefer to optimize for peak computing performance, if may be more computationally efficient use "if not". But, _unless_ you're saying that you never use the word "unless" in everyday language, I think we can agree it's a good word that has good applications. I don't see why that wouldn't be true in programming.
- ajmurmann 4y agoThe best example of vocabulary size and its tradeoffs this is the Guy Steele talk "Growing a Language". One of the best talks ever given.
- slowmovintarget 4y agoUnconscious clarity trumps literary fluidity when reading code.
- guitarbill 4y ago> German famously has a word for nearly everything. I'm not sure that's elegant, in that it requires learning a far greater number of words. That's not quite how it works though, right? Compound words are exactly that, combining two or more words to narrow down the meaning, without having to invent a new word. It's almost like "if not" vs "unless"...
- systems_glitch 4y agoCame here to say this. If you don't like it, don't use it, but it sure does seem to make things easier for other developers (Ruby and not-Ruby-but-assigned-to-this project) to understand. I like it.
- micromacrofoot 4y ago"if" is almost always easier to reason with, "unless" can be elegant, but it's so often misused that it doesn't really matter
- nickelcitymario 4y agoI agree entirely that it can be misused. I'm not sure how often it's misused versus used properly. But I don't see why I should give up a useful logic tool just because others don't know how to use it well? Let me put it this way: Are there _any_ programming paradigms that don't get poorly used? We need to learn how to use our tools well, not reduce them to banality.
- burke 4y agoOn this note: I’m sad ruby style guides generally ban “and” and “or”. raise(“a long error string”) unless valid This reads much worse, when the string pushes the line near max width, than: valid or raise(“.. Of course it’s another idiom to learn but it’s not a difficult one when used simply.
- klodolph 4y agoThat’s a very Perl idiom, did you previously write Perl?
- burke 4y agoNo, I just think for all ruby is bought into these guard clauses, it's sad that we generally reject the feature that allows putting either the condition or the consequence first, depending on which reads better.
- graywh 4y agothe 2nd form implicitly returns the value of valid if it's truthy and nil if it's falsey; the 1st form always returns nil
- bluedino 4y agounless is one of those things I have to read 2-3 times and it totally bogs me down.
- 4pkjai 4y agoI have a similar problem with list.filterNot() in Kotlin
- nickelcitymario 4y agoInteresting! I wouldn't want to argue against your experience. I do wonder if it's an issue of "unless" being misused? Programmers using it just for fun rather than considering whether it's the best choice in context?
- llimllib 4y agoI feel like I have read if statements so many times that I have fast pattern matching circuits in my brain for them. When I come across an `unless`, I can't use them; I have to come back out into "conscious reading" mode, or something like that. Makes me crazy.
- nickelcitymario 4y agoThat makes sense!
- eloisius 4y agoI'm a recovering rubyist (actually I still love ruby, just never get to write it anymore). The only times I felt `unless` was truly more readable than `if !something` was when it was used in the conditional suffix form like do_something unless already_done?
- pantulis 4y agoThis is the poster child use case for "unless", IMHO. Anything else (at least for me) is more difficult to read, it's probably due to being exposed to all thos other languages that do not have that syntactic construct. Using C syntax conditionals feels more natural to me, but again this is all opinionated.
- asdajksah2123 4y agoThe unless is still harder for me to grok. The if !ruby_dev (read as "if not ruby_dev") is so much easier.
- nickelcitymario 4y agoFascinating! I find it slightly easier to understand "unless" than "if not". But only oh-so slightly, and probably not enough to justify making it harder for others to read my code.
- burke 4y agoFor some reason this one feels right to express with if-not to me too. The one place I’ll often use unless is things like: return unless valid raise unless h.key?(k) I think it might have something to do with: 1. How abundantly clear it is that the condition is a Boolean; and 2. The “false” condition indicating a “no work to do” situation. I think I only use them for postfix return, break, next, and raise.
- taeric 4y agoIn lisp, "unless" is a great way to signal that there will not be a dual branch. Similarly, they have "when" for the positive case only. They also have the advantage of not needing a "progn" segment if you want to do more than 1 thing on the case that they are "true". I confess at first I thought they were somewhat superfluous, but they are more readable now that I'm used to them. Completely agreed on it being stylistic, mainly.
- chrisandchris 4y agoDoing Rails for half a year now and usually are pretty good at mental models. I always have to stop at an unless because the double-negative is really hard to evaluate in the mind IMHO. IMHO unless leads to unnecessary nesting. In your example, it reads like _most_ people are ruby dev. I try to keep the most-often excecuted flow as flat as possible (happy path) and just try to nest for additional/special cases. Unless just tries to do... different.
- peruvian 4y agoDifferent taste I guess. I work in Python and always go out of my way to write "if thing is True" or "if thing is False" nowadays to make conditions clear and uniform.
- seydor 4y agoas a non-native speaker, unless requires additional time to parse than "if not" Also note that unless itself contains another negative ( < medieval onlesse) It's just easy to see if more than one conditions are evaluated: if (!ruby_dev && cpp_dev) vs unless (ruby_dev && !cpp_dev)
- topaz0 4y agoI agree with you. I think the complaints come down to "don't give people more confusing ways to write conditionals". And I agree with the complainers that it is easy to write conditionals in a confusing way, and that there are simply more confusing ways to write them when you can also use unless. But I think the problems come from not taking the time to make the conditional easy to parse, which is an issue whether or not you have unless. And it's not just trading if ! for unless (or if for unless !) -- sometimes it's "if valid" vs "unless !valid" vs "if !invalid" vs "unless invalid", depending whether it was easier to write the predicate for valid or for invalid. Even working in a language without unless, I frequently find myself encountering these difficulties, and I find that the only thing that helps is treating it like writing and deciding what logical progression will be the most helpful for the reader. What's most helpful for the reader won't always be to use unless, but sometimes it will, so it's nice to have the option.
- enw 4y agoFor me honestly it's one of the (many) things I dislike the most about Ruby. Sure, I understand the "elegant" aspect, two symbols are shortened to one (although I'd argue that's not that important when it comes to clarity and legibility). But every time I read "unless" in code it's quite jarring. I have to consciously translate it to "if not", and even then seeing the "unless" keeps tripping me off, perhaps because it's awkward in English to start a sentence out of the blue with "unless".
- ravenstine 4y agoIt's a matter of taste, but I tend to agree that the more features or constructs a language has, no matter how terse or convenient, the more unnecessary complexity is generated by using that language. The `unless` keyword makes the interpreter slightly more complicated and is another piece of language the human brain needs to recognize. It may seem inconsequential, but grains of sand make a hill, as they say. My ideal language would leave out pretty much anything that can be achieved with more basic constructs. It would of course have if-else, and leave out `unless`, but there would also be no switch statements or ternaries. Branching must be done with if-else or by looking up a value in a hash. No `for` or `while` loops because a simple `loop` construct with `continue` and `break` statements can do everything that `for` and `while` could do in other languages. No classes or inheritance because they're magical and they can be effectively simulated by the end developer if that's what they really want. What I think would be really cool is to have a language with a syntax like Ruby but with only the most basic of programming language constructs.
- KMag 4y agoMany language implementations internally translate source into a simplified de-sugared dialect as you describe as an early compilation step. I believe both ghc and rustc currently do this. Though, I think it's rare to expand a pattern match/switch into an if-else tree, and much more common to expand an if-else into a 2-way pattern match/switch. If you're really keen on such a language, you could fairly easily implement such a language as a pre-commit hook source code re-formatter so that all of the source in your repository is in your favorite language subset.
- dlkf 4y agoThere’s a cost-benefit analysis here that you are refusing to do: Of the two variants you’ve posted, the first will click immediately with a generalist dev who doesn’t know Ruby. The second will have them reasoning out loud, and then reaching for the docs to double check that their common-sense intuitions are correct. This is not a contrived example. I regularly find myself having to read some code in a language in which I am not proficient. Stuff like ’unless’ is such a pointless obstacle in these scenarios. So ”elegance” doesn’t come free. The cost is a loss of transferable knowledge from other languages. Your intuition is that this cost is low relative to the benefit of ”elegance,” I have the opposite intuition. Why stray from such universal conventions in favour of one person’s subjective aesthetic preference?
- 8note 4y agoThat's a really powerful tool. I can force you to slow down an make sure that you the reader focus on one section of code I've written? A statement that forces you to switch out of inaccurate skiming mode is insanely useful
- lcnPylGDnU4H9OF 4y agoI get your point, though it's also worth pointing out that it doesn't force anything. Admittedly, syntax highlighting will generally help but it's always possible that a skim simply misses the keyword. Practically speaking, that's not how I know Ruby to be written. The convention I follow is to use `unless` when there is no `else` case and only when there is no negation in the expression.
- hosh 4y agoIt is not all about cost-benefit. You say there is a difficult time transferring knowledge from other languages when they see the `unless`. That's fair. My response to that is that, to idiomatically think in Ruby is write code that reads well, and `unless` fits that. Every language has an idiomatic way in which one thinks and reasons with the language. While there are principles that can be transferred over across languages, the way to think in that language does not necessarily transfer. The Ruby community has a heavy emphasis on creating embedded DSLs that seems natural enough to written English, and the Ruby community's style guide is written for that. In contrast to Ruby, Python has idioms that seem to be the inverse of Ruby. The intuitions on what is good, idiomatic Ruby is counter-intuitive in Python. This even extends to the design of Ruby bundler vs. Python virtualenv/pip. As a long time Rubyist, Python rubs me the wrong way (what is intuitive in Python is counter-intuitive in Ruby) until I realized that I used to write that style of code a long time ago with Pascal.
- kuratkull 4y ago'if !<something>' clicks instantly. for 'unless' I have to read out the statement in my head, and draw mental logic lines about what condition this is checking.
- hosh 4y agoThat's how I see it as well. Also, if you need to tag on more conditions, convert it to an `if` The `unless` is idiomatic to the Ruby way of thinking.
- geuis 4y agoNope. It's needless confusion. We're programmers who have stuff to do, and syntactic stuff like unless are not helpful. if (true) and if not(true) is simple and elegant, and doesn't require any person on my team to stop their flow to puzzle out what the code is supposed to be doing at that point.
- class4behavior 4y agoBut inventing totally new languages even for billion dollar projects is totally fine? You want a well-justified, inclusive, and consistent yet adaptable style when collaborating with people. It would be selfish to gatekeep a policy without regard for those principles.
- dyingkneepad 4y agoI have problems with 'unless' even in plain English text. I'm pretty good at English, I live in the USA, but I was not born here and my native language does not have a word for 'unless' (you have to use 3 words to express that idea!). I love Ruby, but the 'if' variation always get immediately parsed by my brain, while the 'unless' variation requires many seconds of thinking.
- layer8 4y agoHow about if you could write except if instead of unless?
- dyingkneepad 4y agoNothing will ever come close to "if not" due to the decades of experience I have reading it everywhere.
- smeagull 4y agoShould I read the damn article or not? I still have no idea
- j33zusjuice 4y ago“If you are [not]” serves a different function than “unless.” “Unless” is a conjunction, and its presence creates a double negative with the end of the sentence making the sentence extra clunky (“unless you’re a Ruby dev, you shouldn’t read this article.”) A few iterations later, we get to the correct syntax, “read this article if you’re a Ruby dev.”
- adverbly 4y ago> Which of the following is better? if !ruby_dev or unless ruby_dev As a ruby dev of 5+ years, I still have an easier time with `if !ruby_dev`. I have to translate `unless` to `if !` every single time to grok something. Almost like an extra step in an algebraic expression being simplified.