!(!!!()) and the value of empty parentheses
Question
What's the return value of the following Ruby code?
var = !(!!!())
var # => ???
The correct answer is
-
falseCorrect -
It raises
SyntaxError -
true -
nil
Explanation
TL;DR
Empty parentheses are a valid expression in Ruby and evaluate to nil. The expression then applies ! four times: nil is falsy, so each negation flips the boolean. nil becomes true, false, true, and finally false. var is false.
Step by step
() # => nil
!() # => true
!!!() # => true
!(!!!()) # => false
Reading inside out:
()evaluates tonil.!()negatesnil.nilis falsy, so the result istrue.!!()negates that:false.!!!()negates again:true.- The outer
!(...)negatestrue, so the whole expression isfalse, and the assignment returns it.
Only nil and false are falsy in Ruby, which is why the first ! turns nil into a proper boolean and every later ! just alternates it.
Under the hood
The compiled instructions make the structure obvious, one putnil followed by four negations:
puts RubyVM::InstructionSequence.compile("!(!!!())").disasm
Output (the == disasm header line is trimmed):
0000 putnil ( 1)[Li]
0001 opt_not <calldata!mid:!, argc:0, ARGS_SIMPLE>[CcCr]
0003 opt_not <calldata!mid:!, argc:0, ARGS_SIMPLE>[CcCr]
0005 opt_not <calldata!mid:!, argc:0, ARGS_SIMPLE>[CcCr]
0007 opt_not <calldata!mid:!, argc:0, ARGS_SIMPLE>[CcCr]
0009 leave
Each opt_not is an optimized call to the ! method (mid:! in the calldata). ! is a real method, defined on BasicObject, so a class can override it, and the VM falls back to a regular method call when that happens.
Edge cases
The useful relative of this puzzle is the double bang, the standard idiom for coercing any value to a strict boolean:
!!nil # => false
!!0 # => true
!!"abc" # => true
One ! gives the negated boolean; two give the value's truthiness as true or false.
Share this quiz
Comments
No comments yet. Be the first.