Controlled block variables

Hi T.

(…) the core problem (…)

a = [1,2,3]
class_eval {
def ameth
p a
end
}

(…) So how does your solution deal with this problem?

I thought you could tell from my examples, but let’s try it with your
exact problem…

You know you can pass objects to eval:

a = [1,2,3]
eval “p a”

results in

[1, 2, 3]

You can even use those objects in blocks:

a = [1,2,3]
eval( “proc{ p a }” ).call

also results in

[1, 2, 3]

But you can’t do so in a method definition:

a = [1,2,3]
self.class.class_eval “def ameth; p a; end”
ameth

results in

(eval):1:in ameth': undefined local variable or method a’ for
main:Object (NameError)

That’s because “a” is interpreted in the scope of the method definition,
where it must be a local variable or a method, which it isn’t.

So the trick is to use a proc as shown above and use it as a method,
which can be done with define_method:

a = [1,2,3]
self.class.class_eval “define_method :ameth, proc{ p a }”
ameth

results in

[1, 2, 3]

If I understood you right, this is what you wanted.

Regards,
Pit

First, small problem

class A
def dolittle
print “duck”
end
def dolittle:hook # where’s the super? what do i do?
print “rabbit”
end
end

A little bigger

class A
def dolittle
print “duck”
end
def dolittle:hook
super
print “rabbit”
end
end

class B < A
def dolittle:hook # am i replacing old hook? (there’s no local dolittle)
super # or am i supering to old hook?
print “fox”
end
end

Much bigger problem: a library the i don’t know how it works, i’m just using
it:

class L
def dolittle
print “duck”
end
def dolittle:hook
super
print “rabbit”
end
end
l = L.new
l.dolittle # => duckrabbit

no no i say, i want dolittle’s “duckradditstew”!

class L
def dolittle:hook
super
print “stew!”
end
end
l.dolittle # => duckstew!

Yuk! I don’t like plain duckstew.

But the worst problem of all is simply that not allowing multiple wraps, so
severely limits the capabilities of this mechinism that it would actually
have no general use whatsoever.

indeed it would actually be highly advisable NOT to ever use it b/c of the
last example given above, and would only ever be really useful for
devleopment/testing purposes alone.

(not to mention other issues with super)

-t0

···

On Wednesday 26 November 2003 06:14 pm, ts wrote:

So ask, should it continue to do so with the addition of hooks? (Not to
mention there are some fundemental problems with this disallowing.)

Which problems ?

Guy Decoux

Actually, this is the problem:
NoMethodError: undefined method `class_eval’ for main:Object

Or did you mean the above code to exist within a class? If so, I have:

class X
a = [1,2,3]
class_eval {
def ameth
p a
end
}
end

X.new.ameth

NameError: undefined local variable or method `a’ for #<X:0x101695f8>

