More Obscure Features of Ruby
First go look at Nick Sieger's post about strange perlisms in ruby, cause it may be interesting for you. But talking about strange features in ruby, I believe there are some that may result even stranger, cause they are not even inherited from other languages, but are matz' own creation, I believe.
super on builtin methods
if you're redefining a builtin method you can use super to access the original one:
>> def puts(*args) >> super(*args) >> super(*args) >> end => nil >> puts 123 123 123
yet if you try with your own:
>> def foo() puts "foo" end
=> nil
>> def foo() super end
=> nil
>> foo
NoMethodError: super: no superclass method `foo'
from (irb):8:in `foo'
from (irb):10
super without arguments
I knew this feature for long, but never used it in real coding, even if I keep thinking it's handy. super, when used without arguments, passes all the arguments, so the above example would become:
>> def puts(a,b) >> super >> super >> end => nil >> puts 345, 567 345 567 345 567 => nil
The evil context-sensitive while and until modifiers:
Can you tell the difference between this two lines?
puts 'hello' while false begin puts 'hello' end while false
Well, the difference is that the latter will print "hello", because the while modifier always does at least one evaluation of the expression when preceded by a begin..end block. The same happens with the until modifier. Luckily, this evil behaviour is supposed to disappear.
do something, handle exceptions.. or else?
Did you know that ruby's begin allows the definition of an else clause? The else clause is actually part of the rescue part of the block,. and is executed whenever an exception is not raised:
>> def check(x) >> begin ?> raise if x==2 >> rescue >> "error" >> else ?> "ok" >> end >> end => nil >> check(1) => "ok" >> check(2) => "error"
..and of course, you do not need begin..
because, I believe you know this, you can write:
>> def check(x) >> raise if x==2 >> rescue >> "error" >> else ?> "ok" >> end => nil >> check(1) => "ok" >> check(2) => "error"
methods with whitespace, yay!
I find this quite useful, actually. If you define a method bypassing the ruby parser with define_method you can give it any name you want.
>> class K
>> define_method("method: hard to get") { 'got!' }
>> end
=> #
>> K.new.send 'method: hard to get'
=> "got!"
You won't be able to call the method with normal ruby syntax, which makes it less or more useful depending on your problem space.
And finally, there is a whole slant of strange things that I believe are remnants of matz' experimenting with the language (is alias $global $other_global used somewhere outside of english.rb?), and even if some of them are quite frightening (if /regex/ anyone?) they will be phased out, so it's ok. If I recall correct ruby also had a glob operator ( <*.c> ) that was killed in the early days, so I trust matz to fix the oddities of the language sooner or later :)
4 Responses to “More Obscure Features of Ruby”
Sorry, comments are closed for this article.
October 7th, 2007 at 10:11 PM
“super on builtin methods” Try this:
And it works! But why? ‘super’ search the same method in included modules and in parent class (recursively) but it can’t call the same, but previusly defined method (like in your example). ‘puts’ method is defined in Kernel module so it works. If ‘puts’ method was defined in “global scope” (precisely, in Object class, because simple ‘def method’ define method in Object class) your first example wouldn’t work.
Watch this:
But…
Sometimes it could be hard to understand (I thought for a while that super could call only method from parent class, I didn’t know about Module example).
October 8th, 2007 at 07:55 PM
ah yes, I knew that this is a side effect of methods in main appearing as private methods in Object, but didn’t think of writing it, thank you :)
(Oh and I’ll fix your formatting ;)
October 9th, 2007 at 01:47 PM
Hi,
The execution of the statement
Is logical! And similar staements exist in most other programming language.
That is the reason why cunstructs like >puts ‘hello’ while false< is usally avoided since the avaluation order is not clear (=second part is evaluated first, and determines if (or how) first part is executed! (Normal spokenlanguage is not always (rearely) clear and logical, but programming langue must (should) be!
October 10th, 2007 at 07:30 PM
Hi Csaba, thanks for your comment. Yeah, I know most languages have a repeat/until loop, and this behaviour is logical if you’re used to them :)
But the point is that postfix while in ruby behaves like a statement modifier, and all of them evaluate the condition before the expression.
Yet, to offer an at-least once semantic ruby has a special case for the combination of begin..end and this keyword, that makes it behave differently from begin p :x end if false, for example.
Anyway matz is the authority in this topic.