From: Daniel Brockman Date: 2005-07-27T07:40:56+09:00 Subject: Re: Lisp on Lines Devin Mullins writes: > One could generalize that solution: > > class Symbol > def to_proc > lambda { |a,*b| a.send(self,*b) } > end Wow, I really like it! Why didn't I think of that? You've unified my version with the usual definition, resulting in the be-all and end-all of Symbol#to_proc. This *so* needs to be put in the standard library. :-) > class Symbol > def *(ary) > ary.inject {|a,b| a.send(self, b)} > end Way cool! I actually like this one, and I'm not kidding. Redefine Array#* to double-dispatch on symbols and this will actually be usable. Think about it— [1,2,3] * "+" means [1,2,3].join("+"), so it makes sense for [1,2,3] * :+ to mean [1,2,3].inject(&:+). More intuitively, we think of ‘[*foo] * "bar"’ as joining the elements of ‘foo’ by "bar". Analogously, we can think of ‘[*foo] * :bar’ as joining, or more correctly *recuding*, the elements of ‘foo’ using :bar. This strikes me as highly intuitive: [1,2,3] * "+" #=> "1+2+3" [1,2,3] * :+ #=> 1 + 2 + 3 As does this (though perhaps slightly less so): [1,2,3] * "foo" #=> "1foo2foo3" [1,2,3] * :foo #=> 1.foo(2).foo(3)" > [crazy APL stuff snipped] > > Now, :+*[1,2,3], :+[1,2,3], and +[1,2,3] are all valid. > (Not that I actually use this libary; just came up with it > to make a point about Ruby to somebody. :P) That's cool; you really managed to take this to its extreme. Of course, ‘:+[1,2,3]’ is too cryptic and ‘+[1,2,3]’ is better written as ‘[1,2,3].sum’, but still. :-) > (I would've overloaded /, but Ruby kept thinking I was > trying to construct a regular expression.) Hmm, what would you have had that do? > And here's a vaguely neat extension of that idea: > > class Symbol > def **(ary) > ary.inject { |a,b| a.send(self, *b) } > end > end > > :gsub ** ["Hello!", > [/Hell/,"Good"] > [/o!/,"bye.]] > > Talk about reducing duplication. :) Wow... amazing. Of course, this ["Hello!", [/Hell/, "Good"], [/o!/, "bye."]] ** :gsub is both longer and more cryptic than this, "Hello!".gsub(/Hell/, "Good").gsub(/o!/, "bye.") but still... the former has *no* duplication. :-) By the way, the above example suggests that it might be useful to have String#gsub take multiple arguments: class String unless method_defined? :gsub1 alias :gsub1 :gsub def gsub(*a) (a.size == 1 ? a.first : a.pairs). inject(self) { |a, b| a.gsub1 *b } end end end module Enumerable def pairs ; groups(2) end def groups(n) (a = entries).each_index { |i| a[i, n] = [a[i, n]] } end end "Hello!".gsub(/Hell/ => "Good", /o!/ => "bye.") #=> "Goodbye." Using a hash to visually pair each expression to its replacement has the unfortunate side effect of effectively randomizing the order of the substitutions, so you'll have to use commas if order is significant: "Hello!".gsub(/Hell/, "Good", /o!/, "bye.") #=> "Goodbye." Anyway, thanks for sharing your cool inventions, Devin. :-) -- Daniel Brockman So really, we all have to ask ourselves: Am I waiting for RMS to do this? --TTN.