Ruby: More about Ruby’s percent literal syntax.

Now the %i[…] Question

Question:

Why is i used for symbols and w for strings?

This comes from Ruby’s percent literal syntax.

Ruby provides a family of % literals.

For example:

%w[one two three]

means:

["one", "two", "three"]

while:

%i[one two three]

means:

[:one, :two, :three]

The letters are essentially mnemonics for the type being produced.


Why w?

%w can be thought of as:

word array

%w[apple banana orange]

produces:

["apple", "banana", "orange"]

These are strings.

The w is commonly understood as referring to words.

For example:

%w[admin editor viewer]

is a convenient way to write:

["admin", "editor", "viewer"]

Why i?

%i means:

symbol array

%i[admin editor viewer]

produces:

[:admin, :editor, :viewer]

The i is associated with identifiers/symbols in Ruby’s percent-literal syntax.

So you can remember:

%i → symbols
%w → strings

Don’t think of the i as meaning “integer” here.

It does not mean integer.


Compare Them Directly

%i[admin editor viewer]

returns:

[:admin, :editor, :viewer]

while:

%w[admin editor viewer]

returns:

["admin", "editor", "viewer"]

You can verify:

%i[admin editor].first.class
# => Symbol

and:

%w[admin editor].first.class
# => String

Why Would I Use %i Instead of [:admin, :editor, :viewer]?

Mostly readability and convenience.

Compare:

ROLES = [
:admin,
:manager,
:editor,
:viewer
]

with:

ROLES = %i[
admin
manager
editor
viewer
]

The second makes it visually obvious:

“This is a list of symbols.”

It is particularly nice for Rails configuration:

SUPPORTED_FORMATS = %i[
json
xml
csv
]

or:

PERMISSIONS = %i[
read
write
delete
publish
]

%i Supports Interpolation Differently

There’s an important distinction:

%i[hello #{name}]

does not interpolate name.

For interpolation, Ruby provides uppercase I:

%I[hello #{name}]

For example:

name = "ruby"
%I[hello #{name}]

produces:

[:hello, :ruby]

Similarly, lowercase/uppercase pairs exist elsewhere:

%w[hello #{name}]

does not interpolate.

%W[hello #{name}]

does interpolate.

So:

%i → symbols, no interpolation
%I → symbols, interpolation
%w → strings, no interpolation
%W → strings, interpolation

This is a useful distinction to know for interviews.


Ruby’s % Literal Family

Once you understand %i and %w, the rest becomes easier.

Ruby has several percent literals:

%q[hello]

Single-quoted-style string.

%Q[hello #{name}]

Double-quoted-style string with interpolation.

%w[one two three]

Array of strings.

%W[one #{two}]

Array of interpolated strings.

%i[one two three]

Array of symbols.

%I[one #{two}]

Array of interpolated symbols.

%r{/users/\d+}

Regular expression.

%s[foo]

Symbol literal.

%x[ls -la]

Executes a shell command and returns its output.


The Mental Model I’d Recommend

Don’t memorize %i as some arbitrary Ruby trick.

Think:

% + type + delimiter

For example:

%i[admin editor]

means:

%
+
i = symbol array
+
[...] = delimiter

Likewise:

%w[admin editor]

means:

%
+
w = word/string array
+
[...] = delimiter

And the delimiter isn’t necessarily [].

You can use:

%i[admin editor]
%i(admin editor)
%i{admin editor}
%i<admin editor>

Although [] is by far the most common/readable form

Percent literals:

%i # symbols
%w # words/strings
%I # interpolated symbols
%W # interpolated strings