I have to say I cried a little bit when I read this - it seems that Matz et al are trying to make the language unparseable.
(Of course, perhaps I'm more sensitive than most, having actually written an Ruby lexer - http://github.com/jasonl/eden - which made me deal with the dusty, hidden corners of the Ruby grammar.)
Yea. So they've move away from the Perl-like 'rocket' syntax to a more JavaScript/Python-like syntax. Ruby+Python hackers will rejoice while Perl+Ruby hackers will pout. This isn't necessarily some 'huge' win.
[Though I guess it could be a 'win' for Rails hackers since they are likely to just be Ruby/Rails+JavaScript hackers.]
As a Perl developer I'd say »More power to them.« Also, since Perl's => is basically a comma operator that turns a bareword on its left into a string, I'd say Ruby's move is a step away from Perl regarding syntax, but a step towards Perl regarding functionality.
Anyway, as a non-Ruby developer I can appreciate the move. Also reminds a bit of some Scheme's ability to prefix and postfix symbols with »:«.
% python -m timeit '{"key": "value", "dr_nic": "The Comedian", "ttl": 42}'
1000000 loops, best of 3: 0.296 usec per loop
% python -m timeit 'dict(key="value", dr_nic="The Comedian", ttl=42)'
1000000 loops, best of 3: 0.771 usec per loop
There are far better ways to make code faster than worrying about the extra fraction of a microsecond you're spending calling dict rather than using the literal syntax.
I was unaware that there was a difference in performance, but a quick timing check shows that it takes about twice as long to create a dictionary with 7 items using dict() than using {}.
It makes sense when I stop to think about what the code would have to do, though.
You're right; I'm seeing dict() with explicit kwargs taking 3 times as long as a literal. My unscientific and non-rigorous benchmarks tell me that the construction and unpacking of the kwargs in the dict() call are the cause of most of the slowdown.
With the time it takes to assign with a literal normalized to 1, I'm seeing dict(kwargs) (with kwargs created before the benchmark) take 2 and dict(key_1=val_1, key_2=val_2, etc.) take 3.
As python runtimes/JITs get better and better, the literal version could get relatively faster, since static assertions can potentially more easily be made about it; whereas the global 'dict' could be replaced with anything, requiring much more sophistication.
Say you use a dict in a non-mutating manner, it is made up of string literals only, and you construct it within a loop; it could be able to be pulled out as an invariant, the same could be true of the function-call case, but potentially not as easily.
In optimizing a dynamic language, the problem of a symbol being replaced like this is no big deal; it's all but the expected norm, and inline caching ought to take care of it.
On invariant code motion: it tends not to be a big win because programmers usually move obvious big code out of loops explicitly. They do that because relying on a compiler optimization to do it is unpredictable; you may accidentally trigger a wall in your optimizer's ability to analyze your code as it grows more complex over time.
But we really are arguing over small potatoes here.
My own opinion is that although Ruby allows string-like symbols (like :"symbol with space"), I think they should be avoided. There may be a case for them, but I've not encountered one yet.
The new syntax works only with conventional symbols (no quotes), not with any other key type, so no integers, strings, objects etc. For everything else, you can fall back to the original syntax. You can even mix then if you really feel the need (yech!)
That said, for almost all use cases hashes use symbols as keys, and for these cases the new syntax is much cleaner and I'm glad to see it
> That said, for almost all use cases hashes use symbols as keys
I'd say there are more vanilla symbol hash uses by number, but the most interesting and powerful things you can do with hashes don't involve symbols for keys, imho.
So, hashes can be considered ordered in 1.9. It's a mistake to corrupt the data structure, in my opinion, but apparently that boat has now sailed. Thanks for the prod to recheck and sorry about the outdated info.
In case anyone doesn’t get it, the comic (and its lapel button), the yellow words to the left, and the phrase "The Comedian" are a reference to the fantastic graphic novel Watchmen.
I couldn't figure out why no one was commenting on this aspect of the post, and all the effort that must have gone into its creation. Maybe folks are just so used to topfunky's blog posts being works of art (see the archives for more examples) that they've come to take it for granted.
It's fairly terrifying what an accretion of these sorts of options did to Perl, and I say that as someone who does a lot of Perl5 coding and enjoys it.
It would be one thing to just have a new symbol that was a drop-in alternative to what works now. But in this case you have a _sometimes_ alternative, so you need to remember a new rule, if only to be able read other people's code. That cognitive cost outweighs any keystroke benefit IMHO.
If so, is your concern based on the impact this has on you personally, or is it based on concern for some mythical other dev who might have problems with the additional "cognitive cost"?
I've been a developing in Ruby now for about 4 years, I think this (the new syntax) is absolutely the right thing to do
This is one of the more upvoted Ruby stories I've seen on HN in some time, and it's a little bit disappointing. Sensationalism and inaccuracy are all it takes these days, eh?
I'm hoping that the story is upvoted more for the artistry of the post, The Watchmen reference and the plead to move to 1.9 and less for the argument of hashrocket vs. colon syntax.
But, given the chance HN will always fan the flames of the argument that lies within.
It's debatable whether aligning the mapping operator - be it a colon or a hash rocket - is a good idea to begin with. The point has been made in the past that if you edit the map so that the longest key changes, you'd have to realign all other entries too. For code versioning, e.g., in shared development, this creates unnecessarily large diff's. For instances, patches become more difficult to read, because they include lines that haven't actually changed content-wise, just layout-wise.
For code versioning, e.g., in shared development, this creates unnecessarily large diff's. For instances, patches become more difficult to read, because they include lines that haven't actually changed content-wise, just layout-wise.
I absolutely agree. The PHP array instantiation syntax is atrocious... I really dislike '=>'. While they're at it they might as well replace array() with [] and/or {}.
It's technically a 'language construct', but it sure does seem like a function. Same with PHP's 'list'. It's not good syntax, in my opinion also. It doesn't even seem like syntax!
Yeah, call_user_func('strlen', 'hello world') works but call_user_func('array', 'hello world') does not. But for ugly syntax, it's hard to beat the $ sigil being required everywhere for no reason at all (unlike Perl where it actually did something).
You're right, I was a bit hasty and didn't consider that. It sure does look like a function though, where other languages typically use {} or something similar.
Having written and shipped 5+ iPhone apps written in the verbosphemy* that is ObjectiveC, I'm strongly looking forward to being able to do all future iPhone apps in a saner language like JavaScript or Python. If I do them at all. Ever again. In fact it's pretty much a hard requirement. Just after this current one ships.
I think people are misunderstanding the title (which is not meant to be taken literally). They won't be removing the hashrocket ever, since (surely) they don't plan to limit hash keys to symbols only. The syntax only works in limited cases (namely symbols without spaces).
Which makes me wonder...why do it all if it is just for a limited case. Seems to make the code less understandable (to me) and it seems an unnecessary change to the language (to me).
I'm not familiar with the particular 'sorting' thing you're doing, but if the first things works, then the second should work in 1.9 if you use the correct syntax -- you have an extra colon. It should be: list.sorting = {name: 'ASC'}
It's more problematic for those that include Ruby extensions in C, but fixing a library to make it 1.9-compatible is not generally that onerous a task (the major exception to this is string encoding, which is fine in simple cases but a complete nightmare in anything complex). If enough people just write patches for a couple of gems they use, everything would be 1.9-compatible soon enough. rvm lets you install all the different Ruby versions you'll need for testing easily enough.
Interesting to see this convergence of syntax. Unfortunately, it's not true that you don't have to learn a "new syntax." As often with Ruby libraries, the devil is in the subtleties.
This does not work (although I think it could):
{"foo bar": 'b'}
but this does:
{:"foo bar" => 'b'}
Without being truly JSON compatible, it's only moderately useful.
One annoyance of Ruby for me has always been that many libraries, such as Rails, allow for symbols or strings interchangeably - but only in "most" cases, often leading to head banging in the other cases.
More intrigue: the syntaxes are also mixable
{foo: 'bar', "add-a" => 'dash', :'or a' => 'space in a symbol'}
You can do it, but is it a good idea? What it implies to me is that at some point in your program, you're constructing symbols from arbitrary strings which aren't known ahead of time. This sounds like a recipe for disaster given that symbols aren't garbage collected.
In fact, like almost everyone else in our space we're looking to hire => http://hashrocket.com/jobs