How to pass argument to the method definition of `[]`? - ruby

How can I pass an argument to the definition of a singleton method of [] on A, in other words A['some_argument']?
class A
def self.[]
# some_argument
end
end

Just as to any other method, using argument list:
class A
def self.[](arg)
puts arg
end
end
A[1]
# => 1

Good answers are already given, but I think they miss to mention an important point.
The method [], when used ordinarily in the form foo[params] is actually in syntax sugar form. The underlying method name is [], and calling it in the underlying form would be foo.[](params).
Syntax sugar plays around with syntax, and transforms a method call in the form foo[params] into foo.[](params). But that does not work in method definition, so you have to define such method in the underlying form, not in the syntax sugar form.

class A
def self.[](*args)
puts args
end
end
> A[1,2,3]
1
2
3

You can also implement "set" functionality
class A
def self.[]=(key, value)
puts "#{key} = #{value}"
end
end
A['one'] = '1'
# one = 1

Related

Ruby Bracket Method with Block

I would like to define the [] method on a class of my own creation to take a block. I have done so as follows.
class A
def self.[](*args, &block)
puts "I am calling #{block} on #{args}."
block.(*args)
end
end
I can invoke this as follows.
# Explicit method invocation
A.[](1) { |x| puts x }
# With a procedure argument
arg = proc { |x| puts x }
A[2, &arg]
However, what I would like to be able to do is this.
A[3] { |x| puts x }
Which unfortunately seems to produce a syntax error. Is there a block syntax for the bracket method, or am I stuck with the first two ways of invoking it? In fact, more generally, which Ruby method names will allow blocks in their invocation, as it seems that there might be a limitation on when this is allowed?
There's not much you can do against a syntax error, so you'll have to change the syntax.
If you accept :
to define (i.e. pollute) an uppercase method inside Kernel (similar to Kernel#Array)
to use parens instead of brackets
You could write :
class A
def self.call_block_with_args(*args, &block)
puts "I am calling #{block} on #{args}."
block.call(*args)
end
end
module Kernel
def A(*args, &block)
A.call_block_with_args(*args, &block)
end
end
It works this way :
A(3) { |x| puts x }
#=>
# I am calling #<Proc:0x000000012b9c50#block_brackets.rb:14> on [3].
# 3
It's not clean, but it's probably the closest you can be to A[3] { |x| puts x }.
Blocks work with normal method calls only.
Ruby has plenty of operators, listing all of them here would be exhaustive, there are more than two dozens. Even `a` and !a and -a are method calls in Ruby. And obviously there are limitations to all these operators, eg + must take one parameter but not more, et cetera.
Fun fact, loop is a method call too.

Why the ruby code will generate an ArgumentError?

Hi I'm working on Ruby Koans. I was wondering why the ArgumentErrorwould be raised if the Dog6.new is returned in the code down below?
class Dog6
attr_reader :name
def initialize(initial_name)
#name = initial_name
end
end
def test_initialize_provides_initial_values_for_instance_variables
fido = Dog6.new("Fido")
assert_equal "Fido", fido.name
end
def test_args_to_new_must_match_initialize
assert_raise(ArgumentError) do
Dog6.new
end
end
Is it because Dog6.newdoesn't have any arguments? Thank you!!
Yes, your assumption is correct.
Dog6.new implicitly calls Dog6#initialize to initialize the newly created instance (one might think about MyClass#initialize as about the constructor for this class,) which apparently has one required argument. Since no argument was given to the call to Dog6.new, the ArgumentError is being raised.
Just adding that if you want to have a constructor with no arguments (after all - some dogs don't have a name....) you could have a default value for the name parameter.
def initialize(name = nil)
#name = name
end
In the initializer for the Dog6 class, initial_name is defined as a parameter required for object construction. If this class were to be instantiated without this argument, an ArgumentError would be raised because the class definition has a method signature such that Dog6.new is invalid, like you guessed. In this case the error you would see would be:
ArgumentError: wrong number of arguments (0 for 1)
Read more about the ArgumentError exception here.

creating method on fly as a parameter while calling singleton method

How's it possible in ruby ?
class Test
# Creating singleton method
def self.some_singleton_method(param1)
puts param1
end
end
# calling singleton method by creating method on fly as a parameter to it
Test.some_singleton_method def method_name(some_param)
# do something
end
## method_name
I've tried many places looking around, can't come up with an idea how's it's working.
Thanks!
It is possible, since def is keyword, that creates new method in current scope, which is Object since you're calling it on the "top" level, i.e. not inside any class. Starting from Ruby 2.1, def returns method name as a symbol, so your code is actually equivalent to
name = def method_name(some_param)
// do something
end
Test.some_singleton_method(name) # outputs "method_name"
EDIT: Thanks to Cary Swoveland for clarification that def is actually a keyword and not a method.
Here are two ways to do that.
#1
class Test
def self.doit(m)
send(m) yield
end
end
Test.doit(:hello) do
puts 'hi'
end
#=> :hello
Test.new.hello
#=> "hi"`.
#2
class Test
def self.doit(str)
eval(str)
end
end
Test.doit "def hello; puts 'hi'; end"
#=> :hello
Test.new.hello
#=> "hi"`.

what does a ruby method ending with an "=" mean?

What does a ruby method ending with an "=" mean?
See the available methods in this print out:
2.2.0 :066 > obj.methods(false)
=> [:label=, :label, :description=, :description, :thumbnail=, :thumbnail, :attribution=, :attribution, :license=, :license, :logo=, :logo, :see_also=, :seeAlso=, :see_also, :seeAlso, :related=, :related, :within=, :within, :metadata=, :metadata, :sequences=, :sequences, :structures=, :structures, :viewing_hint=, :viewingHint=, :viewing_hint, :viewingHint, :viewing_direction=, :viewingDirection=, :viewing_direction, :viewingDirection, :service=, :service]
For example whats this difference between label= and label?
foo= is no different than any other method, except:
it requires precisely one argument and
Ruby permits you to add spaces before the = character.
class Foo
def foo=(other)
puts 'hi'
end
end
Foo.new.foo = 7
hi
class Goo
def goo=
puts 'hi'
end
end
Goo.new.goo=
Ruby says, "I'm waiting for an argument...". So we provide one:
4
and then she complains about what she asked you to do:
#=> ArgumentError: wrong number of arguments (1 for 0)
= methods are typically used to create a setter for an instance variable (if attr_acccessor or attr_writer is not used):
class Foo
def initialize(foo)
#foo=foo
end
# getter
def foo
#foo
end
# setter
def foo=(other)
#foo = other
end
end
f = Foo.new('dog')
f.foo
#=> "dog"
f.foo = 'cat'
#=> "cat"
f.foo
#=> "cat"
the methods ending with "=" are setting the instance variable
look at the answer here: why-use-rubys-attr-accessor-attr-reader-and-attr-writer
It is equivalent of setter methods in other languages, it is just convention so it looks more natural to say
obj.description="Fun Site"
vs
obj.setDescription("Fun Site")
There is nothing special about methods that end in =
You can see this by running the code below:
def bob=
puts "bob="
end
p send('bob='.to_sym)
What is special is the '=' infix operator. When you write self.bob = "bill". It is interpreted as self.send('bob='.to_sym, "bill").
Putting a ? at the end of a method is a hint that it returns a boolean (true/false). Methods that end in ! hint that the method affects the instance. See String#chomp vs String#chomp.
You can find out more about ruby operators at http://www.tutorialspoint.com/ruby/ruby_operators.htm and more about naming conventions at https://github.com/bbatsov/ruby-style-guide#naming

How define custom method of class with special character like [] array in ruby?

how can I create _[ args ]() method in one class?
like said here How does defining [square bracket] method in Ruby work?
a[b] is the same as a.[](b)
a[b] = c is the same as a.[]=(b, c)
I want to do the same thing but with my special characters, like :
my_instance_['foo'] have to be same as my_instance._[]('foo')
my_instance_[:bar] = :baz have to be same as my_instance._[]=(:bar, :baz)
"_[]" special named method with no "()" needed, and no "." point too, when call it.
How writte declaration of this method in ruby?
thx.
If you want instances of your class to be able to use [], then you define a method on the class called []:
class Test
def [](index)
puts index
end
end
Test.new['3'] # writes '3'
In your example, you would use
my_instance_ = Test.new
my_instance_[3]

Resources