From: Robert Klemme Date: 2004-05-13T16:58:56+09:00 Subject: Re: in search of a compelling reason to use ruby.... "Ryan Paul" schrieb im Newsbeitrag news:pan.2004.05.12.19.33.22.639514@sbcglobal.net... > On Wed, 12 May 2004 18:04:17 +0000, gabriele renzi wrote: > > > il Wed, 12 May 2004 16:37:42 GMT, Ryan Paul > > ha scritto:: > > > > > > > >> > >>In python, we have map, filter, and list comprehensions, all of which can > >>be used to manipulate lists in very general ways. In order to do certain > >>things, python users have to stack multiple functions into map statements. > >>Generally, this is actually pretty simple to do, and makes things somewhat > >>intuitive. In ruby, there are a multitude of rather oddly named array > >>functions that have very specific behaviors, most of which can be used > >>with blocks to concisely describe extremely sophisticated operations. > > > > > > In ruby there are a lot of Enumerable functions, not array's :) > > What method do you think is oddly named ? > > I for one, would say inject() but using reduce() or fold() is equally > > non intuitive for me :) > > Its not so much that their names are strange, its the fact that they exist > at all. In python, lists only have like 8 or 9 functions, and they are all > pretty standard and self explanatory (append, count, extend, insert, > remove, reverse, and maybe two or three others). Having things like > collect, replace, assoc, and compact built into arrays is something of a > novelty for a python programmer. I'm used to having to do replacement like > this, for example: > [y for x in listobj if x == z] > > Personally, I feel that it is better to have functions that do these > things, Did you mean to say "methods"? I ask because strictly speaking there are no functions in Ruby. They are all tied to some instance. > because list comprehensions scale grotesquely, so I prefer the way > ruby does it. Not only does ruby provide a ton of useful functions to > start with, but I can add as many of my own as I want! > > Also, the fact that collect doesnt automatically compact really threw me > for a spin. I was using "x.collect {whatever}.compact" until I figured out > that it is easier to do a reject on the inverse of what I would have put > in a python 'filter'. Normally I would first select and then map. That's more efficient IMHO: irb(main):015:0> a = %w{a bb ccc} => ["a", "bb", "ccc"] irb(main):016:0> a.select {|x| /^[ab]/ =~ x}.map {|x| "(#{x})"} => ["(a)", "(bb)"] irb(main):017:0> a.select {|x| x.length > 2}.map {|x| "(#{x})"} => ["(ccc)"] > I added a 'filter' function to the array class that > fixes this for me. It can be far easier if your criterion happens to support ===, like Regexp does. Use #grep: irb(main):008:0> a = %w{a bb ccc} => ["a", "bb", "ccc"] irb(main):009:0> a.grep(/^[ab]/) {|x| "(#{x})"} => ["(a)", "(bb)"] You can easily make up your own criterion: irb(main):010:0> crit = Object.new => # irb(main):011:0> def crit.===(x); x.length > 2; end => nil irb(main):012:0> a.grep(crit) {|x| "(#{x})"} => ["(ccc)"] You can make your life even simpler with: module Criterion def self.create(&b) def b.===(x); call(x);end b end end irb(main):031:0> a = %w{a bb ccc} => ["a", "bb", "ccc"] irb(main):032:0> crit = Criterion.create {|x| x.length > 2} => # irb(main):033:0> a.grep(crit) {|x| "(#{x})"} => ["(ccc)"] > Additionally, having two different names for the same thing (eg: collect > and map) was initially confusing, but only because i'm not used to such > things. Python would NEVER do that. Ruby tries to be nice to people coming from different other languages. Some have map and some have collect. :-) Regards robert