Enumerator usage

I don’t understand the following:

3.times { |i| puts(i) } # ok
3.times.class # Enumerator
n = 3.times
n.class # Enumerator
n { |i| puts(i) } # error!?

To a new Ruby student this error seems ‘conceptually wrong’.

Playing around a bit I’ve discovered that this works:

n.each { |i| puts(i) }

As does:

3.times.each { |i| puts(i) }

Does this inconsistency result from a parser-level layer of ‘syntactic
sugar’? I’m also getting a sense that a ‘block’ is a parser-level
construct,
and a ‘Proc’ is an execution-level object.

So, a related question: given an Enumerator and a 1-ary Proc (lambda):

n = 3.times
f = lambda { |i| puts(i) }

What expression allows us to ‘map’ or ‘apply’ the Proc to each
enumerated value?

There just seems to be something really ‘wrong’ about how Ruby treats
functions:

def f2(i)
puts(i)
end

f2.class # error!?

Functions are not first-class objects? I actually have no idea what f2
is. Clearly its not a symbol bound to an object. It’s ‘something else’.

Intuitively I would have expected the follow two constructs to produce
operatively identical objects:

def f2(i)
puts(i)
end

f2 = lambda { |i| puts(i) }

I’m really puzzled by this. Coming from years of programming in Scheme
I’m quite used to dealing with syntax-layer transformations. But there
is evidently something else going on with Ruby that violates a lot of my
intuitions and expectations. I’m hoping that once I understand it better
it will start to look ‘elegant’ and ‘beautiful’, but right now it looks
kinda ‘scary’ and ‘repugnant’.

Help please!

  • Dave

Subject: Enumerator usage
Date: Tue 22 Jan 13 04:20:57AM +0900

Quoting David R. ([email protected]):

I don’t understand the following:

3.times { |i| puts(i) } # ok
3.times.class # Enumerator
n = 3.times
n.class # Enumerator
n { |i| puts(i) } # error!?

To a new Ruby student this error seems ‘conceptually wrong’.

Ruby documentation is well-made. Make good use of it!

If you type

ri Integer#times

you will read:

–8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<–

int.times {|i| block } -> self
int.times -> an_enumerator


Iterates block int times, passing in values from zero to int - 1.

If no block is given, an enumerator is returned instead.
–8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<–

In your first example you pass a block, so it returns self. In the
second example, you do not provide a block, and an enumerator is
returned.

Note that if you type

3.times { |i| puts(i) }.class

you will get Integer (self, in this case, is the integer 3).

What is an enumerator, then (which is returned by the Integer#times
methods when you do not provide a block)? Use the documentation: read
with care what you obtain when you type

ri Enumerator

There just seems to be something really ‘wrong’ about how Ruby treats
functions:

def f2(i)
puts(i)
end

f2.class # error!?

With def you define a method of the current class (or a method of the
Object class if you are not defining your own class). You do NOT
define a variable. If you want a variable to contain the reference to
your new method, you must type

vrb=method(:f2)

and vrb will be an instance of the Method class, containing a
reference to your method.

I’m hoping that once I understand it better
it will start to look ‘elegant’ and ‘beautiful’, but right now it looks
kinda ‘scary’ and ‘repugnant’.

‘scary’ and ‘repugnant’ are two concepts that express fear. Fear is
the first enemy that has to be won on the path of growth…

Ruby is just different from what you are used to. But it works.

On 21 Jan 2013, at 19:20, David R. [email protected] wrote:

Playing around a bit I’ve discovered that this works:
and a ‘Proc’ is an execution-level object.
functions:
Intuitively I would have expected the follow two constructs to produce
is evidently something else going on with Ruby that violates a lot of my
intuitions and expectations. I’m hoping that once I understand it better
it will start to look ‘elegant’ and ‘beautiful’, but right now it looks
kinda ‘scary’ and ‘repugnant’.

Help please!

In Ruby objects are not first first class.

The commonly given reason for this is that non-first-class blocks are
faster because you don’t have to create objects to use them:

http://mudge.name/2011/01/26/passing-blocks-in-ruby-without-block.html

Alan

‘scary’ and ‘repugnant’ are two concepts that express fear. Fear is
the first enemy that has to be won on the path of growth…

Let me respond to this part of your reply first, to get it out of the
way.

In this context, ‘scary’ should be taken to mean “very difficult and
time-consuming to understand due to gross conceptual inconsistencies and
poorly conceived design.”

For a definition of ‘repugnant’ please visit review the specifications
for ANSI COBOL:
http://pic.dhe.ibm.com/infocenter/pdthelp/v1r1/index.jsp?topic=%2Fcom.ibm.entcobol.doc_3.4%2Frlind.htm

