Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Wow...not a single SO response that said Ruby? I guess that's a good thing for us Rubyists?



Someone else is probably going to mention flip-flops, so let me show you "defined?":

    a = 1
    defined?(a) # => "local-variable"
    defined?(p) # => "method"
    defined?(nothing) # => nil
defined? is a syntax-construct (not a method) which tries to tell you if its "parameter" is defined. The rules for this are rather interesting.

    class String
      def print
        p self
        self
      end
    end
Okay, String#print is just a helper method to prove my point.

    defined?("hello".print)        # => "method"
    defined?("hello".print.strip)  # => prints out "hello", then returns "method"
    defined?("hello".print.stripp) # => prints out "hello", then returns nil
Okay, so defined? may actually call methods for you to figure out if it's "defined" or not. What if we try something more complex:

    defined?(if true then "hello".print.strip end) # => "expression"
Wait, what? This does not call the print method. In fact, this check is done entirely at parse-time. "defined?(if true then … end)" will always return "expression". In fact, anything more complex than local variables, method calls or constant names will just return "expression". Well, except for "defined?" though; defined? can't check itself - it's a syntax error.

Another intresting "feature": If any exception is raised, the whole expression is considered undefined:

    class String; def print; raise; end; end
    
    defined?("hello".print.strip) # => nil


Actually, there is, just not as many upvotes as the others.

http://stackoverflow.com/a/2026849

Basically, it is possible to inherit a random class in ruby.

    class RandomSubclass < [Array, Hash, String, Fixnum, Float, TrueClass].sample
       ...
    end


I wouldn’t call that a strange feature, just a surprising consequence of an un-strange feature, namely that inheritance involves expressions and that classes are first-class entities.

Folks from certain other languages would be just as surprised to find out that you can alias classes by assigning them, return them from functions, and so on.


Another one: class variables!

    # Define two class variables in two different classes:
    class MyClass
      @@base = 1
    end
    
    class OtherClass
      @@base = 2
    end
    
    # Define it in the superclass too:
    class Object
      @@base = 3
    end

    class MyClass
      # Magic! The subclass-variable has now changed!
      p @@base # => 3
    end

    class OtherClass
      # In both classes in fact:
      p @@base # => 3
      
      # And finally, let's reset this:
      @@base = 4
    end

    class Object
      # Whoops, this changes the superclass too:
      p @@base # => 4
    end
Explanation: Two class variables with the same name can't exists in the same class hierachy. Therefore, class variable lookup (and setter) will always traverse to the upmost-class where the variable is defined.

(Hope you don't mind that I wrote these in two different posts.)


I'm still reeling from finding out that zero is true.




Consider applying for YC's Fall 2025 batch! Applications are open till Aug 4

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: