Forum: Ruby RCR? Added syntax for chains that possibly return nil

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Stefan R. (Guest)
on 2007-07-19 17:18
One type of construct in ruby that somewhat annoys me and IMHO reduces
readability is working around cases where an intermediate method might
return nil. Those cases are e.g.

while (line = gets && line.chomp)
foo = (bar && bar.baz && bar.baz.quuz) || default # bar might be nil, so
might bar.baz and bar.baz.quuz

There are some more constructs, most of you surely already used such
stuff or just spread it onto a bit more of lines.
While all of this is fine, maybe that could be improved. My RCR would be
to introduce a new syntax besides . for method invocation, which on the
first nil aborts any further method calls on it and returns nil.

E.g. the above examples would become:
while line = gets->chomp
foo = bar->baz->quuz || default

-> was the first best that came to my mind, if you have better ideas,
please state.
Unlike e.g. making nil to respond to every method returning self, this
solution would put the coder in power as to where he cares about getting
nil (e.g. he wants an exception if foo is nil, so he just writes
foo.bar, if he doesn't want one, he writes foo->bar) and where he just
wants to get the nil value back.

Do you think this RCR is worth to make?

Regards
Stefan
Eugen Minciu (Guest)
on 2007-07-19 20:20
(Received via mailing list)
Excerpts from Stefan R.'s message of Thu Jul 19 16:31:01 +0300
2007:
> While all of this is fine, maybe that could be improved. My RCR would be
> solution would put the coder in power as to where he cares about getting
> nil (e.g. he wants an exception if foo is nil, so he just writes
> foo.bar, if he doesn't want one, he writes foo->bar) and where he just
> wants to get the nil value back.
>
> Do you think this RCR is worth to make?
>
> Regards
> Stefan
>
how about this ugly creature?

<hack>
class Object
  alias regular_method_missing method_missing
  def method_missing(meth)
    if meth.to_s[0]=='_'[0]
      return nil
    else
      regular_method_missing(meth)
    end
  end
end

puts "yay, it works" unless 3._foo._bar._baz
</hack>

Not exactly like your syntax but gets the job done.

Also, you might want to consider the proper way(tm) of doing it (I
think)

<proper way>

begin
  foo.bar.baz.whatever
rescue
  puts "yay it works"
end

</proper way>

Also works as a one liner:
x = begin 3.foo.bar.baz; rescue; nil; end

--
Eugen Minciu.

Wasting valuable time since 1985.
Stefan R. (Guest)
on 2007-07-19 20:44
Eugen Minciu wrote:
> Excerpts from Stefan R.'s message of Thu Jul 19 16:31:01 +0300
> 2007:
>> While all of this is fine, maybe that could be improved. My RCR would be
>> solution would put the coder in power as to where he cares about getting
>> nil (e.g. he wants an exception if foo is nil, so he just writes
>> foo.bar, if he doesn't want one, he writes foo->bar) and where he just
>> wants to get the nil value back.
>>
>> Do you think this RCR is worth to make?
>>
>> Regards
>> Stefan
>>
> how about this ugly creature?
>
> <hack>
> class Object
>   alias regular_method_missing method_missing
>   def method_missing(meth)
>     if meth.to_s[0]=='_'[0]
>       return nil
>     else
>       regular_method_missing(meth)
>     end
>   end
> end

Interesting idea :) This one won't work right away I think, but it's a
starting point.
Btw., you can do ?_ instead of '_'[0]. Syntax would have the benefit of
optimization, though.

> <proper way>
> begin
>   foo.bar.baz.whatever
> rescue
>   puts "yay it works"
> end

You'd have to rescue NoMethodError, since else you could miss important
exceptions. For the same reason, single line rescue is disqualified. And
with a rescue, it is even less readable than working around the nil case
via multiple lines :-/

Regards
Stefan
Stefan R. (Guest)
on 2007-07-19 20:52
Eugen Minciu wrote:
> <hack>
> class Object
>   alias regular_method_missing method_missing
>   def method_missing(meth)
>     if meth.to_s[0]=='_'[0]
>       return nil
>     else
>       regular_method_missing(meth)
>     end
>   end
> end

Reworked it a bit:
class Object
  alias method_missing_no_underscore method_missing
  def method_missing(m,*a,&b)
    m.to_s[0] == ?_ ? send(m.to_s[1..-1],*a,&b) :
method_missing_no_underscore(m,*a,&b)
  end
end

class NilClass
  alias method_missing_no_underscore method_missing
  def method_missing(m,*a,&b)
    m.to_s[0] == ?_ ? nil : method_missing_no_underscore(m,*a,&b)
  end
end

while line = gets._chomp
...
end

so ._ simulates -> with that hack. Thanks for the idea. Should check for
m.to_s != "_", though, since that method is used e.g. with gettext.

Regards
Stefan
Robert D. (Guest)
on 2007-07-19 20:54
(Received via mailing list)
On 7/19/07, Stefan R. <removed_email_address@domain.invalid> wrote:
> While all of this is fine, maybe that could be improved. My RCR would be
> solution would put the coder in power as to where he cares about getting
> Posted via http://www.ruby-forum.com/.
>
>
Hmm I thought we have had this already, but I do not think somebody
made such a concise proposal yet; I am slightly in favor, but gotta
think a lot about it before giving a definite vote, just wanted to
give you some positive feed back for now...

Robert
gabriele renzi (Guest)
on 2007-07-20 01:32
(Received via mailing list)
On Thu, 19 Jul 2007 22:31:01 +0900, Stefan R. wrote:


> Do you think this RCR is worth to make?

Sorry, I may have missed this in the previous thread, but why an inline
rescue clause is not enough?

i.e.

 while (line = gets && line.chomp)
  foo = (bar && bar.baz && bar.baz.quuz) || default # bar might be nil,
so
 might bar.baz and bar.baz.quuz

could be

 while line = gets.chomp rescue nil
  foo = bar.baz.quuz rescue default
 end

I admit I have a strange feeling about a raising loop condition.. but
something like the second line I wrote many times.

This is slightly longer and gives you a little bit less control,
but I think that complex one-line flow control may be a bad thing.

Just my two cents, obviously.
Stefan R. (Guest)
on 2007-07-20 01:37
gabriele renzi wrote:
> On Thu, 19 Jul 2007 22:31:01 +0900, Stefan R. wrote:
>
>
>> Do you think this RCR is worth to make?
>
> Sorry, I may have missed this in the previous thread, but why an inline
> rescue clause is not enough?

>  while line = gets.chomp rescue nil
>   foo = bar.baz.quuz rescue default
>  end

Simple: what if your exception is not the NoMethodError you are worried
about? You'll never know.
Or less dramatic: a bug may stay in your app unnoticed for longer than
necessary.

Regards
Stefan
Robert D. (Guest)
on 2007-07-20 02:03
(Received via mailing list)
On 7/19/07, Stefan R. <removed_email_address@domain.invalid> wrote:
> >   end
>
>
> so ._ simulates -> with that hack. Thanks for the idea. Should check for
> m.to_s != "_", though, since that method is used e.g. with gettext.
>
> Regards
> Stefan
>
> --
> Posted via http://www.ruby-forum.com/.
>

I hate it, this really should be syntax and furthermore it would make
code ugly ( I know beauty lies in the eyes of the beholder ;).
The original idea is quite good, why your shift?

This is a terrible name pollution amongst other bad things :(

Robert
Stefan R. (Guest)
on 2007-07-20 02:06
Robert D. wrote:
On 7/19/07, Stefan R. <removed_email_address@domain.invalid> wrote:
>> so ._ simulates -> with that hack.

> I hate it, this really should be syntax and furthermore it would make
> code ugly ( I know beauty lies in the eyes of the beholder ;).
> The original idea is quite good, why your shift?
>
> This is a terrible name pollution amongst other bad things :(
>
> Robert

Keyword is "simulate" ;-)
This can help trying it out. And I fully agree, that hack is ugly, also
I wouldn't use it in actual code simply because it is "magic" (you have
to know that _* methods are magic, that's not good for code to be
maintained).

Regards
Stefan
Trans (Guest)
on 2007-07-20 02:24
(Received via mailing list)
On Jul 19, 6:31 am, Stefan R. <removed_email_address@domain.invalid> wrote:
> One type of construct in ruby that somewhat annoys me and IMHO reduces
> readability is working around cases where an intermediate method might
> return nil. Those cases are e.g.
>
> while (line = gets && line.chomp)
> foo = (bar && bar.baz && bar.baz.quuz) || default # bar might be nil, so
> might bar.baz and bar.baz.quuz

what about

  foo = bar.baz.quuz rescue default

T.
Stefan R. (Guest)
on 2007-07-20 02:33
Trans wrote:
> what about
>   foo = bar.baz.quuz rescue default

See the answer to gabriele renzi (Simple: what if your exception is not
the NoMethodError you are worried
about? You'll never know.)

Regards
Stefan
Trans (Guest)
on 2007-07-20 03:19
(Received via mailing list)
On Jul 19, 3:33 pm, Stefan R. <removed_email_address@domain.invalid> wrote:
> Trans wrote:
> > what about
> >   foo = bar.baz.quuz rescue default
>
> See the answer to gabriele renzi (Simple: what if your exception is not
> the NoMethodError you are worried
> about? You'll never know.)

I think it rescues all StandardErrors.

T.
Stefan R. (Guest)
on 2007-07-20 03:34
Trans wrote:
> On Jul 19, 3:33 pm, Stefan R. <removed_email_address@domain.invalid> wrote:
>> Trans wrote:
>> > what about
>> >   foo = bar.baz.quuz rescue default
>>
>> See the answer to gabriele renzi (Simple: what if your exception is not
>> the NoMethodError you are worried
>> about? You'll never know.)
>
> I think it rescues all StandardErrors.
>
> T.

Um, Yes, that's exactly the problem about it, wasn't that clear? It
rescues *all* StandardErrors. So you won't notice if something else than
your NoMethodError - which nil would raise - has happened.
Say your gets raises a BrokenPipe exception or similar since the server
you were connected disconnects you because of bad input you send. Your
will never see an exception being raised since that happens in the gets
you just rescue all standarderrors from.

Regards
Stefan
Stephen D. (Guest)
on 2007-07-20 03:38
(Received via mailing list)
Not sure if the existence of features in other languages is generally
considered a good support for RCR's, but Groovy has this feature:
http://groovy.codehaus.org/Statements#Statements-S... (though
the
syntax can't be borrowed)

-Stephen
Logan C. (Guest)
on 2007-07-20 03:42
(Received via mailing list)
On 7/19/07, Stefan R. <removed_email_address@domain.invalid> wrote:
> stuff or just spread it onto a bit more of lines.
> Unlike e.g. making nil to respond to every method returning self, this
> --
> Posted via http://www.ruby-forum.com/.
>
>
More things should yield on success (and not yield on failure) instead
of
(or in  addition to) returning nil.

def process_line
  gets do |line|
      line.chomp.bar { |o| o.baz }
  end
end

while process_line
end

of course this particular example is much better written as

ARGF.each_line do |line|
   line.chomp ...
end

anyway
Eugen Minciu (Guest)
on 2007-07-20 03:57
(Received via mailing list)
Excerpts from Stefan R.'s message of Fri Jul 20 01:06:13 +0300
2007:
> > Robert
>
> Keyword is "simulate" ;-)
> This can help trying it out. And I fully agree, that hack is ugly, also
> I wouldn't use it in actual code simply because it is "magic" (you have
> to know that _* methods are magic, that's not good for code to be
> maintained).
>
> Regards
> Stefan
>
Hi, again
I've been thinking about this a bit more. Here's another approach you
could try. This actually feels a lot less like a hack.

Advantages:
- no namespace pollution
- clarifies what you're trying to do

Disadvantage:
- every time you call it you add an extra, intermediary call to, well,
  call() :)

However, I'm sure that I'm getting something wrong and, again, you can
simplify this to some extent, and improve it. It's just the idea itself
that I wanted to show you. I'm certain you'll find a way to ditch the
call()

def nilsafe(&blk)
  x=Proc.new { Object.method_missing }
  def method_missing(meth,*args,&blk)
    return nil
  end

  begin
    yield blk
  rescue => e
    def method_missing(meth,*args,&blk)
      x.call(meth,args,&blk)
    end
    raise e
  end

  def method_missing(meth,*args,&blk)
    x.call(meth,args,&blk)
  end
end

So from an IRB prompt, after loading it, you can do:

irb(main):002:0> 3.foo.bar.bz
NoMethodError: undefined method `foo' for 3:Fixnum
        from (irb):2
irb(main):003:0> nilsafe { 3.foo.bar.baz }
=> nil
irb(main):004:0> nilsafe do
irb(main):005:1* 3.foo.bar.baz
irb(main):006:1> raise "Some Error here"
irb(main):007:1> end
RuntimeError: Some Error here
        from (irb):6
        from ./safeattr2.rb:8:in `nilsafe'
        from (irb):4
        from :0

the raise could be changed a little to output some nicer results (using
caller) and other such niceties. But it is late now ... ;)

Let me know what you think of this one
Cheers,

--
Eugen Minciu.

Wasting valuable time since 1985.
Trans (Guest)
on 2007-07-20 04:15
(Received via mailing list)
On Jul 19, 4:35 pm, "Stephen D." <removed_email_address@domain.invalid> wrote:
> Not sure if the existence of features in other languages is generally
> considered a good support for RCR's, but Groovy has this 
feature:http://groovy.codehaus.org/Statements#Statements-S... the
> syntax can't be borrowed)

One could ask for something close:

  bar.?.boo.?.quuz

But that's still pretty ick, though it could do that now with a
regular method.

T.
Trans (Guest)
on 2007-07-20 04:18
(Received via mailing list)
On Jul 19, 4:34 pm, Stefan R. <removed_email_address@domain.invalid> wrote:
> > I think it rescues all StandardErrors.
>
> > T.
>
> Um, Yes, that's exactly the problem about it, wasn't that clear? It
> rescues *all* StandardErrors. So you won't notice if something else than
> your NoMethodError - which nil would raise - has happened.
> Say your gets raises a BrokenPipe exception or similar since the server
> you were connected disconnects you because of bad input you send. Your
> will never see an exception being raised since that happens in the gets
> you just rescue all standarderrors from.

So a better RCR maybe it just to qualify the line rescue.
NoMethodError being the more common, maybe a special rescue for that.
Eg.

  bar.baz.quuz ||| default

T.
Nobuyoshi N. (Guest)
on 2007-07-20 07:46
(Received via mailing list)
Hi,

At Fri, 20 Jul 2007 08:35:20 +0900,
Stephen D. wrote in [ruby-talk:260854]:
> Not sure if the existence of features in other languages is generally
> considered a good support for RCR's, but Groovy has this feature:
> http://groovy.codehaus.org/Statements#Statements-S... (though the
> syntax can't be borrowed)

It reminded me of a patch in `[ruby-dev:28217] ANDCALL
operator'.  It was &? though.

http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/...
Stefan R. (Guest)
on 2007-07-20 14:02
Nobuyoshi N. wrote:
> It reminded me of a patch in `[ruby-dev:28217] ANDCALL
> operator'.  It was &? though.
>
> http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/...

Oh, what does it do, or how to use it? I'm sorry, my japanese doesn't go
beyond hajime and tatame... :-/

Regards
Stefan
Robert D. (Guest)
on 2007-07-20 14:32
(Received via mailing list)
On 7/20/07, Trans <removed_email_address@domain.invalid> wrote:
> > >> the NoMethodError you are worried
> > you were connected disconnects you because of bad input you send. Your
> > will never see an exception being raised since that happens in the gets
> > you just rescue all standarderrors from.
>
> So a better RCR maybe it just to qualify the line rescue.
> NoMethodError being the more common, maybe a special rescue for that.
> Eg.
>
>   bar.baz.quuz ||| default
Hmm I like the expressiveness of the original proposal
look at this example

   bar->baz.foo, which has to be written as
   (bar.baz ||| default).foo

of course one could write
   bar.baz.foo ||| default
but it has more permissive semantics and will hide errors that
  bar->baz.foo
will raise
Robert
Trans (Guest)
on 2007-07-20 17:37
(Received via mailing list)
On Jul 20, 6:29 am, "Robert D." <removed_email_address@domain.invalid> wrote:
> but it has more permissive semantics and will hide errors that
>   bar->baz.foo
> will raise
> Robert

But where is default in your example? You'd have:

  (bar->baz || default).foo

T.
Stefan R. (Guest)
on 2007-07-20 17:47
Trans wrote:
> On Jul 20, 6:29 am, "Robert D." <removed_email_address@domain.invalid> wrote:
>> but it has more permissive semantics and will hide errors that
>>   bar->baz.foo
>> will raise
>> Robert
>
> But where is default in your example? You'd have:
>
>   (bar->baz || default).foo
>
> T.

Maybe you should reread the initial proposal. There is no default.
In receiver->method, if receiver is nil, method won't be invoked and the
expressions value is nil. If the receiver isn't nil, method is invoked
on receiver just as with a normal . - HTH

regards
Stefan
Robert D. (Guest)
on 2007-07-20 17:48
(Received via mailing list)
On 7/20/07, Trans <removed_email_address@domain.invalid> wrote:
> >
>
But -> does not support default, that is a feature of your solution.
I have completely overlooked this :(, the -> notation implies nil as
default.

And you are thus right about the example above, your idea is indeed
powerful :)

Robert
Stefan R. (Guest)
on 2007-07-20 18:16
Robert D. wrote:
> On 7/20/07, Trans <removed_email_address@domain.invalid> wrote:
>> >
>>
> But -> does not support default, that is a feature of your solution.
> I have completely overlooked this :(, the -> notation implies nil as
> default.
>
> And you are thus right about the example above, your idea is indeed
> powerful :)
>
> Robert

Well, default can still be established with ->, just the plain old way:
foo = bar->baz || default # if anywhere in the chain is nil, you get the
default

Regards
Stefan
Trans (Guest)
on 2007-07-20 20:29
(Received via mailing list)
On Jul 20, 7:18 am, Stefan R. <removed_email_address@domain.invalid> wrote:
> > Robert
>
> Well, default can still be established with ->, just the plain old way:
> foo = bar->baz || default # if anywhere in the chain is nil, you get the
> default

Sure. I realize. I'm only pointing out that this -> operator is
equivalent to a rescue NoMethodError, so maybe we just need a way to
specify that better, rather then a whole new dispatcher which can
greatly hurt code readability, IMHO. So a keyword besides 'rescue'
might do the trick, maybe 'default' would be better? I just thru |||
out there b/c of it's similarity to ||. So...

  foo = bar.baz default nil

Another possibility... perhaps we can add a feature to #tap (which has
already been added to Ruby 1.9) so that:

  foo = bar.tap.baz

