From: Brian Candler Date: 2007-05-18T21:49:58+09:00 Subject: Re: Coopting String interpolation On Fri, May 18, 2007 at 05:05:07PM +0900, Robert Klemme wrote: > >I'm working in a research > >project and I need to do some "clever stuff" (that's the thing I can't > >disclose) to all the Strings. This thing is "different" depending on > >how strings are composed. All the ways I know for string composition > >but string interpolation (<<, +, concat, gsub, etc.) can be overridden > >redefining methods in the string class. I'm looking for a way to > >intercept the string expansion to do my thing. Does ruby internally > >call some overridable method to compose the strings used in a > >interpolation? > > Likely but also likely not accessible to pure Ruby code. But in your > case (research project) it might be ok to hack the interpreter if you > need to catch all string interpolations. Did you look into this yet? Here's a simpler idea. Given that string interpolation calls to_s, you can use this as your hook if you wrap your objects in a proxy object. You need to ensure that operations like '+' also return an instance of this proxy object, so you can do all the operations you want whilst keeping the string wrapped. Then the only case that to_s is called is when the interpolation takes place, which gives you the hook you're looking for (as long as you're not calling to_s in any other context) Example: class WrapString def initialize(str) @str = str end def str @str end protected :str def +(other) self.class.new(str + (other.str rescue other.to_s)) end # rinse and repeat # Here is your interpolation hook: def to_s str.to_s * 2 end end a = WrapString.new("abc") b = WrapString.new("def") puts "Answer is #{a + b}" a = WrapString.new("abc") b = "def" puts "Answer is #{a + b}" The result of a + b is , and then the interpolation calls to_s which in this case just doubles it to "abcdefabcdef" There's probably a neater implementation of the above using method_missing or a delegation pattern rather than enumerating all the methods of String, but you get the idea. Just a thought? Brian.