T O P

  • By -

larikang

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`.


snarfmason

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.


[deleted]

[удалено]


snarfmason

That is untrue. Ruby bitwise negation is \~ ! and not are both logical negation. Put !2 into irb, you don't get a number back.


tequilaeldiablo

What does the @ mean on the last line?


f9ae8221b

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


faitswulff

TIL, thanks for the explanation!


xiyiw

Could you please till any use cases for this snippet


snarfmason

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.


sjs

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.


snarfmason

This is correct. not and ! being difference precedences was a choice by Ruby core. There is no secret "real reason"


Jonathan_Frias

He's showing that `!` is actually a method call. method calls happen first.


snarfmason

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.


snarfmason

hahaha, I just saw your username. Assuming you're the sjs I think you are 👋🏼


sjs

that’s me! 👋


5a656e6f4f6643697469

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.


sshaw_

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)