Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed last year.
Improve this question
Why I'm getting error back when calling eval_prog on e but it works normally on #e
class Let < GeometryExpression
def initialize(s,e1,e2)
#s = s
#e1 = e1
#e2 = e2
end
def preprocess_prog
Let.new(#s, #e1.preprocess_prog, #e2.preprocess_prog)
end
def eval_prog env
#e2.eval_prog([#s, #e1.eval_prog(env)] + env)
end
end
Presumably you're talking about #e1 and #e2 in this method:
def eval_prog env
#e2.eval_prog([#s, #e1.eval_prog(env)] + env)
end
You get an error from e1.eval_prog(env) because there is no e1 local variable in that scope and no e1 instance method. #e1.eval_prog(env) works because you do have an #e1 instance variable.
If your class looked like this:
class Let < GeometryExpression
attr_accessor :e1, :e2, :s
#...
end
then attr_accessor would give you e1 and e2 methods (and e1= and e2= methods too) and then you could say:
def eval_prog env
e2.eval_prog([s, e1.eval_prog(env)] + env)
end
You might want to use attr_reader instead so that you don't get mutator methods. Or probably just stick with the instance variables to keep the class's interface smaller.
Related
This question already has answers here:
Why do Ruby setters need "self." qualification within the class?
(3 answers)
Closed 6 years ago.
I wrote the binary search tree code with Ruby. I'm now wondering why this code needs self in self.left = Node.new(3) to make a new node.
I was thinking that self can be removed like this left = Node.new(3)because in this case receiver is obvious(an instance to which insert_left method applied). But it seems wrong.. Can you please help me why my thought is wrong.
module BinaryTree
class Node
attr_accessor :value, :left, :right
def initialize(value)
#value = value
end
def insert(v)
case #value <=> v
when 1 then insert_left(v)
when -1 then insert_right(v)
when 0 then nil
end
end
private
def insert_left(v)
if left
left.insert(v)
else
self.left = Node.new(v)
end
end
def insert_right(v)
if right
right.insert(v)
else
self.right = Node.new(v)
end
end
end
end
When calling left = x that's interpreted as a variable assignment. Calling self.left = x is a method call of left= on self. These are obviously two different things but unless you're familiar with the notation this might not make any sense. It isn't especially intuitive and is rather perplexing for beginners, especially when x = left works fine without having to be explicit about left being a variable or a method call.
Unlike some languages that have prefixes on local variables (Perl, PHP, etc.) there's no such identifier in Ruby. As such it interprets things of the form lvalue = expr to be variable assignments and object.property = expo to be method calls to a mutator method.
Ruby does identify instance and class level variables like #x = expr and ##y = expr but that's a different thing altogether.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
I wanted to make a simple DSL where I could pass a bunch of methods to a block, relying on self as the implicit receiver. So basically here you can call the 'say' method on this class object, passing it 'things to say' as methods in the block. The last line returns ['Maria']. I was wondering if this is a good programming practice for creating DSLs and if there are any problems with this approach.
class SaySomething
def initialize
#said = []
end
def hey(name)
#said << name
end
def say(&block)
instance_eval(&block)
end
end
a = SaySomething.new
name = 'Maria'
a.say do
hey(name)
end
a.instance_eval { p #said } #=> produces ['Maria']
I would probably add an attr_accessor :said and then replace your last line with
a.said
#=> ['Maria']
Other than that your code looks fine to me. If you want to learn more about metaprogramming in Ruby, I can recommend the book "Eloquent Ruby".
The only problem with this approach is that any class variables will collide with variables in the same scope as the block. The usual approach is to provide instance evaluation, but also allow the user to specify the class as an argument as a fall back.
class Test
def test; "hello"; end
def say(&b)
if b.arity == 1
b.call(self)
else
instance_eval &b
end
end
end
t = Test.new
test = "fred"
t.say { p test } # "fred"
t.say { |t| p t.test } # "hello"
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I'm new to ruby and I was wondering the following, can I call a method in the same class such as:
class myClass
$myVar = inClass
def inClass
#value = (gets data from db)
end
end
If there is a way to do this, can someone please help me?
You can do as below
class MyClass
def in_class
#value = (gets data from db)
end
def call_inclass
$my_var = in_class # don't use global variable.
end
end
Create a new instance method call_inclass and call the required class in_class from there. Your one will not work, as in_class is an instance method, and within class.. end body self is set to that class. Thus $myVar = in_class will simply thorw an error as no method error. Because $myVar = in_class it will be interpreted implicitly as $myVar = self.in_class, where self is MyClass. in_class is not a method of MyClass, rather an instance method of instances of MyClass.
Thus wrapped the method call to in_class inside another instance method, like here call_inclass.
Another way is make in_class as a singleton method of MyClass. Then it will work.
class MyClass
# again don't use global variable, rather use
# class instance variable, #my_var
$my_var = in_class
def self.in_class
#value = (gets data from db)
end
end
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
Who can explain me the code snippets of "def name" and "def name=()"?
I don't understand why it is defined 2 times.
class Bird < Animal
def initialize(name, length)
#name
#length
end
def name
#name
end
def name=(new_name)
#name = new_name
end
end
These are getter and setter methods
bird = Bird.new("pigeon", length)
=> #<Bird:0x007f93e9b41278>
bird.name
=> "pigeon"
bird.name = 'seagull'
=> "seagull"
bird.name
=> "seagull"
Both of the methods you defined in the class are what's being called here - the call to
bird.name = 'seagull'
is actually syntactic sugar for the method call
bird.name=('seagull')
Of course, the most "rubyish" way to write these methods would be one call to attr_accessor:
class Bird < Animal
attr_accessor :name
def initialize(name, length)
#name = name
#length = length
end
end
This will give you both the getter and setter methods for the name attribute
One returns a value, one sets a value. Look at the method bodies.
def name
#name # return #name
end
def name=(new_name)
#name = new_name # set #name to your argument
end
Also, your initialize method does nothing. I assume you want to set those variables to the arguments you are taking.
def initialize(name, length)
#name, #length = name, length
end
These methods are known as "getters" and "setters", because (unsurprisingly), they 'get' or 'set' a variable.
You can also think of one as a 'command,' which will make some change to the data, and one as a 'query,' which will simply report a value (this is a helpful distinction to keep in mind when you are designing your own methods as well).
Ruby includes three class methods that define these getters and setters for you: attr_reader defines the getter, attr_writer defines the setter, and attr_accessor defines both.
You could just interact directly with the instance variable, but in most situations, code is easier to change and reason about when you use methods to access data rather than messing with the data itself.
I don't understand why it is defined 2 times.
def name to read value from #name and def name= to write value to #name.
The below is a reader(attr_reader) method
def name; #name; end # shortcut is attr_reader :name
The below is a writer(attr_writer) method
def name=(new_name) ; #name = new_name ; end # shortcut is attr_writer :name
A very good documentation What is an accessor?
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
How can I reference an object from a method without passing it as a variable?
I am getting error:
NameError: undefined local variable or method ‘my_object’ for Myclass:Class
class B
attr_accessor :somethings
include Enumerable
def initialize(*values)
self.somethings = []
end
end
my_object = B.new({d:'d'})
class Myclass
def self.my_method
p my_object
end
end
Run: Myclass.my_method
What I do NOT want to do for all my methods is...
def self.my_method(my_object)
p my_object
end
I could also solve the issue with use from a global variable
$my_object = B.new({d:'d'})
However, I only really want to make the variable available to my methods in Myclass class.
I only really want to make the variable available to my methods in Myclass class.
Then you should define it as an instance variable in corresponding scope of Myclass. As it is now, my_object is a local variable and is not visible because of the scope gate.
class Myclass
#my_object = B.new({d:'d'})
def self.my_method
p #my_object
end
end