class Array
def my_uniq(array_taken)
new_array=[]
array_taken.each do |element|
new_array << element unless arr.include(element)
end
end
end
Array.my_uniq([1,2,3,3])
I am using ruby calc1.rb in terminal to call the program. Terminal is in the correct folder and the file is saved in the correct folder.
Output
calc1.rb:9:in `<main>': undefined method `my_uniq' for main:Object (NoMethodError)
It appears previous answers were about either calling the method before it was defined or look, to me, like my solution that calls the class, then invokes the method on an array. Is there a private or undefined method going on here?
You need to create the method as a class method to work. But you created the method as an instance method of the class Array and calling on the Array class object, not on the instance of the Array, thus you got the error.
Below will work :
class Array
def self.my_uniq(array_taken)
new_array=[]
array_taken.each do |element|
new_array << element unless new_array.include(element)
end
new_array
end
end
Array.my_uniq([1,2,3,3])
Looking also at the error, it seems, you called the method my_uniq from top level. But in that case also, it wouldn't work, as on toplevel self is main, instance of Object class.But the method is not defined inside the Object class as an instance method, so bare method call from toplevel also wouldn't work.
Here's the script that I got it to work with in case anyone is wondering
class Array
def self.my_uniq (array_taken)
new_array=[]
array_taken.each do |element|
new_array << element unless new_array.include?(element)
end
new_array
end
end
p Array.my_uniq([1,2,3,3,3])
Related
I'm doing this and it works:
class B
def value
"X"
end
end
class A
def initialize(context)
#context = context
end
def m
Proc.new do
value
end
end
def execute
#context.instance_eval(&m)
end
end
A.new(B.new).execute #=> "X"
But calling m.to_proc is not working...
class B
def value
"X"
end
end
class A
def initialize(context)
#context = context
end
def m
value
end
def execute
#context.instance_eval(&m.to_proc)
end
end
A.new(B.new).execute #=> NameError: undefined local variable or method `value' for #<A:0x007fae2ab02040 #context=#<B:0x007fae2ab02108>>
I want to know why these two examples are different and how to make it work with to_proc
In the second snippet, you are calling m, which returns the result of calling value, which is undefined. (And even if if were somehow magically calling B#value, then B#value returns a String and Strings don't respond to to_proc, so you would get a NoMethodError there.) In the first snippet, you call m, which returns a Proc.
It looks like you are trying to pass the method m itself instead of the result of calling it. In Ruby, methods aren't objects, so you can't just grab them and pass them around (and even if methods were objects, then m is still the syntax for calling m, not for referencing it). You have to ask Ruby's reflection API for a reflective proxy for the method first, using the Object#method method, which returns a Method object representing the method:
#context.instance_eval(&method(:m).to_proc)
Note that the call to to_proc is completely redundant here, since & will call to_proc anyway if the argument isn't a Proc already. (You may have seen something like foo.map(&:bar) before, which will invoke Symbol#to_proc.)
#context.instance_eval(&method(:m))
I am executing a class with only this code in rubymine:
def saythis(x)
puts x
end
saythis('words')
It returns an error: undefined method `saythis', rather than printing the string 'words'. What am I missing here? Replicating this code in irb prints the string 'words'.
I assume you wrote a class like the one below and did not write that code into a irb console. The problem is that you define an instance method, but try to call the method from the class level.
class Foo
def say_this(x) # <= defines an instance method
puts x
end
say_this('words') # <= calls a class method
end
There a two ways to "fix" this:
Define a class method instead of an instance method: def self.say_this(x)
Call the instance method instead of the class method call: new.say_this(x)
What is best practice / syntax for trying to extract internal methods within a class?
class Foo
def initialize
end
def get_value
array = (API CALL TO GET ARRAY)
array.array_lookup("Bar")
end
def array_lookup(query)
self.each do |hash|
if hash[:key] == query
p hash[:value]
end
end
end
end
foo = Foo.new
foo.get_value #=> : undefined method `array_lookup' for #<Array:0x007fd3a49a2ca0 (NoMethodError)
The error message is telling me that my array object doesn't know how to respond to my method which makes sense in that I have an array that doesn't have this method, though I'm wondering how to fix this and similar uses. Do I overwrite the array class? Do I change my self.syntax?
array_lookup is Foo's method. So inside Foo class, you can call it by
array_lookup("Bar")
(without array.)
How about something like this? You turn your custom object into a subclass of Array so you get the array methods like #each. Actually, come to think of it, a better implementation might include mixing in the Enumerable module into your custom class (thinking composition over inheritance).
class Foo < Array
# More robust to change in application if you allow passing
# the query into this method. Just a suggestion.
def get_value(query)
request_data
lookup(query)
end
protected
def request_data
# API call to get data, assume this is array with contents
data = []
# Set contents of this object to contents of returned array
replace(data)
end
def lookup(query)
each do |hash|
if hash[:key] == query
puts hash[:value]
end
end
end
end
foo = Foo.new
foo.get_value("BAR")
I have an array of three NetAddr::CIDR objects and am attempting to sort them using the cidr_sort method of the NetAddr module (http://rubydoc.info/gems/netaddr/1.5.0/NetAddr#cidr_sort-class_method)
When I call the sort method from within my Class as follows:
Class IPv4SummaryNet
attr_accessor :component_nets
#component_nets = []
def add_net(net)
#component_nets = component_nets.to_a.push(net)
end
def sort_component_nets
component_nets_sorted = #component_nets.sort
end
...
end
I get the following error: /usr/local/lib/ruby/gems/2.1.0/gems/netaddr-1.5.0/lib/cidr_shortcuts.rb:216:in 'cidr_sort': undefined method 'length' for #<NetAddr::CIDRv4:0x007f55cbae0088> (NoMethodError)
But if I print the array length from within my program, I get the correct value of 3.
I have also tried using sort_by and NetAddr::cidr_sort(#component_nets) and get the same error.
Why is Ruby telling me length is undefined when the cidr_sort method tries to call it, yet I can call it in my code with no problem?
def sort_component_nets
component_nets_sorted = #component_nets.sort
end
Here Ruby thinks you are trying to create a local variable within the method block, but I assume that you actually want to access the method component_nets_sorted that is outside the block. To do this: you must add the self. prefix to it.
def sort_component_nets
self.component_nets_sorted = #component_nets.sort
end
How does ruby call varz method by using varz[:foo]?
class Component
class << self
def varz
#varz ||= Hash.new
end
end
end
Component.varz[:foo] = 'bar'
puts Component.varz # {:foo=>"bar"}
class << self is used to define the class method,that will be called on the class.
where as #varz represents the instance variable. You might wonder, then why this instance object is doing in class method? This is because class itself is instance of Class.
One more thing to note, in ruby method returns it's last statement. So in your case Component.varz returning the instance variable #varz which is of hash type.
Component.varz[:foo] = 'bar'
this add the key-value pair foo and 'bar' to hash.
And finally,
p Component.varz
you are printing the value returened by the varz method.
You cut it in the wrong way. Component.varz is a method call. To the result of it (which is a hash), [:foo] = applies. The [] and []= methods are special in that you don't put a period between the receiver and the method.