It's the time of year again, and with it comes a bundle of new Ruby 3.1 features getting approved and merged ahead of the December release.
This s...
For further actions, you may consider blocking this person and/or reporting abuse
So, what is the symbol syntax in Ruby 3.1 now? Do they start with a colon, or do they end with a colon?
Same as it has been. This plays off the json style of Hash keys.
I've been using Ruby for 15 years and it is by far my favorite programming language! As I introduce friends and colleagues to Ruby, the two things that seem to constantly trip them up are the symbol syntax vis-a-vis keyword arguments, and hash keys being either symbols or strings.
In my view, it's deeply unfortunate that as of Ruby version 1.9 there are two different ways of declaring symbols that can be quite confusing to people just coming to the language. This is compounded by the fact that keyword arguments share the same syntax, but aren't really symbols per se.
For example, the new hash syntax seems innocuous and both of these examples are equivalent:
However, when looking at the result, there is no way to determine which syntax was used when the hash was declared. This impacts providing guidance in error messages, because we may use the new syntax in the message, when the user wrote the code using the old syntax.
The new hash literal declaration syntax can only be used when keys are symbols. For example, would we expect the bug in the code below obvious to language newcomers?
The ability to coerce a string into a symbol already exists in Ruby, but it uses the original "legacy syntax", which I believe makes the intention much more clear.
Furthermore, both the old and new syntax may be freely combined when declaring hash literals which can lead to some odd looking declarations. For example in order to fix the bug in earlier example, should we write:
When evaluating the validity of the expression above, one must bring several different syntaxes to mind.
The alternative syntax may only be used safely when all hash keys are symbols, and in all other cases the original syntax must be used.
The new syntax effectively doubles the search space when scanning code for references to a given hash key that is a symbol because it might be declared in one of two different forms (leading colon or trailing colon).
The
ActiveSupport::HashWithIndifferentAccess
class exists in part to deal with some of the shortcomings of dealing with Ruby hashes. I really wish that we didn't need such a class and that Ruby would address these issues in a fundamental manner that would help make the language more approachable to newcomers.I mean I agree with you on the general premise that Symbol and String intermingling is confusing, but there's zero chance that gets changed due to the way Ruby works, and I've resigned to that. I've also had that argument several times, but originally in Ruby Symbols and Strings were much more different in terms of GC, memory, and identity. Because of that past it's impossible to change.
As far as this being the straw that broke the camels back? I would disagree. Keyword arguments have done this for a long time, the only difference now is that they can be used on "write" (creating a hash or calling a kwarg function) rather than "read" (kwarg function argument definition).
Even further than that, it is not only symbol and string as keys, but anything that responds to
hash
can be used as a key.That is SUCH a tiny diff for a big change, wow
I may add more tests for edge cases, I can see some potential for issues later without a more formal spec.
This creates copies of the object. The pointer is lost and at the smallest change the code must be changed 101 times. At least it's under javascript. I do not see any progress.
What are you referring to?
Old time javascript "foo = {}; foo.bar = 123;" . When passing foo as an argument to a function, it was passed as a pointer. In the old days javascript to create an object copy was cumbersome "foo_copy = JSON.stringify (foo);". By modifying the code accordingly, it was quite safe to rely on adding the foo attribute, which will be available in the called functions. Modern javascript makes it very easy to create a copy of an object "const {not_my_variable1, not_my_variable2} = foo;". But when I changed the code I wrote "foo.bar = 123;" and in modern javascript I have to check every call to a function to see if a copy of the object has been created and if there I also have to type an extra "bar" variable so that it can be passed to the next function.
This is an unwanted side effect for the syntax sugar.
Cool. Including methods will open for a new (and simpler) way to create polymorphism.
Oh? Have a few examples of ideas there?