Default argument values for blocks

D

David A. Black

Hi --

Hi,

In message "Re: Default argument values for blocks"

|I definitely think a keyword would be better than -> .

Maybe. Some prefer verbosity to clarity. So what keyword you think
"the best"?

In this case I think verbosity *is* clarity :) The -> thing really
has a "line-noise" quality that looks very out of place to me.

I could imagine using the lambda modification posted earlier:

block = lambda(a,b=1) { ... }

for those few times when this would be necessary.

Another idea, since I think at least 99% of this is about
define_method, would be to make some kind of special case treatment
for define_method. But I can't think of a good way to do that.


David
 
E

Eric Mahurin

--- Yukihiro Matsumoto said:
|In addition to handling defaults in arguments, I think these
|issues need to be addressed in blocks/lambdas:
|
|- all variables in the defining scope of a block/lambda are
|prevented from being GCed by the block/lambda (because of
the
|#binding). This can easily result in a leaky program if not
|careful. I discussed several solutions to this in a
previous
|thread.
=20
I think this issue should _not_ be solved by making new
lambda-like
object, but something like making eval a keyword, so that non
referenced local variable can be erased unless eval is called
within
the scope.

I agree. In addition to eval within the block (or even a
method that calls eval), you also have the issue that sometimes
people (including me) have wanted to call eval with
Proc#binding and want access to variables outside the block. I
think the majority of the time that is wanted is when the
binding is from the caller, so those variables won't want to be
GCed yet anyways. One of the solutions I gave was to have all
of the variables not directly referenced in the block be weak
references in Proc#binding, so that GC wouldn't be prevented.=20
GCing those unused variables would delete the weak references
in Proc#binding. I think this solution would maintain the best
compatibility/flexibility and still solve the problem.
|- a facility for making variables local (regardless of
whether
|a variable of the same name exists in the defining scope).=20
|This would also be good to have for a begin-end type block
(I'd
|like to have it for making inlined macros where I don't want
to
|worry about what variables are already used). I discussed
|several solutions for this in another thread.
=20
In 1.9, you can declare block local variables explicitly, by
the
syntax:
=20
foo {|a; b, c| ...} # b and c are block local
=20
so that
=20
b=3D1
5.times{|i;b|
b=3D5 # modifying in-block "b"
p [i,b]
}
p b # outer "b" remain unchanged

EXCELLENT!

Would you consider having something like a begin/end block
having this ability too?

b=3D1
begin(b)
b=3D5
p b # =3D> 5
end
p b # =3D> 1

Or maybe if "eval" became a keyword like you mentioned above
and it could also take a block, you could do this instead:

b=3D1
eval {|;b|
b=3D5
p b # =3D> 5
}
p b # =3D> 1

I'm wanting to avoid the method calls to do this. If eval was
a keyword (or non-redefinable), the above could accomplish it
because it could be in-lined (like begin-end).
|Also, I saw some slides for ruby 2 back in 2003 showing that
|arguments will always be local to the block and other
variables
|in the block will be in the same scope as the defining
scope.=20
|I think always making arguments local is a good thing, but
|never localizing the other variables will be problematic if
|another local variable facility is not provided.
=20
See above.

It doesn't look like arguments are local yet and all variables
inside the block that are not used yet outside are treated
local:

b=3D1
i=3D2
5.times { |i;b|
b=3D5
c=3D6
p [i,b]
}
p [i,b] # =3D> [4, 1] # i changed, b not
p c # undefined local variable or method



__________________________________________________
Do You Yahoo!?
Tired of spam? Yahoo! Mail has the best spam protection around=20
http://mail.yahoo.com=20
 
K

Karl-Heinz Wild

In 1.9, you can declare block local variables explicitly, by the
syntax:

foo {|a; b, c| ...} # b and c are block local

and how I whould have to write that c is global?

foo { | a,b, global c | }
foo { | a, b, <c> | }

Please don't misunderstand my suggestion.
I have no idea if it's possible or not,
but it looks pretty to me :)

regards
Karl-Heinz
 
T

Trans

