LaunchKit
All quizzes
Ruby 2 views

Heredoc delimiters can be almost anything

Question

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

a = <<'"}{|_(_&^+$^)$_$345_$#%$^%^+'
visit ukod.me
"}{|_(_&^+$^)$_$345_$#%$^%^+

a # => ???

The correct answer is

Explanation

TL;DR

This is a valid heredoc. When the delimiter is quoted, as in <<'DELIM', Ruby accepts nearly any characters inside the quotes, symbols included. The parser only needs the closing line to repeat the delimiter exactly. The heredoc body is visit ukod.me plus its trailing newline, so a is "visit ukod.me\n".

Step by step

a = <<'"}{|_(_&^+$^)$_$345_$#%$^%^+'
visit ukod.me
"}{|_(_&^+$^)$_$345_$#%$^%^+

a # => "visit ukod.me\n"
  1. <<'...' opens a heredoc whose delimiter is the string between the single quotes: "}{|_(_&^+$^)$_$345_$#%$^%^+. The quotes are not part of the delimiter; they just let it contain characters that a bare delimiter cannot.
  2. Every following line belongs to the string until a line consists of exactly the delimiter. Here that is the very next line after the body.
  3. A heredoc keeps the newline that ends each body line, hence the trailing \n. The result: "visit ukod.me\n".

An unquoted delimiter is restricted to identifier characters (<<EOF, <<SQL), which is why the symbol soup requires the quoted form.

Edge cases

The quote style around the delimiter controls interpolation in the body, mirroring regular string literals. Single quotes make the body literal; double quotes (and the bare form) interpolate:

name = "world"

literal = <<'END'
hello #{name}
END
literal # => "hello \#{name}\n"

interpolated = <<"END"
hello #{name}
END
interpolated # => "hello world\n"

Two modifiers change how the closing delimiter and indentation are treated. <<~ (squiggly heredoc, Ruby 2.3+) strips the common leading indentation from the body, and <<- merely allows the closing delimiter to be indented:

text = <<~TEXT
  indented
    more
TEXT

text # => "indented\n  more\n"

In real code, stick to short, meaningful, uppercase delimiters (SQL, HTML, TEXT): the delimiter documents what the string contains, and your editor's syntax highlighting will thank you.

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.