Why Does String Interpolation Work in Ruby When There Are No Curly Braces

Why does string interpolation work in Ruby when there are no curly braces?

According to The Ruby Programming Language by Flanagan and Matsumoto:

When the expression to be interpolated into the string literal is simply a reference to a global, instance or class variable, then the curly braces may be omitted.

So the following should all work:

@var = "Hi"
puts "#@var there!" #=> "Hi there!"

@@var = "Hi"
puts "#@@var there!" #=> "Hi there!"

$var = "Hi"
puts "#$var there!" #=> "Hi there!"

String interpolation without #{}

You can actually interpolate global, instance, and class variables omitting the braces:

$world = 'world'
puts "hello, #$world"
# hello, world

In your example both $fg and @fg are uninitialized and thus evaluated to nil, that's why they are intorpolated as empty strings. When you write "abcd#fg" nothing is interpolated because the # is not followed by one of {, @, $.

You can find the feature documented in the RubySpec (thanks to @DavidMiani).

If you ask me, don't rely on this behaviour and always interpolate variables using braces, both for readability and to avoid problems such:

@variable = 'foo'
puts "#@variable_bar"

This will output an empty string instead of the, probably, expected string "foo_bar", because it is trying to interpolate the undefined instance variable @variable_bar.

How does string interpolation work without #{..} syntax?

When the expression to be interpolated is just a reference to a global, instance or class variable, then the braces can be omitted. The braces are only required for more complex expressions.

However, there is a debate about whether omitting the braces is a good idea from a style and readability perspective.

why not always use curly braces in string interpolation?

It is not be a problem since $decade are just a shorthand for ${decade}. So both Strings will end up compiling into the same code. The linter rule is about taste and make the code consistent in your code base.

You can see this in Dart Language Specification in the chapter about "String Interpolation": https://dart.dev/guides/language/specifications/DartLangSpec-v2.2.pdf

The form $id is equivalent to the form ${id}.

To customize which linter rules will run: https://dart.dev/guides/language/analysis-options

Ruby: String interpolation prints the function first when called second

Because the string is created first, which means calling def1, and then the whole string is passed into puts.

We can expand puts "some text #{def1}" out to understand.

string = "some text " + def1.to_s
puts string

As you can see, def1 is called to create the string. def1 prints out 1 itself, it does not return anything (it returns nil). Then the whole string is printed.

That's how all function calls work. The arguments are evaluated, the the function is called.

You'd need to call def1 after printing the prefix.

print "some text "
def1

This is a reason why it's often better to have a function return a value rather than print it itself.

`@` symbol in string causes unexpected results

The @ is a sigil for instance variables in Ruby, and when it follows #, which indicates interpolation, interpolation happens. In your examples, instance variables @X and @XX are called, which I suppose are not defined. If so, then these variables are nil by default, which expands to empty strings by to_s for interpolation. When #@ cannot be interpreted as interpolation (for example @ is invalid instance variable name), then it is recognized as #@ verbatim, and escape characters are inserted in the inspection.

What does %{} do in Ruby?

  1. "Percent literals" is usually a good way to google some information:

    • http://www.sampierson.com/articles/ruby-percent-literals
    • http://en.wikibooks.org/wiki/Ruby_Programming/Syntax/Literals#The_.25_Notation
  2. #{} is called "string interpolation".



Related Topics



Leave a reply



Submit