From: Daniel Brockman Date: 2005-07-27T15:05:19+09:00 Subject: Re: Lisp on Lines Devin Mullins writes: >> Wow, I really like it! Why didn't I think of that? > > You weren't being challenged by someone showing you a code > snippet claiming that APL is a superior language. :) Hmm, yeah, I guess that would've done it. :-) > BTW, change *b to b, in my code. Why? I can't think of any iterators that pass three or more arguments to the block off-hand (at least I can't think of any such cases where it makes sense to simply invoke a single method upon each yield), but does it hurt to support that hypothetical case anyway? >> 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(&:+). >> >> > Actually, I like that a lot more than :+ * [1,2,3]. Yeah... I was thinking they should both work, but I guess that's unnecessary, given that ‘"+" * [1,2,3]’ doesn't work. Random aside: In mathematics, a non-commutable + operator is pretty damn near unthinkable, wheras in computer science it's completely normal. I think that's kind of interesting. >>> (I would've overloaded /, but Ruby kept thinking I was >>> trying to construct a regular expression.) >> >> Hmm, what would you have had that do? > > Sorry, I just assumed that everybody except me knew APL, > so I could just talk about it as if I knew what I was > talking about and get buy-in from everybody else. Ah. In light of this thread, I'm actually a little curious about what other insights one might get from learning APL. > In APL, the syntax for doing that is something akin to > "+ / 1 2 3". But you showed an excellent reason why "*" > makes more sense for Ruby. I see. >> 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. :-) > > Well, if you're doing, like, seven gsubs, the former will > win out, but if you're chaining seven gsubs, you're > probably doing something wrong. Good point. Although I don't think lots of gsubs are any indication that you are doing something wrong. (I'd hate to think *I* ever did something wrong.) > I suppose you could use "** :gsub" to aid in some sort of > configuration file thing: > > class Array > def **(sym) > inject {|a,b| a.send(sym,*b)} end end Nice to see someone else stuffing away those pesky ‘end’s like that. I have my Emacs coloring them really dimly. > gsubs = YAML::load [[/Hell/,"Good"],[/o!/,"bye."]].to_yaml > #your config file here > some_words_ive_got_lying_around = %w{cat dog tree Hello! french oreo!} > some_words_ive_got_lying_around.map! {|word| [word,*gsubs] ** :gsub } > #=> ["cat", "dog", "tree", "Goodbye.", "french", "orebye."] Okay, but with my modified String#gsub, that's better written like this: gsubs.flatten! some_words.map! { |word| word.gsub(*gsubs) } >> 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 > > Heh, never seen that "unless method_defined?" thing before. > I like it, I think. (I'm still not comfortable about the > alias-and-call-original trick, and this makes me a little > more comfortable about it.) Yeah. Having been bitten a few times by the double-aliasing bug that comes into play when a file that uses the “alias and redefine” idiom is loaded twice, I always try to make sure my (declarative) code is resistant to being loaded multiple times. -- Daniel Brockman So really, we all have to ask ourselves: Am I waiting for RMS to do this? --TTN.