Eric said:
I agree. In addition to eval within the block (or even a
method that calls eval), you also have the issue that sometimes
people (including me) have wanted to call eval with
Proc#binding and want access to variables outside the block. I
think the majority of the time that is wanted is when the
binding is from the caller, so those variables won't want to be
GCed yet anyways. One of the solutions I gave was to have all
of the variables not directly referenced in the block be weak
references in Proc#binding, so that GC wouldn't be prevented.
GCing those unused variables would delete the weak references
in Proc#binding. I think this solution would maintain the best
compatibility/flexibility and still solve the problem.

This still avoids a solution to closing scope for other uses. For
instance Class.new.

A = Class.new {
class B
def x; 1; end
end
}

class B
def x; 2; 1
end

A::B
(irb):19: warning: toplevel constant B referenced by A::B

There really needs to be a way to close that off.

T.
 
C

Christophe Grandsire

Selon Karl-Heinz Wild said:
and how I whould have to write that c is global?

foo { | a,b, global c | }
foo { | a, b, <c> | }

Please don't misunderstand my suggestion.
I have no idea if it's possible or not,
but it looks pretty to me :)

If I understood the discussion correctly, you *don't* have to write anyth=
ing if
you want c not to be block local. The planned new behaviour of blocks is =
that
local variables defined in them will be local to the whole scope, not the=
block
itself only, *unless* you indicate them explicitly through the syntax abo=
ve. So
there's no need to indicate globality.

And now someone is probably going to come and say I made a complete fool =
of
myself and didn't understand what is going on ;) (in other words, take th=
is
with a huge AFAIK in front of it).
--
Christophe Grandsire.

http://rainbow.conlang.free.fr

It takes a straight mind to create a twisted conlang.
 
K

Karl-Heinz Wild

If I understood the discussion correctly, you *don't* have to write
anything if
you want c not to be block local. The planned new behaviour of
blocks is that
local variables defined in them will be local to the whole scope,
not the block
itself only, *unless* you indicate them explicitly through the
syntax above. So
there's no need to indicate globality.

You are right. I've overseen that. My intention wasn't to change the
planned new behaviour, only thinking about the syntax.
And now someone is probably going to come and say I made a complete
fool of
myself and didn't understand what is going on ;) (in other words,
take this
with a huge AFAIK in front of it).

But really, I'm not shy to be what I am.
Maybe - sometime a fool :)

regards
Karl-Heinz
 
T

Trans

Yukihiro said:
Hi,

In message "Re: Default argument values for blocks"

||Is there a reason why I can't do this?
||
|| foo = lambda { |foo = bar| puts foo }
|| foo.call
||
||I can't think of any good reason why this isn't valid.
|
|Mostly because yacc does not allow it. It confuses
|
| lambda { |foo = bar| puts foo }
|
|as
|
| lambda { |foo = (bar| puts foo) }
|
|and causes syntax error.

For your information, you can do

foo = ->(foo="bar"){puts foo}
foo.call

What of &?

a.each( &->(foo="bar"){puts foo} ) # Ick.

Can we drop?

a.each( ->(foo="bar"){puts foo} ) # Better.

T.
 
C

Christophe Grandsire

Selon Eric Mahurin said:
Would you consider having something like a begin/end block
having this ability too?

b=3D1
begin(b)
b=3D5
p b # =3D> 5
end
p b # =3D> 1

Interesting. This syntax and the meaning of it remind me of METAFONT's wa=
y of
declaring scope (I seem to be one of the few people on Earth besides Knut=
h who
know a bit of METAFONT, and that's too bad because the language has some
interesting features). In METAFONT (which is structured but not oo) scopi=
ng and
subroutine definitions are completely separate. In other words you have t=
o scope
explicitly when you want a new scope. You do that through (surprisingly e=
nough
;) ) a "begin... end;" block. In the block, all variables from the outsid=
e
scope are known, so if you want to reuse the name of one of those locally=
you
have to explicitly "save" it first. So in METAFONT your example would rea=
d:

b=3D1;
begin
save b;
b=3D5;
message b % =3D> 5
end;
message b; % =3D> 1

I must say I like the "save b" syntax. If begin/end blocks in Ruby are to=
have
the same ability, it may be an idea (I personally find "begin(b)" unclear=
It
looks more to me like you're starting a block somehow indicated by a kind=
of
label "b" or something like that ;) ).
--
Christophe Grandsire.

