What is exactly Ruby's `not` keyword?

75 views Asked by At

The documentation claims that not is just another spelling of ! (supposedly with different precedence).

The parser says that

expr        : command_call
                | keyword_not '\n'? expr
                    {
                        $$ = call_uni_op(p, method_cond(p, $3, &@3), METHOD_NOT, &@1, &@$);
                    /*% ripper: unary!(ID2VAL(idNOT), $:3) %*/
                    }

but not all expressions are valid. It pretty much requires parens. Is this really wanted?

irb> x = !true
=> false

irb> not true
=> false

irb> x = !true
=> false

irb> x = not true
/Users/akim/.gem/ruby/3.3.0/gems/irb-1.12.0/lib/irb/workspace.rb:117:in `eval': (irb):3: syntax error, unexpected `true', expecting '(' (SyntaxError)
x = not true
        ^~~~

    from <internal:kernel>:187:in `loop'
    from /Users/akim/.gem/ruby/3.3.0/gems/irb-1.12.0/exe/irb:9:in `<top (required)>'
    from /opt/local/bin/irb:25:in `load'
    from /opt/local/bin/irb:25:in `<main>'

irb> x = not(true)
=> false

irb> x = (not true)
=> false

(IRB's behavior matches exactly that of MRI.)

1

There are 1 answers

0
Stefan On

Is this really wanted?

Yes and no, it depends on the use case. For assignments, not's low precedence isn't really useful because it requires parentheses due to the assignment operator.

When combined with if however, its low precedence allows to omit parentheses:

if not a == b
  # do something
end

as opposed to ! which has the highest precedence and therefore requires parentheses:

if !(a == b)
  # do something
end

(you could also use unless here, but sometimes if not is more explicit / easier to read)