Bug in lambda?

W

Wilson Bilkovich

Hi --



I don't think so, but part of the problem for me is that there's no
problem -- in other words, I learned that it works with assignment
syntax, and probably haven't made all that much use of it but never
thought there was any reason for it *not* to work that way. I suppose
it's possible to clobber variables, but then it's possible to do that
without blocks, too, if you're not careful about variable names.

I think that the original poster was worried that this script would
print "7". If that's not the case, forgive me. :)

def do_it x, f
f.call 7
p x
end

f = lambda {|x| x}
do_it 1, f

The existing behavior seems much scarier in IRB than in 'real' code.
 
R

Robert Klemme

I think that the original poster was worried that this script would
print "7". If that's not the case, forgive me. :)

def do_it x, f
f.call 7
p x
end

f = lambda {|x| x}
do_it 1, f

What output would you prefer? I don't see how this can print "7" if
that's what you were up to. In fact, I would be scared to see that. :)

Actually the original issue was different IIRC, because the block was
defined in a scope which had the block parameter as a local variable
which is not the case in your example.

Kind regards

robert
 
R

Robert Klemme

Hi --



I don't think so, but part of the problem for me is that there's no
problem -- in other words, I learned that it works with assignment
syntax, and probably haven't made all that much use of it but never
thought there was any reason for it *not* to work that way. I suppose
it's possible to clobber variables, but then it's possible to do that
without blocks, too, if you're not careful about variable names.

Ah, ok. I suspected you had some cool usage for this which I overlooked
and could insert into my repertoire. :)

As you say, there are many ways to shoot yourself in the foot - block
parameters are just one of them.

Kind regards

robert
 
L

Logan Capaldo

I note no one has addressed my concern. I feel like there's an
elephant in the room that only I can see :)
 
R

Robert Klemme

2007/9/11 said:
I note no one has addressed my concern. I feel like there's an
elephant in the room that only I can see :)

I only see an otter. :) I can see how block parameter's scoping rules
creates the issue you demonstrated but IMHO the problem is not limited
to block parameters. As David said already, you will shoot yourself in
the foot if you do not take care when naming variables. I do agree
though that the current block parameter semantics make the situation
worse although I would not go as far as to forbid recursive block
invocations. Still, I think it is a good idea that this is being
worked on.

Kind regards

robert
 
P

Peña, Botp

From: Robert Klemme [mailto:[email protected]]=20
# Actually the original issue was different IIRC, because the block was=20
# defined in a scope which had the block parameter as a local variable=20
# which is not the case in your example.

nonetheless, it is still dangerous on procs/lambda
these block arg var creeping scope just adds to the confusion and danger

