LaunchKit
All quizzes
Ruby 1 views

The braceless #@ivar interpolation shorthand

Question

What's the return value of the following Ruby code?

class Hi
  def initialize(name)
    @name = name
  end

  def to_s = "Hi #@name"
end

Hi.new("RubyCademy").to_s # => ???

The correct answer is

Explanation

TL;DR

#@name inside a double-quoted string is a real interpolation, not a literal. Ruby allows the braces of #{...} to be omitted when the interpolated expression is exactly one instance, class, or global variable. So "Hi #@name" is equivalent to "Hi #{@name}" and returns "Hi RubyCademy".

Step by step

class Hi
  def initialize(name)
    @name = name
  end

  def to_s = "Hi #@name"
end

Hi.new("RubyCademy").to_s # => "Hi RubyCademy"
  1. initialize stores "RubyCademy" in @name.
  2. to_s is an endless method whose body is the string literal "Hi #@name".
  3. When the string literal is evaluated, the parser recognizes #@name as an interpolation of the instance variable, calls to_s on its value, and splices it in.

The shorthand covers exactly three sigils:

@ivar = "instance"
$gvar = "global"

"#@ivar"  # => "instance"
"#$gvar"  # => "global"

Class variables work the same way: "#@@counter" interpolates @@counter. Local variables, method calls, and any expression more complex than a single variable still require the braces:

name = "local"
"#name"    # => "#name" (no interpolation, literal characters)
"#{name}" # => "local"

Edge cases

An uninitialized instance variable evaluates to nil, and nil.to_s is "", so the interpolation silently produces nothing:

"Hi #@missing" # => "Hi "

As with all interpolation, single quotes disable it: 'Hi #@name' contains the literal characters #@name. Most style guides (RuboCop's Style/VariableInterpolation rule included) prefer the explicit #{@name} form: the shorthand is easy to misread as a comment or a literal #, and it breaks as soon as you need @name.upcase instead of @name.

Share this quiz

Comments

No comments yet. Be the first.

Only used to confirm and publish your comment. Never shown publicly, never shared.

Markdown: **bold**, `code`, ```fenced blocks```, > quotes, [links](url). HTML and images are not rendered.