From block to code (also: how to get the bindings of a block)

Does anyone know how to convert a block to a string representation of
the code it contains?

I would need that to inject some code within a block and evaluate the
resulting code.

* I cannot simply append the code because I need the bindings of the block.
* I cannot explicitly return the bindings from the block because I am
working on a DSL.
* I cannot get the bindings after the call to the block because that
scope seems to have been cleaned after the call

···

--
Chiaroscuro

chiaro scuro wrote:

Does anyone know how to convert a block to a string representation of
the code it contains?

Read the source file?

Cheers,
Dave

Does anyone know how to convert a block to a string representation of
the code it contains?

lib/r2chacks.rb in ZenHacks has this.

I would need that to inject some code within a block and evaluate the
resulting code.

* I cannot simply append the code because I need the bindings of the block.

Bindings are not preserved. You'd need more magic than PT has to get these along with the block.

* I cannot explicitly return the bindings from the block because I am
working on a DSL.
* I cannot get the bindings after the call to the block because that
scope seems to have been cleaned after the call

If you need the bindings from a proc you are probably trying to solve the wrong problem.

···

On Apr 27, 2006, at 12:35 AM, chiaro scuro wrote:

--
Eric Hodel - drbrain@segment7.net - http://blog.segment7.net
This implementation is HODEL-HASH-9600 compliant

http://trackmap.robotcoop.com

how would I know what is the source file and lines associated with a block?

I was really hoping to get the info from the runtime, but I guess that
what you suggest could also be a pragmatic option.

···

On 4/27/06, Dave Burt <dave@burt.id.au> wrote:

chiaro scuro wrote:
> Does anyone know how to convert a block to a string representation of
> the code it contains?

Read the source file?

Cheers,
Dave

--
Chiaroscuro
---
Liquid Development: http://liquiddevelopment.blogspot.com/

> Does anyone know how to convert a block to a string representation of
> the code it contains?

lib/r2chacks.rb in ZenHacks has this.

I'll check it out thanks.

If you need the bindings from a proc you are probably trying to solve

the wrong problem.

I would normally agree with you, but this is not a design problem or a
domain-conceptualization problem.

It's a language-twisting problem that imposes otherwise unimportant
constraints on what I can and cannot do.

···

On 4/30/06, Eric Hodel <drbrain@segment7.net> wrote:

On Apr 27, 2006, at 12:35 AM, chiaro scuro wrote:

--
Chiaroscuro
---
Liquid Development: http://liquiddevelopment.blogspot.com/

chiaro scuro wrote:

Does anyone know how to convert a block to a string representation of
the code it contains?

Read the source file?

how would I know what is the source file and lines associated with a block?

I was really hoping to get the info from the runtime, but I guess that
what you suggest could also be a pragmatic option.

OK, here are some practical options. (Sorry for the previous comment. I
was trying to dig this stuff up from my memory, but Quiz 34 came up
instead.)

#1: You can store a Proc with its code if you're willing to forgo
closure of the the environment and to use syntax like this:

method_name %{
  proc_code
}

