irb(main):001:0> class Object
irb(main):002:1> def method_missing meth_id
irb(main):003:2> nil
irb(main):004:2> end
irb(main):005:1> end
=> nil
irb(main):006:0> a = String.new
=> ""
irb(main):007:0> a.blah
=> nil
irb(main):008:0> a.blah.whatever
=> nil
irb(main):009:0> a.length
=> 0
irb(main):010:0> a.length.whatever
=> nil
irb(main):011:0>
HTH,
Felix
···
-----Original Message-----
From: John Wells [mailto:lists@sourceillustrated.com]
Sent: Saturday, August 18, 2007 5:37 AM
To: ruby-talk ML
Subject: Emulating a Groovy feature?
PS: Forgot to mention: you can always use the "rescue" modifier:
x = foo.bar.baz rescue nil
···
2007/8/20, Robert Klemme <shortcutter@googlemail.com>:
2007/8/18, John Wells <lists@sourceillustrated.com>:
> Guys,
>
> There's something called Safe Navigation in Groovy (http://groovy.codehaus.org/Statements#Statements-Safenavigation\) that I find very appealing.
>
> So, Groovy will allow you to safely walk an object graph, even if that graph has nulls in it (the walk will short circuit):
>
> def foo = null
> def bar = foo?.something?.myMethod()
> assert bar == null
>
> Is there an easy way to hack an equivalent out in Ruby?
Try this in IRB
class Object
class Holder
def __ref() @ref end
def initialize(ref,&b) @ref = ref
instance_eval(&b)
end
def method_missing(s,*a,&b) @ref = @ref.send(s,*a,&b) rescue nil
self
end
end
def safe(&b)
Holder.new(self,&b).__ref
end
end
F = Struct.new :name
f=F.new "foo"
f.safe { name.size > 10 }
f.safe { name.xxx }
You could use some naming convention as in Groovy as well (which you would check in the body of method_missing), or perhaps wrap the activation of that catchall in a block like this:
with_safe_navigation do
regular code
end
Once you can reopen NilClass like that I think there are ways to emulate that feature.
-- fxn
···
On Aug 18, 2007, at 2:55 PM, Arlen Christian Mart Cuss wrote:
Sure, NilClass can be reopened just fine:
class NilClass
def method_missing(name, *args)
nil
end
end
nil.invoices.find(5) # -> nil
The only problem I can see here is that it's not quite optional.
The value of the expression is replaced by the value of the expression after the "rescue" in this form. And no, you don't need a block. The Pickaxe 1st edition does not seem to mention it but it's definitively a legal Ruby feature.
Kind regards
robert
···
On 21.11.2007 18:24, Jake Cutter wrote:
On Aug 20, 2007 4:07 AM, Robert Klemme <shortcutter@googlemail.com> wrote:
x = foo.bar.baz rescue nil
Interesting thread....glad someone else has hit this need.
How does the above work, exactly? You're rescuing without a block?
Doesn't it have to be something like:
Begin-Rescue-End blocks tend to slow things down significantly - does JUST including rescue also take those penalties to speed?
- Ari Brown
···
On Nov 21, 2007, at 2:40 PM, Robert Klemme wrote:
The value of the expression is replaced by the value of the expression after the "rescue" in this form. And no, you don't need a block. The Pickaxe 1st edition does not seem to mention it but it's definitively a legal Ruby feature.
His conclusions: "Using rescue is not much more expensive than running naked. In my tests in particular, it never was more than 5% slower. It might even be cheaper than multiple tests."
Cheers from NYC,
Luke
···
On Nov 21, 2007, at 2:47 PM, thefed wrote:
Begin-Rescue-End blocks tend to slow things down significantly - does JUST including rescue also take those penalties to speed?
His conclusions: "Using rescue is not much more expensive than running naked. In my tests in particular, it never was more than 5% slower. It might even be cheaper than multiple tests."
It slows down JRuby a bit more than Ruby 1.8, unfortunately, because of the way the JVM manages exception handling and operand stacks. But generally you won't notice it, since nontrivial code bodies will be quite a bit faster than 1.8.
It slows down JRuby a bit more than Ruby 1.8, unfortunately, because of the way the JVM manages exception handling and operand stacks. But generally you won't notice it, since nontrivial code bodies will be quite a bit faster than 1.8.
Actually, it just occurred to me that this is entirely a factor of local variable handling; when rescue is involved, JRuby has to switch from stack-based local variables to heap-based local vars. I'm working on a few ways to mitigate this cost for the general case, so this perf hit may go away.
It seems however that the rescue clause is not part of Ruby1.9
anymore, maybe, if this is confirmed, you might not want to optimize
this.
Cheers
Robert
···
On Nov 23, 2007 10:07 AM, Charles Oliver Nutter <charles.nutter@sun.com> wrote:
Charles Oliver Nutter wrote:
> It slows down JRuby a bit more than Ruby 1.8, unfortunately, because of
> the way the JVM manages exception handling and operand stacks. But
> generally you won't notice it, since nontrivial code bodies will be
> quite a bit faster than 1.8.
Actually, it just occurred to me that this is entirely a factor of local
variable handling; when rescue is involved, JRuby has to switch from
stack-based local variables to heap-based local vars. I'm working on a
few ways to mitigate this cost for the general case, so this perf hit
may go away.
You mean the one line rescue syntax mentioned before? Interesting, I
can't find any docs via Google on this being removed in 1.9. Where are
you finding this info?
Seems strange that such a useful feature would be removed...
···
On 11/23/07, Robert Dober <robert.dober@gmail.com> wrote:
It seems however that the rescue clause is not part of Ruby1.9
anymore, maybe, if this is confirmed, you might not want to optimize
this.
> It seems however that the rescue clause is not part of Ruby1.9
> anymore, maybe, if this is confirmed, you might not want to optimize
> this.
You mean the one line rescue syntax mentioned before? Interesting, I
can't find any docs via Google on this being removed in 1.9. Where are
you finding this info?
From Ruby 1.9 itself
I thought,
But I just cross checked and it works like charm.
Very sorry about the noise.
Cheers
Robert
···
On Nov 23, 2007 3:11 PM, John Wells <lists@sourceillustrated.com> wrote:
On 11/23/07, Robert Dober <robert.dober@gmail.com> wrote:
Seems strange that such a useful feature would be removed...