[HN Gopher] Read this post 'unless' you're not a Ruby developer
       ___________________________________________________________________
        
       Read this post 'unless' you're not a Ruby developer
        
       Author : genericlemon24
       Score  : 213 points
       Date   : 2022-12-13 07:41 UTC (15 hours ago)
        
 (HTM) web link (jesseduffield.com)
 (TXT) w3m dump (jesseduffield.com)
        
       | PaulHoule wrote:
       | I liked "unless" in Perl and also the                  X if Y
       | X unless Y
       | 
       | syntax. I want to see some language that brings back the "noise
       | words" from COBOL for that matter.
        
       | athenot wrote:
       | For all of Perl's permissiveness, this is one situation that is
       | explicitely dissallowed:                   unless condition
       | # do A         else           # do B         end
        
       | lucidone wrote:
       | I'm not a very experienced Ruby developer but RuboCop does a
       | pretty good job at guiding and teaching you to use `unless` as a
       | guard in method definitions, e.g.:                 def
       | my_method(required_thing)         raise 'required_thing is
       | required' unless required_thing.present?                  ...
       | end
       | 
       | In practice, this hasn't been as issue as a consequence of the
       | tooling and ecosystem around Ruby.
        
         | ilyt wrote:
         | and why                   def my_method(required_thing)
         | raise 'required_thing is required' if !required_thing.present?
         | 
         | is a problem ?
        
           | lucidone wrote:
           | I don't think it's a problem necessarily. "unless" is more
           | obvious to me since since it visually stands out more than
           | "if !required_thing" while I'm casually scanning the code.
           | So, in practice, it acts as an indication from the author of
           | the code to the reader that "this line of code is a guard
           | since we're using an unless".
        
       | otikik wrote:
       | Do not use unless Unless it's a one-liner
        
       | rwoerz wrote:
       | Reminds me of the
       | 
       | do not do <statements> unless not <expression>
       | 
       | of some fun programming language whose name I forgot.
        
       | [deleted]
        
       | FpUser wrote:
       | When reading code ! in condition can be overlooked relatively
       | easily so I do not really see anything wrong with "unless".
        
       | hk1337 wrote:
       | It's a bit awkward to grasp initially but personally I like it. I
       | don't wish it in all languages but it works in ruby. It
       | especially works well in templates and checking collections.
       | 
       | Honestly, I find negative checks like `if !something` ugly, I
       | would much rather check if the result is true than !true. The
       | same with unless, I would prefer to check unless false than
       | unless not false or unless !false
        
       | snshn wrote:
       | Clickbaity. Very clickbaity.
        
       | inerte wrote:
       | I used to write my if/else like the author advocates. The "true"
       | condition first, followed by the "false".
       | 
       | A long time ago, a friend code reviewed and asked me to change to
       | the most common condition first, as advocated in the Code
       | Complete book (which I hadn't read at the time).
       | 
       | I still think it reads better if/else as true/false, but I am
       | also big on having standards and a coding style, even if I
       | disagree with them.
       | 
       | I mean, unless there's a lack of coding standard I will follow
       | it.
        
       | arunix wrote:
       | This is a useful feature to have when writing one liners e.g.
       | % cat words         all         these         worlds         are
       | yours
       | 
       | Which I believe is one of the reasons Perl allows it:
       | % perl -ne 'print unless /^a/' words         these         worlds
       | yours
       | 
       | And Ruby does too:                   % ruby -ne 'print unless
       | /^a/' words         these         worlds         yours
        
       | azlev wrote:
       | Some people like, some people hate, that's why we have multiple
       | languages to choose.
        
       | 0x457 wrote:
       | hmm, you're doing `unless` with `!` in condition you're doing it
       | wrong.                   unless user.has_errors?
       | user.save         end
       | 
       | IMO better than `if !user.has_errors?`, at least for me: I will
       | read it as "unless" in my head even in languages that only have
       | `if`. You know what? I will just start using `unless` even
       | harder, I will even make a rust macro for that.
        
       | sshine wrote:
       | I'm currently writing assembler for a virtual machine that has a
       | "skiz" instruction.
       | 
       | It means "skip if zero".
       | 
       | The double negative always trips me up.
       | 
       | I had to write "don't skip if not zero" next to it the first
       | dozen or so times.
        
       | uticus wrote:
       | Ruby is an interface between at least three realms: the human
       | (typically English conversant), the machine (instruction-based),
       | and logic.
       | 
       | Not unique and not the best, but popular and usable enough to be
       | fascinating for anyone who's given more than passing thought to
       | how difficult it is to communicate in any one realm separately
       | (let alone across realms).
       | 
       | For example, I had a meeting with POs recently where it took an
       | hour to communicate a concept in English and distill a logic
       | diagram from it. I'm not placing blame on English (although some
       | would [1]), POs, or myself. It's just common experience that
       | communication is difficult.
       | 
       | Personally I always enjoy flexibility and expressiveness when
       | writing (English or code), usually when reading (English or
       | code), and sometimes when debugging (English or code). So I like
       | Ruby pretty well. YMMV.
       | 
       | [1] https://news.ycombinator.com/item?id=33513666 &
       | https://news.ycombinator.com/item?id=22689959
        
       | zelphirkalt wrote:
       | Ruby is not the only language with "unless", actually. For
       | example it exists in GNU Guile as well (https://www.gnu.org/softw
       | are/guile/manual/html_node/Conditio...). However, due to the
       | usual structure of functions and the last expression being the
       | return value, one always expects a return value (why else call
       | the function?). So "when" and "unless" are only seen inside
       | procedures, which have side effects.
        
       | Lapsa wrote:
       | and why does Rubocop's Ruby Style Guide matter?
        
         | Karunamon wrote:
         | Ask the people who blindly apply and enforce Python pep8 which
         | assumes everybody is on an 80 column glass terminal in the age
         | of throwaway PCs having 16:9 screens.
        
       | ndsipa_pomu wrote:
       | Reminds me of my pet hate in user interfaces - having a check box
       | for a negative condition such as "disabled" rather than having
       | "enabled" and changing the default state of it.
        
       | thunderbong wrote:
       | IMHO, 'unless' in Ruby works best for single checks. It's just a
       | convenient form of 'if not'. That's about it.
       | 
       | I always insist on _not_ using  'unless' if it's not clearly
       | readable as an english phrase or if there's an 'else' as well.
       | 
       | A similar pattern I follow with 'if !'. If there's an 'else'
       | condition always put the positive check first and the negative
       | one in the else, rather than the other way around.
       | 
       | Footguns are equally possible using complex 'if !' statements.
        
       | actionfromafar wrote:
       | I had to read the title five times to decide if I was supposed to
       | read it. I'm sold.
        
         | mypastself wrote:
         | Are you saying you _don't_ want to have to apply De Morgan 's
         | Theorem any time you read a headline?
        
         | eyelidlessness wrote:
         | I'm one of those weirdos who can inline a double negative
         | instantly so, I didn't read it yet but I probably will because
         | I'm curious about the title anyway
        
           | eyelidlessness wrote:
           | Oh my dear lord I didn't think I'd actually disagree with the
           | f'ing article but I had like 8 cases today that made me wish
           | I had a built in if-not keyword! I mean, every language with
           | the billion dollar mistake probably needs a language feature
           | designed to pay back some of that.
        
             | trfzx wrote:
             | I think the author would probably be fine with an if-not.
             | It doesn't hide the double negation like unless.
        
           | [deleted]
        
         | layer8 wrote:
         | So you'd be in favor of dropping "unless" from the English
         | language because it was misused in that title? :)
        
       | revskill wrote:
       | You need to use it when you want to be negative of ALL the thing
       | after unless.
       | 
       | Basically, do_something unless A
       | 
       | Then it's simple now to manipulate the inside of A, as you only
       | take care of the positive ! That's beautiful and simple design.
       | 
       | Example is you want to validate something.
       | 
       | raise Error unless someValidCondition.
       | 
       | Now decompose someValidCondition by just using positive
       | connectives, simple right ?
        
       | jpmattia wrote:
       | > _The human brain, impressive as it is, grinds to a halt when
       | parsing with double negatives._
       | 
       | Things like this sound like: "I have this characteristic,
       | therefore everyone has this characteristic."
       | 
       | Some of us ain't got no problem with double negatives, and often
       | find that "unless" tightens up code nicely, especially for single
       | negatives.
        
       | celeritascelery wrote:
       | When I see unless in the prefix position (unless x then y) I have
       | mentally read it twice. I reread it as `if not` because otherwise
       | my brain can't grok it. But if it is in the postfix position (y
       | unless x) then it is super easy for me to grok. I think that is
       | because how we would use it in natural language.
        
       | stormdennis wrote:
       | Unless would drive me insane. I do use IF NOT but when reading
       | code my brain understands this format most clearly:
       | 
       | IF some-expression
       | 
       | ELSE Do-something
        
         | shortcake27 wrote:
         | `unless` is generally used for guard clauses (eg `return unless
         | authorized?`) or when there's only one branch. You don't tend
         | to see `unless` used with multiple branches.
        
           | Alifatisk wrote:
           | This, I've mostly used unless with guard clauses
        
       | codegangsta wrote:
       | I find `if not` to be a far superior version, simply because it
       | reads similarly to it's `if` counterpart, specifically for how
       | conventionally condition methods are written in ruby.
       | 
       | `return if not valid?` or `return if invalid?`
       | 
       | Both make sense in my brain, whereas
       | 
       | `return unless valid?`
       | 
       | Feels like I need to make another connection to understand it
        
       | al2o3cr wrote:
       | TLDR: "I don't understand De Morgan's laws and so it's the
       | languages's fault" :P
        
       | jbaber wrote:
       | It's a matter of taste.
       | 
       | I find inheriting code riddled with witty logic puzzles
       | distasteful, so prefer my predecessor to have written Python,
       | which constrained them from crafting too many.
       | 
       | Some people want a project to be a series of cryptic crosswords.
       | For them perl/ruby/C.
       | 
       | When _I_ write perl /ruby/C, I restrain myself from filling it
       | with cool puzzles, but I usually don't get to inherit code from
       | myself.
        
       | davedx wrote:
       | I mean this is `ruby` for you, this is one of its principles,
       | providing more than one way of doing something and making that
       | thing "ergonomic and pleasurable". I don't think many devs who
       | choose to use ruby would want to proscribe things like unless?
        
       | phplovesong wrote:
       | Many languages try to be too cute. I was just reading up on the
       | newish "Roc" language. There i saw List.dropIf and List.takeIf,
       | thats basically just filter with a slipped bool check.
        
       | stefano_c wrote:
       | I've been writing Ruby for 20+ years and "unless" (the whole
       | language, actually) immediately clicked for me when I first
       | learned it.
       | 
       | That said, I only use it in 2 cases:
       | 
       | * as a trailing condition (do_something unless this), mainly for
       | early returns * as the only arm of a multi-line block (unless
       | this ... end, no "else" blocks - Rubocop would yell at me anyway)
       | 
       | And then only if the condition is either a simple value, or a
       | combination of simple values (this && that, this || that).
       | 
       | That's it. Never had a problem with double negatives or
       | accidentally inverting the logic.
        
         | pmontra wrote:
         | This is basically how I use unless too. Complex conditions are
         | complicated enough to grasp without inflicting an unless on me.
         | But for simple cases it is a nice to have feature.
         | 
         | Of course one can avoid it at all but of course one cannot
         | avoid to spend time on it when reading somebody's else code.
        
         | masklinn wrote:
         | FWIW HN does not support markdown lists (or markdown anything
         | other than emphasis and code blocks really), you need to add an
         | empty line between your "list items" so the comment parser
         | treats them as separate paragraphs instead of munging them
         | together as just one.
        
       | gjadi wrote:
       | In Common Lisp, there is `unless' and `when' but they don't allow
       | `else' branch.
       | 
       | (when CONDITION BODY)
       | 
       | (unless CONDITION BODY)
       | 
       | The value of the statement is BODY or NIL if it wasn't executed.
       | 
       | I can't remember a time when it wasn't clear (though you can
       | always build usage that are unclear).
        
         | tsimionescu wrote:
         | I think they mainly exist because `if' otherwise requires a
         | `progn' if you want more than one expression in the true
         | branch.
        
           | tmtvl wrote:
           | And using `cond' for 1 clause is a bit silly.
           | (cond ((massivep building)              (print-mass-warning
           | building)              (install-antigrav-module building)))
        
       | corytheboyd wrote:
       | You can contrive bad usage of just about anything in any
       | language. Nobody actually writes "unless ... else". The few times
       | it's come up it's been shot down in code reviews. unless is still
       | perfectly fine for simple one line statements though.
       | 
       | Do I think Ruby NEEDS unless? No. Does this keep me awake at
       | night? No lol
        
       | masklinn wrote:
       | I don't disagree with the essay, and I do generally dislike
       | "unless" as it's a cutesy statement which does not pull its
       | weight (it would probably be better if there was no "else" clause
       | at all).
       | 
       | However I find some of the examples / justifications unfortunate
       | e.g.
       | 
       | > I find the second option less readable because it suggests that
       | raising the error would be the normal thing to do, when in fact
       | it's the exceptional thing to do.
       | 
       | It's not tho. The normal thing to do is to reject access, being
       | an admin is exceptional. A restricted endpoint should absolutely
       | assume the user is _not_ authorised.
        
         | dkdbejwi383 wrote:
         | Fair enough argument for that particular example, but I think
         | the author's point still stands for the other example (if
         | !user.suspended do send_email end)
        
           | e12e wrote:
           | That example makes more sense as:                 send_email
           | unless user.suspended?
           | 
           | Here we see that we normally send email - except for the
           | exceptional case of the user being suspended.
        
       | PaulRobinson wrote:
       | As the article starts to explore, it's more useful in the context
       | of a single line conditional with a single boolean to evaluate,
       | or what I sometimes call a "dangling conditional". This is valid
       | ruby:                   do_something if boolean_expression
       | 
       | All unless does is allow you to negate it using an expression
       | that's more natural to most people                   do_something
       | unless boolean_expression
       | 
       | To me the negation of an if with ! is less clear in this context.
       | For example:                   puts "That's a prime" if
       | is_prime?(variable)
       | 
       | makes sense. So does:                   puts "That's not a
       | prime!" unless is_prime?(variable)
       | 
       | Far more so than:                   puts "That's not a prime!" if
       | !is_prime?(variable)
       | 
       | The author decides however to add more conditionals. Fine, don't
       | do that. Or that it's unreadable in some contexts. Fine, don't do
       | that either.
       | 
       | The whole point of Ruby - the only reason it really exists - is
       | that it should be fun and easy and not require you to spend too
       | much time stressing over rules. If you read a piece of Ruby and
       | don't like it, change it. It's not Python - there is more than
       | one way. Use the way that makes sense in the context you're using
       | it.
       | 
       | If you can't trust yourself or your team to do that wisely in a
       | project, consider changing languages, because guess what? The
       | language isn't going to change because you don't like that thing.
        
         | neilv wrote:
         | Maybe these dangling conditionals are easier for you to read,
         | but not for me.
         | 
         | Were I reading through real-world code that did things like
         | that:
         | 
         | "OK, then we do this, and then we do that, and then-- Oh wait!
         | Backtrack! We didn't do that thing at all! ... Now where were
         | we, on our _actual_ bug, before some very special person 's
         | syntactic speed bumps?"
        
           | Draiken wrote:
           | But these are not absolutes. You can learn to use and read
           | `unless` just as effortlessly as you did with `if`. I didn't
           | learn to use/read `unless` on college. But I did focus on
           | trying to learn these things and today I have another tool in
           | my belt.
           | 
           | It's an opportunity to get better at something versus banning
           | it from usage because we aren't used to it.
           | 
           | Growing is, for me, almost always the right choice.
        
             | neilv wrote:
             | Dangling conditionals the parent was talking about. Where
             | the conditional comes after the thing you told it to do.
             | Computationally, that's increased backtrack/lookahead _for
             | no good reason_.
             | 
             | Regarding `unless`, that's a different matter. I was
             | actually the person who proposed adding an `unless` syntax
             | to Racket, and later regretted it. I was bikeshedding,
             | before I knew something more useful to do.
             | 
             | This isn't about learning new things to add to our mental
             | toolbox. This is about our difficulty to introspect on our
             | own thought processes and effectiveness, and about
             | bikeshedding.
             | 
             | Software engineering competence is hard, or we wouldn't
             | have all the huge expenditures, slipped project schedules,
             | and _rampant_ security vulnerabilities. Redundant syntax
             | forms that objectively makes it harder to read (see the
             | lookahead and parser theory), solely because someone
             | imagined it was sometimes easier to read this way (see
             | dying languages Perl and Ruby) is just wasting our time,
             | when we could be tackling the real problems.
             | 
             | (Though us pulling theories about programming and process
             | out of our posteriors, to defend to the death, is arguably
             | half our problem in industry right now.)
        
         | torton wrote:
         | The impetus to write the article seems to be Rubocop, whose
         | rules are suggesting a specific way of doing things. But
         | specific instances of a specific rule can be overridden, and if
         | a rule proves itself to be more trouble than it's worth it can
         | be disabled entirely.
         | 
         | I would go so far as to suggest jumping into Rubocop "cold
         | turkey", meaning all rules on, is not very helpful on an
         | existing codebase. The way my team approached Rubocop on a
         | particular large legacy codebase was to start with a few hand
         | picked rules that were non-controversially good, and discuss
         | new rules one at a time as we gradually fixed the existing
         | issues.
        
         | ufmace wrote:
         | I agree with this - I always found the single ! in conditionals
         | to be too easy for your eyes to slide past and miss. Using
         | `unless` makes it jump out harder that you're only doing the
         | thing if the condition is `false`.
        
       | jbverschoor wrote:
       | I almost never write unless, unless it makes absolute sense in
       | English, and it only has one condition
        
         | eric-hu wrote:
         | never_write_unless unless makes_sense_in_english &&
         | has_only_one_condition
        
       | sod wrote:
       | Without syntactic sugar that differentiates a language from
       | another, I see no way for a new language to become popular. So
       | while some decisions may seem confusing, they helped gathering
       | interest. IMO ruby and python became so popular because of their
       | quirks.
        
       | sph wrote:
       | The worst thing about `unless` and double negatives, is having
       | been raised in a culture with different double negative rules
       | than English. In Italian a double negative is still negative.
       | 
       | I know boolean logic pretty well, but `unless !something` still
       | trips me up to this day.
        
         | hnbad wrote:
         | There are two different kinds of double negatives and English
         | actually has both.
         | 
         | E.g. `I can't get no satisfaction` is structurally equivalent
         | to French `ne ... pas`, i.e the second `no` is a reaffirmation,
         | not a negation.
         | 
         | On the other hand `read this unless you're not a developer` is
         | a logical double negation and thus equivalent to `read this if
         | you're a developer`. In practice of course there are usually
         | implied subtleties that make the two not entirely equivalent
         | (the same way synonyms are conceptually interchangeable but may
         | carry different subtext).
         | 
         | EDIT: I can't actually think of any true "double negative" in
         | English that isn't indirect (e.g. `indirect` being synonymous
         | with `not direct` thus `not indirect` being synonymous with
         | `not not direct` and `not not` cancelling itself out). The only
         | direct forms I can think of behave like `not ... no` in my
         | first example, i.e. re-affirmations of the negative rather than
         | double negations.
         | 
         | I think most of the complaints about "double negatives" (where
         | the Rolling Stones line is usually cited as an example) are
         | stylistic preferences or intentional misunderstandings based on
         | arbitrary prescriptions (which are usually based in other
         | languages like Latin that are perceived as "purer" or "more
         | sophisticated").
        
           | tialaramex wrote:
           | The phrase for what's going on in that Rolling Stones lyric
           | is "Negative concord" and yes, it's normal in many languages
           | and that includes a lot of non-prestige English variants.
           | 
           | "Ain't nobody got time for that" is clear, likewise "I didn't
           | go nowhere" and "He ain't take nothing from nobody" and when
           | something is not clear ("That ain't nothing" could mean it
           | is, or it is not, something) context usually suffices.
        
           | sixhobbits wrote:
           | > any true "double negative" in English that isn't indirect
           | 
           | A: Do you like your hometown?
           | 
           | B: Well, I don't not like my hometown
           | 
           | In boolean logic, not false is true, but in English there's
           | often a middle ground. See also
           | https://en.wikipedia.org/wiki/Law_of_excluded_middle
        
         | sshine wrote:
         | Ain't nobody got time for that!
        
           | jjgreen wrote:
           | yeah yeah
        
           | soheil wrote:
           | Funny how human languages converge.
        
         | codethief wrote:
         | > In Italian a double negative is still negative.
         | 
         | Same in Spanish!
         | 
         | I think you're making a very good point here - understanding
         | "unless" (quickly, i.e. without having to think about it) very
         | much depends on one's understanding of the English language
         | and/or one's mother tongue. Sure, one can probably get used to
         | it (like one gets used to what "if/else" means etc.), but it
         | definitely increases the mental effort needed to read &
         | understand code.
        
           | yebyen wrote:
           | I think we're going to have problems if we try to make all
           | languages consistent for users of all languages.
           | 
           | If and unless _are_ English language keywords besides being
           | Ruby keywords; and in Spanish, the word for  "if" and the
           | word for "yes" only differ by an accent mark.
        
           | zelphirkalt wrote:
           | In Spanish I usually translated double negation like this:
           | 
           | "No! (Wrong!) There is no ..."
           | 
           | Bringing it back down to 1 level of negation, for it to make
           | logic sense again.
        
         | jack_riminton wrote:
         | I'd never use an 'unless !something', always an 'if something'
        
       | jacobsenscott wrote:
       | I don't like!.! Is not a word, but unless is. Unless is great
       | unless you use it wrong.
        
       | anm89 wrote:
       | I've been doing Rails for 10+ years and `unless x` absolutely
       | breaks my mind. I have to internally convert it to `if !x` and
       | evaluate it in my head 90% of the time.
        
       | swyx wrote:
       | this title beautifully demonstrates the point. if there were an
       | oscars for blogpost titles, this would be a nominee.
        
       | davesque wrote:
       | I've always felt that language features like 'unless' in Ruby and
       | also things like 'on' and 'off' in Coffeescript fall squarely
       | into the category of _too clever._ Simplicity will always win
       | until the end of time.
        
         | vidarh wrote:
         | To me your two statements here are in conflict with each other.
         | I use "unless" in Ruby _when it leads to simpler code_. That
         | ability to write code which reads simpler is its sole reason
         | for existing.
         | 
         | (the _headline_ however, is an exceedingly bad example)
        
       | 3pt14159 wrote:
       | There are two main reasons unless is great and I miss it now that
       | I primarily program in python.
       | 
       | 1. It is a negative, and that is a great thing when there are
       | boolean conditions. Yes, you can wrap the whole thing in
       | brackets, but when doing a visual scan quickly over code, they're
       | easier to miss than the giant `unless` token which guarantees
       | that you won't have an early closing bracket. The more the number
       | of terms go up, the more I have to be fastidious with watching
       | where brackets begin and end.
       | 
       | 2. It _hints_ to the expected flow of things. Isn 't the first
       | more readable to you?                   return :allow_air_travel
       | unless self.nuclear_war_ongoing?                  return
       | :allow_air_travel if ! self.nuclear_war_ongoing?
       | 
       | Or I'll put it another way. If you do a search of your own hacker
       | news comments on BigQuery, will you never find the english word
       | "unless" outside of a Ruby discussion there? You could say "if
       | not" why bother using an extra word? Or what about "not true" do
       | you ever say that when you could just say "false" like Dwight
       | from The Office?
       | 
       | Basically my argument boils down to this:
       | 
       | Bears. Beats. Battlestar Galactica.
        
       | evolve2k wrote:
       | Assume all references to valid_token were to an opposite method
       | named 'invalid_token' and suddenly the 'unless' will make much
       | more sense.
       | 
       | X = 5 unless invalid_token
       | 
       | Much better than
       | 
       | X = 5 if !invalid_token
       | 
       | Here the humans inability to easily process double negatives, is
       | now an argument for using 'unless' in the right circumstances.
        
       | rodgerd wrote:
       | The whole premise - that double negatives don't work for humans -
       | is invalid. Natural languages have and continue to make use of
       | double negatives and double positives (and in some cases, the
       | positive-negative).
       | 
       | Obviously if your specific language doesn't make use of it, or
       | makes use of it in a different way to ruby (e.g. is your natural
       | language treating the second negative as a negation of the
       | negative, or an intensifier of it?) then ruby's grammar will seem
       | unnatural. But that's going to be true for anyone who's trying to
       | map their natural language onto a programming language whose
       | grammar is different to theirs.
        
       | hbrn wrote:
       | I've seen quadruple negatives in Python:                   if not
       | no_unavailable_items:           ...         else:           ...
       | 
       | unless on it's own is fine, but humans will misuse it if you're
       | not careful.
       | 
       | You can address it with code reviews/standards/linters and get
       | the best of both worlds.
        
       | schneems wrote:
       | I used to love unless, but now I prefer `if !`. Sometimes when I
       | read `unless` i manually make the conversion in my head. The only
       | problem i've run into is standardrb thinks otherwise and I've not
       | mustered up the energy to bikeshed that change through.
        
       | jmuguy wrote:
       | We use it exclusively for guard statements at the beginning of a
       | function, and we keep it to a single statement per line
       | 
       | return unless token.present? return unless user.valid? return
       | unless foo = get_foo(user)
       | 
       | Its extremely readable and easy to grok imo.
        
       | [deleted]
        
       | beeforpork wrote:
       | How about 'ifnot'?
       | 
       | Although I like 'unless' in Ruby, Perl, CommonLisp (sometimes a
       | condition is just naturally the other way of how 'if' wants it),
       | I acknowledge that people get emotional and really hate it. Maybe
       | a better alternative would be 'ifnot' to avoid the ! operator and
       | the parentheses.
        
       | pmarreck wrote:
       | Elixir has the same "unless" statement but I hardly see it used
       | in practice, and frankly I've never missed it, probably due to
       | the reasons cited
        
       | gmiller123456 wrote:
       | I work with so many languages on a regular basis, I specifically
       | avoid such language features, I won't even use the _x if y_
       | syntax. My cognitive effort is better spent memorizing other
       | specific things about the language.
       | 
       | That said, I think the author is overselling the need to not use
       | such features. Despite my aversion to using such features, I have
       | no problem reading them.
        
       | lamontcg wrote:
       | Use rubocop. Ban the use of `unless` except as a trailing
       | conditional and ban double-negatives. Then the only thing you can
       | do is `foo unless whatever?` and if someone comes along and
       | modifies that to something horrible rubocop will yell at them
       | that it is horrible (and `rubocop -a` will auto-fix it).
       | 
       | Use the tools.
        
       | mrtweetyhack wrote:
        
       | shortcake27 wrote:
       | I really don't understand the author's point about adding extra
       | conditions. They admit that many people will find a single
       | condition with `unless` more readable. They then complain that it
       | becomes unreadable when adding another condition. OK, so swap it
       | out for an `if` at that point. No one is forcing you to keep
       | using `unless` if the requirements change. "You should use a
       | suboptimal solution to cater for unknown future requirements" is
       | a terrible argument.
        
         | tebbers wrote:
         | Exactly my first thought too.
        
         | doodpants wrote:
         | Indeed. I personally never fail to avoid not using "unless",
         | unless there isn't a lack of extra conditions such that not
         | refraining from instead using "if" wouldn't avoid not being
         | less clear.
        
           | airstrike wrote:
           | SURGEON GENERAL'S WARNING: reading this sentence before
           | consuming caffeine may cause significant brain damage
        
           | scambier wrote:
           | I'm not sure that making this sentence as obtuse as possible
           | is a great idea to convey your point.
        
             | lsaferite wrote:
             | Making it as obtuse as possible was very likely _the_
             | point.
        
         | thedanbob wrote:
         | To be fair, he makes the point that
         | 
         | > there's this bizarre quirk of human psychology where
         | developers retain the unless against all odds
         | 
         | I have refactored a number of unwieldy `unless` statements
         | written by colleagues so maybe there's something to that.
        
         | roboben wrote:
         | That's exactly how I use 'unless'. Simple on condition (no else
         | branch) use cases in one liners, anything more complex, I move
         | to if. Best of both world I'd say!
        
           | aqme28 wrote:
           | That's the generally recommended style! I hate this post.
           | It's arguing against something that is well known to be a bad
           | practice (that's fine), but it seems to put the fault for
           | this on Ruby itself.
        
           | JeremyNT wrote:
           | Yes! And rubocop can encourage the use of 'unless' in only
           | these simple situations where it does enhance legibility.
           | 
           | https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Style/Unle.
           | ..
           | 
           | https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Style/Unle.
           | ..
        
         | saghm wrote:
         | > "You should use a suboptimal solution to cater for unknown
         | future requirements" is a terrible argument
         | 
         | Not exactly the same, but over the years I've heard people
         | argue against having super customized shell configurations
         | (e.g. completions, prompts, highlighting) because they won't be
         | available if you have to use a different environment (e.g.
         | sshing into a temporary cloud server to debug something failing
         | in CI). I don't pretend that other people will value tradeoffs
         | the same as me, but it's a mindset I can't really imagine ever
         | having. I'd rather be happy most of the time even if I know I'm
         | going to be unhappy for short periods occasionally in the
         | future, and I don't really think the slight efficiency gain in
         | the uncommon case due to being used to not having nice features
         | is going to outweigh the larger efficiency gain for the much
         | more common case.
         | 
         | At the risk of straying entirely off-topic, I've seen this in
         | non-professional contexts at times as well; I recently had a
         | friend in an online game mention that he doesn't like to
         | utilize a convenience feature that happens for a couple weeks
         | each year as part of a special even because he would miss it
         | too much the rest of the time. While I don't think the tradeoff
         | is quite as obvious to me for this sort of thing, I feel like
         | occasionally having a fun temporary addition is worth it just
         | for the change of pace, and I'm generally able to adapt to the
         | loss of a minor convenience relatively quickly after losing it.
         | It seems sort of like a question of "maximizing peak happiness"
         | versus "minimizing peak unhappiness" or even "maximizing
         | average happiness"; I like having something to get excited
         | about every now and then even if it leads to feeling blase
         | about things for a bit later because I get bored if things stay
         | the same for too long.
        
           | meatmanek wrote:
           | As an analogy to your shell customization thing:
           | 
           | I switched from QWERTY to Dvorak a long time ago, a few years
           | after learning to touch type. Does it make me more efficient
           | on my own computer? Probably slightly -- Dvorak really is a
           | well-designed keyboard layout, but it's impossible to know
           | whether my WPM is any higher than it would've been on QWERTY.
           | However, I make way more mistakes and type way more slowly
           | whenever I sit down at a QWERTY keyboard. I had to re-learn
           | how to touchtype QWERTY after switching to Dvorak, and my
           | skill never got back to the same level. It also leads to
           | extra inconvenience every time I lend my computer to someone
           | else, install a new OS, etc.
           | 
           | I think this means my average typing speed (weighted average
           | of the time spent at Dvorak keyboards + QWERTY keyboards) is
           | probably flat or possibly lower than if I had just stuck with
           | QWERTY. When combined with all the effort I spent learning
           | Dvorak, re-learning QWERTY, and making many mistakes in the
           | early years, I think my lifetime productivity is probably
           | even lower. I don't recommend that people switch, even if I
           | think Dvorak really is a better layout.
        
         | Draiken wrote:
         | I believe this is somewhat prevalent in the Ruby community as
         | of late where people try as hard as possible to "lock down" the
         | language and limit the ways you can get to a solution in the
         | name of the proverbial "ease of understanding".
         | 
         | I wholeheartedly disagree and believe we should instead grow
         | the developers to understand these different approaches as
         | opposed to labeling half of the language "bad practice".
         | 
         | As I said in another comment. Ruby was built to have multiple
         | ways of doing the same tasks and criticizing it for this is...
         | pointless.
         | 
         | Yes people can create monstrosities with all of these
         | variations, but that's true with any powerful tool. If you
         | dislike Ruby for being Ruby, pick another language.
        
           | rubyist5eva wrote:
           | > we should instead grow the developers to understand these
           | different approaches as opposed to labeling half of the
           | language "bad practice".
           | 
           | > As I said in another comment. Ruby was built to have
           | multiple ways of doing the same tasks and criticizing it for
           | this is... pointless.
           | 
           | Agreed 100% with this take. If I only wanted 1 way to
           | accomplish something no matter how inelegant it might be in
           | that context, I would use Python. I choose Ruby specifically
           | because of how expressive it is. It makes it a bit tougher
           | when working in a team with 2 or more opinionated devs, ie.
           | "should we use more functional or more OO approaches to solve
           | a problem" but this is a culture and communication issue, not
           | a language problem. Having a good rubocop setup and staying
           | within the confines of your agreed upon ruleset is a good
           | start.
           | 
           | For example you can use rubocop to enforce dissallowing
           | `unless !condition`, then it's just not an issue anymore -
           | these kinds of issues dissapear before code even makes it to
           | review.
        
           | FpUser wrote:
           | >"As I said in another comment. Ruby was built to have
           | multiple ways of doing the same tasks and criticizing it for
           | this is... pointless. Yes people can create monstrosities
           | with all of these variations, but that's true with any
           | powerful tool. If you dislike Ruby for being Ruby, pick
           | another language."
           | 
           | Exactly the reasons I use C++. Well, after crazy performance,
           | efficiency and single executable deployment.
        
             | fl_ciq wrote:
             | I like C++ because I find angle brackets to be harmonious
             | to the eye.
        
           | techdragon wrote:
           | I love an expressive programming language, it's why Go makes
           | me feel like I'm brushing my teeth with sandpaper...
           | 
           | But there's such a thing as too much flexibility,
           | expressiveness and flexibility often go hand in hand as
           | flexible language lets you make things as expressive as you
           | want... but things can be expressive without the same level
           | of flexibility if they are well designed.
           | 
           | I find Rust strikes a good balance for low level language
           | work, it feels more expressive than C because of higher level
           | language features but it's not necessarily as flexible as C
           | with things like the borrow checker nagging you to be safe
           | unless you turn it off.
           | 
           | Lisp... too flexible, too expressive. Lisp code reminds me of
           | the phrase "that depends on what the definition of _is_ ,
           | is".
           | 
           | Scheme and scheme likes including weird step cousins like
           | JavaScript share the unfortunate result of this and your
           | drowning in custom DSLs and no one quite codes the same way
           | unless you have rigorous tooling to enforce a team style.
           | 
           | Ruby falls foul of this for me too. It's too flexible, it's
           | very expressive and I enjoyed reading the tutorials and
           | learning the basics. But the moment I discovered real code I
           | was immediately recoiling in horror .... It was a disaster...
           | a spaghetti mess of overrides redefining and meta-programming
           | in general. It made it impossible for me to ever trust the
           | environment I coded it since I had to constantly inspect
           | everything to make sure someone hadn't done something crazy
           | like enhanced the "+" sign to transform numbers to strings
           | for avoiding something like a sql injection risk in a
           | specific context and whoopsie, leaked the behaviour globally
           | so now any time you added integers you got concatenated
           | strings... but _only after the library was dynamically loaded
           | on first query_ ... maddening stuff...
           | 
           | Stuff like this is why ruby is too flexible.
        
             | FpUser wrote:
             | I do not program in Ruby as there was no business need but
             | I have rough idea on what it can do. My view on the horror
             | you've encountered is that the so called "programmers" that
             | produce such abominations should be sent back to school.
             | 
             | I understand business idea of having monkeys producing code
             | for cheap but I think this approach is misguided.
        
         | asdajksah2123 wrote:
         | The author's point is that conditions in code tend to add up.
         | 
         | What may start as a simple single condition, may not remain
         | that way a year later.
         | 
         | Since there's always the possibility of a certain conditional
         | becoming more complicated, it makes sense to opt for the
         | equivalent solution that makes adding those additional
         | conditions easier.
         | 
         | The alternative is to change the keyword when you add those
         | additional conditions, but in most workplaces it's very
         | possible that someone with less rigor than you might come in
         | and add those new conditions and not make the change.
         | 
         | And then if you want to add a new condition you need to parse
         | and understand the more complicated new conditional first,
         | before you can change it.
         | 
         | This adds a lot of maintainability risk for what appears to be,
         | in the best case, a very minor benefit.
        
           | shortcake27 wrote:
           | While I agree with the other comment re premature
           | optimization, when using guard clauses you can also break up
           | your conditions into multiple statements which is arguably
           | the most readable solution. The author's example could be
           | written as:                 return unless valid_token
           | return if expired?
           | 
           | This scales extremely well if you're concerned about future
           | conditions.
        
           | draw_down wrote:
        
           | WillPostForFood wrote:
           | That strikes me as a premature optimization. If you have a
           | single condition, and unless makes it more readable, use
           | unless. If the conditions do pile up in the future, change it
           | to an if.
        
             | quest88 wrote:
             | Great, now you've got this weird logic on your style guide
             | that your code reviewers will have to point to, and
             | hopefully the new engineers on your team will remember. But
             | maybe they're in a hurry and will quickly add another
             | expression just this one time, multiplied by many
             | engineers.
             | 
             | It's far simpler to ban use of unless.
        
               | WillPostForFood wrote:
               | It is neither weird, nor complex. Use unless in cases
               | where the if has a single, negative condition.
        
       | locallost wrote:
       | My guess is what's putting me off on unless is the baked in
       | negative. If I look at a condition and imagine "if true" I can
       | follow along, but "unless true" makes me think "what does that
       | even mean". Another issue might be that not everyone is a native
       | english speaker (like me), and that we underestimate that
       | thinking in boolean logic might not be the most natural thing in
       | the world, and once you learn it, you usually learn it in a
       | foreign language. Substituting "if !" with "unless" just throws a
       | wrench in the patterns you're used to using.
       | 
       | I disliked it as well in CoffeeScript. The use of else blocks is
       | especially annoying, but even otherwise I don't like it. Some
       | might say you shouldn't use it with an else block, but this is
       | not realistic if you work in a team.
        
       | soheil wrote:
       | "Unless" should only be used when the imperative condition is
       | simple.
       | 
       | You don't understand Ruby if you think there is something wrong
       | with trying to have more than one option to do things, imperfect
       | shortcuts and more human-readable code.
       | 
       | Unless works really well when there is one named boolean variable
       | after it and it's named correctly or if the condition is simple
       | to understand.
       | 
       | It also works well when used inline and without an else
       | statement. For other cases "if" is better-suited. But then again
       | "unless" is another option in your tool chain that makes for a
       | more elegant programming language if you're not a stickler and
       | not constantly finding yourself pining for a platonic language.
       | user = User.find(2000)       return unless user
       | 
       | It'd be easier to miss the "!" character in the case of "if !".
       | 
       | It also makes code read better in English.
        
       | ilyt wrote:
       | I found that if not opening new scope was way more annoying than
       | _option_ to use unless that nearly nobody picks. I.e
       | if cond             a = 1         end
       | 
       | leaks a to outside and a will be nil if condition does not happen
        
       | rco8786 wrote:
       | Love Ruby. Hate unless.
        
       | DogLover_ wrote:
       | Kinda similar, you oftentimes don't need to use an `else`
       | statement. It is way overused and leads to code with too much
       | indentation.
        
       | dimitrios1 wrote:
       | As you learn more programming languages, these cute little
       | operators become less cute and appealing, as you realize that
       | !condition would be far more ubiquitous and transferable than
       | something like unless condition.
       | 
       | I "grew up" in my career as a rails dev myself, but I favor
       | things that are immediately clear to the broadest amount of
       | people possible these days. And if you truly miss these
       | constructs, in any language where you have metaprogramming, which
       | is most these days amongst the broadly used ones, it should be
       | trivially to implement them, should you insist on continuing to
       | use them.
       | 
       | I use Elixir for my "fun" language these days, and they provide
       | unless/2 as a macro, (if/2 is also a macro), but I haven't found
       | myself reaching to use it once.
        
       | 1123581321 wrote:
       | statement unless condition is a wonderful bit of syntactic sugar.
       | It reads like natural English if the variable or method it is
       | evaluating is named well.
       | 
       | Yes, sometimes you have to refactor into a traditional if.
       | Sometimes you make the conditional its own method (which you'd
       | end up doing anyway, assuming it didn't stop at two or three
       | conditions.) These are light tasks as the project grows.
       | 
       | Starting a line with unless, on the other hand, does not work for
       | me. It is also awkward in short English sentences. And long
       | English sentences, where beginning with unless is more
       | appropriate, don't have analogies in single-line ruby statements.
        
         | brabarossa wrote:
         | >It reads like natural English
         | 
         | That's a problem for those who learn it as a second language
         | and have to translate "unless" to "if not" every single time.
        
           | 1123581321 wrote:
           | Don't you know the word after awhile? Ruby core and standard
           | libraries have many English words in them that are harder to
           | learn than basic one-syllable words on the level of "if not."
        
       | clolege wrote:
       | The real problem is that _all_ negatives make it harder to
       | understand things. They open the door for double (and triple)
       | negatives to find their way into the code, and then bang: The
       | only person who can read it is the person who wrote it.
       | 
       | Since unless has a not built into it, it has a lot of potential
       | to confuse people. In my experience, guard clauses are the only
       | place where they make sense.                 def mute_mic
       | return unless mic_active?                ..       end
       | 
       | In this sense, you know that the entirety of the function is an
       | expected (positive) case.
        
         | weatherlite wrote:
         | I agree guard classes are great with unless...other places not
         | so much
        
       | gexla wrote:
       | Just to help people out. If you can't write out the title as a
       | conditional statement in Ruby, you're not the intended audience.
       | Though it still may be interesting as a discussion in
       | conditionals in general.
        
       | kazinator wrote:
       | common-lisp has functions called remove-if-not (applicative) and
       | delete-if-not (destructive version).
       | 
       | The spec says that [t]he functions delete-if-not and remove-if-
       | not are deprecated.
       | 
       | But all that is wrong is their double negative name. remove-if-
       | not is precisely the same thing as keep-if, which is too useful
       | to deprecate. Numerous languages have a function like this,
       | sometimes called filter or similar.
        
       | weatherlight wrote:
       | When I write ruby, and I love ruby, I don't do too much condition
       | branching of logic.                   - `if` and `unless` are for
       | guards. The meat of every method, (the happy path) is at the
       | bottom of that method.         - If there are legitimately two
       | options that branch on a conditional, I try to make sure that
       | both branches return the same type. (feature flags, a/b feature
       | testing, etc.)         - If I can refactor code to a case
       | statement, I will 95% of the time
       | 
       | This article screams, "I don't use a linter" or "I work at a
       | company that doesn't have a style guide."
        
         | thomascgalvin wrote:
         | I don't write ruby at all, but this is how I write my Java,
         | Kotlin, and Javascript; fail-fast at the top of the method,
         | with the happy path following.
         | 
         | And I'll take it one step further: I see a multi-line branch as
         | a code smell in and of itself. If something in a branch takes
         | multiple statements, I am of the opinion that the body of that
         | branch should probably broken out into a method.
         | 
         | So if we're going off the article title, my code might look
         | something like                 val isNotRubyDev =
         | !user.isRubyDev       if(isNotRubyDev) return              //
         | ...read article
        
       | aidenn0 wrote:
       | Common Lisp has an unless macro, but it lacks an else clause,
       | implicitly taking the value "nil" if the test expression is true.
       | It's probably most useful for aborting the flow of the code,
       | e.g.:                 (unless foo (error "Foo should not be
       | nil"))
       | 
       | In less functional code, you sometimes see it for default values
       | (though "OR" seems to be more idiomatic for that case):
       | (unless foo (setf foo 3))
       | 
       | Regardless it has few of the downsides that TFA mentions (the
       | sole exception being introducing a double-negative for unplanned
       | compound test statements), but I don't find something like
       | (unless (and foo (not bar)) (error ...)))
       | 
       | To be that unclear; we want both "foo" and "!bar" or error.
        
       | ricardobeat wrote:
       | That's a lot of words for a simple matter of cleanliness. Do not
       | use 'unless' for complex expressions, only single conditions. I
       | personally hate grouped negatives like the one shown:
       | !(valid_token && !expired)
       | 
       | This expression is also a double (triple?) negative, and a lot
       | harder to parse. The correct approach is to make the
       | `valid_token` flag take `expired` into account, or add a third
       | variable that represents validity, not append `expired` to the
       | unless clause. This keeps everything readable, if the variable
       | names are descriptive enough:                   valid_token =
       | token.valid? && !expired         return 'invalid' unless
       | valid_token
       | 
       | It's also damning that the author uses `unless ... else` as his
       | starting point for the critique, while he is aware that the style
       | guide says "Do not use unless with else" (briefly acknowledged in
       | the last section).
        
       | bryanrasmussen wrote:
       | on a project about a decade ago I had written some ruby code in a
       | non-rubyish manner (non-rubic?) in that I had written if
       | statements.
       | 
       | I had actually decided to write them as if statements because
       | that way I didn't have to make one particular logical check (I
       | can't really remember what the logic was, just that it had to do
       | with language and Swedish language legal documents did not have a
       | particular rule that Danish ones did.
       | 
       | So a senior Ruby dev who admittedly was a lot better than me in a
       | lot of things but did have the habit of making incredibly
       | boneheaded bugs sometimes, went through and rewrote all my if
       | statements as unless statements - inadvertently reversing the
       | logic.
       | 
       | A week later bug comes up I get blamed because it was the thing I
       | worked on I was embarrassed, and I went through the code fixing
       | but then I thought - wait I wouldn't have written this as an
       | unless because I need to do one extra statement that way! After
       | digging through I caught our senior dev, the very guy blaming me
       | for causing bugs.
       | 
       | Ah the revenges of youth are very sweet.
        
       | OliverGilan wrote:
       | I actually completely agree with the author. I remember coming
       | across my first unless statement while trying to find the source
       | of a nasty bug and I spent probably 5 minutes just trying to
       | decipher the behavior of the unless block because my brain had
       | some roadblock with the double negatives. This has become a lot
       | easier to understand as I've used Ruby more but it still seems
       | like a massive opportunity for cognitive complexity and errors
       | for little gain
        
       | fl_ciq wrote:
       | Unless seems to be pretty common in many languages.
       | https://www.indifferentlanguages.com/words/unless In my mind the
       | javascript community would do well to address the idiosyncrasies
       | in its language standard before criticizing other languages for
       | using common human language patterns. If you want to pick on ruby
       | for being weird with conditionals, consider the following.
       | if 0           puts 'true'        end
       | 
       | which will print true. I think there is a much greater chance
       | that 0 being true will cause problems with programmers from other
       | languages than using unless which is quite natural to humans.
       | Ruby is first and foremost a language for humanity, and probably
       | dead last a language for ease of implementation.
       | 
       | > As a general rule I think that if a language has some feature
       | for which there is already a commonly understood syntax across
       | other languages, it should just use that syntax. If you're
       | introducing a complete paradigm shift, then that's fine, but
       | unless is not that: it's just a different way to write if ! and
       | people jumping back and forth between ruby and, say, javascript,
       | now have one extra idiosyncracy to keep in mind.
        
         | yanis_t wrote:
        
         | gsinclair wrote:
         | Only false and nil are falsey, and the language shines for it.
         | There is nothing weird about zero being a truthy value.
        
           | fl_ciq wrote:
           | In what other languages does 0 evaluate to true?
        
             | nanny wrote:
             | Lua, Elixir, Common Lisp, Scheme, Racket, Clojure.
             | 
             | Most statically-typed languages don't let you evaluate 0 as
             | a boolean.
             | 
             | IMO, 0 is a value, and values should be truthy. 0 being
             | falsy is only a wart from C.
        
               | fl_ciq wrote:
               | Thanks for that, I had no idea. Do you know if zero is
               | truthy in erlang? It makes sense for elixir (based on
               | ruby) but I'm wondering if erlang is that way too.
        
           | jacobsenscott wrote:
           | Yes, this is one of ruby's best features.
        
       | moonchrome wrote:
       | I don't have a problem with double negation but I hate ruby for
       | this kind of design - pointless aliases for everything.
       | 
       | It's the exact opposite of pythons "There should be one- and
       | preferably only one -obvious way to do it" - they intentionally
       | create solutions that have zero practical benefit - it's just
       | fuels arguments based on preferences and introduces mental
       | overhead due to inconsistency.
        
         | nonrandomstring wrote:
         | In Perl I once saw someone write;                 unless
         | predicate         do this       else unless impossible_thing
         | do the impossible
         | 
         | What it did at runtime I have no idea, but it broke my brain
         | for the rest of the week.
        
           | ilyt wrote:
           | if !cond1             do this         elsif !cond2
           | do that
           | 
           | ?
           | 
           | it's literally just `!` equivalent. Honestly I haven't seen
           | much code using unless in wild. Especially that it is
           | literally shorter to just !
        
         | sshine wrote:
         | To be fair, Ruby inherited "unless" from Perl.
         | 
         | And Perl literally has the opposite design principle, TIMTOWTDI
         | or "there is more than one way to do it".
         | 
         | I'm not arguing here -- I prefer the "one obvious way"
         | principle.
         | 
         | But you can design a beautiful programming language without
         | regard for the long-term learnings of software engineering.
         | 
         | I always liked Perl's "unless", and I always made sure to not
         | abuse it with double negatives or other contorted conditions
         | that are, in themselves, reasonable. I also promised myself I
         | wouldn't write very big programs in Perl.
        
           | gpvos wrote:
           | I only know `unless` from Perl, and it can make your code
           | clearer if used sparingly. For example it allows you to
           | express preconditions positively:                   die "You
           | may only use port numbers 1024 and higher"             unless
           | $port >= 1024;
        
             | TomSwirly wrote:
             | die "Port numbers below 1024 are forbidden"             if
             | $port < 1024;
             | 
             | is hardly unreadable spaghetti code.
        
               | gpvos wrote:
               | Okay. Now compare:                   die "You may only
               | use port numbers 1024 and higher"             unless
               | $port >= 1024 || is_root(current_uid());              die
               | "Port numbers 1024 are forbidden"             if $port <
               | 1024 && !is_root(current_uid());
        
           | aspyct wrote:
           | Ruby is basically Perl++
        
             | mattm wrote:
             | Ruby is Perl 6
        
             | greenpeas wrote:
             | ruby is OOPerl
        
           | [deleted]
        
           | lloeki wrote:
           | > Everyone has an individual background. Someone may come
           | from Python, someone else may come from Perl, and they may be
           | surprised by different aspects of the language. Then they
           | come up to me and say, 'I was surprised by this feature of
           | the language, so Ruby violates the principle of least
           | surprise.' Wait. Wait. The principle of least surprise is not
           | for you only. The principle of least surprise means principle
           | of least my surprise. And it means the principle of least
           | surprise after you learn Ruby very well. For example, I was a
           | C++ programmer before I started designing Ruby. I programmed
           | in C++ exclusively for two or three years. And after two
           | years of C++ programming, it still surprises me.
           | 
           | - Matz, c.a 2003
        
           | TurboHaskal wrote:
           | I came to Ruby from Perl, and I love `unless`. One of the
           | first things I do in any Lisp is build my own unless macro
           | unless the dialect already has it :)
        
             | nolls wrote:
        
         | drstewart wrote:
         | Wow, I didn't realize Python did this. So, for example, does it
         | enforce functions with single returns or ones with multiple
         | return sites? Also, does it prefer shallowly nested functions
         | with guard clauses or highly nested if / else clauses?
         | 
         | Really curious to see the one and only one obvious way these
         | are handled.
        
         | aqme28 wrote:
         | I love Ruby for this kind of stuff. You don't have to have
         | arguments about which syntax you prefer, you can just use the
         | one you prefer and let your coworkers use theirs.
         | 
         | However, a lot of developers love very strict style guidelines.
         | I've never understood why, but it's a discussion I get into
         | very very often.
        
           | soiler wrote:
           | Hm, I have the exact opposite interpretation. This is exactly
           | the kind of feature that leads to arguments. If `unless`
           | didn't exist, what argument could people be having about
           | using `if !`?
           | 
           | In a shared codebase, I think there should be as few (equally
           | effective) ways to express an idea as possible. (Obviously
           | there can be more- and less-efficient ways to write a
           | function; I'm referring only to style.) The more arbitrary
           | choices people have, the more time is wasted on choosing one.
           | 
           | If you're coding alone, that's fine - you just pick what you
           | like, and spend as long as you like making that decision. But
           | in a shared codebase, developers writing in different styles
           | is a net negative on quality & readability. Spending time
           | debating which style to prefer is a worthwhile, but
           | unnecessary time sink. Automatically enforcing a pre-defined
           | style is efficient and effective - that's why Prettier
           | exists, is widely used, and has few configuration options.
        
         | vidarh wrote:
         | And I love it for exactly this kind of design. It's what makes
         | well-written Ruby read well. And while it's one more way of
         | making badly-written Ruby read badly, in my opinion at least
         | with Ruby you have the _option_ of writing code that reads
         | well. I 've yet to see Python code that looks readable to me.
        
         | Draiken wrote:
         | People can prefer the "one obvious way" and you can use a
         | language that has that as its motto. Ruby was built with
         | "developer happiness" as an objective and I don't see it
         | changing any time soon.
         | 
         | I'll never understand these sorts of articles because they
         | criticize the subject for not being what they explicitly
         | aren't.
         | 
         | "I hate spoons because they can't cut like knives"
        
         | fl_ciq wrote:
         | Python is a communist apartment block, brutal in design and
         | conformity and not very efficient.
        
         | perlgeek wrote:
         | Y'know, I've written a lot of python these past years, and
         | python is just full of aliases and different ways to do things.
         | 
         | Just an example: "if x is not None:" is syntactic sugar for "if
         | not x is None:".
         | 
         | String formatting: there are f-strings, % replacement, .format,
         | probably more methods.
         | 
         | And that's _fine_ , languages evolve over time, add better ways
         | to do things, and don't deprecate the old way.
         | 
         | It's the hypocrisy of flaunting that motto while the language
         | is so full of the exact opposite that always annoys me.
        
         | peoplefromibiza wrote:
         | > It's the exact opposite of pythons "There should be one- and
         | preferably only one -obvious way to do it"
         | unless python.major_version > 1
         | 
         | other zen of python's rules that did not live up the
         | expectations
         | 
         | - beautiful is better than ugly => tell that to numpy or pandas
         | 
         | - readability counts => (!z!)
         | 
         | - if the implementation is hard to explain, it's a bad idea =>
         | then the World is full of very bad ideas
        
         | soheil wrote:
         | It's not pointless, it makes code read better. It's another
         | option to have. It's not meant for every use case. It indicates
         | you don't understand Ruby if you find yourself using an
         | "unless" in a complex boolean operation. It's meant for simple
         | cases like an inline return statement                 return
         | unless User.exists(id=100)
        
           | quietbritishjim wrote:
           | I'll admit I'm not a Ruby developer, but wow it allows return
           | conditionally inside an expression? What were the language
           | designers thinking?! I can't think of any other language that
           | allows return inside an expression (or break/continue). Let's
           | see: C, C++, C#, Python, Javascript, Object Pascal, Java,
           | Rust; all nope. That is indefensible.
        
             | maybe_pablo wrote:
             | Kotlin has this, check out
             | https://kotlinlang.org/docs/returns.html
        
             | ckolkey wrote:
             | If and unless can be used as post-fix clauses. Also, in
             | ruby, -everything- is an expression, so... of course you
             | can return from there
        
               | vidarh wrote:
               | This isn't exactly true. It's a syntax error to put a
               | return anywhere where the grammar expects a value
               | expression, because it's one of few constructs in Ruby
               | that doesn't return a value (contrast with e.g. "if" and
               | "def" and "class", all of which return a value).
               | 
               | E.g. "42 == (return true)" is a syntax error while "42 ==
               | if false; true; end" is syntactically valid.
               | 
               | You can return in the expression in the comment above
               | because the return is at statement level - nothing above
               | it in the grammar requires a value (but obviously allows
               | it).
               | 
               | Off the top of my head I can't remember which other
               | keywords fall in that category. Obviously "end", "then",
               | "alias" and there'll be a few more, but for _most_
               | keywords in Ruby you 're right they can be treated as
               | expressions.
        
             | vidarh wrote:
             | It's not doing "return conditionally inside an expression".
             | The above statement is equivalent to:                  if
             | !condition          return        end
             | 
             | In other words, the return in question has no argument. The
             | unusual (but not unique) aspect of Ruby here is that
             | if/unless can suffix the "then" block and not just prefix
             | it.
        
             | tsimionescu wrote:
             | You've listed languages that separate statements from
             | expressions in their syntax. There is a whole other family
             | of languages where choose consists entirely of expressions
             | - starting with LISP in the 50s, and including virtually
             | all FP languages today (F#, Ocaml, Haskell, SML, Clojure).
             | Ruby happens to be one a member of the latter group. To be
             | fair, most of the languages in that group don't have an
             | equivalent of return/break/continue either - I think only
             | Ruby and some Lisps do.
             | 
             | Regardless, all of the languages above except C and maybe
             | Object Pascal can still have control stop in the middle of
             | an expression, since an expression can throw an Exception
             | (indirectly). Returning is not significantly different from
             | that.
        
             | [deleted]
        
             | jack_riminton wrote:
             | Nah, it's pretty cool once you get used to it
        
             | tialaramex wrote:
             | > I can't think of any other language that allows return
             | inside an expression ... Rust
             | 
             | Er, what?
             | 
             | You understand almost _everything_ in Rust is an expression
             | right?                   let x = if yeah_nah() { return 5;
             | } else { "X" };
             | 
             | That return is an expression, obviously we mostly care
             | about the expression's side effect which is a change of
             | control flow to leave the function with some sort of
             | integer 5 as the return value (the function signature tells
             | Rust which kind of integer this 5 is) - but the expression
             | "return 5" itself does have a type, it's ! aka Never, an
             | Empty Type because no values of this type can exist -
             | because the side effect will change the control flow before
             | we need a value.
             | 
             | Rust's type inference engine is fine with this because
             | under type arithmetic all the values fit in a single type,
             | the type of "X" - &'static str - there are no values on the
             | left to disrupt that.
        
           | ilyt wrote:
           | return if !User.exists(id=100)
           | 
           | reads just fine and takes less letters. I don't think unless
           | is "bad", it's just unnecessary
           | 
           | > It indicates you don't understand Ruby if you find yourself
           | using an "unless" in a complex boolean operation. It's meant
           | for simple cases like an inline return statement
           | unless `git status -s | grep -v 'RAILS_VERSION\\|CHANGELOG\\|
           | Gemfile.lock\\|package.json\\|version.rb\\|tasks/release.rb'`
           | .strip.empty?           abort "[ABORTING] `git status`
           | reports a dirty tree. Make sure all changes are committed"
           | end
           | 
           | is not exactly very readable and this
           | unless connection.adapter_name == "Mysql2" && options[:id] ==
           | :bigint                 if [:integer,
           | :bigint].include?(options[:id]) && !options.key?(:default)
           | options[:default] = nil                 end               end
           | 
           | isn't glancable either. Just random snippets from Rails code.
           | You can see how author wanted some bonus points and used
           | unless, if, and ! too. Sure it isn't hard to figure out but
           | it makes it needlesly obtuse
        
           | moonchrome wrote:
           | God that's such a landmine when reading code. Seeing a return
           | without an explicit change of scope... Why ? To save one line
           | ?
           | 
           | Yep that's why I hate ruby - worked on one mature codebase
           | for a year and after seeing various such gems used across the
           | project - from >10 devs - I'm confident I will never touch
           | the language again.
        
             | pmontra wrote:
             | Those one line returns are particularly handy at the
             | beginning of methods, to validate or process arguments and
             | return immediately for simple cases.
        
               | hnzix wrote:
               | Short circuiting is such a beautiful way of avoiding
               | giant nested "if" mountains. I wish it was more widely
               | used.
        
               | ilyt wrote:
               | right but                   if condition { return }
               | 
               | works well enough in other languages and shows actual
               | condition (the important part) to programmer first. if
               | that _if_ and extra brackets is really too long Perl way
               | is also option.                   condition || return
        
             | soheil wrote:
             | If you're returning who cares about the scope? Are you
             | saying visually you'd like to have indentation inside the
             | if body? If that's the case there is also nothing stopping
             | you in most languages from doing something as nasty as:
             | a=1;b=2;c=3;d=a+b==c?4:5;return d
        
               | moonchrome wrote:
               | I do because return means end of scope. Except in your
               | example it hides the fact that it's creating it's own
               | scope.
               | 
               | I'm not arguing other languages can't produce bad code,
               | just that ruby is particularly suited for it especially
               | as number of developers working on code increases. I've
               | seen people propose a linter to enforce consistency - but
               | at that point I might as well chose a language with
               | better design choices - plenty of alternatives these
               | days.
        
               | codesnik wrote:
               | It doesn't create no scope. Even for variables.
        
               | ezekg wrote:
               | Ruby doesn't create a new scope for if/unless.
        
               | multiplegeorges wrote:
               | > I've seen people propose a linter to enforce
               | consistency - but at that point I might as well chose a
               | language with better design choices - plenty of
               | alternatives these days.
               | 
               | You're seriously proposing that adding a linter has the
               | same organizational costs as _changing languages
               | entirely_. Meanwhile, back in the real world...
               | 
               | Ruby has major advantages over many other languages and a
               | linter is basic tooling you should have in every
               | development environment.
        
             | swat535 wrote:
             | Those are called Guard clauses and they are implement in
             | plenty of systems.. this paradigm has nothing to do with
             | "Ruby".
             | 
             | In any case, the Ruby community already has good guidelines
             | on the "Unless" usage, there are few scenarios where they
             | are useful but it's not like you find them everywhere in a
             | codebase.
             | 
             | For example, we don't use "Unless" with "Else", or use
             | Unless with negation (like the article), or use Unless in
             | nested If statement, etc. Rubocop will catch many of these
             | and warn you.
             | 
             | My point is that experienced engineers will use the
             | language as it was intended to and not abuse its features.
        
         | chillfox wrote:
         | The problem is that what is obvious depends upon your way of
         | thinking. To me very little in Python makes sense, but I
         | understand that it does to someone and that's cool. There's no
         | reason to hate on a language just because it doesn't click with
         | your way of thinking.
        
       | Arubis wrote:
       | `unless` is great. Rubocop (used everywhere) would flag and offer
       | to autocorrect this title for the double-negation.
        
       | strzibny wrote:
       | You are now likely attracting all the Ruby devs here:D
        
       | jjgreen wrote:
       | The visual difference between a ! and an l is not that great,
       | send_email if !user.suspended?
       | 
       | or                   send_email if luser.suspended?
       | 
       | The latter could easily be an aggressive dev sending abusive
       | emails to users they dislike enough to call lusers, at first
       | glance at least ...
        
         | SanjayMehta wrote:
         | Brought back memories of alt.sysadmin.recovery.
        
         | quietbritishjim wrote:
         | Perhaps a Python style spelt-out `not` for boolean negation
         | would have been a better solution for this than `unless` in
         | deep retrospect?                   send_email if not
         | user_suspended?
        
           | jjgreen wrote:
           | Ruby has "not", but the precedence rules between "not" and
           | "!" differ
        
             | quietbritishjim wrote:
             | Well I really showed myself up as commenting on a topic
             | that I know nothing about! :-)
             | 
             | But that's actually ideal in this context, a really low
             | precedence operator is exactly what you want because you
             | can swap `unless` for `if not` without worring about extra
             | parentheses:
             | 
             | send_email if not user_suspended? || user_opt_out?
        
               | greenpeas wrote:
               | I wouldn't use this. Relying on tricky operator
               | precedence can trip up your readers. It's better to just
               | wrap everything in parentheses. I also use parentheses
               | when mixing && and ||, even though their precedence
               | relationship is (probably) more widely known.
               | 
               | I generally avoid `not`, `and`, `or` keywords.
        
         | hnbad wrote:
         | Sadly `!` never caught on. But I suppose being visually similar
         | to `-` isn't much better.
        
           | Joker_vD wrote:
           | The "logical negation" sign used to have the vertical line as
           | long as "|", so e.g. "!A" looked more like "-|A" but fully
           | vertically aligned with the letter. Sadly, this glyph fell
           | out of usage in fonts in favour of "minus with
           | cedilla/descender".
        
             | jjgreen wrote:
             | I'd always understood it came from Frege's
             | _Begriffsschrift_ , a small descender from a horizontal
             | line (part of a larger diagram), so like a short wide T,
             | then lost its right arm later. Would you have some
             | examples? (a quick google images shows nothing like that
             | ...)
        
           | tsimionescu wrote:
           | If it's not a shift+<something> key on a popular keyboard
           | layout, it's not going to gain widespread adoption in
           | programming.
        
             | housecarpenter wrote:
             | ! is shift+` on the most common UK keyboard layout, but
             | yeah, it would probably need to be popular _in America_.
        
         | forkerenok wrote:
         | Funny, when I read your point, I was sure and ready counter
         | with an argument that code editors must highlight symbols and
         | unary operators differently (colours, maybe spacing as well).
         | But I just checked this on a couple of Ruby and JS highlighters
         | and they are actually not! :scream:
        
       | klooney wrote:
       | Unless and ternaries are great signals in a pull request that you
       | should build a truth table and double check it. They're backwards
       | all the time, especially in less tested, error handling
       | codepaths.
        
         | asdajksah2123 wrote:
         | ternaries are expressions.
         | 
         | Just because of that they are far superior to if/else/unless,
         | unless ;-) you're using the ternaries to execute statements
         | with side effects instead of just returning a value.
        
           | giraffe_lady wrote:
           | Those are also expressions in ruby.
        
       | twic wrote:
       | So:
       | 
       | > Read this post 'unless' you're not a Ruby developer
       | 
       | But:
       | 
       | > Read this post if you're a Ruby developer
       | 
       | Surely?
       | 
       | Seriously though, the main way Ruby went wrong was an obsession
       | with this entirely superficial kind of expressiveness and
       | simplicity. Rubyists will lard their code with all sorts of
       | "convenient" and "easy" features, to save a few keystrokes here
       | and there, at the expense of bloating their APIs and hiding
       | weird, hard-to-reason about magic.
        
       | rukuu001 wrote:
       | The actual literal meaning of 'unless' has evaporated from my
       | brain trying to parse that title
        
       | shric wrote:
       | I'm mildly surprised the article doesn't mention that Perl, one
       | of the languages that influenced Ruby, also has unless.
        
         | dgunay wrote:
         | In Perl you can write postfix conditionals: `thing() unless
         | $condition`, which at least is more natural usage of "unless"
         | to a native English speaker than the other way around. That's
         | the best way to use it IMO.
        
           | byroot wrote:
           | It's the same in Ruby. It's even mentioned in TFA.
        
         | sshine wrote:
         | Those who don't know history are doomed to repeat it. ;-)
        
         | rjsw wrote:
         | Common Lisp has unless too, I use it where it makes sense.
        
       | nickelcitymario wrote:
       | 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.
        
         | asdajksah2123 wrote:
         | The unless is still harder for me to grok.
         | 
         | The if !ruby_dev (read as "if not ruby_dev") is so much easier.
        
           | nickelcitymario wrote:
           | Fascinating! 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 wrote:
           | For 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.
        
         | dlkf wrote:
         | There'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?
        
           | hosh wrote:
           | It 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.
        
             | antod wrote:
             | I have a long history of Python and it fits my brain well,
             | but the last 7 or so years have been in Ruby shops. I still
             | struggle with trying to write idiomatic Ruby sad to say.
             | 
             | I do like `unless` in Ruby, but only when it is the one
             | liner form and the exception happens pretty rarely. The
             | multi line form often takes a lot of effort to parse for me
             | if it is more than a very simple expression.
        
             | dlkf wrote:
             | This is a great comment. The language I use most is Python,
             | and I am definitely biased toward its conventions. It's
             | interesting to hear from the other side of the fence.
             | 
             | I want to suggest a slight reframing: instead of saying:
             | "It is not all about cost-benefit," you could say "here is
             | an addition to the 'benefits' column that hasn't been
             | considered yet."
             | 
             | It's a totally reasonable argument; much better than
             | "elegance." This was my main problem: that the critique of
             | `unless` was much more plausible than the defence.
        
           | marcosdumay wrote:
           | Personally, I don't think "readable by people that don't know
           | the language" is a reasonable feature to optimize a language
           | around.
           | 
           | And if you go on that direction, almost the everything on the
           | language is a larger roadblock than an oddly placed
           | conditional.
        
             | afandian wrote:
             | I wrote Ruby for years (for fun). I always had to stop and
             | think twice about 'unless' and translate it into 'if not'.
        
             | dlkf wrote:
             | I _never_ suggested we "optimize the language around this
             | feature." I only suggested that it is a higher virtue than
             | some user on HN's subjective concept of "elegance."
             | 
             | What do you think is more important: the speed at which C
             | programmers can navigate your code base, or one person's
             | subjective idea of "elegance"?
        
               | marcosdumay wrote:
               | "Elegance" can mean many things, some irrelevant, some
               | very important. But the speed at which C programmers can
               | navigate some non-C code is absolutely irrelevant.
               | 
               | Specifically about Ruby, with it's infinite levels of
               | metaprograming and "you can even redefine the meaning of
               | blank space" philosophy, it's not 'unless' that will stop
               | anybody.
        
           | 8note wrote:
           | That'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 wrote:
             | I 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.
        
         | seydor wrote:
         | as 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)
        
         | enw wrote:
         | For 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 wrote:
           | It'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.
        
             | 8note wrote:
             | Why bother with loop, continue, and break when you can have
             | a more generic if+goto that can handle all the cases?
             | 
             | You can simulate the loop behaviour if that's what you
             | really want
        
               | ravenstine wrote:
               | I've thought about that, but that's closer to the metal
               | than I prefer and I think it's not beneficial for less
               | experienced programmers.
               | 
               | Structured programming is, I believe, a good idea for the
               | vast majority of use cases. Though one can _technically_
               | use structured programming while using goto, encouraging
               | goto can therefore allow programmers to go down a path
               | that is counterproductive. It 's basically the opposite
               | end of the spectrum from OOP where encouragement of
               | rampant objectiveness and inheritance makes programmers
               | write code that is way too complicated.
               | 
               | There's absolutely a place for goto. I once made a
               | "language" (actually YAML) specifically for developing
               | for the Amazon Alexa platform, and it used something
               | similar to goto called "go to scene" and "go to random".
               | For that sort of thing, goto can be much more practical
               | and even easier to reason about than "better" constructs
               | in general purpose high-level programming languages. It's
               | just not something I would consider appropriate for the
               | kind of language I am proposing, though I still ponder on
               | it.
        
             | KMag wrote:
             | Many 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.
        
         | systems_glitch wrote:
         | Came 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.
        
         | welder wrote:
         | I 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 wrote:
           | I 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 wrote:
             | I'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.
        
         | micromacrofoot wrote:
         | "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 wrote:
           | I 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.
        
             | micromacrofoot wrote:
             | I used to work at a garage, and while an impact wrench can
             | be the fastest way to put a tire back on a car, I
             | eventually banned it entirely.
             | 
             | Everyone's lazy or overwhelmed at some point, and it made
             | mistakes too easy to make (the problem is that it
             | overtightens the lug nuts because the ease of use removes
             | the proper physical feedback).
             | 
             | In situations where you don't have the bandwidth to
             | perfectly educate everyone and enforce rules, sometimes
             | it's easier to limit the toolset. A tire iron can be
             | misused too, but it's a little harder.
        
             | burke wrote:
             | On 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 wrote:
               | That's a very Perl idiom, did you previously write Perl?
        
               | graywh wrote:
               | the 2nd form implicitly returns the value of valid if
               | it's truthy and nil if it's falsey; the 1st form always
               | returns nil
        
         | taeric wrote:
         | In 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.
        
         | dyingkneepad wrote:
         | I 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 wrote:
           | How about if you could write _except if_ instead of _unless_?
        
         | bluedino wrote:
         | _unless_ is one of those things I have to read 2-3 times and it
         | totally bogs me down.
        
           | 4pkjai wrote:
           | I have a similar problem with list.filterNot() in Kotlin
        
           | wruza wrote:
           | Just reread _until_ you get it.
        
             | layer8 wrote:
             | Admittedly, _until_ (as the negation of _while_ for loops)
             | tends to be more straightforward to grasp than _unless_.
        
           | nickelcitymario wrote:
           | Interesting! 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 wrote:
             | I 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.
        
               | areichert wrote:
               | Man, I feel like you hit the nail on the head here...
               | this is definitely the best way I could think to
               | articulate why `unless` throws me off so much.
               | 
               | Weirdly, Ruby was one of the first languages I learned
               | early in my career, and at the time I had no problem with
               | `unless`. But after years of experience with other
               | languages, I similarly feel that `if` statements now
               | trigger the fast pattern matching circuits in my brain,
               | while `unless` makes me do a double-take and basically
               | translate it into `if not`
               | 
               | At first I thought I was just becoming dumber with age,
               | but I like your explanation better :P
        
               | nickelcitymario wrote:
               | That makes sense!
        
               | mathstuf wrote:
               | Same here. I can handle chaining conditions and narrowing
               | things down, but once there's a De Morgan's filter on the
               | thing, there's just too much state to juggle because
               | what's in front of my eyes is not a refresher for what I
               | actually need to remember ("ok, it says `n < 0`...(De
               | Morgan filter)...n is positive" is too much IMO).
               | 
               | That said, I feel it's really down to double+ negation
               | being hard to handle. `if` with a single negation is
               | fine; `unless` is _automatically_ a negation, so you 're
               | just off to a bad start on that front. I feel like the
               | only viable use is in a case like Rust's `let ... else {
               | diverge }` where anything that fails the condition is
               | guaranteed to diverge (typically, return) and I can just
               | ignore it when reading the overall codeflow. But Ruby
               | mixes that up and does `diverge unless ...` which puts
               | the diverging part "up front" and "in the way" for such
               | readings.
        
               | eloisius wrote:
               | I'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 wrote:
               | This 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.
        
             | gnufied wrote:
             | Also as a non-native English speaker, unless always makes
             | me do a double take. It is not a word that naturally
             | translates in my head, but that might just be me.
        
             | hosh wrote:
             | In Ruby (and Crystal), I tend to use `unless` for guards at
             | the top of the method, or returns. These are typically
             | `return foo unless baz`.
             | 
             | When I write Elixir, `unless` gets awkward in a functional
             | style of programming, and Elixir has guard clauses and
             | pattern matching. I pretty much never use `unless` in
             | Elixir despite using it in Ruby for years.
             | 
             | Sometimes, I'll add extra methods with a negation in the
             | name itself. So for example                 # instead of
             | return "invalid" unless valid?       return []        if
             | empty?            # I define invalid?() and do       return
             | "invalid" if invalid?       return []        if empty?
        
               | mjevans wrote:
               | Perl also had that delayed syntax check style as an
               | option and I HATED IT.
               | 
               | THING if logical condition
               | 
               | Filter First is far better self-documentation: if
               | condition THING
        
               | layer8 wrote:
               | It works well in cases where you have an operation that
               | consists of a certain sequence of statements, where one
               | of the statements has to be omitted in a particular
               | atypical situation. Instead of having interrupt the
               | sequence with an _if_ , you just tag the particular
               | statement with the omitting condition at the end. That's
               | also when _unless_ tends to be intuitive, because it
               | suggests an atypical condition.
        
               | hosh wrote:
               | That's a matter of what fits better with the structure of
               | how you think internally, and not necessarily that there
               | is an objectively better way for self-documentation.
               | 
               | For example, I can totally see how imperative-first would
               | mess up people with neurodivergant brains.
               | 
               | Tangent -- Ruby takes a lot of inspiration from Perl.
        
             | [deleted]
        
             | [deleted]
        
             | RestlessMind wrote:
             | I think it is also an issue of familiarity with English.
             | Not all developers are fluent in English.
        
         | peruvian wrote:
         | Different 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.
        
         | chrisandchris wrote:
         | Doing 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.
        
         | kuratkull wrote:
         | '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.
        
         | geuis wrote:
         | Nope. 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 wrote:
           | But 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.
        
         | JasonFruit wrote:
         | You've demonstrated that it is trivially replaced by 'if' and
         | negation. I think that's almost the definition of inelegant.
        
           | akira2501 wrote:
           | Go to the store and get milk, unless we already have some.
           | 
           | Go to the store and get milk, if not we already have some.
        
           | aaronbrethorst wrote:
           | One of the hallmarks of Ruby is a full embrace of the notion
           | of There's More Than One Way To Do It. Generations of
           | developers around the world have seen this as being a core
           | part of Ruby's elegance--at least to their minds (myself
           | included).
        
           | nickelcitymario wrote:
           | Only 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 wrote:
             | The 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 wrote:
             | Unconscious clarity trumps literary fluidity when reading
             | code.
        
             | [deleted]
        
             | guitarbill wrote:
             | > 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"...
        
               | KMag wrote:
               | Correct. The chief difference between English and German
               | in this respect is the use of spaces (and what is
               | considered a word). In German, you can basically drop the
               | spaces from a noun phrase and call it a word, but it's
               | basically a low-consequence surface syntax difference.
               | 
               | Side note: ancient Greek didn't use spaces, and many
               | other languages (Thai and Written Chinese are the ones
               | with which I'm most familiar) either don't use spaces or
               | make spaces optional. The distinction between a phrase
               | and a word gets a bit blurry at times, and I find the
               | distinction is seldom useful, particularly when making
               | comparisons across languages.
        
               | nickelcitymario wrote:
               | Fascinating! I had no idea. I stand by my main point, but
               | perhaps German wasn't a good example. It's just the one
               | that comes up all the time when people say "Did you know
               | X language has a word for Y?", it's almost always German.
               | Now I know why!
        
           | layer8 wrote:
           | By the same token, using _until_ instead of _while_ and
           | negation would be inelegant, but I think _until_ is less of a
           | stumble block than _unless_.
        
           | jewel wrote:
           | It's Ruby though, where Array has "size", "length", and
           | "count", all of which are equivalent. The programmer chooses
           | which one they prefer based on the context or their style or
           | the phase of the moon.
           | 
           | Ruby inherits the Perl philosophy of "There's more than one
           | way to do it". Compare with Python, and its "There should be
           | one -- and preferably only one -- obvious way to do it."
           | 
           | It's true that it makes the compiler less elegant, but Ruby
           | optimizes for the programmer at the expense of the compiler.
        
             | scruple wrote:
             | Equivalent in output but not in implementation /
             | performance. Does that matter? Not usually, no, but it
             | depends.
        
             | eloisius wrote:
             | Not exactly the same. It's been a while, but if I recall,
             | count takes a predicate block so you can do things like
             | `numbers.count { |n| n.even? }`
        
               | vidarh wrote:
               | It can also take an argument and will then return the
               | count of the number of items which compares equal to the
               | argument.
               | 
               | "count" is only equivalent to "length" and "size" when
               | called with no argument and no block, and should be
               | slower for that case (it includes a comparison of arity
               | _and_ a call to rb_block_given_p() in MRI before it
               | returns the array length).
        
           | chillfox wrote:
           | Negation makes code harder to read and understand.
        
             | nickelcitymario wrote:
             | I'm getting the impression that this is not universally
             | true. It's true for me. I find the word "unless" helpful
             | when it eliminates double negatives.
             | 
             | But there are enough people on this thread who feel
             | differently that it makes me wonder if maybe we're wrong.
             | If code is meant to be read and understood by all, and if
             | "unless" is confusing to a large number of people, maybe
             | those of us who like it should knock it off.
             | 
             | I do find it more elegant and easier to read, but maybe you
             | and I can process double negatives easier than the anti-
             | unless crowd are able to process "unless" logic.
             | 
             | If that's the case, I'd be willing to sacrifice my
             | preference for "unless" for the greater good.
        
               | lsaferite wrote:
               | > double negatives
               | 
               | Could you give an example of a double negative in this
               | case?
               | 
               | I ask because using "if" does not lend itself to double
               | negatives in my experience, but just thinking about
               | "unless" I see double negatives being an issue (since
               | unless is already negating the operand).
        
               | petre wrote:
               | Maybe he means unless this and|or|xor that. That's what I
               | use it for rather than negate every paraneter.
        
               | layer8 wrote:
               | Sometimes adding a temporary boolean variable is a good
               | way to resolve a double (or single) negative.
        
               | chillfox wrote:
               | People are different, so different things click with how
               | they think.
               | 
               | I would likely not be a programmer if it weren't for Ruby
               | and it doing things different.
               | 
               | I had tried to learn programming for years (JavaScript,
               | Python, Java, C#), none of it stuck or progressed beyond
               | following tutorials and one of the things I had serious
               | issues with was negation.
               | 
               | Then I came across Ruby and it just kinda clicked into
               | place like no other language had. With Ruby I was able to
               | do my own things within a month.
               | 
               | Now I don't really have a problem picking up other
               | languages anymore. But there's others out there right now
               | struggling to learn programming and there should be as
               | many programming languages doing things different as
               | possible to increase the chance that they come across one
               | that is obvious for the way they think.
               | 
               | This idea of there should only be one way of doing things
               | is poison in my opinion.
        
             | asdajksah2123 wrote:
             | Unless has negation built in.
             | 
             | Which is why unless is such a hard concept for people to
             | grasp, not just in code, but also in regular English.
             | 
             | At least the "if not" makes the negation explicit, which
             | can then be easily eliminated using several different
             | techniques (early return, swap with the else condition) if
             | the negation is confusing enough.
             | 
             | However, "unless" necessarily includes negation because
             | that's how the word is defined.
        
               | mattarm wrote:
               | > Which is why unless is such a hard concept for people
               | to grasp, not just in code, but also in regular English.
               | 
               | This is the first I've heard about this confusion over
               | the word "unless" in English.
               | 
               | In spoken English I do notice that most often the
               | "unless" comes after a statement. Example: "I'll be there
               | on time, unless the bus is late." That is more clear (to
               | me) than "I'll be there on time, if the bus is not late."
               | Maybe not by coincidence, I tend to like "unless" when it
               | follows the action in in Ruby code, too.
        
           | shakow wrote:
           | A for can be replaced by a while and a jump, that does not
           | make it more or less elegant.
           | 
           | IMHO, something ``elegant'' in programming is not something
           | that can't be built form something else (or we will all end
           | up in writing only CMOVs), but something that conveys the
           | meaning of its author precisely and concisely - which makes
           | it inherently subjective. I'm in the `unless` team, I can
           | perfectly understand if you are in the `no unless` team, but
           | this argument does not make a lot of sense.
        
             | JasonFruit wrote:
             | Note that I said 'trivially'. The structure and meaning of
             | an 'unless' construction is the same as 'if', adding or
             | removing only a negation. Using 'while' and a jump to
             | construct a loop is much more expressively distant from
             | 'for'.
        
             | nine_k wrote:
             | The `for` is a very ergonomic syntax to mapping a
             | computation to every element of a sequence. The `while`
             | does a really different thing, it's not about sequences at
             | all, but about checking some bit of mutable state
             | repeatedly.
        
               | shakow wrote:
               | > The `for` is a very ergonomic syntax to mapping a
               | computation to every element of a sequence.
               | 
               | The very ergonomic solution to map a computation to every
               | element of a sequence is `map`. In this case, `for` is
               | filled with bookkeeping that does not matter.
        
               | [deleted]
        
               | nine_k wrote:
               | I edited out "syntax sugar" that was in the post
               | initially.
               | 
               | Also, the `for` operator definitely predates the `map`
               | function. Some people also prefer `map` to be more or
               | less pure and expect it to return a usable list; `for `
               | has no such expectation, it e.g. may consist solely in
               | printing elements.
        
         | hosh wrote:
         | That'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.
        
         | smeagull wrote:
         | Should I read the damn article or not? I still have no idea
        
         | j33zusjuice wrote:
         | "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."
        
         | topaz0 wrote:
         | I 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.
        
       | makoto12 wrote:
       | I've written ruby everyday for the past 5 years. I still cannot
       | read an unless statement and understand it first time. Most of
       | the time i'm translating it to `if !` anyway.
        
       | quickthrower2 wrote:
       | I take issue with the word unless. "Un" means opposite and "Less"
       | means, well less, so unless means more. So `unless` should just
       | be a straight alias for `if`.
        
         | layer8 wrote:
         | You're missing that less is more. ;)
        
         | _moof wrote:
         | The "un" in unless isn't the negating prefix "un-"; it's the
         | word "on" with a change of vowel. The etymology is "on less[er
         | condition than]," e.g., "Abort the launch on less than the
         | rocket is deemed safe to fly."
        
         | xcambar wrote:
         | Sure. Except for every single existing use case of the word.
        
       ___________________________________________________________________
       (page generated 2022-12-13 23:02 UTC)