Fear has nothing whatsoever to do with what I’m inquiring about.

Ruby is just different from what you are used to. But it works.

COBOL also works.


As for the other parts of your response, thanks. I’ll have a closer look
at the language spec in the coming days. My questions are arising from
carefully working through of Collingbourne’s “The Book of Ruby”, so it’s
not as if I’m floundering away in the dark, on my own, ignoring external
resources.

For the record, on my system:

ri Integer
Nothing known about Integer

So I’ll also have to figure out why that is not working.

Thanks again for your responses.

_ Dave

Subject: Re: Enumerator usage
Date: Tue 22 Jan 13 05:31:43AM +0900

Quoting David R. ([email protected]):

COBOL also works.

I should know… Back in 1978, during my last year at high school, I
did a course of COBOL programming.

Believe me: there is some difference :wink:

For the record, on my system:

ri Integer
Nothing known about Integer

So I’ll also have to figure out why that is not working.

mm. Ruby without ri is a very lonely chap. I believe there are
equivalent resources online, but I can’t say wheræ

Thanks again for your responses.

Glad to be of help!

Carlo

On Mon, Jan 21, 2013 at 8:20 PM, David R. [email protected]
wrote:

I don’t understand the following:

3.times { |i| puts(i) } # ok
3.times.class # Enumerator
n = 3.times
n.class # Enumerator
n { |i| puts(i) } # error!?

Yes, because there is no method “n”. The block makes it parse as a
method call.

Does this inconsistency result from a parser-level layer of ‘syntactic
sugar’? I’m also getting a sense that a ‘block’ is a parser-level
construct,
and a ‘Proc’ is an execution-level object.

In a way: Proc is the class of the block instance:

irb(main):006:0> def f(&b) b end
=> nil
irb(main):007:0> x = f {|a| puts a}
=> #Proc:[email protected]:7(irb)
irb(main):008:0> x.class
=> Proc

So, a related question: given an Enumerator and a 1-ary Proc (lambda):

n = 3.times
f = lambda { |i| puts(i) }

What expression allows us to ‘map’ or ‘apply’ the Proc to each
enumerated value?

Invoking method #each as you’ve shown above. More correctly, invoking
any method will do. Some methods just ignore the block.

There just seems to be something really ‘wrong’ about how Ruby treats
functions:

def f2(i)
puts(i)
end

f2.class # error!?

Ruby is not a functional language so methods are not first class
objects.

Functions are not first-class objects? I actually have no idea what f2
is. Clearly its not a symbol bound to an object. It’s ‘something else’.

Keyword “def” introduces a method definition. The method is bound to a
class (what class depends on context) under the identifier given.

Intuitively I would have expected the follow two constructs to produce
operatively identical objects:

def f2(i)
puts(i)
end

f2 = lambda { |i| puts(i) }

They won’t.

I’m really puzzled by this. Coming from years of programming in Scheme
I’m quite used to dealing with syntax-layer transformations. But there
is evidently something else going on with Ruby that violates a lot of my
intuitions and expectations. I’m hoping that once I understand it better
it will start to look ‘elegant’ and ‘beautiful’, but right now it looks
kinda ‘scary’ and ‘repugnant’.

It will be easier for you if you stop expecting Ruby to be a
functional programming language - it isn’t. As simple as that. Ruby
is a dynamically but strictly typed object oriented programming
language. Even though it has some support for functional style
programming and also real closures.

Cheers

robert

Robert K. wrote in post #1093088:

Ruby is not a functional language so methods are not first class
objects.

It will be easier for you if you stop expecting Ruby to be a
functional programming language - it isn’t. As simple as that. Ruby
is a dynamically but strictly typed object oriented programming
language. Even though it has some support for functional style
programming and also real closures.

That puts it in perspective. Out with the old idioms, in with the new;
the price to be paid for doing away with all those parentheses. Thanks.

_ Dave

Robert K. wrote in post #1093088:

Ruby is not a functional language so methods are not first class objects.

I’ve just learned that methods can be first class objects:

add_two = 2.method(:+)
add_two.class # => Method
(1…3).map(&add_two) # => [3,4,5]

Using this idiom, methods become first class objects.

It appears that Ruby may well facilitate many (if not all) of the
functional idioms I’m fond of using. There may be some performance
penalties associated with some of these idioms however.

So this whole topic area seems much more robust and arcane than is
apparently commonly understood. It’s not as simple as “Ruby is not a
functional language” and “methods are not first class objects”. It’s
obviously a bigger matter of understanding the Ruby class hierarchy and
full syntax.

