Are blocks objects? What messages can they handle?

Stop me if I'm making any unwarranted assumptions here:

Blocks are basically just a special kind of object passed to a method in
Ruby -- aren't they?

That makes them objects -- right?

So . . . how does one send a message to the block before it is passed as
an argument? Is that even possible?

I ask based on curiosity and a desire to better understand the language,
rather than as any kind of need to solve a real-world problem.

···

--
Chad Perrin [ original content licensed OWL: http://owl.apotheon.org ]

A block is a syntactical construct, not an object. A Proc is the
object-ized form of a block. If you want to do something on the block,
you need to turn it into an object first.

An analogy might be that the string "def" is a syntactical construct
that creates a method, but it is not itself an object. You can't write
"def.(...)" and have it be meaningful in this context.

So . . . how does one send a message to the block before it is passed as
an argument? Is that even possible?

You could make it a Proc first and pass that instead. For example, say
you have a method which passes some arguments to a block:

···

======

def execute(*args, &block); yield *args if block; end

=> nil

execute(1, 2, 3) { |*args| puts "args are: #{args.inspect}" }

args are: [1, 2, 3]
=> nil

Instead of supplying the block, you could pass a block argument:

======

printer = lambda { |*args| puts "args are: #{args.inspect}" }

=> #<Proc:0x0000000125eeb8@(irb):12 (lambda)>

execute(1, 2, 3, &printer)

args are: [1, 2, 3]

Since `printer` is an object, you can call whatever methods you'd like
on it before passing it as a block. Of course, you still need to wind
up with something that looks like a block, or else the `yield` won't
work. For example, you might have a Proc that creates `printers` for
you:

======

printer_factory = lambda { |message_prefix| lambda { |*args| puts "#{message_prefix}: #{args.inspect}" } }

=> #<Proc:0x000000011f9f90@(irb):17 (lambda)>

Now we can ask this Proc to create a printer for us, which we'll then
pass into `execute` as a block argument:

======

execute(1, 2, 3, &printer_factory.("the arguments to this printer are"))

the arguments to this printer are: [1, 2, 3]

Make sense?

~ jf
--
John Feminella
Principal Consultant, BitsBuilder
LI: http://www.linkedin.com/in/johnxf
SO: User John Feminella - Stack Overflow

On Sun, Jul 3, 2011 at 10:12, Chad Perrin <code@apotheon.net> wrote:

Stop me if I'm making any unwarranted assumptions here:

Blocks are basically just a special kind of object passed to a method in
Ruby -- aren't they?

That makes them objects -- right?

So . . . how does one send a message to the block before it is passed as
an argument? Is that even possible?

I ask based on curiosity and a desire to better understand the language,
rather than as any kind of need to solve a real-world problem.

--
Chad Perrin [ original content licensed OWL: http://owl.apotheon.org ]

John,
    although I was not original question author, wanted to thank you for
that great explanation and example.

stephenb

···

2011/7/3 John Feminella <johnf@bitsbuilder.com>

A block is a syntactical construct, not an object. A Proc is the
object-ized form of a block. If you want to do something on the block,
you need to turn it into an object first.

An analogy might be that the string "def" is a syntactical construct
that creates a method, but it is not itself an object. You can't write
"def.(...)" and have it be meaningful in this context.

> So . . . how does one send a message to the block before it is passed as
> an argument? Is that even possible?

You could make it a Proc first and pass that instead. For example, say
you have a method which passes some arguments to a block:

======
> def execute(*args, &block); yield *args if block; end
=> nil

> execute(1, 2, 3) { |*args| puts "args are: #{args.inspect}" }
args are: [1, 2, 3]
=> nil

Instead of supplying the block, you could pass a block argument:

======
> printer = lambda { |*args| puts "args are: #{args.inspect}" }
=> #<Proc:0x0000000125eeb8@(irb):12 (lambda)>

> execute(1, 2, 3, &printer)
args are: [1, 2, 3]

Since `printer` is an object, you can call whatever methods you'd like
on it before passing it as a block. Of course, you still need to wind
up with something that looks like a block, or else the `yield` won't
work. For example, you might have a Proc that creates `printers` for
you:

======
> printer_factory = lambda { |message_prefix| lambda { |*args| puts
"#{message_prefix}: #{args.inspect}" } }
=> #<Proc:0x000000011f9f90@(irb):17 (lambda)>

Now we can ask this Proc to create a printer for us, which we'll then
pass into `execute` as a block argument:

======
> execute(1, 2, 3, &printer_factory.("the arguments to this printer are"))
the arguments to this printer are: [1, 2, 3]

Make sense?

~ jf
--
John Feminella
Principal Consultant, BitsBuilder
LI: http://www.linkedin.com/in/johnxf
SO: User John Feminella - Stack Overflow

On Sun, Jul 3, 2011 at 10:12, Chad Perrin <code@apotheon.net> wrote:
> Stop me if I'm making any unwarranted assumptions here:
>
> Blocks are basically just a special kind of object passed to a method in
> Ruby -- aren't they?
>
> That makes them objects -- right?
>
> So . . . how does one send a message to the block before it is passed as
> an argument? Is that even possible?
>
> I ask based on curiosity and a desire to better understand the language,
> rather than as any kind of need to solve a real-world problem.
>
> --
> Chad Perrin [ original content licensed OWL: http://owl.apotheon.org ]
>

I was the author of the original question, and I agree. Thanks.

···

On Mon, Jul 04, 2011 at 12:15:54AM +0900, Stephen Boesch wrote:

John,
    although I was not original question author, wanted to thank you for
that great explanation and example.

--
Chad Perrin [ original content licensed OWL: http://owl.apotheon.org ]

John,
although I was not original question author, wanted to thank you for
that great explanation and example.

Just one point of nitpicking:

A block is a syntactical construct, not an object. A Proc is the
object-ized form of a block. If you want to do something on the block,
you need to turn it into an object first.

An analogy might be that the string "def" is a syntactical construct
that creates a method, but it is not itself an object. You can't write
"def.(...)" and have it be meaningful in this context.

> So . . . how does one send a message to the block before it is passed as
> an argument? Is that even possible?

You could make it a Proc first and pass that instead. For example, say
you have a method which passes some arguments to a block:

======
> def execute(*args, &block); yield *args if block; end
=> nil

I'd rather use these in pairs because the conversion of a block to an
accessible object has some overhead:

- block_given? and yield
- &b and b / b.call

So either

def execute(*args)
  yield *args if block_given?
end

or

def execute(*args, &block)
  block[*args] if block
end

respectively

def execute(*args, &block)
  block.call(*args) if block
end

Usually you only need the form with &block if you need to store the
block or pass it on to another method, e.g.

def foo
  yield 123
end

def bar(&b)
  foo(&b) # pass on
end

bar {|x| p x} # will print 123

Kind regards

robert

···

On Sun, Jul 3, 2011 at 5:15 PM, Stephen Boesch <javadba@gmail.com> wrote:

2011/7/3 John Feminella <johnf@bitsbuilder.com>

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

I found this site to be useful:
http://innig.net/software/ruby/closures-in-ruby.rb

···

On Sun, Jul 3, 2011 at 12:26 PM, Chad Perrin <code@apotheon.net> wrote:

On Mon, Jul 04, 2011 at 12:15:54AM +0900, Stephen Boesch wrote:

John,
although I was not original question author, wanted to thank you for
that great explanation and example.

I was the author of the original question, and I agree. Thanks.

--
Chad Perrin [ original content licensed OWL: http://owl.apotheon.org ]

That is a fair point, Robert. I didn't use block_given? because I
wanted to show that indeed, `block` is an object by the time you can
see it in the method. Using "if block_given?" might not have made that
clear, but I thought that writing "if block" makes it unambiguous that
`block` is a real object with its own semantics.

~ jf

···

--
John Feminella
Principal Consultant, BitsBuilder
LI: http://www.linkedin.com/in/johnxf
SO: User John Feminella - Stack Overflow

On Mon, Jul 4, 2011 at 11:54, Robert Klemme <shortcutter@googlemail.com> wrote:

On Sun, Jul 3, 2011 at 5:15 PM, Stephen Boesch <javadba@gmail.com> wrote:

John,
although I was not original question author, wanted to thank you for
that great explanation and example.

Just one point of nitpicking:

2011/7/3 John Feminella <johnf@bitsbuilder.com>

A block is a syntactical construct, not an object. A Proc is the
object-ized form of a block. If you want to do something on the block,
you need to turn it into an object first.

An analogy might be that the string "def" is a syntactical construct
that creates a method, but it is not itself an object. You can't write
"def.(...)" and have it be meaningful in this context.

> So . . . how does one send a message to the block before it is passed as
> an argument? Is that even possible?

You could make it a Proc first and pass that instead. For example, say
you have a method which passes some arguments to a block:

======
> def execute(*args, &block); yield *args if block; end
=> nil

I'd rather use these in pairs because the conversion of a block to an
accessible object has some overhead:

- block_given? and yield
- &b and b / b.call

So either

def execute(*args)
yield *args if block_given?
end

or

def execute(*args, &block)
block[*args] if block
end

respectively

def execute(*args, &block)
block.call(*args) if block
end

Usually you only need the form with &block if you need to store the
block or pass it on to another method, e.g.

def foo
yield 123
end

def bar(&b)
foo(&b) # pass on
end

bar {|x| p x} # will print 123

Kind regards

robert

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

Jeremy, that was an excellent synopsis of the functionality of blocks,
procs, methods and lambdas. I'm starting to get my head around
anonymous functions, closures and currying.

Thanks.

···

I found this site to be useful:
http://innig.net/software/ruby/closures-in-ruby.rb

You can almost feel the authors pain in documenting all that.

If your interested in a colorized version of Paul Cantrell's tutorial:

http://rubyprogrammer.net/~stu/closures-in-ruby.rb.html

···

On Mon, Jul 4, 2011 at 1:23 PM, Joe Peric <peric.joe@gmail.com> wrote:

Jeremy, that was an excellent synopsis of the functionality of blocks,
procs, methods and lambdas. I'm starting to get my head around
anonymous functions, closures and currying.

Thanks.

>
> I found this site to be useful:
> http://innig.net/software/ruby/closures-in-ruby.rb
>
>