http://rainbow.conlang.free.fr

It takes a straight mind to create a twisted conlang.
 
T

Thomas

What of &?
a.each( &->(foo="bar"){puts foo} ) # Ick.

Can we drop?

a.each( ->(foo="bar"){puts foo} ) # Better.

I was dreaming for a long time of a ruby dialect that has all these
fancy arrows haskell has. Everybody proposing arrows, please (try to)
read some haskell code.

But seriosly, I personally would prefer something in the line lambda(x,
y=1) {...} as it was proposed by other people too.

The => in the hash syntax is IMHO already one kind of arrow too much.

Regards,
Thomas.
 
M

Martin DeMello

Thomas said:
I was dreaming for a long time of a ruby dialect that has all these
fancy arrows haskell has. Everybody proposing arrows, please (try to)
read some haskell code.

But seriosly, I personally would prefer something in the line lambda(x,
y=1) {...} as it was proposed by other people too.

And here I was wishing for \(foo="bar") {}, the way Haskell does it :)
(Seriously - I've always found that the best of all the lambda
notations)

martin
 
C

Christophe Grandsire

Selon Thomas said:
I was dreaming for a long time of a ruby dialect that has all these
fancy arrows haskell has. Everybody proposing arrows, please (try to)
read some haskell code.

I have and can only concur. The arrows make things pretty confusing in mo=
st
places.
But seriosly, I personally would prefer something in the line lambda(x,
y=3D1) {...} as it was proposed by other people too.

The problem is that "collection.each lambda(foo=3D"bar") {puts foo}" has =
to be the
ugliest and most long-winded thing I've seen in a long time. It's OK for =
making
a Proc, but to use as a block it's just plain wrong.

However, it's nearly impossible a problem to solve. Any solution will pro=
bably
look rather awful. We just need to find the least offensive one :) . Unle=
ss one
finds a way to parse "{|foo=3D"bar"| puts foo}" correctly. That'd be the =
best
solution.
The =3D> in the hash syntax is IMHO already one kind of arrow too much.

Hasn't a change been accepted that allows one to use ":" as an alternativ=
e to
"=3D>" in hashes?

Hey, what about ":(foo=3D"bar"){puts foo}"? It's still not beautiful but =
it's
still less annoying, and in Ruby we are already used to see colons at the
beginning of a word. Of course, overloading ":" may not be considered a g=
ood
idea, but it shouldn't be a parsing problem as this one would always be
followed by a "(" (and that doesn't happen with symbols). And:

collection.each:(foo=3D"bar"){puts foo}

isn't that bad :) .
--
Christophe Grandsire.

http://rainbow.conlang.free.fr

It takes a straight mind to create a twisted conlang.
 
M

Martin DeMello

Yukihiro Matsumoto said:
Hi,

In message "Re: Default argument values for blocks"

|> foo = ->(foo="bar"){puts foo}

|-> means lambda?

Yes, as in Perl6. "lambda" here means lambda in other languages, not
the lambda method in Ruby.

Why not \ as in Haskell instead? Looks much more like the actual letter
lambda (which is what motivated its use in Haskell) and is two
keystrokes less to type (counting the shift for >).

martin
 
C

Christophe Grandsire

Selon Martin DeMello said:
And here I was wishing for \(foo=3D"bar") {}, the way Haskell does it := )
(Seriously - I've always found that the best of all the lambda
notations)

I wouldn't mind that one. "\" isn't too instrusive, and as a LaTeX fan I'=
m quite
used to it. But see my former post on the subject.
--
Christophe Grandsire.

http://rainbow.conlang.free.fr

It takes a straight mind to create a twisted conlang.
 
C

Christophe Grandsire

Selon Martin DeMello said:
Why not \ as in Haskell instead? Looks much more like the actual letter
lambda (which is what motivated its use in Haskell) and is two
keystrokes less to type (counting the shift for >).

Well, keystrokes are keyboard-dependent. At home, to get a \ I have to do=
an
Alt-Gr (Dutch keyboard:
http://www.microsoft.com/globaldev/keyboards/kbdne.htm). So for me the ga=
in in
only one keystroke, and Alt-Gr / on this keyboard is not always an easy t=
ask ;)
 
C

Christophe Grandsire

