Is There a Literal Notation for an Array of Symbols

Is there a literal notation for an array of symbols?

Yes! This is possible now in Ruby 2.0.0. One way to write it is:

%i{foo bar}  # => [:foo, :bar]

You can also use other delimiters, so you could also write %i(foo bar) or %i!foo bar! for example.

This feature was originally announced here:

http://www.ruby-lang.org/zh_TW/news/2012/11/02/ruby-2-0-0-preview1-released/

It is mentioned in the official documentation of Ruby here:

http://ruby-doc.org/core/doc/syntax/literals_rdoc.html#label-Percent+Strings

Using %i and %I symbol array literal


I'm having trouble finding what the %i does in relation to a symbol array.

It is an array literal for an array of symbols. It does the same thing in relation to symbol arrays as ' does to strings.

Create array of symbols

The original answer was written back in September '11, but, starting from Ruby 2.0, there is a shorter way to create an array of symbols! This literal:

%i[address city state postal country]

will do exactly what you want.

What is array literal notation in javascript and when should you use it?

array literal notation is where you define a new array using just empty brackets. In your example:

var myArray = [];

It is the "new" way of defining arrays, and I suppose it is shorter/cleaner.

The examples below explain the difference between them:

var a = [],            // these are the same
b = new Array(), // a and b are arrays with length 0

c = ['foo', 'bar'], // these are the same
d = new Array('foo', 'bar'), // c and d are arrays with 2 strings

// these are different:
e = [3], // e.length == 1, e[0] == 3
f = new Array(3); // f.length == 3, f[0] == undefined

Reference: What’s the difference between “Array()” and “[]” while declaring a JavaScript array?

What does %w(array) mean?

%w(foo bar) is a shortcut for ["foo", "bar"]. Meaning it's a notation to write an array of strings separated by spaces instead of commas and without quotes around them. You can find a list of ways of writing literals in zenspider's quickref.

Mutating an array of symbols

You convert symbol to string, but you don't assign it and you keep using symbol. Also use map instead of each. A quickfix would be:

s = [:aplha, :beta, :kappa, :phi]

def pluralSym(sym, out = [])
sym.map! do |s|
str = s.to_s
if str.match(/a$/)
out = str.sub(/a$/, "ae")
elsif s.match(/i$/)
out = str.sub(/i$/, "is")
else
out = str
end
out.to_sym
end
end

Is { 'symbol name': some value } valid Ruby 2 syntax for Hashes?


{ :my_key => "my value" } 
{ my_key: "my value" }
{ :'my_key' => "my value" }
{ :"my_key" => "my value" }

None of the above lines uses 2.x-only syntax. They are all also valid 1.9 syntax. (See demonstration.)

{ "my_key": "my value" }
{ 'my_key': "my value" }

That's feature request #4276 which landed in 2.2. That means it's invalid syntax in 2.1 or even older versions. It also means that an implementation that claims to implement 2.2 has to support it.

defining array in javascript

They do the same thing. Advantages to the [] notation are:

  • It's shorter.
  • If someone does something silly like redefine the Array symbol, it still works.
  • There's no ambiguity when you only define a single entry, whereas when you write new Array(3), if you're used to seeing entries listed in the constructor, you could easily misread that to mean [3], when in fact it creates a new array with a length of 3 and no entries.
  • It may be a tiny little bit faster (depending on JavaScript implementation), because when you say new Array, the interpreter has to go look up the Array symbol, which means traversing all entries in the scope chain until it gets to the global object and finds it, whereas with [] it doesn't need to do that. The odds of that having any tangible real-world impact in normal use cases are low. Still, though...

So there are several good reasons to use [].

Advantages to new Array:

  • You can set the initial length of the array, e.g., var a = new Array(3);

I haven't had any reason to do that in several years (not since learning that arrays aren't really arrays and there's no point trying to pre-allocate them). And if you really want to, you can always do this:

var a = [];
a.length = 3;

Prefer %w(...) to a literal array?

Voila!, one benchmark:

require 'benchmark'

n = 1_000_000
Benchmark.bm(11) do |b|
b.report('%w') { n.times { %w[a b c d e f g h i j k l m n o p q r s t u v w x y z] } }
b.report('explicit') { n.times { ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'] } }
b.report('numerics') { n.times { [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26] } }
end

user system total real
%w 2.590000 0.000000 2.590000 ( 2.591225)
explicit 2.590000 0.000000 2.590000 ( 2.584781)
numerics 0.300000 0.000000 0.300000 ( 0.309161)

user system total real
%w 2.590000 0.000000 2.590000 ( 2.591516)
explicit 2.590000 0.000000 2.590000 ( 2.584155)
numerics 0.300000 0.000000 0.300000 ( 0.308896)

user system total real
%w 2.590000 0.000000 2.590000 ( 2.592848)
explicit 2.590000 0.000000 2.590000 ( 2.585558)
numerics 0.300000 0.000000 0.300000 ( 0.308570)

I added the "numerics" array test because I suspected that %w is faster than using explicit strings due to testing for stringiness. %w doesn't need to do that, because it assumes everything is a string. After running it three times it's a wash as far as dealing with strings. Numbers rule, strings drool, and all that.


The previous benchmarks were run using Ruby 1.9.3-p286 on my system at work. I tested again using my old MacBook Pro at home, using Ruby 1.8.7-p358, so the following numbers are slower due to the differences in the hosting hardware, plus running an older Ruby:

                user     system      total        real
%w 3.070000 0.000000 3.070000 ( 3.080983)
explicit 3.100000 0.000000 3.100000 ( 3.093083)
numerics 0.950000 0.040000 0.990000 ( 0.990535)

user system total real
%w 3.080000 0.010000 3.090000 ( 3.076787)
explicit 3.090000 0.000000 3.090000 ( 3.089246)
numerics 0.950000 0.030000 0.980000 ( 0.989579)

user system total real
%w 3.080000 0.000000 3.080000 ( 3.073877)
explicit 3.090000 0.000000 3.090000 ( 3.091576)
numerics 0.950000 0.030000 0.980000 ( 0.989132)

On 1.8.7, %w was a tiny bit faster consistently, which probably gave rise to the speed-rumors.

Is it inefficient to use implicit array creation (a.k.a. shorthand or literal notation) in loops or function parameters?

Adam Cameron technically answered my question in one of his comments, but since it wasn't his "official" answer, I'll provide my own (along with a little perspective).

The answer is: YES. It is, in fact, inefficient to use implicit array creation in the manner demonstrated in my second example. Does that mean you won't be able to get away with it most of the time? Of course not! But, I've presented two methods of performing the same operation, the second of which is half as efficient as the first in terms of memory usage (and even a tiny bit slower)-- in my world, that's worth knowing about! If you're still going to insist on using implicit array creation in that situation, it might not hurt to ask yourself why. Is it because you think compressing your code onto one line impresses the girl programmers? I guess that's something. "Readability" seems to be the most popular excuse, though (it is, after all, the only measure by which implicit array/struct creation is not objectively inferior to explicit) If, like me, you find readability to be an ambiguous, moving target, there's nothing wrong with letting efficiency influence how you code. If you know how to write an efficient algorithm, don't let the popular "premature optimization" hyperbole scare you into writing an inefficient one instead. That demonstrates a lack of perspective just as much as premature optimization does.



Related Topics



Leave a reply



Submit