[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Re: ruby1.9 block scope

Yukihiro Matsumoto

9/30/2008 6:53:00 PM

Hi,

In message "Re: ruby1.9 block scope"
on Wed, 1 Oct 2008 03:40:08 +0900, Mike Gold <mike.gold.4433@gmail.com> writes:

|> * Class.new and define_method is a rather rare examples, of which
|> non-block counterpart introduce new scopes.
|
|But it's not a rare example for me. It's a great solution to an
|otherwise tangled problem. When I have more time I can post some code
|if my example is not convincing.

<snip rest>

Thank you for your valuable input. And don't worry I have not decided
to put this in the language, even after 2.0.

matz.


9 Answers

Nobuyoshi Nakada

10/1/2008 3:58:00 AM

0

Hi,

At Wed, 1 Oct 2008 03:53:26 +0900,
Yukihiro Matsumoto wrote in [ruby-talk:316501]:
> Thank you for your valuable input. And don't worry I have not decided
> to put this in the language, even after 2.0.

How about making all local variables other than block arguments
method/class/toplevel?

--
Nobu Nakada

Brian Candler

10/1/2008 8:19:00 AM

0

Nobuyoshi Nakada wrote:
> How about making all local variables other than block arguments
> method/class/toplevel?

On the plus side:

def my_find(a)
# res=nil not needed!
a.each { |e| res = e if e =~ /foo/ }
res
end

On the minus side:

m = lambda { |x,y| tmp = x*2; tmp + y }

Here tmp becomes a "static" variable (in C-speak) by default, unless you
write

m = lambda { |x,y;tmp| ... }

I think this could cause hard-to-find bugs if the lambda is invoked from
multiple threads, and a lot of confusion for people expecting functions
written in this form to be side-effect free.

I guess it could become another difference between lambda and
Proc/block. I'm not sure if that would make things less confusing or
more.

I still think the current rule ("tmp is part of the closure if it is
assigned to earlier in the method") is much more sane than the suggested
alternative ("tmp is part of the closure if it is assigned to earlier
*or later* in the method")
--
Posted via http://www.ruby-....

Joe Wölfel

10/1/2008 1:59:00 PM

0


On 1 oct. 08, at 04:18, Brian Candler wrote:

> Nobuyoshi Nakada wrote:
>> How about making all local variables other than block arguments
>> method/class/toplevel?
>
> On the plus side:
>
> def my_find(a)
> # res=nil not needed!
> a.each { |e| res = e if e =~ /foo/ }
> res
> end


res = a.find { |e| e =~ /foo/ }

Brian Candler

10/1/2008 3:26:00 PM

0

Joe Wölfel wrote:
> On 1 oct. 08, at 04:18, Brian Candler wrote:
>
>> end
> res = a.find { |e| e =~ /foo/ }

Yes I know. That's why I called it "myfind". I made a simple concrete
example of a pattern: iterate doing each, assign something during the
iteration, use the assigned value outside of the iteration.

Enumerable#find by itself is not sufficient for all programming needs.
--
Posted via http://www.ruby-....

Joe Wölfel

10/1/2008 3:31:00 PM

0

Agreed. But it would be a stronger example if it were something
that couldn't be done easily without a new language feature.


On 1 oct. 08, at 11:26, Brian Candler wrote:

> Joe W=F6lfel wrote:
>> On 1 oct. 08, at 04:18, Brian Candler wrote:
>>
>>> end
>> res =3D a.find { |e| e =3D~ /foo/ }
>
> Yes I know. That's why I called it "myfind". I made a simple concrete
> example of a pattern: iterate doing each, assign something during the
> iteration, use the assigned value outside of the iteration.
>
> Enumerable#find by itself is not sufficient for all programming needs.
> --=20
> Posted via http://www.ruby-....
>


Suraj Kurapati

10/1/2008 8:29:00 PM

0

Brian Candler wrote:
> def my_find(a)
> # res=nil not needed!
> a.each { |e| res = e if e =~ /foo/ }
> res
> end

IMHO, the res=nil is necessary to preserve the semantics of a closure:

A lambda/closure should *enclose* the variables around it into a neat
package. It should *not* emit new variables into its surroundings!
Otherwise, it would be something like an "opener" instead of a
"closure".

> I still think the current rule ("tmp is part of the closure if it is
> assigned to earlier in the method") is much more sane than the suggested
> alternative ("tmp is part of the closure if it is assigned to earlier
> *or later* in the method")

I agree wholeheartedly and I hope Ruby does not change in this regard.
--
Posted via http://www.ruby-....

Daniel DeLorme

10/2/2008 4:41:00 AM

0

Joe Wölfel wrote:
>
> On 1 oct. 08, at 04:18, Brian Candler wrote:
>>
>> def my_find(a)
>> # res=nil not needed!
>> a.each { |e| res = e if e =~ /foo/ }
>> res
>> end
>
> res = a.find { |e| e =~ /foo/ }

Actually that has a slightly different effect.
Brian's my_find finds the *last* matching expression. ;-)


Daniel DeLorme

10/2/2008 5:27:00 AM

0

Suraj Kurapati wrote:
> Brian Candler wrote:
>> def my_find(a)
>> # res=nil not needed!
>> a.each { |e| res = e if e =~ /foo/ }
>> res
>> end
>
> IMHO, the res=nil is necessary to preserve the semantics of a closure:
>
> A lambda/closure should *enclose* the variables around it into a neat
> package. It should *not* emit new variables into its surroundings!
> Otherwise, it would be something like an "opener" instead of a
> "closure".

If you're thinking in terms of lambdas and anonymous functions then I
can see how you would think that. But I think of blocks more in terms of
control structures. Variables defined inside a "if" or "while" statement
continue existing outside of the if/while, and so should variables
defined inside a block.

I don't deny that that lambdas are useful, but I do think we have a
conflict here: blocks are used both as control structures and as
lambdas, and those two would benefit from having different scoping rules.

--
Daniel


Joe Wölfel

10/2/2008 1:06:00 PM

0

Yes. You are right. In that case might be good to not perform a =20
regular expression match on every element.
res =3D a.reverse.find { |e| e =3D~ /foo/ }

On 2 oct. 08, at 00:41, Daniel DeLorme wrote:

> Joe W=F6lfel wrote:
>> On 1 oct. 08, at 04:18, Brian Candler wrote:
>>>
>>> def my_find(a)
>>> # res=3Dnil not needed!
>>> a.each { |e| res =3D e if e =3D~ /foo/ }
>>> res
>>> end
>> res =3D a.find { |e| e =3D~ /foo/ }
>
> Actually that has a slightly different effect.
> Brian's my_find finds the *last* matching expression. ;-)
>
>