What Does the Equal ('=') Symbol Do When Put After the Method Name in a Method Definition

What does the equal ('=') symbol do when put after the method name in a method definition?

That snippet defines a Virtual Attribute (or a "setter" method) so that "express_token" looks like an attribute, even though it's just the name of the method. For example:

class Foo
def foo=(x)
puts "OK: x=#{x}"
end
end
f = Foo.new
f.foo = 123 # => 123
# OK: x=123

Note that the object "f" has no attribute or instance variable named "foo" (nor does it need one), so the "foo=" method is just syntactic sugar for allowing a method call that looks like an assignment. Note also that such setter methods always return their argument, regardless of any return statement or final value.

If you're defining a top-level setter method, for example, in "irb", then the behavior may be a little confusing because of the implicit addition of methods to the Object class. For example:

def bar=(y)
puts "OK: y=#{y}"
end
bar = 123 # => 123, sets the variable "bar".
bar # => 123
Object.new.bar = 123 # => 123, calls our method
# OK: y=123
Object.public_methods.grep /bar/ # => ["bar="]

Why do method definitions return symbols?

IRb always displays the result of calling inspect on the value of the last expression that was evaluated. It doesn't matter whether that expression is a literal expression, a conditional expression, a message send, a class definition expression or a method definition expression.

Everything returns a value in Ruby, i.e. everything is an expression, there is no such thing as a statement in Ruby.

In the past, the return value of a method definition expression was undefined. Most Ruby implementations simply returned nil from a method definition expression, but Rubinius for example returned the CompiledMethod object for the method that was defined.

With Ruby 2.1, the return value of a method definition expression was standardized to be the Symbol corresponding to the method's name. This allows you to use the method definition expression as an argument in methods that expect the name of a method as an argument.

Some examples:

# Before Ruby 2.0:
def foo; end
private :foo

# After Ruby 2.0:
private def foo; end # similar for `protected`, `public`, `module_function`

# Before Ruby 2.0:
def map; end
alias_method :collect, :map

# After Ruby 2.0:
alias_method :collect, def map; end

On a personal note, I would have preferred a method definition expression to evaluate to an UnboundMethod object corresponding to that method, and methods like public, private, protected, alias_method, module_function etc. should be amended to accept UnboundMethods in addition to Symbols and Strings.

What does a method turn into with the equal sign left out in Scala?

Such method definition is called procedure. It's a special syntax for Unit-returning methods:

def someMethod(a: Int): Unit = {
println(a)
println("---------")
}

It's not a recommended syntax.
Martin Odersky believes it was a bad decision to include this syntax. See Keynote - Scala with Style chapter 45.

Meaning of # symbol

def #{attr_name}=(attr_name)
@#{attr_name} = attr_name
@#{attr_name}_history = [nil] if @#{attr_name}_history.nil?
@#{attr_name}_history << attr_name
end

If attr_name variable where equal to, let's say, "params". This would actually transform into this:

def params=(attr_name)
@params = attr_name
@params_history = [nil] if @params_history.nil?
@params_history << attr_name
end

Why that happens? Because of something called String interpolation. If you write #{something} inside a String, something will be evaluated and replaced inside that String.

And why whould the above code work even though it's not in a String?

The answer is, because it is!

Ruby gives you different ways to do things, and there is an alternative syntax for some literals, that goes like that: %w{one two three} where {} could be any delimiter, as long as you use the same or the corresponding closing one. So it could be %w\one two three\ or %w[one two three], they would all work.

That one, %w is for Arrays, %Q is for double-quoted String. If you wanna see all of them, I suggest you take a look at this: http://www.ruby-doc.org/docs/ProgrammingRuby/html/language.html

Now, in that code

class Class
def attr_accessor_with_history(attr_name)
attr_name = attr_name.to_s # make sure it's a string
attr_reader attr_name # create the attribute's getter
attr_reader attr_name+"_history" # create bar_history getter
class_eval %Q{ << # STRING BEGINS
def #{attr_name}=(attr_name)
@#{attr_name} = attr_name
@#{attr_name}_history = [nil] if @#{attr_name}_history.nil?
@#{attr_name}_history << attr_name
end
} << # STRING ENDS
end
end

We can see the whole part with the String interpolation is inside a %Q{ }. That means the entire block is a big double-quoted String. And that's why the String interpolation will successfully do it's job before sending the String to eval.

When to use the equals sign in a Scala method declaration?

I actually disagree pretty strongly with Daniel. I think the non-equal syntax should never be used. If your method is being exposed as an API and you're worried about accidentally returning the wrong type, add an explicit type annotation:

object HelloWorld {
def main(args: Array[String]): Unit = {
println("Hello!")
123
}
}

The non-equal syntax is shorter and might look "cleaner", but I think it just adds the possibility of confusion. I have sometimes forgotten to add an equal sign and believed my method was returning a value when actually it was returning Unit. Because the non-equal and equal-with-inferred-type syntaxes are so visually similar, it's easy to miss this problem.

Even though it costs me a little more work, I prefer the explicit type annotations when they matter (namely, exposed interfaces).

What does the question mark at the end of a method name mean in Ruby?

It is a code style convention; it indicates that a method returns a boolean value (true or false) or an object to indicate a true value (or “truthy” value).

The question mark is a valid character at the end of a method name.

https://docs.ruby-lang.org/en/2.0.0/syntax/methods_rdoc.html#label-Method+Names

how do i pass a block to a method whose name ends with equals sign?

The syntax sugar for methods ending in = does make it special. You can still do things like pass multiple arguments to that method, or pass a block, but not in any pretty or convenient manner:

class Foo
def bar=(a,b=nil)
p [a,b]
if block_given?
yield "hi"
else
puts "No block"
end
end
end

f = Foo.new
f.bar = 42
#=> [42, nil]
#=> No block

f.bar = 42, 17
#=> [[42,17], nil]
#=> No block

f.send(:bar=,42,17) do |x|
puts "x is #{x.inspect}"
end
#=> [42, 17]
#=> x is "hi"

Another way in which these methods are special is that when called with the syntax sugar they evaluate to the right hand value, not the return value of the method:

class Foo
def bar=(a)
return 17 # really explicit
end
end

f = Foo.new

x = (f.bar = 42)
p x
#=> 42

x = f.send(:bar=,42)
p x
#=> 17

Defining method in Ruby with equals

Generally, do_something is a getter, and do_something= is a setter.

class Foo
attr_accessor :bar
end

is equivalent to

class Foo
def bar
@bar
end

def bar=(value)
@bar = value
end
end

To answer your question about the difference in behavior, methods that end in = always return the right hand side of the expression. In this case returning action, not action.inspect.

class Foo
def do_something=(action)
"stop"
end
end

?> f = Foo.new
?> f.do_something=("drive")
=> "drive"


Related Topics



Leave a reply



Submit