Calling #[] on a ruby method [closed] - ruby

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
Create a method that can be called in this manner
some_named_method(string_1, string_2, int_1, int_2)[Integer]
I've just learned that if a method is being called like so some_named_method[80] - that method is a Proc / lambda (? still a little unsure of this any elaboration would be great)
Guidelines are, arguments are optional, in groups of two, based on the tests provided, but the number in brackets will always be present. It is used to create an Array, which is operated on, depending on the params being passed in.. So ->
some_named_method[Integer] # => [0..Integer]
some_named_method('Hey', 'There')[Integer] # some operations based on the string arguments and => [0..Integer]
some_named_method('Hey', 'There', 3, 5)[Integer]
How do you make a lambda have optional arguments in this way?
ANSWER (I think)
When a method is being called in this way, some_named_method(*args)[Integer], one of two things is happening. Either the method returns an array, so #[] is being called on that array, returning whatever object is at the specified index
OR
that method contains a proc / lambda, and whatever is inside the #[some_arguement] is being passed as an argument(s) to that proc / lambda

If I understand the question, you want a method that takes any number of arguments, and returns an object that will create a range of numbers when the [] method is used.
This method takes any number of arguments (using the * splat operator), and then returns a proc, which [] can be used on.
def some_named_function(*args)
proc do |length|
# Do something with the args?
(0..length).to_a
end
end
And then it can be used like this:
some_named_function[3] # => [0, 1, 2, 3]
some_named_function('optional', 'args')[1] # => [0, 1]

Related

