RCR? Added syntax for chains that possibly return nil

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

···

--
Posted via http://www.ruby-forum.com/.

Excerpts from Stefan Rusterholz's message of Thu Jul 19 16:31:01 +0300 2007:

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

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.

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

···

On 7/19/07, Stefan Rusterholz <apeiros@gmx.net> 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

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

--
Posted via http://www.ruby-forum.com/\.

--
I always knew that one day Smalltalk would replace Java.
I just didn't know it would be called Ruby
-- Kent Beck

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.

···

On Thu, 19 Jul 2007 22:31:01 +0900, Stefan Rusterholz wrote:

Do you think this RCR is worth to make?

--
goto 10: http://www.goto10.it
blog it: http://riffraff.blogsome.com
blog en: http://www.riffraff.info

what about

  foo = bar.baz.quuz rescue default

T.

···

On Jul 19, 6:31 am, Stefan Rusterholz <apei...@gmx.net> 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

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-Safenavigation (though the
syntax can't be borrowed)

-Stephen

···

On 7/19/07, Stefan Rusterholz <apeiros@gmx.net> 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

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

--
Posted via http://www.ruby-forum.com/\.

--
Stephen Duncan Jr

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

···

On 7/19/07, Stefan Rusterholz <apeiros@gmx.net> 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

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

--
Posted via http://www.ruby-forum.com/\.

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 :wink:

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?

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

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

a @ http://drawohara.com/

···

On Jul 19, 2007, at 7:31 AM, Stefan Rusterholz wrote:
--
we can deny everything, except that we have the possibility of being better. simply reflect on that.
h.h. the 14th dalai lama

Eugen Minciu wrote:

Excerpts from Stefan Rusterholz'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 :slight_smile: 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

···

--
Posted via http://www.ruby-forum.com/\.

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

···

--
Posted via http://www.ruby-forum.com/\.

gabriele renzi wrote:

···

On Thu, 19 Jul 2007 22:31:01 +0900, Stefan Rusterholz 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

--
Posted via http://www.ruby-forum.com/\.

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

···

--
Posted via http://www.ruby-forum.com/\.

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.

···

On Jul 19, 4:35 pm, "Stephen Duncan" <stephen.dun...@gmail.com> 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-Safenavigation\(though the
syntax can't be borrowed)

Hi,

At Fri, 20 Jul 2007 08:35:20 +0900,
Stephen Duncan 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-Safenavigation (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/ruby-dev/28217

···

--
Nobu Nakada

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

--
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 :frowning:

Robert

···

On 7/19/07, Stefan Rusterholz <apeiros@gmx.net> wrote:

--
I always knew that one day Smalltalk would replace Java.
I just didn't know it would be called Ruby
-- Kent Beck

I think it rescues all StandardErrors.

T.

···

On Jul 19, 3:33 pm, Stefan Rusterholz <apei...@gmx.net> 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.)

Nobuyoshi Nakada 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/ruby-dev/28217

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

Regards
Stefan

···

--
Posted via http://www.ruby-forum.com/\.

Robert Dober 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 :frowning:

Robert

Keyword is "simulate" :wink:
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

···

On 7/19/07, Stefan Rusterholz <apeiros@gmx.net> wrote:

--
Posted via http://www.ruby-forum.com/\.

Trans 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

···

On Jul 19, 3:33 pm, Stefan Rusterholz <apei...@gmx.net> wrote:

--
Posted via http://www.ruby-forum.com/\.

Hi,

At Fri, 20 Jul 2007 19:02:59 +0900,
Stefan Rusterholz 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/ruby-dev/28217

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.

···

--
Nobu Nakada