From: "MaxLap (Maxime Lapointe) via ruby-core" <ruby-core@...> Date: 2024-05-20T13:02:52+00:00 Subject: [ruby-core:117940] [Ruby master Feature#20498] Negated method calls Issue #20498 has been updated by MaxLap (Maxime Lapointe). Thanks for the feedback. I updated the gist to have an example with arguments in the call: ```ruby puts A.new.!exists?(with_friends: true, skip_administrator: true) ``` This highlights some problems with the alternatives: * Calls at the end (such as `.!` or `.not`) are very easy to miss if there are arguments given to the method. The longer the args, the most likely to be missed: ```ruby puts A.new.exists?(with_friends: true, skip_administrator: true).! puts A.new.exists?(with_friends: true, skip_administrator: true).not ``` * Using a no block (ex: `foo.!(&:exists?)`) as ufuk (Ufuk Kayserilioglu) suggested is no longer clean looking. The extra syntax ends up almost hiding the `!`: ```ruby foo.!{ _1.exists?(with_friends: true, skip_administrator: true) } ``` --- About `p "".non.empty?`: I personally dislike this pattern because there is a clear performance cost to it (extra method call & creating an object). As a result, whenever I would have to use it, I would wonder if the cleaner looking code is worth it knowing it's wasteful at the same time. (I know it's not much, but it's enough for me to ask myself each time, I dislike Rails' `.not.where` pattern since it could have simply been `not_where` or `where_not`.) @nobu: I'd say it's both syntax sugar and an operator, just like `&.`. ---------------------------------------- Feature #20498: Negated method calls https://bugs.ruby-lang.org/issues/20498#change-108355 * Author: MaxLap (Maxime Lapointe) * Status: Open ---------------------------------------- I want to propose the following syntax: `foo.!bar`. I know it's already valid syntax, but please read on for details. When someone write a somewhat long line of code that is negated, the main way I've seen of doing it is: ``` must_create_user = !User.where(somelong: :condition, even_more: "thing").exists? ``` I personally highly dislike it, as I must keep the "not" in the back of my mind as I read the line. When quickly reading a line like this, it's super easy to misread and understand the opposite result. The current ways around this I can think of are: * rename the variable (can be annoying) * Use `unless` (only possible when in a condition; some people, like me, have a hard time grapsping a `unless`) * use a `.!`in the end (`foo.exists?.!`), I've never seen that and it looks ugly to me (this is subjective). * create a new method name with the negated meaning (not always possible) My proposal would look like this: ``` must_create_user = User.where(somelong: :condition, even_more: "thing").!exists? ``` You cannot forget the bang that you saw 15 words ago, it's right there. It also basically reads as English: "user where ... doesn't exists". The main argument against this I can think of is that it's technically already a valid syntax. I believe it's frowned upon to override the bang operator and I'm not aware of places where it is overridden to with also having a parameter. I made a prototype in RubyNext, which you can try here: https://ruby-next.github.io/#gist:0e133bf6f27f2437193dc034d58083dc -- https://bugs.ruby-lang.org/ ______________________________________________ ruby-core mailing list -- ruby-core@ml.ruby-lang.org To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org ruby-core info -- https://ml.ruby-lang.org/mailman3/postorius/lists/ruby-core.ml.ruby-lang.org/