I’ve only been studying Ruby for three days and I’m still obviously
struggling with the basics. But at least now I see that Ruby has some
‘hidden’ potential.

_ Dave

On Jan 21, 2013, at 2:20 PM, David R. [email protected]
wrote:

Does this inconsistency result from a parser-level layer of ‘syntactic
sugar’? I’m also getting a sense that a ‘block’ is a parser-level
construct,
and a ‘Proc’ is an execution-level object.

I don’t think it is stressed enough that a block is a syntactic
structure
that is always part of a method call.

When a method executes, the block associated with the method call can
be executed implicitly via the ‘yield’ keyword, or explicitly reified
into a Proc object. Once captured within an Proc object it can be
executed
via the #call or #[] methods on the object (which are instance methods
of
the Proc class).

The reification (or capture) can be triggered via the block argument in
a formal argument list:

def foo(arg0, &block)
yield("arg to the block) # call implicit block
block.call(“arg to block”) # call same block via Proc#call
instance method
block[“arg to block”] # call same block via Proc#[] instance
method
end

or the reification can be triggered on demand:

def foo(arg0)
if some_condition)
captured = Proc.new # Proc.new without explicit block
captures current implicit block
else
yield(“arg to block”) # call implicit block
end
end

Proc objects can also be created via the Kernel#proc method call:

addition = proc { |a,b| a + b }
multiplication = proc { |c,d| c * d }

puts addition.call(1,2) # => 3
puts multiplication.call(2,10) # => 20

In these examples, the blocks are syntactically part of the calls to to
the proc method.

puts addition.class # => Proc
puts multiplication.class # => Proc

Gary W.

Nice and helpful it is.

Thanks to all

Gary W. wrote in post #1093103:

On Jan 21, 2013, at 2:20 PM, David R. [email protected]
wrote:

Does this inconsistency result from a parser-level layer of ‘syntactic
sugar’? I’m also getting a sense that a ‘block’ is a parser-level
construct,
and a ‘Proc’ is an execution-level object.

I don’t think it is stressed enough that a block is a syntactic
structure

But it is possible to create a block programmatically during runtime by
creating a Proc and converting it to a block with the & operator.

that is always part of a method call.

This page helped clear up a lot of my confusion:

http://eli.thegreenplace.net/2006/04/18/understanding-ruby-blocks-procs-and-methods/

Now I understand that blocks are a shorthand notation than many Ruby
programmers avoid. Depending on the case, using blocks may make the
program easier or harder to understand. But more than a mere matter of
style, there are performance penalties involved, depending on which
constructs are used:

http://www.confreaks.com/videos/427-rubyconf2010-zomg-why-is-this-code-so-slow

When a method executes, the block associated with the method call can
be executed implicitly via the ‘yield’ keyword, or explicitly reified
into a Proc object. Once captured within an Proc object it can be
executed
via the #call or #[] methods on the object (which are instance methods
of the Proc class).

And Procs can be converted into blocks, using the ‘&’ operator.

multiply = lambda{ |x| x*2 }
[1,2,3].map &multiply

The reification (or capture) can be triggered via the block argument in
a formal argument list:

def foo(arg0, &block)
yield("arg to the block) # call implicit block
block.call(“arg to block”) # call same block via Proc#call
instance method
block[“arg to block”] # call same block via Proc#[] instance
method
end

or the reification can be triggered on demand:

def foo(arg0)
if some_condition)
captured = Proc.new # Proc.new without explicit block
captures current implicit block
else
yield(“arg to block”) # call implicit block
end
end

Understood. Here’s a cleaned-up version of your example code with
example calls:

def foo(arg0, &block)
yield(“arg to yield”) # call implicit block
block.call(“arg to block.call”) # call same block via Proc#call
instance method
block[“arg to block[]”] # call same block via Proc#[] instance
method
end

foo(nil){|x| puts(x)}

def foo2(arg0)
if (arg0)
captured = Proc.new # Proc.new without explicit block captures
current implicit block
captured[“Proc.new”]
else
yield(“yield”) # call implicit block
end
end

foo2(true) {|x| puts(x)}
foo2(false){|x| puts(x)}

Proc objects can also be created via the Kernel#proc method call:

addition = proc { |a,b| a + b }
multiplication = proc { |c,d| c * d }

puts addition.call(1,2) # => 3
puts multiplication.call(2,10) # => 20

In these examples, the blocks are syntactically part of the calls to to
the proc method.

puts addition.class # => Proc
puts multiplication.class # => Proc

All understood. It’s coming into focus. Thanks.

_ Dave

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs