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?
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
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.
Problem with so much syntactic sugar is you need to retain/recall the semantics of the vocabulary. As a polyglot programmer who doesn't write much code anymore, it slows me down.
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.
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
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?
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.
When I started writing these as pipeline execution. Then I’ll use a maybe?() instead if the conditional does not need to depend on the result of a previous operation.
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.
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.