2

I cannot see the value of the instance variable @model when I call the lambda @description. Is this possible? I only see " is very good." when I call show_description. Thanks in advance.

class Car
  def initialize(model)
    @model = model
  end

  def description
    @description = lambda{yield}
  end

  def show_description
    @description.call
  end
end

c = Car.new("Ford")
c.description{"#{@model} is very good."}
puts c.show_description # => " is very good."

3 Answers 3

3

c.description{"#{@model} is very good."} wouldn't show you what you want. Point is, the block you passing, has access to the outside scope, where no variable @model is found, thus @model is nil. It is called encapsulation, due to this, outside world wouldn't be able to know/access directly the state of an object, in your case the object is c. Here object's state means value to the instance variables lies in object c. But using methods, you can read/update the states of the objects.

Thus do as c.description{"#{c.model} is very good."}.

Your code can be re-written as :

class Car
  attr_reader :model

  def initialize(model)
    @model = model
  end

  def description
    @description = yield
  end

  def show_description
    @description
  end
end

c = Car.new("Ford")
c.description{"#{c.model} is very good."}
puts c.show_description
# >> Ford is very good.
Sign up to request clarification or add additional context in comments.

Comments

1
  1. Since you are saving the proc instance as @description, it is better to access that via a variable rather than using yield.

    def description &pr
      @description = pr
    end
    
  2. You need to evaluate @description in the appropriate environment, i.e. within the instance of Car.

    def show_description
      instance_exec(&@description)
    end
    

With the fixes as above, it will work as you intended.

c = Car.new("Ford")
c.description{"#{@model} is very good."}
puts c.show_description
# => Ford is very good.

By the way, you can simplify "#{@model} is very good." to "#@model is very good.".

2 Comments

@CarySwoveland Yes it is correct.. cvar, gvar abd ivar don't need {..}, only # is enough. Example - >> @x = 12 => 12 >> "I have #@x pens" => "I have 12 pens"
Thanks a lot. A method from BasicObject, I didn't know.
1

You can do it like this:

class Car
  attr_reader :model

  def initialize(model)
    @model = model
  end

  def description
    @description = lambda{yield}
  end

  def show_description
    @description.call
  end
end

c = Car.new("Ford")
c.description{"#{c.model} is very good."}
puts c.show_description #Ford is very good.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.