The Crystal Programming Language Forum

Is it possible to remove unless keyword?

As all know, Crystal brought many concepts from Ruby.
Why remove all alias methods, but keep unless left?
No language use unless, like JAVA, Go, PHP, C++, Python. All of them use if !.

2 Likes

It’s a good point but I don’t consider them aliases. Instead, they are opposites.

The standard library has also select and reject. Depending on each case, one or another might be preferable.

On the other hand aliases like filter, select, or map and collect, are exactly the same.

That said, I wouldn’t mind removing the unless keyword, I often find it confusing. It would be a huge breaking change but the formatter could make it easier to upgrade. But at this point I have a feeling we won’t change this. It’s also one of Ruby’s signatures, so it’s nice to have that in Crystal. And Elixir has it too, and Elixir also borrows some ideas from Ruby.

8 Likes

I think unless can make a lot of boolean expressions easier to read, but I agree it’s often used confusingly. Specifically, some people replace every occurrence of if ! with unless, but some expressions read more easily with if !.

This is true of any convenience, though. Postfix conditionals are super handy for guard clauses, but someone is invariably going to put them at the end of a 300-character line and you won’t know it’s there unless you’ve scrolled all the way to the right (the use of an “unless” clause at the end of this run-on sentence is intentional :joy:). Rails is an iconic example of people abusing conveniences — both the framework itself and apps built on top of it.

Crystal does a lot to remove ways to shoot yourself and your whole team in the foot, but I think the tradeoff of keeping unless can be worth it. At the end of the day, we’re responsible for the code we write. If something reads better with if ! instead of unless, you can change that in your code. :slightly_smiling_face:

6 Likes

When writing return unless X or next unless X you know that X holds for the rest of the block. Been able to read that, directly, is a great feature.

14 Likes

Please don’t mess with unless. :angry:

7 Likes

I think unless improves code readability, especially in the case of next unless x or break unless x.

7 Likes

I don’t have a Ruby background, but like unless, also looks a lot better then if !

4 Likes

A guide from https://github.com/airbnb/ruby/blob/master/README.md

Never use unless with else. Rewrite these with the positive case first.

# bad
unless success?
  puts 'failure'
else
  puts 'success'
end

# good
if success?
  puts 'success'
else
  puts 'failure'
end

Avoid unless with multiple conditions.

  # bad
  unless foo? && bar?
    ...
  end

  # okay
  if !(foo? && bar?)
    ...
  end

Avoid unless with comparison operators if you can use if with an opposing comparison operator.

  # bad
  unless x == 10
    ...
  end

  # good
  if x != 10
    ...
  end

  # bad
  unless x < 10
    ...
  end

  # good
  if x >= 10
    ...
  end

  # ok
  unless x === 10
    ...
  end
1 Like

We learn from other language, not only ruby and its ancestor language. Before 1.0, we can remove some bad, confusing syntax. After 1.0, It will be more difficult to do that. People will enjoy writing code in one way.

2 Likes

I’m really trying to understand your motivation to fix something that ain’t broke.
If you have a preference to code in a certain idiomatic way nothing is forcing you to use unless. So why are you so vehement about forcing others to not be able to use unless in their code? :unamused:

9 Likes

I disagree with all of this, why purposefully limit yourself with unless by not allowing things like else? Experiment, try reading these out loud.

unless x == 10 : Unless x is equal to 10
if x != 10 : If x does not equal 10

They feel almost exactly the same.

why is unless x == 10 considered bad, but unless x === 10 is considered good form? In this case it would seem that they would act identical.

return not_found(ctx) if article.nil?
return not_found(ctx) if !article
return not_found(ctx) unless article

The 3 forms are readable. No need to remove, let alone impose. Just a matter of preference.

11 Likes

For me unless has one really good use-case, as a guard cause in methods. Just like @nico described above like soe.

def calc_total_points(x,y,y)
  return "Not Enough Points in the 1st set" unless x > 10
  
  points = y+x+z 
  puts "You got enough points #{points}"
  points
end 

It’s just easy to read.

Removing it will cause a lot of breakages, and will diminish programmer experience by just a tiny bit, for no significant marginal gain.

2 Likes

This is exactly the issue, 3 ways to do exactly the same thing. Not mentioning things like unless !arcticle.
Plus, there are weird behaviors like elsif can’t be used after unless, but else can.

When reading, we can easily think that unless var == other is the same as if var != other, but it is in fact if !(var == other), this might make a difference. We have to always think the negation globs everything after the keyword.


A similar topic is also loop, until and while true.

I guess you’d prefer Python then :laughing: . Its syntax is more human readable than Ruby: if not X and not Y or Z, vs if !X && !Y || Z. It is a matter of expressiveness vs readable and more verbose.

unless is only here because of Ruby. An alternative is to have not, which is a lot more flexible and as readable.

I’m in favor of removing it unless someone has any objections.

</joke>

4 Likes

I prefer to keep it. For me ! is more mental overhead for simple guard clauses and the like.

3 Likes

while true is what you said if we agree, unless new elements come, we should not loop on this topic until things are settled.

I’ll add, my message I can delete_if if you reject(!) it (ref). :joy:

1 Like