does the trick.

T.
Stefan R. (Guest)
on 2007-07-20 20:35
Trans wrote:
> Sure. I realize. I'm only pointing out that this -> operator is
> equivalent to a rescue NoMethodError,

So how can I explain to you that it *isn't*?

> Another possibility... perhaps we can add a feature to #tap (which has
> already been added to Ruby 1.9) so that:

Somebody else here on the list uses a method 'ergo' to do what -> would
do. Similar disadvantages as the ._methods solution.

Regards
Stefan
Trans (Guest)
on 2007-07-20 21:19
(Received via mailing list)
On Jul 20, 9:36 am, Stefan R. <removed_email_address@domain.invalid> wrote:
> Trans wrote:
> > Sure. I realize. I'm only pointing out that this -> operator is
> > equivalent to a rescue NoMethodError,
>
> So how can I explain to you that it *isn't*?

Just tell me, how isn't it? The end result seems exactly the same me.
How does:

  foo = (bar.baz default bar).quuz default quux

differ in result from:

  foo = (bar->baz || bar)->quuz || quux

> > Another possibility... perhaps we can add a feature to #tap (which has
> > already been added to Ruby 1.9) so that:
>
> Somebody else here on the list uses a method 'ergo' to do what -> would
> do. Similar disadvantages as the ._methods solution.