How does find method work in Ruby [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I understood the working of find method i.e. looks for the first occurrence. But I don't understand how find method is implemented at class level. Can somebody explain me the flow of this below written code? Also explain me the relation between find method and yield. How the values are passed between yield call and find call? Also explain what is the use of nil. Thanks.
class Array
def find
each do |value|
return value if yield(value)
end
nil
end
end
[1,3,5,7,9].find {|v| v*v > 30}
First of all; you know how yield works right??
{|v| v*v>30}
every item in the array is passed to this block as param v = every element
Explaination:
return value if yield(value) signifies that the current item of the array is returned from the find method if the block passed return true for the any item of the array.
So, it only returns single item; actually the first item matching the condition; unlike select method that returns every item matching the condition.
2.2.1 :030 > [1,2,3].select{|x| x>1}
=> [2, 3]
Moreover; the each do |value| iterates over the the current/self instance of Array class

How can I define a method which arguments have no type in Ruby [closed]

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
If I defined a method:
def weird_method(first_argument, second_argument)
#code here
end
so this way I can pass arguments like : 1, :digit, 'some', "more"(Fixnum, Symbol, String etc.) , BUT what If I wanted to pass just this: argument1, argument2 , I mean values that have no type and look like local variables but they actually are not. How can I accept them somehow and use them in the method body?
PS: I need it for implementing a small DSL that could do that kind of stuff in the .isntance_eval when blok is passed
Something.with_method do
sum 1, 2 #(I can implement it)
play volleyball #(I can NOT implement it)
swim further #(I can NOT implement it)
eat "a lot" #(I can implement it)
end
EDIT:
Everything could go on the palce of volleyball and further. I am just gave an example. sum, play, swim, eat are methods defined in the Something class.
Symbols exist for exactly the purpose you're talking about here: They're values that just evaluate to themselves. The symbol :volleyball is the symbol :volleyball and that is all it will ever be. It has no other value or meaning.
If you just want it to read differently for aesthetic purposes, your best bet would probably be to define methods that return the appropriate symbol (e.g. def volleyball() :volleyball end). But this seems unidiomatic.
If you really want people to be able to send just about anything that isn't already a method, you could implement a method_missing along the lines of def method_missing(m, *args) m.to_sym end. But I really find this design awkward in most contexts I can think of.
class Something
attr_reader :callstack
def initialize
#callstack = {}
end
def self.with_method &block
self.new.instance_exec &block
end
def method_missing method, *params
params.empty? ? method : callstack[method] = params
end
end
Something.with_method do
sum 1, 2
play volleyball
swim further
eat "a lot"
puts callstack # => {:sum=>[1, 2], :play=>[:volleyball], :swim=>[:further], :eat=>["a lot"]}
end
Does this help?
You must pass objects as method arguments. What functionality are you trying to accomplish by passing arbitrary non-defined names? You could always pass them as a string and then use the string to use the text inside the method.
ex.
def self.methodname(arg1, arg2)
arg1 = arg2
end
Class.methodname("greeting","hello")
would set the variable greeting equal to 'hello'

String interpolation for keys in array? [closed]

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 supposed to be doing this:
attribute_name = "key_i_want"
scores = []
candidates.each do |candidate|
scores.push candidate.attributes.merge(:{#attribute_name} => {stuff})
end
scores
What I want to happen is that the category name, which in this case has the key "key_i_want", gets added to the hash, and its value will be "stuff". Is there some kind of "interpolate string" function, where I can add hash k-v pairs to an existing hash.
Another thing, what happens in this function is that I have an empty array called "scores", fill it up with the candidate+score hashes, and return the array scores at the end, is there some kind of syntactic sugar or something for this?
Here is the way to merge, as well as the cleaner way to create scores:
scores = candidates.map do |candidate|
candidate.merge({attribute_name => stuff})
end
This uses Hash#merge and Array#map (assuming candidates is an Array).
Ruby has syntactic sugar that wraps method parameters in a Hash for you if you write them in pairs with => between them. So the second line could also be this:
candidate.merge(attribute_name => stuff)
Also, if attribute_name is a String but the rest of the keys in candidate are Symbols, use String#to_sym so that the resulting Hash will have consistent keys:
candidate.merge({attribute_name_string.to_sym => stuff})
Is there some kind of "interpolate string" function, where I can add hash k-v pairs to an existing hash.
No need for interpolation.
Do this:-
merge(attribute_name => stuff)
Another thing, what happens in this function is that I have an empty array called "scores", fill it up with the candidate+score hashes, and return the array scores at the end, is there some kind of syntactic sugar or something for this?
attribute_name = "key_i_want"
candidates.each_with_object([]) do |candidate,scores|
scores.push candidate.attributes.merge(attribute_name => stuff)
end

What does `each` method return? [closed]

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
When I call
#data.each do |d|
some code here
end
what does the each method return? An array of objects? Or more generally, what does do...end block take?
It iterates over the members of the enumerable object. So if #data is an array it will return the elements of the array one at a time as d. Exact behavior depends on the type of object. See the docs
Books.all returns a object, that although it is not an array, behaves like one in this case.
each returns the receiver, in this case #data.
The do ... end is a block.
The each method will run the block (using the method yield) once for each value in data. This is called an iterator. For an array it will iterate over all the values in the array, for a hash it will run once per every pair of (key,value). You can define your own iterator for your own classes.
The return value of each depends on the object it is invoked. When invoked on an array it will return the array.
In your case the method each will execute the block once per each value and send each value as a parameter to the block.
For example-
a = [1,2,3]
a.each do |n|
p n
end
is just the same as
p a[0]
p a[1]
p a[2]

How to pass a function instead of a block [duplicate]

This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
Shorter way to pass every element of an array to a function
I know this will work:
def inc(a)
a+1
end
[1,2,3].map{|a| inc a}
but in Python, I just need to write:
map(inc, [1,2,3])
or
[inc(x) for x in [1,2,3])
I was wondering whether I can skip the steps of making a block in Ruby, and did this:
[1,2,3].map inc
# => ArgumentError: wrong number of arguments (0 for 1)
# from (irb):19:in `inc'
Does anyone have ideas about how to do this?
According to "Passing Methods like Blocks in Ruby", you can pass a method as a block like so:
p [1,2,3].map(&method(:inc))
Don't know if that's much better than rolling your own block, honestly.
If your method is defined on the class of the objects you're using, you could do this:
# Adding inc to the Integer class in order to relate to the original post.
class Integer
def inc
self + 1
end
end
p [1,2,3].map(&:inc)
In that case, Ruby will interpret the symbol as an instance method name and attempt to call the method on that object.
The reason you can pass a function name as a first-class object in Python, but not in Ruby, is because Ruby allows you to call a method with zero arguments without parentheses. Python's grammar, since it requires the parentheses, prevents any possible ambiguity between passing in a function name and calling a function with no arguments.
Does not answer your question but if you really just want to increment all your variables, you have Integer#next
4.next
#=> 5
[1,2,3].map(&:next)
#=> [2, 3, 4]

Resources