SitePoint Sponsor

User Tag List

Results 1 to 10 of 10
  1. #1
    SitePoint Member The_Big_K's Avatar
    Join Date
    May 2008
    Location
    In my home
    Posts
    18
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Question Understanding Ruby Interpreter

    Hi there,

    I'm back with my noobie question

    If I type 1 or Hello world at the ruby prompt, the interpreter returns what I typed in.

    Can anyone explain why does the interpreter returns what I just typed? I understand that the returned value is not the number or a string, but its a fully qualified object.

    But what's the point in returning an object?

  2. #2
    SitePoint Enthusiast AllTom's Avatar
    Join Date
    Feb 2008
    Location
    Wherever danger lies...
    Posts
    48
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    What's the down-side? All things in Ruby are represented by objects for consistency.
    There are some things you shouldn't try to code at home.

  3. #3
    SitePoint Member The_Big_K's Avatar
    Join Date
    May 2008
    Location
    In my home
    Posts
    18
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    No, there's no down-side. I just want to know why should the Ruby Interpreter throw the objects back in user's face :P

    I agree that what we get back are the objects; the question is 'Why'?

  4. #4
    SitePoint Guru
    Join Date
    Aug 2005
    Posts
    986
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Because things like numbers and strings are self-evaluating. If you type 1+2 you get back 3. If you type 3 you get back 3. This is the logical behavior to me What did you expect the Ruby interpreter to do?

  5. #5
    SitePoint Member The_Big_K's Avatar
    Join Date
    May 2008
    Location
    In my home
    Posts
    18
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Haha

    Yes, its logical and I don't have any problem with Ruby sending back objects. Maybe I should have asked "What the use of having those objects thrown back?"

    Or is it the 'Return Value' of successful acceptance of a number or a an expression or a string?

  6. #6
    SitePoint Guru
    Join Date
    Aug 2005
    Posts
    986
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Ruby calls .inspect on the return value of the expression. Inspect returns a string representation of the object. For strings this is the string enclosed in "", for numbers this is just the number. For arrays this is [first element, second, ...]. You can define your own .inspect:

    Code ruby:
    class Person
      def initialize(first_name, last_name, sex)
        @first_name = first_name
        @last_name = last_name
        @sex = sex
      end
     
      def title
        case @sex
        when :male: "Mr."
        when :female: "Ms."
        end
      end
     
      def inspect
        "#{title} #{@first_name} #{@last_name}"
      end
    end

    It works like this:

    Code:
    irb> Person.new("Joe", "Average", :male)
    => Mr. Joe Average
    As you can see, the Ruby intepreter called .inspect and printed the result to the console.

  7. #7
    SitePoint Member
    Join Date
    Oct 2007
    Posts
    21
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    It makes sense if you think about it at an abstracted level:

    Everything in Ruby is an object. With in those objects are methods. Therefore a Fixnum is an object. Now when you type 1 + 2, You are internally calling the + method in the Fixnum object (initialized to 1) passing in another Fixnum object (2). This method returns the sum of the the receiver (1) and the argument (2) to create a new FixNum (3).

    It might make more sense to see it written like this:

    >> 1.+(2) # That's right +() is a valid method
    => 3

    Now, I'm not 100% the actual internals when you have a single object on a like such as

    >> 3
    => 3

    But I would assume that there is a method that gets called whenever the value of an objects is requested, and subsequently returns the value. I'd say this goes right back to the core of the Ruby interpreter.

    I hope that isn't MORE confusing

  8. #8
    SitePoint Guru
    Join Date
    Aug 2005
    Posts
    986
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    If you really want to understand this you should write an interpreter for arithmetic expressions (like 2*(3+4)). It's not hard at all but very enlightening.

  9. #9
    SitePoint Member The_Big_K's Avatar
    Join Date
    May 2008
    Location
    In my home
    Posts
    18
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks a ton, Fenrir2 & madpilot!

    I guess I'm falling in love with Ruby.

  10. #10
    SitePoint Guru
    Join Date
    Aug 2005
    Posts
    986
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I made a simple arithmetic expression evaluator:

    Code ruby:
    class Expression
    end
     
    class Constant < Expression
      def initialize(value)
        @value = value
      end
     
      def eval(variables)
        @value
      end
    end
     
    class Variable < Expression
      def initialize(name)
        @name = name
      end
     
      def eval(variables)
        variables[@name] || fail("Undefined variable #{@name} in #{variables.inspect}")
      end
    end
     
    class Operator < Expression
      def initialize(left, right)
        @left = left
        @right = right
      end
     
      def eval(variables)
        operate(@left.eval(variables), @right.eval(variables))
      end
    end
     
    class Plus < Operator
      def operate(a,b)
        a+b
      end
    end
     
    class Minus < Operator
      def operate(a,b)
        a-b
      end
    end
     
    class Times < Operator
      def operate(a,b)
        a*b
      end
    end
     
    require 'test/unit'
     
    class ArithmeticTest < Test::Unit::TestCase
      def test_plus
        expression = Plus.new(Constant.new(3), Constant.new(5))
        assert_equal expression.eval({}), 3+5
      end
     
      def test_variables
        a = 2
        b = 4
        expression = Times.new(Variable.new(:a), Plus.new(Constant.new(3), Variable.new(:b)))
        assert_equal expression.eval(:a => a, :b => b), a*(3+b)
      end
     
      def test_undefined_variable
        expression = Variable.new(:a)
        assert_raise RuntimeError do
          expression.eval({:b => 2})
        end
      end
    end
     
    # syntactic sugar
    class Expression
      def +(x)
        Plus.new(self,x)
      end
     
      def -(x)
        Minus.new(self,x)
      end
     
      def *(x)
        Times.new(self,x)
      end
     
      def to_expression
        self
      end
    end
     
    class Numeric
      def to_expression
        Constant.new(self)
      end
    end
     
    class Symbol
      def to_expression
        Variable.new(self)
      end
    end
     
    def expr(thing)
      thing.to_expression
    end
     
    class ArithmeticSugarTest < Test::Unit::TestCase
      def test_plus
        expression = expr(3) + expr(5)
        assert_equal expression.eval({}), 3+5
      end
     
      def test_variables
        a = 2
        b = 4
        expression = expr(:a) * (expr(3) + expr(:b))
        assert_equal expression.eval(:a => a, :b => b), a*(3+b)
      end
     
      def test_undefined_variable
        expression = expr(:a)
        assert_raise RuntimeError do
          expression.eval({:b => 2})
        end
      end
    end

    Hope this helps
    Something along the lines of the eval() method in the Constant class is what the Ruby interpreter does when you type in a number or a string.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •