[...] Tom Locke and I have similar proclivities. He says: [...]
This neat hack just popped into my head — something I’ve wanted for ages. But what is it for?
class Object
def _?()
self
end
end
class NilClass
def _?()
SafeNil.new
end
end
class SafeNil
def method_missing(*args, &b)
nil.send(*args, &b) rescue nil
end
end
[...] Tom Locke and I have similar proclivities. He says: [...]
Nice extra trick Daniel. For my money I think I’d rather not have those SafeNil objects floating around my app who knows where.
The usage pattern is that you always call a method directly on the ._?. If you follow that, the SafeNil object is never seen.
You’re right, and my suggested change is wrong, because you need the resulting object to evaluate as false in case it is used as a condition.
AFAIK there’s no way to make an arbitrary object evaluate to false in Ruby. Maybe that would be an interesting Ruby 1.9 extension:
class A
include Falseness
end
then instances of A would evaluate to false in ‘if’ statements.
Interesting idea. I think Python has user-defined ‘truthness’ along these lines.
Good in loose views for missing methods? I dunno. SafeNil makes me nervous…
Awesome! very useful!
2000% speed increase if you define SafeNil this way:
class SafeNil
def method_missing(method, *args, &b)
return nil unless nil.respond_to? method
nil.send(method, *args, &b) rescue nil
end
end
Only problem with this way would be if you define methodmissing on nil to route method calls to it, because then respondto? wouldn’t be accurate
[...] The Ternary Destroyer Filed under: Uncategorized — coderrr @ 6:59 pm I just ran across this Hobo blog post which describes an awesome way to get rid of a lot of use cases for the ternary operator. [...]
Why not just use single-line conditionals?
x = string_or_nil.length unless string_or_nil.nil?
x #=> nil
Or, if you’re looking for compound conditions:
if (not string_or_nil.nil?) && (string_or_nil.length == 4)
This seems like a fair bit of cleverness to avoid making your guard conditions explicit — which seems to me like it could make maintenance more of a pain than it already is.
Also, unlike the ternary operator, this doesn’t allow you to specify a fallback value without using || or some other comparison. Why not this:
x = (string_or_nil && string_or_nil.length) || 6
Other than that, cool Ruby trick.
Coda — all of your examples have one thing in commen that this operator was specifically intended to avoid. string_or_nil occurs twice.
The places where I use _? are where I don’t have the value in a local variable, and I don’t want to assign it to one just because I have an operation to perform “only if the value is not nil”. e.g.
if Foo.expensive_method_call._?.closed?
...
I see this pattern all the time in my code and I really enjoy not having to make the code more verbose. To me this reads like a spec, once you’ve internalised the simple _? operator.
[...] Monkey-patching proposals have abounded in the Ruby community recently – including, but not limited to Object#andand, Object#? and SafeNil and Object#method. [...]
[...] The above code is taken from this post The post didn’t mention io, but I assumed it is inspired by it. In ruby you can’t just use the “?” for your method name, therefore, _ is prepended before “?”.Now you can do following without checking the parent object: offer.?.price.?.formatted_amount [...]
[...] I came across a few other alternatives that were entertaining the idea of using method_missing, but let’s [...]
stringornil._?.length
Cute. Suggestion:
Then
stringornil._?.length * 4
I call mine null:
class Object
def null
n = Object.new
def null.method_missing(name, *args)
null
end
n
end
end
(stringornil||null).length * 4
best,
Dan