See Ruby Quiz 38: SerializableProc - Ruby Quiz - SerializableProc (#38)

#2: You can get it from (I think) the runtime, using ZenHacks'
Proc.to_ruby. See Ryan Davis' post in response to the same quiz:
http://www.ruby-talk.org/cgi-bin/scat.rb/ruby/ruby-talk/148082

Cheers,
Dave

Does ParseTree solve your problem?

http://rubyforge.org/projects/parsetree/

- James Moore

If you need the bindings from a proc you are probably trying to solve the wrong problem.

I would normally agree with you, but this is not a design problem or a domain-conceptualization problem.

I doubt your problem is really that special.

It's a language-twisting problem that imposes otherwise unimportant constraints on what I can and cannot do.

If you're doing something this ugly you're probably doing something very wrong.

···

On Apr 30, 2006, at 1:30 PM, chiaro scuro wrote:

On 4/30/06, Eric Hodel <drbrain@segment7.net> wrote:

--
Eric Hodel - drbrain@segment7.net - http://blog.segment7.net
This implementation is HODEL-HASH-9600 compliant

http://trackmap.robotcoop.com

I dunno know about the binding (maybe you can use method_missing + Binding.of_caller)

but one to get the code (well the ast, which is pretty darn close) is do something like:
require 'parse_tree'

def recipe(name, &blk)
    class A; end
    A.class_eval { define_method(:code, &blk) }
    pt = ParseTree.new
    sexprs = pt.parse_tree(A)
end

···

On Apr 30, 2006, at 4:30 PM, chiaro scuro wrote:

On 4/30/06, Eric Hodel <drbrain@segment7.net> wrote:

On Apr 27, 2006, at 12:35 AM, chiaro scuro wrote:

> Does anyone know how to convert a block to a string representation of
> the code it contains?

lib/r2chacks.rb in ZenHacks has this.

I'll check it out thanks.

If you need the bindings from a proc you are probably trying to solve

the wrong problem.

I would normally agree with you, but this is not a design problem or a
domain-conceptualization problem.

It's a language-twisting problem that imposes otherwise unimportant
constraints on what I can and cannot do.

--
Chiaroscuro
---
Liquid Development: http://liquiddevelopment.blogspot.com/

The quiz is a great resource, thanks.

In this case it happens that I can ignore closures.

However, I don't need closures I don't see why Ruby shouldn't
implement a method to return the code of a block..

···

On 4/27/06, Dave Burt <dave@burt.id.au> wrote:

chiaro scuro wrote:
>>> Does anyone know how to convert a block to a string representation of
>>> the code it contains?
>> Read the source file?
> how would I know what is the source file and lines associated with a block?
>
> I was really hoping to get the info from the runtime, but I guess that
> what you suggest could also be a pragmatic option.

OK, here are some practical options. (Sorry for the previous comment. I
was trying to dig this stuff up from my memory, but Quiz 34 came up
instead.)

#1: You can store a Proc with its code if you're willing to forgo
closure of the the environment and to use syntax like this:

method_name %{
  proc_code
}

See Ruby Quiz 38: SerializableProc - Ruby Quiz - SerializableProc (#38)

#2: You can get it from (I think) the runtime, using ZenHacks'
Proc.to_ruby. See Ryan Davis' post in response to the same quiz:
http://www.ruby-talk.org/cgi-bin/scat.rb/ruby/ruby-talk/148082

Cheers,
Dave

--
Chiaroscuro
---
Liquid Development: http://liquiddevelopment.blogspot.com/

I found an alternative way to get the bindings.. I posted about it here:
http://liquiddevelopment.blogspot.com/2006/04/way-of-meta-part-iv-hijacking-local.html

the DSL code looks like this:

shopping_list "english breakfast" do
    tomatoes = 2, :green
    sausages = 3
    eggs = 2, :big
    bacon = 4
the end

···

--
Chiaroscuro
---
Liquid Development: http://liquiddevelopment.blogspot.com/

On 4/27/06, James Moore <banshee@banshee.com> wrote:

Does ParseTree solve your problem?

http://rubyforge.org/projects/parsetree/

- James Moore

> I would normally agree with you, but this is not a design problem
> or a domain-conceptualization problem.

I doubt your problem is really that special.

it's special in respect to the fact that goes against the boundaries of the
language, so it cannot necessarily rely on beautiful 'natural' constructs
that apply within the conceptual boundaries of the language.

It's a language-twisting problem that imposes otherwise unimportant
> constraints on what I can and cannot do.

If you're doing something this ugly you're probably doing something
very wrong.

Eric, how would you do it?

recipe "breakfast" do
  eggs = 2, :big
  bacon = 3
end

this should add to a global hash (or return directly) the following:

{
  :eggs => [2,:big],
  :bacon => [3]
}

I need to keep the equal signs.

···

On 5/1/06, Eric Hodel <drbrain@segment7.net> wrote:

--
Chiaroscuro
---
Liquid Development: http://liquiddevelopment.blogspot.com/

If it works, it's brilliant!

···

On 5/2/06, Logan Capaldo <logancapaldo@gmail.com> wrote:

On Apr 30, 2006, at 4:30 PM, chiaro scuro wrote:

> On 4/30/06, Eric Hodel <drbrain@segment7.net> wrote:
>>
>> On Apr 27, 2006, at 12:35 AM, chiaro scuro wrote:
>>
>> > Does anyone know how to convert a block to a string
>> representation of
>> > the code it contains?
>>
>> lib/r2chacks.rb in ZenHacks has this.
>
> I'll check it out thanks.
>
> If you need the bindings from a proc you are probably trying to solve
>> the wrong problem.
>
> I would normally agree with you, but this is not a design problem or a
> domain-conceptualization problem.
>
> It's a language-twisting problem that imposes otherwise unimportant
> constraints on what I can and cannot do.
>
> --
> Chiaroscuro
> ---
> Liquid Development: http://liquiddevelopment.blogspot.com/

I dunno know about the binding (maybe you can use method_missing +
Binding.of_caller)

but one to get the code (well the ast, which is pretty darn close) is
do something like:
require 'parse_tree'

def recipe(name, &blk)
    class A; end
    A.class_eval { define_method(:code, &blk) }
    pt = ParseTree.new
    sexprs = pt.parse_tree(A)
end

--
Chiaroscuro
---
Liquid Development: http://liquiddevelopment.blogspot.com/

chiaro scuro wrote:

I found an alternative way to get the bindings.. I posted about it here:
Liquid Development: The Way of Meta - Part IV - Hijacking Local Variables in DSLs

the DSL code looks like this:

shopping_list "english breakfast" do
   tomatoes = 2, :green
   sausages = 3
   eggs = 2, :big
   bacon = 4
the end

"The end" meaning "return the block's local variable binding" is a very
interesting way to approach it. Steal the block's locals! Cool!

Cheers,
Dave

This is my big question; why do you need the equal signs? I see
nothing inherent about the "recipe" domain that makes the equal signs
necessary or even desirable. If you were willing to ditch them, a
whole slew of simpler and cleaner implementations are available.

Jacob Fugal

···

On 5/1/06, chiaro scuro <kiaroskuro@gmail.com> wrote:

Eric, how would you do it?

recipe "breakfast" do
  eggs = 2, :big
  bacon = 3
end

this should add to a global hash (or return directly) the following:

{
  :eggs => [2,:big],
  :bacon => [3]
}

I need to keep the equal signs.

> I would normally agree with you, but this is not a design problem
> or a domain-conceptualization problem.

I doubt your problem is really that special.

it's special in respect to the fact that goes against the boundaries of the
language, so it cannot necessarily rely on beautiful 'natural' constructs
that apply within the conceptual boundaries of the language.

It's a language-twisting problem that imposes otherwise unimportant
> constraints on what I can and cannot do.

If you're doing something this ugly you're probably doing something
very wrong.

Eric, how would you do it?

recipe "breakfast" do
eggs = 2, :big
bacon = 3
end

this should add to a global hash (or return directly) the following:

{
:eggs => [2,:big],
:bacon => [3]
}

def recipe(name, &block)
   o = Object.new
   o.instance_variable_set :@attrs, {}
   def o.method_missing(name, *args)
     name = name.to_s.sub(/add_/, '').intern
     @attrs[name] = args
   end
   o.instance_eval &block
   return o.instance_variable_get(:@attrs)
end

ingredients = recipe 'breakfast' do
   add_eggs 2, :big
   add_bacon 3
end

p ingredients

I need to keep the equal signs.

Why?

···

On May 1, 2006, at 12:50 PM, chiaro scuro wrote:

On 5/1/06, Eric Hodel <drbrain@segment7.net> wrote:

--
Eric Hodel - drbrain@segment7.net - http://blog.segment7.net
This implementation is HODEL-HASH-9600 compliant

http://trackmap.robotcoop.com

I realize that would make it much easier in ruby.
It's just that the equal signs make lots of sense to my DSL users. (forget
the recipes, it's just an example)

Look, it's not a matter of life or death. *of course* I can do without if
there is no alternative.
(eventually I did find a solution to this -although it's a cheesy one- but I
am not saying yet :wink:

It just bothers me that I cannot access that context if I need to, and in
this case I do.

···

On 5/1/06, Jacob Fugal <lukfugl@gmail.com> wrote:

On 5/1/06, chiaro scuro <kiaroskuro@gmail.com> wrote:
> I need to keep the equal signs.

This is my big question; why do you need the equal signs? I see
nothing inherent about the "recipe" domain that makes the equal signs
necessary or even desirable. If you were willing to ditch them, a
whole slew of simpler and cleaner implementations are available.

Jacob Fugal

--
Chiaroscuro
---
Liquid Development: http://liquiddevelopment.blogspot.com/

my users like them :slight_smile:

but the main point is that it upsets me that I cannot get the language to do
what I want. Don't extrapolate too much from this statement.. I don't want
to do crazy things, just use equal to assign variables and then get them
back.

I am complaining a bit, but ruby is still the nicer way to design DSLs out
there.

···

On 5/2/06, Eric Hodel <drbrain@segment7.net> wrote:

> I need to keep the equal signs.

Why?

--
Chiaroscuro
---
Liquid Development: http://liquiddevelopment.blogspot.com/

it would be tough to convince me that people wouldn't find this syntax
natural:

   harp:~ > cat a.rb
   class Recipe < Hash
     attr 'name'
     def initialize name, &b
       @name = name
       instance_eval &b
     end
     def method_missing m, *a, &b
       m = m.to_s.delete '='
       self[m] = a.size > 1 ? a : a.shift
     end
   end
   def recipe(*a, &b) Recipe.new(*a, &b) end

   r =
     recipe "breakfast" do
       eggs 2, :big
       bacon 3
     end

   p r

   harp:~ > ruby a.rb

   {"bacon"=>3, "eggs"=>[2, :big]}

for example, write down a recipe and see if you use the '=' sign :wink:

regards.

-a

···

On Tue, 2 May 2006, chiaro scuro wrote:

On 5/1/06, Jacob Fugal <lukfugl@gmail.com> wrote:

On 5/1/06, chiaro scuro <kiaroskuro@gmail.com> wrote:
> I need to keep the equal signs.

This is my big question; why do you need the equal signs? I see
nothing inherent about the "recipe" domain that makes the equal signs
necessary or even desirable. If you were willing to ditch them, a
whole slew of simpler and cleaner implementations are available.

Jacob Fugal

I realize that would make it much easier in ruby.
It's just that the equal signs make lots of sense to my DSL users. (forget
the recipes, it's just an example)

Look, it's not a matter of life or death. *of course* I can do without if
there is no alternative.
(eventually I did find a solution to this -although it's a cheesy one- but I
am not saying yet :wink:

It just bothers me that I cannot access that context if I need to, and in
this case I do.

--
be kind whenever possible... it is always possible.
- h.h. the 14th dali lama

In return for keeping the equals signs, would the users let you get away
with a few 'at' symbols?

def recipe(name, &blk)
  o = Object.new
  o.instance_eval(&blk)
  o.instance_variables.inject({}) do |h,s|
    h[s[1..-1]] = o.instance_variable_get(s)
    h
  end
end
# => nil

recipe "eggs and bacon" do
  @eggs = [2,:big]
  @bacon = 3
end
# => {"bacon"=>3, "eggs"=>[2, :big]}

(Though I'd really recommend most of the other ideas from this thread
over this).

···

On Tue, 2006-05-02 at 05:11 +0900, chiaro scuro wrote:

On 5/1/06, Jacob Fugal <lukfugl@gmail.com> wrote:
>
> On 5/1/06, chiaro scuro <kiaroskuro@gmail.com> wrote:
> > I need to keep the equal signs.
>
> This is my big question; why do you need the equal signs? I see
> nothing inherent about the "recipe" domain that makes the equal signs
> necessary or even desirable. If you were willing to ditch them, a
> whole slew of simpler and cleaner implementations are available.
>
I realize that would make it much easier in ruby.
It's just that the equal signs make lots of sense to my DSL users. (forget
the recipes, it's just an example)

--
Ross Bamford - rosco@roscopeco.REMOVE.co.uk