Issue #11816 has been updated by Marc-Andre Lafortune.


Glad to see we're headed towards having `x&.foo.bar` not be the same as `(x&.foo).bar`.

When we ask about `&.` vs operators, we can see that the question is similar to that of precedence, right? We could say that currently in trunk, `&.` has same "precedence" as `.`, which we now agree is not ideal. We need to bump `&.` down at least one level.

So either `&.` has a "precedence" just lower than `.`, or we (well, Matz) decide to make it even lower.

My guess is that the ideal would if `&.` has a "precedence" in between comparison operators (<, >=, ...) and equality operators (==, <=>, ...)

This way:

    x = nil
    x&.foo.bar # => nil
    x&.foo[42] # => nil
    x&.foo[42] = 43 # => nil
    x&.foo * 42 # => nil 
    x&.foo + 42 # => nil
    x&.foo << 42 # => nil
    x&.foo < 42 # => nil
    x&.foo == 42 # => false     ### This is where the precedence of &. is higher
    x&.foo || 42 # => 42
    x&.foo ? 1 : 2  # => 2

My reasoning is that this divides the operators cleanly into those that we never want to apply to `nil` (e.g. `+`), from those that can be applied to it (e.g. `||`).


----------------------------------------
Bug #11816: Partial safe navigation operator
https://bugs.ruby-lang.org/issues/11816#change-55568

* Author: Marc-Andre Lafortune
* Status: Open
* Priority: Normal
* Assignee: Yukihiro Matsumoto
* ruby -v: preview 2
* Backport: 2.0.0: UNKNOWN, 2.1: UNKNOWN, 2.2: UNKNOWN
----------------------------------------
I'm extremely surprised (and disappointed) that, currently:

    x = nil
    x&.foo.bar # => NoMethodError: undefined method `bar' for nil:NilClass

To make it safe, you have to write `x&.foo&.bar`. But if `foo` is never supposed to return `nil`, then that code isn't "fail early" in case it actually does. `nil&.foo.bar` is more expressive, simpler and is perfect if you want to an error if `foo` returned `nil`. To actually get what you want, you have to resort using the old form `x && x.foo.bar`...

In CoffeeScript, you can write `x()?.foo.bar` and it will work well, since it gets compiled to

    if ((_ref = x()) != null) {
      _ref.foo.bar;
    }

All the discussion in #11537 focuses on `x&.foo&.bar`, so I have to ask:

Matz, what is your understanding of `x&.foo.bar`?

I feel the current implementation is not useful and should be changed to what I had in mind. I can't see any legitimate use of `x&.foo.bar` currently.




-- 
https://bugs.ruby-lang.org/