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?
"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
#{}
is called "string interpolation".
Related Topics
Rails :Dependent =≫ :Destroy VS :Dependent =≫ :Delete_All
In Ruby on Rails, to Extend the String Class, Where Should the Code Be Put In
How to Determine If One Array Contains All Elements of Another Array
Mixing Keyword With Regular Arguments in Ruby
Ruby Regular Expression Using Variable Name
Saving Enum from Select in Rails 4.1
Understanding Ruby'S Load Paths
Should Gemfile.Lock Be Included in .Gitignore
Protected and Private Methods in Rails
How to Search File Text For a Pattern and Replace It With a Given Value
Ruby Style: How to Check Whether a Nested Hash Element Exists
Ruby MySQL2 Gem Installation on Windows 7
Best Explanation of Ruby Blocks
What's Different Between Each and Collect Method in Ruby
Ruby Objects and Json Serialization (Without Rails)
How to Convert a Unix Timestamp (Seconds Since Epoch) to Ruby Datetime