Selon Christophe Grandsire said:
Well, keystrokes are keyboard-dependent. At home, to get a \ I have to = do an
Alt-Gr (Dutch keyboard:
http://www.microsoft.com/globaldev/keyboards/kbdne.htm). So for me the = gain
in
only one keystroke, and Alt-Gr / on this keyboard is not always an easy= task
;)

For some reason, the rest of this message didn't seem to go through. Here=
it is
again then:

"But that's beside the point. If my idea of using ":" doesn't get off the
ground, I'll be happy to vote for "\". It has a precedent after all."
--
Christophe Grandsire.

http://rainbow.conlang.free.fr

It takes a straight mind to create a twisted conlang.
 
D

Devin Mullins

Christophe said:
Hey, what about ":(foo="bar"){puts foo}"? It's still not beautiful but it's
still less annoying, and in Ruby we are already used to see colons at the
beginning of a word. Of course, overloading ":" may not be considered a good
idea, but it shouldn't be a parsing problem as this one would always be
followed by a "(" (and that doesn't happen with symbols). And:

collection.each:(foo="bar"){puts foo}

isn't that bad :) .
+1
 
D

Devin Mullins

Trans said:
This still avoids a solution to closing scope for other uses. For
instance Class.new.

A = Class.new {
class B
def x; 1; end
end
}

A::B
(irb):19: warning: toplevel constant B referenced by A::B
Ho. That is wacky. Same thing for normal constants and for class
variables, of course, 'cept no warning for class variables.

class A
def self.B
Class.new {
@@share = "hello!"
}
end
end
B = A.B
p B.class_eval { @@share } #=> error, uninitialized? wha?
A.class_eval { @@share = 'duck' }
p B.class_eval { @@share } #=> "duck"

You can actually just do Class.new and get the class-variable-sharing
thing -- I just stuffed the block in there 'cause I'm wondering about
the uninitialized part.

C:\Documents and Settings\dlm>irb
irb(main):001:0> Class.new {
irb(main):002:1* @@share = 'hello' }
=> #<Class:0x2cff5a0>
irb(main):003:0> @@share
=> "hello"
irb(main):004:0>

C:\Documents and Settings\dlm>irb
irb(main):001:0> class A
irb(main):002:1> B = Class.new { @@share = 'hello' }
irb(main):003:1> end
=> A::B
irb(main):004:0> A.class_eval { @@share }
NameError: uninitialized class variable @@share in Object
from (irb):4
from (irb):4:in `class_eval'
from (irb):4:in `class_eval'
from (irb):4
irb(main):005:0> A::B.class_eval { @@share }
NameError: uninitialized class variable @@share in Object
from (irb):5
from (irb):5:in `class_eval'
from (irb):5:in `class_eval'
from (irb):5

Wha???

Devin
 
Y

Yukihiro Matsumoto

Hi,

In message "Re: Default argument values for blocks"

|Why not \ as in Haskell instead? Looks much more like the actual letter
|lambda (which is what motivated its use in Haskell) and is two
|keystrokes less to type (counting the shift for >).

A backslash is the most unfortunate character, which is caught by yen
sign problem. In Japanese encoding, appearance of the character
varies font to font. On some font (e.g. on my Emacs) it is shown as a
backslash, on other font (e.g. on my Firefox), it is shown as a
Japanese currency sign, Yen (two dashes over captal Y). Indeed, a
backslash can reminds me lambda, but yen sign does not have any clue
for lambda. This must be a tiny problem for non Japanese.

matz.
 
Y

Yukihiro Matsumoto

Hi,

In message "Re: Default argument values for blocks"

|Hey, what about ":(foo="bar"){puts foo}"? It's still not beautiful but it's
|still less annoying, and in Ruby we are already used to see colons at the
|beginning of a word. Of course, overloading ":" may not be considered a good
|idea, but it shouldn't be a parsing problem as this one would always be
|followed by a "(" (and that doesn't happen with symbols). And:
|
|collection.each:(foo="bar"){puts foo}
|
|isn't that bad :) .

I have never thought of that. Hmm, let me think about it during the
conference trip. I'm leaving tomorrow morning.

matz.
 

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

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,901
Latest member
Noble71S45

Latest Threads

Top