Browsing the blog archives for July, 2009.

Ruby dup vs clone

programming

I have had this question about the difference between Ruby’s clone and dup method multiple times now. And I have always had this fuzzy feeling that “they are almost the same thing”. Today my colleague asked it again and I decided to dig it out. Here’s what Ruby API docs say about them:

Object#clone
Produces a shallow copy of obj—the instance variables of obj are copied, but not the objects they reference. Copies the frozen and tainted state of obj.

Object#dup
Produces a shallow copy of obj—the instance variables of obj are copied, but not the objects they reference. dup copies the tainted state of obj. See also the discussion under Object#clone. In general, clone and dup may have different semantics in descendant classes. While clone is used to duplicate an object, including its internal state, dup typically uses the class of the descendant object to create the new instance.

This method may have class-specific behavior. If so, that behavior will be documented under the #initialize_copy method of the class.

So in essence, both produce shallow-copies of the object. clone copies the frozen and tainted state while dup copies only the tainted state. Even after reading that documentation twice, it’s still murky in my head (probably coz I have not had a chance to write code to notice the frozen or tainted state specifically.)

Here’s a gem from ruby-talk that Google brought up: http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/6328. So Matz says:

`clone’ copies everything; internal state, singleton methods, etc.
`dup’ copies object contents only (plus taintness status).

And so I wrote a bit of code to see it myself (and thus remember it). Here’s a very simple Person class:

class Person
  attr_accessor :name
end

Now we instantiate a Person object (p) and add then an singleton method on the new object (p) to say hi:

p = Person.new
p.name = "The Man"

# now add a singleton method on p:
def p.say_hi
  "'sup"
end

See that it’s all working:

irb(main):014:0> puts p.inspect
#<person :0xb7e83340 @name="The Man">
=> nil
irb(main):015:0> puts p.say_hi
'sup
=> nil

Now create a clone and a dup of it:

the_clone = p.clone
the_dup = p.dup

Both the clone and the dup have the same instance variables (which are shallow-copies BTW), but only the clone has the singleton method (say_hi) in it:

irb(main):018:0> the_clone.name
=> "The Man"
irb(main):019:0> the_dup.name
=> "The Man"
irb(main):020:0> the_clone.say_hi
=> "'sup"
irb(main):021:0> the_dup.say_hi
NoMethodError: undefined method `say_hi' for
(Person :0xb7e83340 @name="The Man")
        from (irb):21
        from :0
irb(main):022:0>

So that makes me feel that clone has to do more work than dup does. Hence dup might be more beneficial for performance compared to clone (unless you really need to use clone). Comments are welcome!

Add the first comment

GNU Screen

tech

If you have nothing to do with Linux you probably can stop reading now. Unless you want to get introduced to a very nice tool in the Linux world. I can say without doubt that this saves me at least an hour every month. In addition it gets you away from doing some mundane “set-up” like things every time to start working. It has a load of features but today I’ll just scratch the surface. But it’ll be enough to start you off and I promise you’ll be glad you found screen.

One of the programs that I love and can’t go through the day without is GNU Screen. It’s like a Window manager, but only for your terminals. You know, like you are working with so many terminals/consoles/terminal-windows all the time (one to the DB, one with vim open, one to run the tests, one to run the program etc., one to watch the logs, a few to prod boxes etc.). And then you disconnect and then reconnect (from home, somewhere else) and you have to set-up all that again?

Yeah screen can help you with all that. My work pattern involves connecting to a screen session (and I get all the windows/context loaded). Whether I connect from work, home from somewhere else, all I have to say is:

$ screen -ls (to see what sessions I have running)
$ screen -R some-session-name

And it’s wicked-easy to switch between different windows, search through your history etc. You can also configure it to do a few “start-up” things every time. For example, at home, I have screen

  1. configured to Open 4 windows when it starts up and
  2. have window-0 go to my code dir (to teh root of my RubyOnRails part of the site)
  3. start up auto-test on window-1
  4. show the logs on window-2
  5. ssh into the blue host (which hosts my site)

Since the windows are persisted, I don’t have to do all these things every time I connect (for a lazy programmer (and all programmers are lazy aren’t they?) that’s a lot of help). You can even share the screens with someone else (I have not tried that yet though).

Anyway, I hope you are sold by now. Even if you are not, spend some time (shouldn’t be more than a couple of hours) installing/configuring/running screen and you will soon reap the rewards. To get you started:

A word about configuring: heard that Ubuntu will soon shipping with decent .screenrc (sane default configuration) so you don’t have to. Meanwhile you can configure it yourself (as in the Red Hat guide above) or look at these cool options: http://linux.dsplabs.com.au/gnu-screen-screenrc-configuration-file-p13/. Here is my .screenrc:

vbell off
vbell_msg "Ring"

# detach on hangup
autodetach on

# don't display copyright page
startup_message off

# scroll back
defscrollback 1000

# setup the caption
hardstatus alwayslastline "%{-b gk}%-w%{+b kg}%50>%n %t%{-b gk}%+w %=%C%< "

# right/left bindings
bindkey "^[[c" next
bindkey "^[[d" prev
bindkey "^[[b" focus

# Set the altscreen so that when you quit vi, it will go back to
# what it was before
altscreen on

And finally, my delicious links for screen.

Happy “screen”-ing :)

Add the first comment