from (irb):13:in `ameth’

So ‘a’ is not evaluated as nil, it cannot be evaluated.

Ooops. You’re right, not nil, rather unknown. I was thinking @a, which would
be nil b/c it gets substantiated upon use.

I hate to ask at this late stage, but what’s the problem? If you want to
make the value ‘a’ available to the dynamically created method ‘ameth’,
maybe you could try this

class Z
@@a = [1,2,3]
class_eval {
def ameth
@@a.length
end
}
end

Z.new.ameth # => 3

If you don’t know in advance what your variable names are going to be, use
a hash. You don’t have to resort to global variables; class variables are
there to help. And so am I :slight_smile:

That was basically Ryan’s soluiton. (on ruby-core) But again it’s really just
a work around.

The “problem”, if we disect it to its roots, is two-fold. The first is a
discrepency in eval’s scope ability when a string it used versus a block:

eval “#{a}”
eval {a}

Mind you, I do understand what’s going on that makes this happen. That’s not
the problem. Rather, from the point of view of a user, or POLS, if you will,
that the scope changes, is discongruous. And is not even apparent from this
example b/c it isn’t an issue here. It is only when you do something like

eval “def ameth; #{a}; end”
eval {def ameth; a; end}

that the change becomes evident.

The second problem then derives from the first, b/c now, in order to get the
greater scope that the string “version” of eval offers, one has to convert
the objects into literals. Which is a pain and also is inefficient,
considering that the object’s already “right there!”.

I think for a Ruby expert this may be hard to comprehend becasue you
understand what Ruby is doing so well, it is almost second nature. But take a
step back and really look at this from a nuby’s point of view (the spirit of
POLS in my opinion). Then consider:

“With a string I can get to a but I have to make it a literal.”
“With a block I don’t need the literal, but I can’t get to a.”

-t0

···

On Friday 28 November 2003 02:31 am, Gavin Sinclair wrote:

Thanks Gavin. I read it over. And I certainly understand the distinction. To
sum up: foo.aproc is sending a message called ‘aproc’ to the object ‘foo’.
But it’s still returning an Proc object. Yes? There’s probably something
obvious that I’m just overlooking here, but I don’t see the reason why Ruby
can’t infer the #call message when a Proc object (or Method object for that
matter) is returned given with parens.

aproc() # → aproc.call()

in a fashion similiar to how it can infer self as a reciever.

-t0

···

On Friday 28 November 2003 02:40 am, Gavin Sinclair wrote:

On http://ruby-doc.org, you can find a link to “Ruby Eye for the Python
Guy”, which contains a link to an explanation of the difference between
Python and Ruby in terms of “methods as first class objects”. That
document, on onestepback.org, is essential reading.

In short, the message-passing paradigm is paramount in Ruby. You may say
that ‘foo.aproc is a Proc object’, but the reality is that ‘foo.aproc’ is
the result of sending the message ‘aproc’ to ‘foo’. Nothing more, nothing
less. And there are good reasons why that won’t change. Making parens
optional is just a superficial reason.

Okay, I think I know what you’re saying. So you’re defining a method for the
variable that would be visible from within the def. Another viable solution.
Sorry, I wasn’t able to pick up on this from the frist post.

I image we could even abstract this further using:

class Object
def methodize(sym, var)
class_eval “define_method “#{sym}meth”, proc{ var }”
end
end

or something to that effect.

Thanks!
-t0

P.S. Did you see Austin’s post on core?

···

On Friday 28 November 2003 11:49 pm, Pit Capitain wrote:

So the trick is to use a proc as shown above and use it as a method,
which can be done with define_method:

a = [1,2,3]
self.class.class_eval “define_method :ameth, proc{ p a }”
ameth

results in

[1, 2, 3]

If I understood you right, this is what you wanted.

  class A
    def dolittle
      print "duck"
    end
    def dolittle:hook # where's the super? what do i do?
      print "rabbit"
    end
  end

only print "rabbit"

A little bigger

  class A
    def dolittle
      print "duck"
    end
    def dolittle:hook
      super
      print "rabbit"
    end
  end

  class B < A
    def dolittle:hook # am i replacing old hook? (there's no local dolittle)
      super # or am i supering to old hook?
      print "fox"
    end
  end

print "duckrabbitfox"

Much bigger problem: a library the i don't know how it works, i'm just using
it:

Don't modify library that you don't know

But the worst problem of all is simply that not allowing multiple wraps, so
severely limits the capabilities of this mechinism that it would actually
have no general use whatsoever.

You must have a mechanism to change the ordering in this case (see
Allegro) and [ruby-talk:86170]

Guy Decoux

From T. Onama:

In short, the message-passing paradigm is paramount in Ruby. You may
say that ‘foo.aproc is a Proc object’, but the reality is that
‘foo.aproc’ is the result of sending the message ‘aproc’ to ‘foo’.
Nothing more, nothing less. And there are good reasons why that won’t
change. Making parens optional is just a superficial reason.

Thanks Gavin. I read it over. And I certainly understand the
distinction. To sum up: foo.aproc is sending a message called ‘aproc’
to the object ‘foo’. But it’s still returning an Proc object. Yes?

Maybe. It could return a String, nil, a FroBoz, anything really.

There’s probably something obvious that I’m just overlooking here, but
I don’t see the reason why Ruby can’t infer the #call message when a
Proc object (or Method object for that matter) is returned given with
parens.

aproc() # → aproc.call()

in a fashion similiar to how it can infer self as a reciever.

aproc() calls the method ‘aproc’ (sends the message :aproc) with no
arguments. It can’t add a magic :call message in there.

Maybe - I’m not sure - you’re under the misunderstanding that, or maybe
you’re proposing that the following should occur:

class Example
def ameth(x)
x + 1
end
end

e = Example.new

e.ameth # returns Proc
# return value equiv. to proc { |x| x + 1 }

Instead of

e.ameth → ArgumentError: 0 for 1

This is the “methods as first class objects” wish that Python implements.
Is that what you’re proposing? If so, I missed it or misunderstood it in
previous messages.

I sympathise with the wish that methods be first class, and that you can
pass them around, but when I red Jim Weirich’s article
(http://onestepback.org/index.cgi/Tech/Ruby/PythonAndRuby.rdoc) that door
forever closed in my mind.

If you can clear up the misunderstandings I have about where you’re coming
from, I’d like to hear your proposals.

Cheers,
Gavin

Hi,

···

At Sat, 29 Nov 2003 18:13:27 +0900, T. Onoma wrote:

class Object
def methodize(sym, var)
class_eval “define_method “#{sym}meth”, proc{ var }”
end
end

This will be parsed as:

  class_eval "define_method " # a comment

You’ll want to do:

  class_eval {define_method "#{sym}meth", proc {var}}


Nobu Nakada

Hi T.

Okay, I think I know what you’re saying. So you’re defining a method for
the variable that would be visible from within the def. Another viable
solution.

I imagine we could even abstract this further using:

class Object
def methodize(sym, var)
class_eval “define_method “#{sym}meth”, proc{ var }”
end
end

That’s more or less what I did in my first post. But I think you still
don’t see the full potential. You can do much more in the proc than
simply returning an object. In fact, when you wanted to write

a = [1,2,3]
class_eval %{
def meth

end
}

but couldn’t because “a” wasn’t visible, with define_method you can
instead write

a = [1,2,3]
class_eval %{
define_method :meth, proc{

}
}

A silly example:

def add_long_method_to_class( klass, a, h )
klass.class_eval %{
define_method :long_generated_method, proc{
local_var = a.size
h[ “s” ] = local_var
p h
# do more stuff
}
}
end

This defines a method “long_generated_method” for the given klass, using
two objects passed as parameters inside the method. You can call it like

add_long_method_to_class String, [ 1, 2, 3 ], { “x” => 1 }

“hi”.long_generated_method

This prints

{“x”=>1, “s”=>3}

P.S. Did you see Austin’s post on core?

No, seems I missed it. Looking into the archive, he wants to have a template

ACCESSOR_METHODS = %Q{self.rss_?_list << “?”}

and then substitute values for the placeholders. For the first
placeholder he has to use his string substitution method, but for the
second he could directly pass an object, for example:

ACCESSOR_METHODS = %Q{self.rss__list << value}

He then can evaluate it like so:

value = [ 1, 2, 3 ] # could be every object
module_eval ACCESSOR_METHODS.gsub( //, “element” )

Notice that the “value” in the ACCESSOR_METHODS template is substituted
by the “value” variable in the surrounding scope of module_eval. I can
remember that I have been very surprised when I first saw this magic in
someone’s code (don’t know where it was though). It is a really powerful
mechanism.

HTH

Regards,
Pit

class A
def dolittle
print “duck”
end
def dolittle:hook # where’s the super? what do i do?
print “rabbit”
end
end

only print “rabbit”

Let’s see… non POLS, double semantic meaning…

A little bigger

class A
def dolittle
print “duck”
end
def dolittle:hook
super
print “rabbit”
end
end

class B < A
def dolittle:hook # am i replacing old hook? (there’s no local
dolittle) T> super # or am i supering to old hook?
print “fox”
end
end

print “duckrabbitfox”

How to produce “duckfox” ?

Much bigger problem: a library the i don’t know how it works, i’m just
using T> it:

Don’t modify library that you don’t know

Misses the whole point of AOP.

“AOP introduces aspects, which encapsulate behaviors
that affect multiple classes into reusable modules.”

But the worst problem of all is simply that not allowing multiple wraps,
so T> severely limits the capabilities of this mechinism that it would
actually T> have no general use whatsoever.

You must have a mechanism to change the ordering in this case (see
Allegro) and [ruby-talk:86170]

Think about singletons.

-t0

···

On Wednesday 26 November 2003 07:14 pm, ts wrote:

Maybe - I’m not sure - you’re under the misunderstanding that, or maybe
you’re proposing that the following should occur:

class Example
def ameth(x)
x + 1
end
end

e = Example.new

e.ameth # returns Proc
# return value equiv. to proc { |x| x + 1 }

Instead of

e.ameth → ArgumentError: 0 for 1

This is the “methods as first class objects” wish that Python implements.
Is that what you’re proposing? If so, I missed it or misunderstood it in
previous messages.

Like I said, I may be overlooking something obvious here, but what i mean is
this:

class Example
def ameth
proc { |x| x + 1 }
end
end

e = Example.new

e.ameth # return equiv. to proc { |x| x + 1 }

But…

e.ameth(2) # → 3

In otherwords, Ruby wouldn’t assume that the arity is automatically wrong, but
rather that the method may return a proc (or method) to which the parameters
can be applied. Granted, this may mean the possibility of not so obvious
errors when it is not the case. And like I said, there may be something I’m
overlooking that makes this impossible. But that’s the thought I’m having,
anyway. It further means that

e.ameth()(2) # → 3

actually means something --it is the “unambiguous” form of the above.

I sympathise with the wish that methods be first class, and that you can
pass them around, but when I red Jim Weirich’s article
(http://onestepback.org/index.cgi/Tech/Ruby/PythonAndRuby.rdoc) that door
forever closed in my mind.

That’s what I read. And I’m not really suggesting that they be first class
objects. Only that Ruby might be able to “fake it”, so to speak.

If you can clear up the misunderstandings I have about where you’re coming
from, I’d like to hear your proposals.

I truly appreciate your interest, Gavin.

Thanks,
-t0

···

On Friday 28 November 2003 04:59 am, Gavin Sinclair wrote:

Thanks for the fix! :slight_smile:

-t0

···

On Saturday 29 November 2003 10:58 am, nobu.nokada@softhome.net wrote:

This will be parsed as:

  class_eval "define_method " # a comment

You’ll want to do:

  class_eval {define_method "#{sym}meth", proc {var}}

but couldn’t because “a” wasn’t visible, with define_method you can
instead write

a = [1,2,3]
class_eval %{
define_method :meth, proc{

}
}

A silly example:

def add_long_method_to_class( klass, a, h )
klass.class_eval %{
define_method :long_generated_method, proc{
local_var = a.size
h[ “s” ] = local_var
p h
# do more stuff
}
}
end

This defines a method “long_generated_method” for the given klass, using
two objects passed as parameters inside the method. You can call it like

add_long_method_to_class String, [ 1, 2, 3 ], { “x” => 1 }

“hi”.long_generated_method

This prints

{“x”=>1, “s”=>3}

Yes, your right, I had “blinders on” and really was missing your point.
define_method opens up the scope. It’s really kind of funny that it does so
–or should I say that def does not. The fact that def’s not a real method,
like define_method makes all the difference.

Then you’re ecapsulating the whole thing using parameteres with which you can
gernerate new varaitions on the method. That really can be amazingly
powerful. Hm…I admit, I’m impressed.

I’m going to keep this in the back of my mind for a while churning over
application. There’s something about, something compelling. My immediate
impression is sort-of, “why do I use def at all?” I’m sure I’m over
simplifying but it is at least worth some thought.

P.S. Did you see Austin’s post on core?

No, seems I missed it. Looking into the archive, he wants to have a
template

ACCESSOR_METHODS = %Q{self.rss_?_list << “?”}

and then substitute values for the placeholders. For the first
placeholder he has to use his string substitution method, but for the
second he could directly pass an object, for example:

ACCESSOR_METHODS = %Q{self.rss__list << value}

He then can evaluate it like so:

value = [ 1, 2, 3 ] # could be every object
module_eval ACCESSOR_METHODS.gsub( //, “element” )

Notice that the “value” in the ACCESSOR_METHODS template is substituted
by the “value” variable in the surrounding scope of module_eval. I can
remember that I have been very surprised when I first saw this magic in
someone’s code (don’t know where it was though). It is a really powerful
mechanism.

Now this is a trip! I was just talking about this in an earlier discussion.
Its dyanmic scoping. [ Actually I think I may have slightly misinterpreted
Austin’s post, but now to my benefit :slight_smile: ] I don’t know if you caught that
talk. Of course the problem with dynamic scoping is the dependency on
specific varable names like ‘value’. But in particular contexts you can reuse
code, even pass it around. In generic contexts its even more useful. Take it
to the extreme and you have almost total code reflection.

Very interesting stuff!!

HTH

IDID !!!

-t0

···

On Sunday 30 November 2003 12:34 am, Pit Capitain wrote:

It’s not faking anything, though. e.ameth is a callable object (it
looks like a callable object, therefore it looks like it’s faking
method-as-a-first-class-object) only because it is a Proc.

Method-as-a-first-class-object requires that for any value of ‘e’ and
‘ameth’, the following holds true: e.ameth is a callable object,
unless it’s a NoMethodError.

In the case you describe, it’s only the case if e.ameth returns a
Proc, so it’s a very special case.

We can forget about methods, etc. What we’re talking about comes down
to this: should this syntax work?

p = proc { |x| x + 1 }
n = p(5) # => 6

That has been discussed on the list before. I’m not au fait with all
the whys and wherefores, but the proposition has never excited me, nor
has it gathered significant support.

Cheers,
Gavin

···

On Friday, November 28, 2003, 7:00:20 PM, T. wrote:

Like I said, I may be overlooking something obvious here, but what i mean is
this:

class Example
def ameth
proc { |x| x + 1 }
end
end

e = Example.new

e.ameth # return equiv. to proc { |x| x + 1 }

But…

e.ameth(2) # → 3

In otherwords, Ruby wouldn’t assume that the arity is automatically wrong, but
rather that the method may return a proc (or method) to which the parameters
can be applied. Granted, this may mean the possibility of not so obvious
errors when it is not the case. And like I said, there may be something I’m
overlooking that makes this impossible. But that’s the thought I’m having,
anyway. It further means that

e.ameth()(2) # → 3

actually means something --it is the “unambiguous” form of the above.

I sympathise with the wish that methods be first class, and that you can
pass them around, but when I red Jim Weirich’s article
(http://onestepback.org/index.cgi/Tech/Ruby/PythonAndRuby.rdoc) that door
forever closed in my mind.

That’s what I read. And I’m not really suggesting that they be first class
objects. Only that Ruby might be able to “fake it”, so to speak.

T. Onoma wrote:

Maybe - I’m not sure - you’re under the misunderstanding that, or maybe
you’re proposing that the following should occur:

class Example
def ameth(x)
x + 1
end
end

e = Example.new

e.ameth # returns Proc
# return value equiv. to proc { |x| x + 1 }

Instead of

e.ameth → ArgumentError: 0 for 1

This is the “methods as first class objects” wish that Python implements.
Is that what you’re proposing? If so, I missed it or misunderstood it in
previous messages.

Like I said, I may be overlooking something obvious here, but what i mean is
this:

class Example
def ameth
proc { |x| x + 1 }
end
end

e = Example.new

e.ameth # return equiv. to proc { |x| x + 1 }

But…

e.ameth(2) # → 3

What’s wrong with

 e.ameth[2]

?

Your proposal means that () should be an operator that could be overloaded as
it is the case in C++ or Python (?). But this leads to lots of confusion and
IMHO doesn’t give so many advantages. Indeed, this would make the program much
less readable, as you would not be able to distinguish between method calls and
other things.

Unlike Python, we don’t really have functions. Ruby is pure OO! So (almost)
everything is a method call, except e.g. (), which is required to group
parameters for a method call.

In otherwords, Ruby wouldn’t assume that the arity is automatically wrong, but
rather that the method may return a proc (or method) to which the parameters
can be applied. Granted, this may mean the possibility of not so obvious
errors when it is not the case. And like I said, there may be something I’m
overlooking that makes this impossible. But that’s the thought I’m having,
anyway. It further means that

What should happen if the method do not return a proc, but e.g. an integer?
How should Ruby know in advance what you’re actually returning from the method?
You can’t decide this before actually executing it. You would need to execute
the method first with no arguments, to then decide that it does not return a
proc and then fail. That’s pretty ugly, IMO.

e.ameth()(2) # → 3

What’s the advantage here. Why not simply use

 e.ameth()[2] 

or

 e.ameth[2] 

Both do not introduce any ambiguity. And why is a proc special at all? It’s an
object like any other. Then you’d have to use the same syntax for Array, Hashes
and so on, too.

Proc’s can be used as virtual arrays, so it’s good that they respond to the
same method as Arrays or Hashes do.

Regards,

Michael

···

On Friday 28 November 2003 04:59 am, Gavin Sinclair wrote:

Hey Capitain,

Was just wondering if I got the jist of what you were showing me, or am I
still missing something?

T

···

On Sunday 30 November 2003 12:34 am, Pit Capitain wrote:

but couldn’t because “a” wasn’t visible, with define_method you can
instead write

a = [1,2,3]
class_eval %{
define_method :meth, proc{

}
}

A silly example:

def add_long_method_to_class( klass, a, h )
klass.class_eval %{
define_method :long_generated_method, proc{
local_var = a.size
h[ “s” ] = local_var
p h
# do more stuff
}
}
end

This defines a method “long_generated_method” for the given klass, using
two objects passed as parameters inside the method. You can call it like

add_long_method_to_class String, [ 1, 2, 3 ], { “x” => 1 }

“hi”.long_generated_method

This prints

{“x”=>1, “s”=>3}

Yes, your right, I had “blinders on” and really was missing your point.
define_method opens up the scope. It’s really kind of funny that it does so
–or should I say that def does not. The fact that def’s not a real
method, like define_method makes all the difference.

Then you’re ecapsulating the whole thing using parameteres with which you
can gernerate new varaitions on the method. That really can be amazingly
powerful. Hm…I admit, I’m impressed.

I’m going to keep this in the back of my mind for a while churning over
application. There’s something about, something compelling. My immediate
impression is sort-of, “why do I use def at all?” I’m sure I’m over
simplifying but it is at least worth some thought.

P.S. Did you see Austin’s post on core?

No, seems I missed it. Looking into the archive, he wants to have a
template

ACCESSOR_METHODS = %Q{self.rss_?_list << “?”}

and then substitute values for the placeholders. For the first
placeholder he has to use his string substitution method, but for the
second he could directly pass an object, for example:

ACCESSOR_METHODS = %Q{self.rss__list << value}

He then can evaluate it like so:

value = [ 1, 2, 3 ] # could be every object
module_eval ACCESSOR_METHODS.gsub( //, “element” )

Notice that the “value” in the ACCESSOR_METHODS template is substituted
by the “value” variable in the surrounding scope of module_eval. I can
remember that I have been very surprised when I first saw this magic in
someone’s code (don’t know where it was though). It is a really powerful
mechanism.

Now this is a trip! I was just talking about this in an earlier
discussion. Its dyanmic scoping. [ Actually I think I may have slightly
misinterpreted Austin’s post, but now to my benefit :slight_smile: ] I don’t know if
you caught that talk. Of course the problem with dynamic scoping is the
dependency on specific varable names like ‘value’. But in particular
contexts you can reuse code, even pass it around. In generic contexts its
even more useful. Take it to the extreme and you have almost total code
reflection.

Very interesting stuff!!

HTH

IDID !!!

-t0

Sure, I understand. I’m just wonder if it can be done. Hence my original
question. Or whether there is some impossible barrier. That’s all.

-t0

P.S. I’ll research the archives too. Thanks.

···

On Friday 28 November 2003 12:08 pm, Gavin Sinclair wrote:

We can forget about methods, etc. What we’re talking about comes down
to this: should this syntax work?

p = proc { |x| x + 1 }
n = p(5) # => 6

That has been discussed on the list before. I’m not au fait with all
the whys and wherefores, but the proposition has never excited me, nor
has it gathered significant support.

Hi Tom.

Was just wondering if I got the jist of what you were showing me, or am I
still missing something?

As far as I can tell from your replies, I think you understood what I
wanted to show. I haven’t used this stuff yet in my own code, so I can’t
tell you more about it. Thanks for listening so far :slight_smile:

Regards,
Pit

T. Onoma wrote:

We can forget about methods, etc. What we’re talking about comes down
to this: should this syntax work?

p = proc { |x| x + 1 }
n = p(5) # => 6

That has been discussed on the list before. I’m not au fait with all
the whys and wherefores, but the proposition has never excited me, nor
has it gathered significant support.

Sure, I understand. I’m just wonder if it can be done. Hence my original
question. Or whether there is some impossible barrier. That’s all.

One thing that comes to my mind is this:

The () notation seems to make sense for a variable that happens
to refer to a proc. But what if you stick parens on a variable
that isn’t a proc? This seems like a syntax error, but it would
have to be detected at runtime.

foo = proc {…}
1.upto(5) do |i|
foo = “Haha!!” if i==4
foo() # What happens when i is 4?
end

Hal

···

On Friday 28 November 2003 12:08 pm, Gavin Sinclair wrote:

yes, weird errors. that’s a big minus.

-t0

···

On Friday 28 November 2003 08:21 pm, Hal Fulton wrote:

One thing that comes to my mind is this:

The () notation seems to make sense for a variable that happens
to refer to a proc. But what if you stick parens on a variable
that isn’t a proc? This seems like a syntax error, but it would
have to be detected at runtime.

foo = proc {…}
1.upto(5) do |i|
foo = “Haha!!” if i==4
foo() # What happens when i is 4?
end