RCR? Added syntax for chains that possibly return nil

On 7/20/07, Trans [email protected] 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

On Jul 20, 6:29 am, “Robert D.” [email protected] 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.

Trans wrote:

On Jul 20, 6:29 am, “Robert D.” [email protected] 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

On 7/20/07, Trans [email protected] 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 :slight_smile:

Robert

Robert D. wrote:

On 7/20/07, Trans [email protected] 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 :slight_smile:

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

On Jul 20, 7:18 am, Stefan R. [email protected] 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.

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

On Jul 20, 9:36 am, Stefan R. [email protected] 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.

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

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/

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/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.

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 :slight_smile:
What was the reason it was rejected?

Regards
Stefan

On Jul 20, 10:18 am, Trans [email protected] 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.

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 :slight_smile:
What was the reason it was rejected?

It wasn’t rejected, at least explicitly. Just no response.

On 7/20/07, Trans [email protected] 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
as we have already shown that there are equivalent language constructs
anyway…
… still thinking.

Robert

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

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

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

On 7/21/07, Daniel DeLorme [email protected] 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.:

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