views:

71

answers:

2

I would like to achieve the following by introducing a new operator (e.g. :=)

a := b = {}
b[1] = 2
p a # => {}
p b # => {1=>2}

As far as I understand, I need to modify the Object class, but I don't know what to do in order to get what I want.

require 'superators'
class Object
  superator ":=" operand # update, must be: superator ":=" do |operand|
    # self = Marshal.load(Marshal.dump(operand)) # ???
  end
end

Could you help me with this?


Update

Ok, superators will probably not help me here, but I still want such operator. How can I (or you) create an extension for Ruby, which I could load as a module?

require 'deep_copy_operator'
a !?= b = {} # I would prefer ":=" but don't really care how it is spelled
b[1] = 2
p a # => {}
p b # => {1=>2}
+1  A: 

First of all, the syntax for superators is

superator ":=" do |operand|
  #code
end

It's a block, because superator is a metaprogramming macro.

Secondly, you have something going their with Marshal...but it's a bit of magic-ish. Feel free to use it as long as you understand exactly what it is you're doing.

Thirdly, what you are doing isn't quite doable with a superator (I believe), because self cannot be modified during a function. (if someone knows otherwise, please let me know)

Also, in your example, a must first exist and be defined before being able to call the method := in it.

Your best bet is probably:

class Object
  def deep_clone
    Marshal::load(Marshal.dump(self))
  end
end

to generate a deep clone of an object.

a = (b = {}).deep_clone
b[1] = 2
p a # => {}
p b # => {1=>2}
Justin L.
Surely the operand goes after the do, right? Because it's a block argument?
Chuck
Ok, thanks, it must be a block not method indeed. Using `deep_clone` would help, but it makes it messy, especially if one has not 2 but 5 hashes to initialize. So I am really curious about making such operator.
Andrey
@chuck - You're right; I made a typo; @Andrei - It's impossible without getting really messy, because you are basically wanting to modify `self`, as well as calling a method on an object that is not yet defined.
Justin L.
Could you perhaps provide an example of what you are doing? There might be a more efficient way than using superators; perhaps a generator of sorts?
Justin L.
I am rewriting my PHP-code in Ruby, and need to [initialize several auto-vivifying hashes](http://stackoverflow.com/questions/3172342/how-to-handle-combination-for-auto-vivifying-hash-in-ruby). So far I came to `a,b,c=AutoHash.new.few 3`, which I would be [happy to replace](http://stackoverflow.com/questions/3165331/multiple-initialization-of-auto-vivifying-hashes-using-a-new-operator-in-ruby) by `a:=b:=c=AutoHash.new`
Andrey
+3  A: 

Hi, wow, superators look neat! But unfortunately, this won't work for you, for two reasons. First, your operator does not match the regex (you cannot use a colon). Easy enough, find a new operator. But the second one I don't think can be overcome, the superator is basically a method name defined on the object to the left. So you can't use it for assignment statements. If your variable is not defined, then you cannot use it, that would raise an error. And if it is defined, then you can't change its type in any way that is obvious to me (maybe with some level of reflection and metaprogramming that is way beyond anything I know, but it honestly seems unlikely... of course, I would have never expected it to be possible to create superators, so who knows).

So I think you're back to hacking parse.y and rebuilding your Ruby.

Joshua Cheek
Thanks again, Joshua! I still have some hope that one can create such operator without recompiling Ruby. Otherwise, my code will be harder to use by other people. My hope is that one can make a module/gem, which others can install and enable such operator.
Andrey