In Ruby, how do single-quoted and double-quoted string literals differ, and where do %q and %Q fit?
answer
- one interpolates, one does not
- single quotes: only \\ and \' escape
- '\n' is backslash plus n
- %q is single, %Q and % are double
- #@var shorthand in double quotes
basics
~10 sDouble-quoted strings process escape sequences such as \n and \t and interpolate #{...}; single-quoted strings do neither, except for ' and \. %q(...) behaves like single quotes, %Q(...) and %(...) like double quotes.
solid answer
~40 sA double-quoted literal is **processed**: escape sequences such as `\n`, `\t` and `\u00e9` become the characters they name, and `#{expr}` is evaluated and inserted. A single-quoted literal is taken almost **verbatim**: it recognises only `\'` and `\\`, so `'\n'` is two characters, a backslash and an `n`, and `'#{total}'` stays literal text. The percent forms choose the same behaviour with a delimiter you pick: `%q(...)` acts like single quotes, `%Q(...)` and bare `%(...)` like double quotes, which removes the need to escape embedded quotes: `%q(She said "it's hot")`. In double quotes, the shorthands `#@total`, `#@@count` and `#$mode` also interpolate instance, class and global variables without braces, a trap when a literal `#@` is meant.
code
ruby · 8 linestotal = 7.5
"Total:\t#{total}" # => "Total:\t7.5" (a real tab)
'Total:\t#{total}' # => "Total:\\t\#{total}"
'\n'.length # => 2
"\n".length # => 1
'it\'s' # => "it's"
%q(say "hi") # => "say \"hi\""
%(#{total} due) # => "7.5 due"go deeper
Recall that double quotes interpolate and process escapes, single quotes do not, and that %q and %Q mirror them. Be able to predict '\n'.length.
Explain the exact escape rules on both sides, including unknown escapes in double quotes and the #@ivar shorthand, and when a percent literal beats escaping.
Spot the production versions of these bugs: a style cleanup that turns \n into literal text, or #@ in user-facing copy that silently swallows text.
Decide what a team's linter should enforce for quote style and why the rule needs exceptions for text containing #{, backslashes or quotes.
## Two kinds of literal Ruby has two basic string literal forms, and they differ in how much the parser **processes** the text between the quotes. | Feature | `"double"` | `'single'` | |---|---|---| | `#{expr}` interpolation | yes | no, kept as text | | `\n`, `\t`, `\u00e9`, `\e` escapes | yes | no | | `\'` | not needed | yes, a single quote | | `\\` | a backslash | a backslash | | Unknown escape like `\d` | the character itself: `"d"` | kept: backslash and `d` | | `#@ivar`, `#@@cvar`, `#$global` shorthand | yes | no | - **Double quotes** are the everyday choice when text contains values or control characters. - **Single quotes** are the choice for text that must stay exactly as typed: regular-expression sources, Windows paths, templates that contain `#{` on purpose. Both produce ordinary `String` objects; once parsed, a literal without interpolation is the same kind of string whichever quotes wrote it, so pick by meaning. ## Escapes in detail In a double-quoted literal the backslash starts an **escape sequence**: - `"\n"` is one character, a newline; `"\t"` is a tab. - `"\u00e9"` is the character é; `"\u{1F600}"` takes a code point in braces. - `"\""` embeds a double quote. - `"\d"` is simply `"d"`: an unknown escape yields the character itself. In a single-quoted literal only two sequences exist: 1. `'\''` is a single quote. 2. `'\\'` is one backslash. Everything else keeps its backslash: `'\n'.length` is `2`, and `'C:\temp'` keeps both the backslash and the `t`. ## Percent literals When the text contains quotes, a **percent literal** lets you pick a delimiter instead of escaping: ```ruby %q(She said "it's too hot") # like single quotes %Q(Order ##{order_id} is ready) # like double quotes %(Order ##{order_id} is ready) # bare % is %Q ``` - `%q` behaves like single quotes: no interpolation, and only backslashes and the chosen delimiter can be escaped. - `%Q` and bare `%` behave like double quotes. - Delimiters can be `()`, `[]`, `{}`, `<>` or a pair of other punctuation such as `|` or `:`. Bracket pairs may nest: `%q(a (b) c)` is valid. ## The receipt example Printing a coffee-shop receipt header shows each form in its natural place: ```ruby shop = "Bean There" order = 1042 puts "#{shop}\tOrder ##{order}" # tab and interpolation puts 'Prices include VAT\n' # prints the backslash and n puts %q(Ask for our "barista's pick") ``` The second line prints `Prices include VAT\n` literally, a common surprise when someone switches quote styles during a style-guide cleanup. ## Adjacent literals Ruby joins **adjacent string literals** at parse time, which is handy for long text split across lines: ```ruby footer = "Thank you for visiting " \ 'Bean There' # => "Thank you for visiting Bean There" ``` - Any mix of single-quoted, double-quoted and percent literals can be joined, as long as a percent literal is not the last one; `"a" %q{c}` is parsed as a method call instead. - The trailing backslash continues the line; without it, the second literal would be a separate statement. - Each piece keeps its own rules: the double-quoted part interpolates, the single-quoted part does not. ## Interpolation shorthands In double-quoted strings `#` followed by a sigil interpolates without braces: - `"#@total"` inserts `@total`. - `"#@@count"` inserts the class variable `@@count`. - `"#$mode"` inserts the global variable `$mode`. This is why `"Email: support#@example"`-style text can silently lose part of itself: `#@example` reads an instance variable, usually `nil`, and inserts an empty string. Escape the hash (`"\#@"`) or use single quotes. ## Choosing in practice - Use **double quotes** when you interpolate or need an escape. - Use **single quotes** or `%q` for literal backslashes and `#{` sequences. - Use `%Q` or `%(...)` when interpolated text also contains double quotes. - Many teams let a linter enforce one default quote style; the behaviour differences above are what make a mechanical switch risky.
- What does "support#@example" produce inside a method where @example is unset?`#@example` is interpolation shorthand for the instance variable `@example`. Unset, it reads as `nil`, which interpolates as an empty string, so the result is `"support"`. Escape the hash as `\#` or use single quotes.
- Which characters can be escaped inside %q(...)?Only the backslash and the delimiters you chose. `%q` otherwise behaves like a single-quoted string: no interpolation and no `\n`-style escapes. Nested bracket pairs such as `%q(a (b) c)` need no escaping.
- What does "\d" evaluate to in a double-quoted Ruby literal?`"d"`. In a double-quoted string an unrecognised escape yields the character itself, so the backslash disappears. That is why regular-expression text is usually written as a Regexp literal or in single quotes.
saying these in an interview costs you the question
- Single-quoted strings interpolate #{} but skip escape sequences
- '\n' is a newline in single quotes too
- %q is the interpolating percent literal and %Q is the literal one
- Single quotes are much faster at run time, so always prefer them
- Only #{} interpolates; #@ivar in double quotes is plain text