Why is it ok to write, but not ||

I understand that there is a difference in priority, as shown in another answer :

p foo = false || true
# => true

p foo = false or true
# => false

But there seems to be more than that between orand ||.

For instance:

p foo = 42 or raise "Something went wrong with foo"
# => 42
p foo = nil or raise "Something went wrong with foo"
# => Something went wrong with foo (RuntimeError)
p foo = 42 || raise "Something went wrong with foo"
# => syntax error, unexpected tOP_ASGN, expecting end-of-input

I expected to receive:

p foo = 42 or raise "Something went wrong with foo"
# => 42
p foo = nil or raise "Something went wrong with foo"
# => Something went wrong with foo (RuntimeError)
p foo = 42 || raise "Something went wrong with foo"
# => Something went wrong with foo (RuntimeError)

But this is a syntax error. So what's going on?

+4
source share
2 answers

Theory:

Here's a priority table for Ruby.

This table is not visible, but a call to the Ruby method without parentheses has a lower priority than ||and =, but higher than or. See question .

So, for your code, from highest to lowest priority:

  • ||
  • =
  • raise "something"
  • or

Expression with or

foo = 42 or raise "Something went wrong with foo"

=:

( foo = 42 ) or raise "Something went wrong with foo"

raise:

( foo = 42 ) or ( raise "Something went wrong with foo" )

or:

( ( foo = 42 ) or ( raise "Something went wrong with foo" ) )

||

foo = 42 || raise "Something went wrong with foo"

||:

foo = ( 42 || raise ) "Something went wrong with foo"

!

:

foo = 42 || (raise "Something went wrong with foo") #=> 42

foo = 42 || raise("Something went wrong with foo")  #=> 42

foo = 42 || raise 

!

, puts p !

:

p [1,2,3].map do |i|
  i*2
end

:

#<Enumerator: [1, 2, 3]:map>

, , :

[2, 4, 6]
+8

|| or .

, - . , , ||, . Ruby , and or .

,

A or B

# can be considered equivalent to

if A then A else B end

A || B

# can be considered equivalent to

A.or { B } # given a hypothetical "logical or" method

or

p foo = false or true

temp = p(foo = false) # => nil
if temp
  temp
else
  true
end

, , false true

[1] pry(main)> p foo = false or true
false
=> true
[2] pry(main)> foo
=> false

p foo = false || true

( , )

p(foo = false.|(true))

, , prints true true

[1] pry(main)> p foo = false || true
true
=> true
[2] pry(main)> foo
=> true
+1

Source: https://habr.com/ru/post/1664732/


All Articles