simple example (got this fr avi's post),

botp@pc4all:~$ irb
irb(main):001:0>
irb(main):002:0* x=3D"this is a test"
=3D> "this is a test"
irb(main):003:0> fac =3D lambda{|x| if x =3D=3D 0 then 1 else fac.call(x =
- 1) * x end}
=3D> #<Proc:0xb7dcda90@(irb):3>
irb(main):004:0> puts fac.call(3)
0
=3D> nil
irb(main):005:0> quit
botp@pc4all:~$ irb
irb(main):001:0> fac =3D lambda{|x| if x =3D=3D 0 then 1 else fac.call(x =
- 1) * x end}
=3D> #<Proc:0xb7d6542c@(irb):1>
irb(main):002:0> puts fac.call(3)
6
=3D> nil

kind regards -botp
 
P

Peña, Botp

From: Robert Klemme [mailto:[email protected]]=20
# On 10.09.2007 16:52, (e-mail address removed) wrote:
# > I don't think so, but part of the problem for me is that there's no
# > problem -- in other words, I learned that it works with assignment
# > syntax, and probably haven't made all that much use of it but never
# > thought there was any reason for it *not* to work that way.=20
# I suppose
# > it's possible to clobber variables, but then it's possible=20
# to do that
# > without blocks, too, if you're not careful about variable names.
#=20
# Ah, ok. I suspected you had some cool usage for this which I=20
# overlooked and could insert into my repertoire. :)

irb(main):001:0> require 'with_index'
=3D> true
irb(main):002:0> a=3D[1,2,3,4]
=3D> [1, 2, 3, 4]
irb(main):007:0> i=3Dnil
=3D> nil
irb(main):008:0> a+=3D1 until a.all_w_index?{|x,i| x>3}
=3D> nil
irb(main):009:0> a
=3D> [4, 4, 4, 4]

note, that i modified #all? so i will know where the trigger was
same also with #any?..

irb(main):010:0> a=3D[1,2,3,4,5]
=3D> [1, 2, 3, 4, 5]
irb(main):011:0> a+=3D1 while a.any_w_index?{|x,i| x<4}
=3D> nil
irb(main):012:0> a
=3D> [4, 4, 4, 4, 5]

but you can do same w scratch vars
though w an added assignment, i find it clearer..

irb(main):029:0> a=3D[1,2,3,4,5]
=3D> [1, 2, 3, 4, 5]
irb(main):030:0> even=3Dnil
=3D> nil
irb(main):031:0> a[even]+=3D1 while a.any_w_index?{|x,i| even=3Di; =
x%2=3D=3D0}
=3D> nil
irb(main):032:0> a
=3D> [1, 3, 3, 5, 5]
irb(main):033:0> odd=3Dnil
=3D> nil
irb(main):034:0> a[odd]+=3D1 while a.any_w_index?{|x,i| odd=3Di; =
x%2!=3D0}
=3D> nil
irb(main):035:0> a
=3D> [2, 4, 4, 6, 6]


the idioms would be likened to,=20

part =3D nil
machine.repair(part) while machine.any?{|part| part.broken?}

and

broken =3D nil
machine.repair(broken) while
machine.any?{|part| (broken=3Dpart).broken?}

so that is,

"repair part while there is any part broken"
vs
"repair broken part while there is any part broken"

your choice.

# As you say, there are many ways to shoot yourself in the foot - block=20
# parameters are just one of them.

Arggh, the scary part is you wont even know if you've been shot until =
you're dead --too late. I myself do not like block args (or any args for =
that matter) clobbering local, global, and instance vars. Surely, it is =
not the intent of the programmer to clobber them, nor is it an intuitive =
intent to peek on arg values from the outside (is that being =
obj-oriented?). I clobber what i clobber. When coding an arg var, surely =
i do not need to bother and question myself "will this var clobber other =
vars?". Ruby should help me on that, not put fear on it. I wonder what =
is the original intent of matz when he designed that feature. It is =
scary. I've been hit by it. And now i have to be careful about naming my =
vars. Is shadowing arg vars really used much in practice? It is not a =
fun part of ruby if you ask me. or maybe, it is just too much fun for =
me. forgive the non-ruby-hacker, pls :( =20

kind regards -botp
 
D

dblack

--1926193751-1012482009-1189512197=:9810
Content-Type: MULTIPART/MIXED; BOUNDARY="1926193751-1012482009-1189512197=:9810"

This message is in MIME format. The first part should be readable text,
while the remaining parts are likely unreadable without MIME-aware tools.

--1926193751-1012482009-1189512197=:9810
Content-Type: TEXT/PLAIN; charset=X-UNKNOWN; format=flowed
Content-Transfer-Encoding: QUOTED-PRINTABLE

Hi --

Arggh, the scary part is you wont even know if you've been shot
until you're dead --too late. I myself do not like block args (or
any args for that matter) clobbering local, global, and instance
vars. Surely, it is not the intent of the programmer to clobber
them, nor is it an intuitive intent to peek on arg values from the
outside (is that being obj-oriented?). I clobber what i clobber.
When coding an arg var, surely i do not need to bother and question
myself "will this var clobber other vars?". Ruby should help me on
that, not put fear on it. I wonder what is the original intent of
matz when he designed that feature. It is scary. I've been hit by
it. And now i have to be careful about naming my vars.

Is that bad? :)
Is shadowing
arg vars really used much in practice? It is not a fun part of ruby
if you ask me. or maybe, it is just too much fun for me. forgive the
non-ruby-hacker, pls :(

But you always have to avoid clobbering variables:

x =3D 1
...
...
x =3D gets
...
if x > 0 # blows up

I think the only hurdle is just realizing that:

{|x| ... }

is an assignment to x. After that, it's no more dangerous or
error-prone than any other occasion when you have to choose a name for
a temporary (or not) variable and assign to it.


David

--=20
* Books:
RAILS ROUTING (new! http://www.awprofessional.com/title/0321509242)
RUBY FOR RAILS (http://www.manning.com/black)
* Ruby/Rails training
& consulting: Ruby Power and Light, LLC (http://www.rubypal.com)
--1926193751-1012482009-1189512197=:9810--
--1926193751-1012482009-1189512197=:9810--
 
L

Logan Capaldo

I think the only hurdle is just realizing that:

{|x| ... }

is an assignment to x. After that, it's no more dangerous or
error-prone than any other occasion when you have to choose a name for
a temporary (or not) variable and assign to it.
It's not though. It's _almost_ like an assignment to x, except when
it's like passing a parameter. If it really was always just assigning
to x, my example would overflow in both cases, which while not my
personal ideal, would make me happier than the current situation.
 
R

Robert Klemme

2007/9/12 said:
It's not though. It's _almost_ like an assignment to x, except when
it's like passing a parameter. If it really was always just assigning
to x, my example would overflow in both cases, which while not my
personal ideal, would make me happier than the current situation.

Actually I believe David is right. It *is* just an assignment to x
but you have to keep in mind the scoping rules of blocks. Basically
the notation |x| is just a shortcut for an assignment with a parameter
when the block is called. But the general scoping rule for local
variables in blocks is that they are block local when not defined
outside of the block. This is the same regardless whether a var name
occurs between bars or on the left side of an assignment.

Kind regards

robert
 
L

Logan Capaldo

Actually I believe David is right. It *is* just an assignment to x
but you have to keep in mind the scoping rules of blocks. Basically
the notation |x| is just a shortcut for an assignment with a parameter
when the block is called. But the general scoping rule for local
variables in blocks is that they are block local when not defined
outside of the block. This is the same regardless whether a var name
occurs between bars or on the left side of an assignment.
I'm pretty sure everything you said is factual. I still think it's wrong.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,776
Messages
2,569,603
Members
45,189
Latest member
CryptoTaxSoftware

Latest Threads

Top