Feature #11034
closedNil Conditional
Description
Hi everyone !
Some time ago I was thinking about Nil Conditional Operator in Ruby (??
). This would be particularly useful to avoid frequent checking for nil, and should behave and look like Null Conditional Operator introduced in C# 6.0.
I was thinking about something like this (assume var
is nil or doesn't exist):
var??.method1.method2(123, 345).method3 { |i| i == 1 }
=> nil
When var
is nil or doesn't exist, code above should return nil or NilConditionalClass object instead of raising NoMethodError or NameError.
This can also work with methods (assume var
exists):
var.method1??.method2(a, b)
=> nil
When var
exists and can receive method1
, but method1
returns nil - this shouldn return nil instead of raising NoMethodError: undefined method
method2' for nil:NilClass`
When var
exists and is not nil, and can receive method1
, and object returned by method1
can receive method2
this, of course should behave as expected (like version without ??
operator) and return value according to implementation of method2.
When var
doesn't exist - this should raise NameError.
I tried to create gem for that (https://github.com/grzesiek/nil-conditional) but from now on, only native implementation seems reasonable.
What do you think about that feature ? Maybe it is already considered, but I couldn't find anything similar at Google/this issue tracker (in that case I'm sorry for duplicate).
Thanks in advance for feedback !
Kind regards,
Grzegorz
Updated by nobu (Nobuyoshi Nakada) over 9 years ago
- Description updated (diff)
A local variable written in code always exists.
I think this is a duplicate ticket but can't find the former tickets.
Updated by nobu (Nobuyoshi Nakada) over 9 years ago
IIRC, there were some discussions like:
- the condition is only whether
nil
or not, or whether responds to the method or not - the result when the condition doesn't match will be the receiver itself or
nil
and others.
Also, I'm afraid that ??
would conflict with the current syntax.
Updated by grzesiek (Grzegorz Bizon) over 9 years ago
Hi Nobuyoshi, thanks for reply !
Yes, this Nil Conditional Operator has to introduce new syntax. That is why this cannot be achieved via gem. Currently - of course - double question mark ?? violates syntax (in some cases) or is treated as tenary operator. But this doesn't have to be ??.
I also agree that my version of nil conditional is too permissive and shouldn't return nil if variable does not exist. This was just less difficult to implement ;)
I simply believe that Nil Conditional Operator would be useful for every rubyist. In my opinion it is worth talking over, considering.
I will try to find related issue.
Kind regards,
Grzegorz
Updated by recursive-madman (Recursive Madman) over 9 years ago
This is similar to a pattern I have seen somewhere else:
var = 123.4
var.try.round #=> 123
var = nil
var.try.round #=> nil
Which doesn't introduce a new operator and can be implemented like this:
class Object
def try
self
end
end
class NilClass
def try
IgnoreCall.new
end
class IgnoreCall
def method_missing(*a)
nil
end
end
end
By the way, fun fact:
?????:?? #=> '?'
Updated by grzesiek (Grzegorz Bizon) over 9 years ago
@Recursive Madman - try is not native function. It is Active Support Core Extension.
Moreover implementation and behavior of try is not stable (is changing depending on Rails version), it will not work when creating train wrecks and is terribly ugly.
Of course - this can be, in some specific way, achieved by using gem (like nil_conditional gem), but, in my opinion, only native implementation will be reasonable enough. Only native solution for that problem will be stable, consistent, short and concise.
What do you think ?
Kind regards,
Grzegorz
Updated by akr (Akira Tanaka) over 9 years ago
- Related to Feature #1122: request for: Object#try added
Updated by grzesiek (Grzegorz Bizon) over 9 years ago
Hi again !
I've made new attempt to create nil conditional operator (https://github.com/nil-conditional). This is Ruby implementation, you can check it out here: https://github.com/grzesiek/nil-conditional/blob/master/lib/nil_conditional.rb.
It is simple, it encapsulates objects in NilConditional instance. Sample usage:
def nil_test(str)
str._?.concat("456")
end
nil_test("123")
=> "123456"
nil_test(nil)
=> #<NilConditional:0x007fc602016718 @object=nil>
nil_test(nil).nil?
=> true
What do you think about that ? It seems (for me) that this is sufficient, and native implementation is not necessary with this approach.
Anyway, thanks for feedback !
Kind regards,
Grzegorz
Updated by akr (Akira Tanaka) about 9 years ago
- Related to Feature #11537: Introduce "Safe navigation operator" added
Updated by matz (Yukihiro Matsumoto) about 9 years ago
- Status changed from Open to Closed
We will introduce .?
#11537 which address this proposal.
Matz.