Comments by yashi and gotoken: > > Characters are integers in ruby. > > 'hello'[0] -> 104 > > no, there is only String class. all char is an instance of class > String. And, [] is a method in class String to get _char code_. Ok, so it would have been more accurate to say: Indexing a string in ruby gives you an Integer. I'm still not clear on why this is the case, or how it's useful. A few other languages: python: string[0] -> StringType C: stringp[0] -> char haskell: string !! 0 -> Char smalltalk: string at: 1 -> Character In perl, strings are not sequences and can't be indexed, so you have to use substr, which gives a string. ruby: string[0] -> Fixnum The other languages approaches seem more intuitive. For example, in the haskell prelude: type String = [Char] -- strings are lists of characters So why doesn't ruby have a Char class? > If I may add, "hello"[0].chr == "h". Note that String object is not > always a character string, String can represent a octet (byte) string. Well, that's because Integers happen to respond to the chr message, it's still an Integer ('hello'[0].type -> Fixnum). Hmm, I think String objects *are* always character strings, I think what you mean is that they are not always *printable* character strings :) But that's not for the language to decide, whether or not it's printable depends on your character set, and neither has any bearing on what [] should return. If I index a binary string, I still wouldn't expect to get a fixnum, since if I slice 4 elements I don't get a 32-bit int, but a string. --- > >So, here are some comparisions between attribute access in ruby and python: > > ruby python > >method (in class def) meth object.meth # obj is self > >attribute (in class def) @attr object.attr # obj is self > >method (everywhere else) object.meth object.meth > >Constant Class::Const object.Const > >in general depends object.attr > > Interesting :) > > Another viewpoint is avairable. > > class Foo > X = 'Constant' > Y = 'Constant' > def Foo.X; 'method' end > end > Foo::X #=> "Constant" > Foo::X() #=> "method" > Foo.X #=> "method" > Foo.Y #!!NameError: undefined method `Y' for Foo:Class > > I think the primary meaning of <module>::<identifier> is name space > identification whareas <module>.<identifier> is method call. In the > latter, <module> can be considered as a receiver, i.e., an object. OK, I can understand the bit about <obj>.<ident> is a method call, wheras <obj>::<ident> is a Constant retriever (not attribute retriever, since those are just methods in ruby), even if I don't like it :) But my real question was "if '.' and '::' are used for different purposes, why does '::' work like '.'?" 'Foo::X' -> "Constant" vs. 'Foo::X()' -> "method" just underlines that question. Does this seem a bit 'trap-like' to anyone else? OK, I'm sure a perl programmer, who is used to subtle changes when you put parentheses in, wouldn't blink. Ok, maybe a perl programmer would blink and be just as confused as the rest of us, but he'd be more inclined to accept it without question :) --- > > Suppose you write "defined? foo". defined? has to evaluate its arguments, > > which makes me think it ought to throw a NameError if foo isn't defined'. > I'm > > confused. > > if 'defined?' raise an exception, what's the point of having > 'defined?'? > > # I must be miss-understanding your question. > > even in the toplevel, you are in an instance of class Object. so > 'defined? foo' means defined? self.foo. you can always check what > method an instance has with method 'methods'. Yes, well even 'self.defined? self.foo' has to evaluate self.foo. > is there a way to get a list of variables that has been defined? You tell me, I'm the newbie here :) Based on my fuzzy understanding on ruby, I'd say no, because defined variables are just methods of self, and there's no way to tell what a method will give you unless you call it. No wait, I'm thinking of @attrs. > >Suppose you write "defined? foo". defined? has to evaluate its arguments, > >which makes me think it ought to throw a NameError if foo isn't defined'. > >I'm confused. > > `defined?' is a kind of operator, and its argument is checked by the > parser. I understand it is similar to sizeof operator in C. Ah, this makes more sense, defined? isn't a method at all. I thought everything was a message send in ruby? :) It *could* be "just another message send" if you spelled it 'defined? :foo' or 'defined? "foo"'. So why not? --- > > > > The only things that are false in ruby are nil, false, NIL, and FALSE: > > if 0 then 'hello' end -> "hello" > > this one came up on ruby-talk, Matz said "it's matter of how far you > define 'false'" Hmm, I define false as: "that which, when you put it in an 'if' expression, evaluates the 'else' clause". I have no problem with 0 being true. It forces you to write the (mostly) clearer 'if foo != 0', and be disciplined about what is a boolean and what isn't, which seems like one of those ideas that sound good for large systems, but just annoy quickie-script-hackers. In, e.g. But if you're going down that road, it seems it only makes sense if you go *all* the way, i.e. only 'true' or 'false' is accepted by 'if' and friends. Everything else throws an exception. In e.g. haskell, True is true and False is false, nothing else. Of course, anything else would make the static typing unhappy :) > >Ruby also has > >catch (:foo) { > > throw :foo, "hello" > >} -> "hello" > > > >I'm not sure what the exact difference is between the two forms, or why there > >are two in the first place. > > catch-throw doesn't raise an exception. See [ruby-talk:01286] > and [ruby-talk:01344]. 1) Although there are no errors, you want to escape from one "mode" to another drastically. (2) You want to escape from deeply nested loop drastically. (3) You want to write obfuscated code. Hmm, so I guess throw/catch is supposed to be a control structure, while exceptions are supposed to be only for errors? And throws can only be caught in one place (which 1344 seems to imply)? > >Ruby has single-inheritance to reduce complexity, which is a nice idea. But > >in return we get *four* ways to import modules and/or extend classes: > >include, extend, load, and require. And I'm not clear as to the exact > >difference between these. Documentation seems to be sparse here. > > Well, > > `extend' appends functions of a module to an object; > `include' appends features of a name space (i.e. module) to another space; > `load' inserts code included a file to other program; > `require' is similar to `load' except never read file twice. Ah, this is useful. Perhaps useful enough to go in the FAQ? So extend, since it applies to single objects, is sort of like include for singletons? --- > >Ruby has ||, "or", &&, and "and" operators (eek). And they function slightly > >differently (faq 4.10). > > You don't like operator? ;) Not ones that look the same and work *almost* the same. > text = ARGF.read || "" > puts text.gsub(....) > > text = ARGF.read or exit 1 > text.each do |line| .... end Or maybe what you really mean: def f(x) x * 2 end false or f 5 -> 10 false || f(5) -> 10 false || f 5 -> SyntaxError I think this just means that || binds too tightly. So the question is "why, then, do you need '||'?" I know perl does this because perl tries to be just as confusing as C or more, so it adopts all the traps of C in addition to adding its own (but then goes and changes 'break' and 'continue'... go figure). I guess this is so confused C programmers will feel just as confused in perl, maybe they're more comfortable that way :) > >Methods are not first class in ruby. > > However, bounded method is available: > > plus_one = 1.method(:+) #=> #<Method: Fixnum#+> > plus_one.call(10) #=> 11 > plus_one[10] #=> 11 That's useful information (more efficient than wrapping them in lambdas, which are not exactly methods anyway). That "looks like array index, but is really a method call" is a bit weird, but I guess not much worse than the "looks like bit-shift, but is really stream-append" thing C++ loosed on the world. Why not provide a () method like python's __call__? --- > >The fact that methods are not first class in ruby means you have to remember > >two mutually exclusive different ways to do things, depending on whether the > >value is a method or not: > > > > python ruby binding ruby method > >create new name for object: new = old new = old alias new old > >delete binding for object: del obj ? undef meth > > No way to delete (if I'm not mistaken). --- > >The only things that are false in ruby are nil, false, NIL, and FALSE: > >if 0 then 'hello' end -> "hello" > >nil and false, while mostly similar, have 'different behaviours elsewhere' > >(faq 7.4), but I'm not sure what that means. Careful with that 0 is true > >stuff, it's easy to forget that if you're not used to it. I'm also not sure > >why true, nil, and false have UPPERCASE equivalents. I guess nil and false > >could be useful for 'three value logic' which sometimes pops up (usually in > >databases). > > I'm guessing it comes from Lisp. ALIASEs are left for historical > reason. Or maybe smalltalk. But that still doesn't explain the 'different behaviours elsewhere' bit (and the fact that nil != false). If it were merely a case of "can't decide whether to type 'nil' or 'false' so I'll let people use (and the flip side: force people to read) both (like python != and <>), then they would have been exactly equivalent. And, finally, here's a real ruby question: What's the general idiom for parallel iteration in ruby? This is what I was able to figure out: def zip(*a) r = [] 0.upto(a.collect {|i| i.length}.max - 1) { |i| r << a.collect {|elt| elt[i]} } r end zip(lst1, lst2, lst3).collect {|a, b, c| print a, b, c, "\n"} Which seems to work. I wasn't sure if ruby would do pattern matching, but it appears it does, at least here. However, I'm sure there is a better way that doesn't require making my own function...