From: Adam Shelly Date: 2008-01-31T10:20:16+09:00 Subject: Re: Idiomatic way to copy parameters ? On 1/30/08, Leif Eriksen wrote: > > def self.gradient(hex_start="000000", hex_end="FFFFFF", steps=256) > [hex_start,hex_end].each do |hex| > hex.sub!(/^(0[xX]|#)/) do |match| > match = '' # remove any leading # or Ox > > So the strings that are passed in are permanently munged by the sub! . > OK I get that, and to solve it I did this > > def self.gradient(param_start="000000", param_end="FFFFFF", steps=256) > #make local copies of parameters > hex_start = String.new(param_start) > hex_end = String.new(param_end) > > [hex_start,hex_end].each do |hex| > hex.sub!(/^(0[xX]|#)/) do |match| > ... > > So in effect I copy the parameter strings into local vars, to avoid > munging what the user passes me and annoying them. > > But is this the ruby way ? Is this the idiomatic way to avoid > side-effects on objects passed in as parameters ? > I'm no idiom expert, but I'd say no. You are correct that if you are going to do a destructive operation without affecting the caller, you need to make a copy. But usually, it's simpler to just get a modified copy by calling the non-destructive version: def self.gradient(hex_start="000000", hex_end="FFFFFF", steps=256) hex_start=hex_start.gsub(/^(0[xX]|#)/,'') hex_end=hex_end.gsub(/^(0[xX]|#)/,'') ... end -Adam