Why is the Binding object so useless?

T

Tony Arcieri

[Note: parts of this message were removed to make it a legal post.]

I am used to Ruby being a rather reflective language that gives carte
blanche to the programmer. So I found this rather surprising:
TypeError: no marshal_dump is defined for class Binding

Whaa?
NoMethodError: undefined method `new' for Binding:Class

Huh?
=> []

You're kidding me, right?

I would expect you to be able to do all of the above. In addition to that,
it's sure be nice to do some of the following:
=> "--- !ruby/object:Binding \na: 1\nb: 2\nc: 3\n" # YAML dump of a Binding
object

And hey, maybe Binding#inspect could give a little more information than its
object_id?

Canned responses to apologists:

= Why do you want to do that?

I don't know, why should you be able to redefine Integer#+?

= No really, why do you want to do that?

I would like to implement a remote REPL with a stateless Ruby server and a
non-Ruby client

= Just use DRb!

I am really not wanting to open up an addition port just for DRb nor pursue
solutions which involve a non-Ruby client talking the DRb protocol.
Embedding some form of Ruby interpreter client side is not an option.

Props to Rubinius for fixing some of these problems!

irb(main):001:0> Binding.new
=> #<Binding:0x2e0>

Yay! A clean binding!
=> "\004\bo:\fBinding\000"

Amazing!
 
B

Brian Candler

Tony said:
= No really, why do you want to do that?

I would like to implement a remote REPL with a stateless Ruby server and
a
non-Ruby client

Your proposed feature would also make things like the ActionPack
template rendering much cleaner. grep for "local_assigns" in
action_view/renderable.rb (rails 2.3.x) and weep. Here is what they end
up doing, where local_assigns is a hash of variable=>value bindings:

def compile!(render_symbol, local_assigns)
locals_code = local_assigns.keys.map { |key| "#{key} =
local_assigns[:#{key}];" }.join

source = <<-end_src
def #{render_symbol}(local_assigns)
old_output_buffer =
output_buffer;#{locals_code};#{compiled_source}
ensure
self.output_buffer = old_output_buffer
end
end_src

(Rails 3 is the same, but the file is action_view/template.rb and the
method is compile not compile!)

The above is probably what your REPL server should do.

I guess what you propose wasn't implemented simply because it involves
work to convert bindings between their internal representation and
external forms like Hash and Marshal#dump. If you grab an existing live
binding and pass it around, the conversion isn't required.
 
R

Robert Klemme

2010/1/25 Tony Arcieri said:
I am used to Ruby being a rather reflective language that gives carte
blanche to the programmer. =A0So I found this rather surprising:

TypeError: no marshal_dump is defined for class Binding

Whaa?

I don't think it does make sense to serialize a binding for the same
reason that you cannot create a new binding: a binding is bound to a
particular program context - I assume this also includes caller stack
and other internal state.

Even if a binding contains local variables what is the effect of
deserializing a binding? If your local variables get updated that is
certainly not a good idea. If you want to serialize state use objects
with the proper state.
NoMethodError: undefined method `new' for Binding:Class

Huh?

A binding is not a regular object but it is a handle on the state of
the runtime. A method object cannot be serialized as well because
that would mean that the original code would have to be written (and
read); this also has security implications (in the case of Method).

But if you have to_hash you can serialize that.
I would expect you to be able to do all of the above. =A0In addition to t= hat,
it's sure be nice to do some of the following:

=3D> #<Binding:0x1018130b0> # new binding object with the given variables
bound

As above.
=3D> "--- !ruby/object:Binding \na: 1\nb: 2\nc: 3\n" # YAML dump of a Bin= ding
object

Same as above for Marshal.
And hey, maybe Binding#inspect could give a little more information than = its
object_id?

Yeah, #to_hash and #inspect sound pretty good. You might even add a
method #update receiving a Hash which is interpreted as a mapping from
local variables to values and which overwrites the current binding.

Kind regards

robert

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

Tony Arcieri

[Note: parts of this message were removed to make it a legal post.]

I don't think it does make sense to serialize a binding for the same
reason that you cannot create a new binding: a binding is bound to a
particular program context - I assume this also includes caller stack
and other internal state.

Why can't bindings be independently garbage collected objects too? (as it
appears they are in rbx)

Even if a binding contains local variables what is the effect of
deserializing a binding? If your local variables get updated that is
certainly not a good idea. If you want to serialize state use objects
with the proper state.

The goal is to have an object to pass to eval as the binding argument, not
to update locals.

Ideally I could pass a fresh binding (made with Binding.new) to eval, and
when eval is finished it will be updated with whatever assignments were made
in the evaluated code. I could then serialize this and persist it until the
next eval call.
 

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,770
Messages
2,569,583
Members
45,074
Latest member
StanleyFra

Latest Threads

Top