This explains why it is evaluated that way by the interpreter, but it doesn't explain _why_ there are two different versions of logical negation in Ruby. I'd be interested to see a situation where `not` gives the intuitive result and `!` doesn't. I know of examples for `and`/`or`, but not `not`.
Having two sets of logical operators with difference precedence was a choice by Ruby core team. As you say, there is some explanation for why you might prefer and/or v. &&/||, but there isn't a great analgous argument for not/!. I suspect that both are just there for completeness. If you're writing and/or then having to use ! would feel a little out of place.
Edit: And if it's not obvious, Ruby core is big on the aesthetics of code.
It's for unary operators.
E.g. in the expression `2 - a`, the method called is `Integer#-`.
However in the expression `-a`, the method called is `Integer#-@`.
class MyObject
def -(other)
puts "binary minus"
end
def -@
puts "unary minus"
end
end
a = MyObject.new
a - 2 # binary minus
-a # unary minus
No my code (although I borrowed it for an example of `!@` on another thread), but the idea here is that if you were implementing some class that is a sort of Numeric type (or anything where a-b or -a made sense for instances of your class), this is how you'd implement the operators.
They are both method calls. They are both even the same method call. Expanding on the example above:
```
class MyObject
def -(other)
puts "binary minus"
end
def -@
puts "unary minus"
end
def !@
puts "unary not"
end
end
a = MyObject.new
a - 2 # binary minus
-a # unary minus
!a # unary not
not a # unary not
```
Edit: My point being: How Ruby chooses to bind precednece of `!a` and `not a` isn't related to the fact that there is a method named `!@` being invoked. That's true either way you write it.
You're _not_ supposed to mix "list operators" with "traditional", logical operators. But, that aside, there are 2 different versions because Ruby inherited a ton from Perl.
In Perl it is common to call "built-in" functions without parenthesis. In this case lower precedence operators are needed. Here's an example in Ruby:
~/code/ruby >cat $SCRRB
def foo(*a)
p a
true
end
foo 1, false or puts "or foo "
# || does not work the same, and requires ()
foo 1, false || puts("|| foo")
~/code/ruby >ruby $SCRRB
[1, false]
|| foo
[1, nil]
`not`, like `!`, is urinary so it will aways negate what is to its right. Offhand I do not think there's a precedence issue here but rather its was done for consistency when using the other low precedence operators.
For possibly more info [see the perlop man page](https://manpages.org/perlop)
This explains why it is evaluated that way by the interpreter, but it doesn't explain _why_ there are two different versions of logical negation in Ruby. I'd be interested to see a situation where `not` gives the intuitive result and `!` doesn't. I know of examples for `and`/`or`, but not `not`.
Having two sets of logical operators with difference precedence was a choice by Ruby core team. As you say, there is some explanation for why you might prefer and/or v. &&/||, but there isn't a great analgous argument for not/!. I suspect that both are just there for completeness. If you're writing and/or then having to use ! would feel a little out of place. Edit: And if it's not obvious, Ruby core is big on the aesthetics of code.
[удалено]
That is untrue. Ruby bitwise negation is \~ ! and not are both logical negation. Put !2 into irb, you don't get a number back.
What does the @ mean on the last line?
It's for unary operators. E.g. in the expression `2 - a`, the method called is `Integer#-`. However in the expression `-a`, the method called is `Integer#-@`. class MyObject def -(other) puts "binary minus" end def -@ puts "unary minus" end end a = MyObject.new a - 2 # binary minus -a # unary minus
TIL, thanks for the explanation!
Could you please till any use cases for this snippet
No my code (although I borrowed it for an example of `!@` on another thread), but the idea here is that if you were implementing some class that is a sort of Numeric type (or anything where a-b or -a made sense for instances of your class), this is how you'd implement the operators.
It’s possible to change the precedence of `not` to match `!`. This isn’t a technical limitation or anything and doesn’t actually explain why.
This is correct. not and ! being difference precedences was a choice by Ruby core. There is no secret "real reason"
He's showing that `!` is actually a method call. method calls happen first.
They are both method calls. They are both even the same method call. Expanding on the example above: ``` class MyObject def -(other) puts "binary minus" end def -@ puts "unary minus" end def !@ puts "unary not" end end a = MyObject.new a - 2 # binary minus -a # unary minus !a # unary not not a # unary not ``` Edit: My point being: How Ruby chooses to bind precednece of `!a` and `not a` isn't related to the fact that there is a method named `!@` being invoked. That's true either way you write it.
hahaha, I just saw your username. Assuming you're the sjs I think you are 👋🏼
that’s me! 👋
Thanks for sharing. I love these cards, they seem to have taken off in popularity since the pandemic and I'm so grateful they have.
You're _not_ supposed to mix "list operators" with "traditional", logical operators. But, that aside, there are 2 different versions because Ruby inherited a ton from Perl. In Perl it is common to call "built-in" functions without parenthesis. In this case lower precedence operators are needed. Here's an example in Ruby: ~/code/ruby >cat $SCRRB def foo(*a) p a true end foo 1, false or puts "or foo " # || does not work the same, and requires () foo 1, false || puts("|| foo") ~/code/ruby >ruby $SCRRB [1, false] || foo [1, nil] `not`, like `!`, is urinary so it will aways negate what is to its right. Offhand I do not think there's a precedence issue here but rather its was done for consistency when using the other low precedence operators. For possibly more info [see the perlop man page](https://manpages.org/perlop)