Ah, right. I like #ergo, but it's not quite that same as this -> as it
only applied to nil. Wouldn't -> be more like:

  def arrow
    @_op ||= Functor.new{ |op, *args|
      begin
        self.send(op, *args)
      rescue NoMethodError
        nil
      end
    }
  end

T.
ara.t.howard (Guest)
on 2007-07-20 21:25
(Received via mailing list)
On Jul 19, 2007, at 7:31 AM, Stefan R. wrote:

> One type of construct in ruby that somewhat annoys me and IMHO reduces
> readability is working around cases where an intermediate method might
> return nil. Those cases are e.g.

i feel your pain, however i feel that moves towards calling things
and having the side effect ignored will lead to new classes of subtle
bugs.  for instance

   path.gsub! File::SEPARATOR, '\\'

returns nil for no sub for a reason: i may be an error if no
substitution was done...

still, i agree there are cases where i makes sense to chain/ignore

>
> while (line = gets && line.chomp)

while( (line = gets or break).chomp )
end

but i'm just playing devil's advocate there ;-)

> first nil aborts any further method calls on it and returns nil.
> nil (e.g. he wants an exception if foo is nil, so he just writes
> foo.bar, if he doesn't want one, he writes foo->bar) and where he just
> wants to get the nil value back.
>
> Do you think this RCR is worth to make?

it does, but in the meantime we can use something like:

   http://drawohara.tumblr.com/post/6304449



a @ http://drawohara.com/
Nobuyoshi N. (Guest)
on 2007-07-20 21:53
(Received via mailing list)
Hi,

At Fri, 20 Jul 2007 19:02:59 +0900,
Stefan R. wrote in [ruby-talk:260938]:
> > It reminded me of a patch in `[ruby-dev:28217] ANDCALL
> > operator'.  It was &? though.
> >
> > http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/...
>
> Oh, what does it do, or how to use it? I'm sorry, my japanese doesn't go
> beyond hajime and tatame... :-/

In short, same as your proposal.
  (tmp = h[:a] and tmp[:b])
can be without the temproray variable:
  h[:a]&?[:b]

and
  h.a and h.a.b
can be:
  h.a&?b

And a followup was to make nil? to take a block which is
called when the receiver isn't nil.
Stefan R. (Guest)
on 2007-07-20 22:21
Nobuyoshi N. wrote:
> In short, same as your proposal.
>   (tmp = h[:a] and tmp[:b])
> can be without the temproray variable:
>   h[:a]&?[:b]
>
> and
>   h.a and h.a.b
> can be:
>   h.a&?b
>
> And a followup was to make nil? to take a block which is
> called when the receiver isn't nil.

Ah, interesting, so I'm not the first to propose this :)
What was the reason it was rejected?

Regards
Stefan
Trans (Guest)
on 2007-07-20 22:44
(Received via mailing list)
On Jul 20, 10:18 am, Trans <removed_email_address@domain.invalid> wrote:
>
>   foo = (bar.baz default bar).quuz default quux
>
> differ in result from:
>
>   foo = (bar->baz || bar)->quuz || quux

I went back and reread the first post. You actually want it to only be
effective on nil. Okay, I see the basic difference. In my example if
bar.baz returned nil then the default quux would be the result. In
yours it would be bar. However, I'm not sure that's better. I can just
do

   foo = (bar.baz || bar).quuz default quux

to get your behavior. But your technique can not do what mine can.

T.
unknown (Guest)
on 2007-07-20 22:57
(Received via mailing list)
Hi,

At Sat, 21 Jul 2007 03:21:53 +0900,
Stefan R. wrote in [ruby-talk:261012]:
> Ah, interesting, so I'm not the first to propose this :)
> What was the reason it was rejected?

It wasn't rejected, at least explicitly.  Just no response.
Robert D. (Guest)
on 2007-07-21 02:07
(Received via mailing list)
On 7/20/07, Trans <removed_email_address@domain.invalid> wrote:
> >
> effective on nil. Okay, I see the basic difference. In my example if
> bar.baz returned nil then the default quux would be the result. In
> yours it would be bar. However, I'm not sure that's better. I can just
> do
>
>    foo = (bar.baz || bar).quuz default quux
>
> to get your behavior. But your technique can not do what mine can.
>
> T.
>
Yes indeed Stefan your idea is interesting Tom took it a step further,
I do not like either of the syntaxes but these are two bright ideas
nevertheless, I feel that the power of Tom's solution somehow
justifies the syntax.

Ara's point is important too, how big are chances that this syntax
will be abused of?
But it is not as important as it might seem at first sight <ducking>
as we have already shown that there are equivalent language constructs
anyway...
... still thinking.
>
>
Robert
Thomas Gantner (Guest)
on 2007-07-21 02:11
(Received via mailing list)
on Fri 20. July 2007 18.28, Trans wrote:
> ...
>
>   foo = bar.baz default nil
>
> Another possibility...
>
> T.

I prefer this solution to the otherwise also very elegant variant with
'->'.
With 'default' (or '|||' or ...) we can also catch all the syntactically
special methods like '==' '<=>', '[]', all the operators ('&', '*', ...)
etc.

-Thomas
Daniel DeLorme (Guest)
on 2007-07-21 09:13
(Received via mailing list)
Stefan R. wrote:
> Trans wrote:
>> Sure. I realize. I'm only pointing out that this -> operator is
>> equivalent to a rescue NoMethodError,
>
> So how can I explain to you that it *isn't*?

rescue NoMethodError has the same disadvantage as rescue StandardError;
it may catch errors that you did not intend to. e.g.:

foo = Object.new
def foo.bar
   baz()
end

foo.bar->boo
=> NoMethodError: undefined method `baz'

begin
   foo.bar.boo
rescue NoMethodError
end
=> nil

>> Another possibility... perhaps we can add a feature to #tap (which has
>> already been added to Ruby 1.9) so that:
>
> Somebody else here on the list uses a method 'ergo' to do what -> would

