Riddle me this (a question about expressions)

Hi –

On Tue, 26 Sep 2006, Rick DeNatale wrote:

On 9/24/06, [email protected] [email protected] wrote:

end

can’t see anyway to explain the results syntactically other than
saying that the ‘raise … rescue …’ is an rvalue in the assigment.

I still agree with you :slight_smile: I find it interesting to look at what
raise is actually doing/returning, but clearly x gets its 1 from that
whole expression, and there’s no way (that I can see) to drive a wedge
between the calling of raise and the execution of the rescue clause.

I can’t agree.
Neither can I. The rescue modifier is a special dispensation, but
raise is still just a method call and shouldn’t cause a syntax error.

David

I’m still thinking a “stacked” exception might explain the behavior.
When an unrescued raise enters the exception handler, then the further
void assignment exception that you get with return never happens
because the interpreter is already in an exception context and simply
aborts before it sees the next exception (right side of assignment
evaluated first). But if the exception is rescued, the nil return from
raise is assigned (unless the value of the rescue is used, ala Kero’s
example?). With return you simply break out of the context and leave
the assignment dangling, so you get the void assignment exception. That
seems to make sense…

Regards,
Jordan

On 9/25/06, Rick DeNatale [email protected] wrote:

 x = raise rescue 1

And some have expressed the opinion that both should be disallowed.

I can’t agree. I think that the proper documentation of
Kernel#raise/Thread#raise should be that it causes a non-local return
unless it is rescued, in which case the value is the value of the
expression in the rescue. That’s how it works now.

Well, those words are sort of confusing:

begin
@x = raise
rescue
42
end

p @x #=> nil

@x = raise rescue 42

p @x #=> 42

To put the result into better perspective, the binding of = is to the
entire expression including the rescue, which has the result of 42
[1]. This makes much more sense as one could imagine an invisble
wrapper like:

@x = begin raise rescue 42 end

So should raise w/o the rescue be illegal? (no begin/end semantically)

Of course the final arbiter is Matz.

Agreed. I personally think that this is a rather unimportant corner
case. I’m not sure I would change anything myself.

Brian.

[1] Note that:

x = begin
raise
resue
42
end

p x #=> 42

On 9/25/06, Brian M. [email protected] wrote:

rescue
42
end

p @x #=> nil

@x = raise rescue 42

p @x #=> 42

No it’s the same thing. The value of the lvalue in this case is the
value of raise, which since the raise was rescued is 42.

I think that my proposed documentation covers this case.

To put the result into better perspective, the binding of = is to the
entire expression including the rescue, which has the result of 42
[1].

Except in this case the only ‘entire expression’ which includes the
rescue is:

begin; x=raise;rescue; 42;end

And x is not being assigned the value of this expression.

This makes much more sense as one could imagine an invisble
wrapper like:

@x = begin raise rescue 42 end

But I think it makes even more sense to explain the syntax as it is
rather than modifying it.

So should raise w/o the rescue be illegal? (no begin/end semantically)

Too fussy, I think.

raise
resue
42
end

p x #=> 42

Again this is the same case in slightly different clothing.

The value of the begin expression is that of the last statement, which
is the raise expression, …


Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

On 9/25/06, Rick DeNatale [email protected] wrote:

@x = raise
No it’s the same thing. The value of the lvalue in this case is the
value of raise, which since the raise was rescued is 42.

I think that my proposed documentation covers this case.

No it doesn’t. I would say that is was rescued in my example as well.
The language might look like:

Kernel#raise/Thread#raise causes a non-local return unless it is
rescued, in which case the result of the begin…end block is the
result of the expression in the rescue clause.

To put the result into better perspective, the binding of = is to the
entire expression including the rescue, which has the result of 42
[1].

Except in this case the only ‘entire expression’ which includes the rescue is:

begin; x=raise;rescue; 42;end

And x is not being assigned the value of this expression.

Actually, single line rescue has tighter bindings than =. So it would
be like I show.

x = raise rescue 42

becomes:

x = (raise rescue 42)

This makes much more sense as one could imagine an invisble
wrapper like:

@x = begin raise rescue 42 end

But I think it makes even more sense to explain the syntax as it is
rather than modifying it.

That was my attempt. I am explaining that:

x = raise “something” rescue 42

has the same result as:

x = begin raise “something” rescue 42 end

This dispelling any doubt about what other differences might be. We
could safely use such a mechanism mentally if it happened to help us.

So should raise w/o the rescue be illegal? (no begin/end semantically)

Too fussy, I think.

I’m not sure what you mean here. I am trying to say that it is overly
complex to think of raise as an expression which returns. It’s kind of
like trying to get the result of calling a continuation; it doesn’t
return one. It is much easier to use a structured interpretation where
there are begin…end clauses which happen to behave very dependably.

Brian.

Funnily enough, despite having blogged it two weeks ago, I failed to
mention that you can hack around the “void value expression” problem:

def foo
$a = (return 7; 5)
end

p foo #=> 7
p $a #=> nil
END

Devin

On Tue, Sep 26, 2006 at 06:24:38AM +0900, [email protected] wrote:

Hi –

def raise_value

It is; that expression evaluates to 1, and that’s what x gets. But I

I can’t agree.

Neither can I. The rescue modifier is a special dispensation, but
raise is still just a method call and shouldn’t cause a syntax error.

David

I think a more interesting question is, whether or not raise should be
a method. It is a method in, Smalltalk for instance, but Smalltalk also
reifies the callstack. I agree that a method should not cause a syntax
error (in that position), but I’m not
so sure I agree with the idea that raise should be a method. But it
isn’t my baby.

On 2006.09.27 11:18, Devin M. wrote:

Funnily enough, despite having blogged it two weeks ago, I failed to
mention that you can hack around the “void value expression” problem:

You can get around it, yes, but should not. A return
simply is a different kind of beast an the kind of
code that spawned this thread is nonsensical. Why
would one assign the result of an expression that
can never complete (nor do anything useful with
the assignment).

def foo
$a = (return 7; 5)
end

def foo
$a = nil
7
end

Eero S. wrote:

You can get around it, yes, but should not. A return
simply is a different kind of beast an the kind of
code that spawned this thread is nonsensical.
Well, DUH. Thanks for ruining my party.

Personally, I’ll only use return as a cheap guard clause at the top of a
method definition (return “He gently caresses her left shoulder.” unless
you.age > 18) – often it saves a couple lines. Otherwise, I try to get
all functional on everybody’s ass.

Nonetheless, nonsense is fun. Hamhock!

Devin
Or, if you prefer: SPOOOOOOOOOOOOOOON!

Devin M. wrote:

Or, if you prefer: SPOOOOOOOOOOOOOOON!

Heh! Spork! :slight_smile:

+1

Regards,
Jordan

Patrick T. wrote:

will never get set if the function will return cleanly none the less?

def foo()
x = 0
x = if 3 > 4
return 8
else
return 9
end
return x
end

I think the return statement has void context itself

check out this - in fact what you are doing is:

return (return “foo”)

lopex

Patrick T. wrote:

The second declaration doesn’t run at
all. I get a “void value expression” error. Is the runtime looking
into my if statement, realizing that there is no ability for x to get
set and failing?
No. The ‘return’ keyword is one of the few things in Ruby that isn’t an
expression – it doesn’t have a return value. Ruby’s complaining 'cause
you’re trying to set x to it.

Devin