That would be me

> do. Similar disadvantages as the ._methods solution.

except with less namespace pollution :-P

I have to admit the -> keyword would be better. With ergo I have to
propagate the check to every step of the call chain:
   a.b.ergo.c.ergo.d.ergo.e
where -> would allow a simple
   a.b->c.d.e
(assuming that you only want to guard against b being nil)

But since other languages (e.g. PHP) use -> for method access, I think
we would see a lot of newbies blindly using -> for all method calls and
then wondering why things go awry. Maybe ".?" would be better? Or maybe
we're over-thinking and this feature isn't really used often enough to
warrant its own operator and a more verbose form like ergo is enough...

Daniel
Robert D. (Guest)
on 2007-07-21 12:16
(Received via mailing list)
On 7/21/07, Daniel DeLorme <removed_email_address@domain.invalid> wrote:
> Stefan R. wrote:
> > Trans wrote:
> >> Sure. I realize. I'm only pointing out that this -> operator is
> >> equivalent to a rescue NoMethodError,
> >
> > So how can I explain to you that it *isn't*?
>
> rescue NoMethodError has the same disadvantage as rescue StandardError;
> it may catch errors that you did not intend to. e.g.:
<snip>
This is a little detail I have overseen in the discussion
-> *is not* equivalent to rescue NoMethodError, if I have understood
correctly

a-> b
is

begin
  a.b
rescue NoMethodError
  raise unless a.nil?
  ===========
end

Robert
This topic is locked and can not be replied to.