Ruby’s Hashes and Perl’s Autovivification, in JavaScript
raganwald.com
raganwald.com
I think the whole point was to help generate a few very long json files (http://docs.grafana.org/reference/dashboard/#dashboard-json) but in the end I had way more fun with this new concept!
Perl autovivifies on existence checks. This has led to A LOT of bugs.
Particularly since native Perl objects have all the behaviors of hashes so instead of getting the equivalent of a null exception Perl happily creates a hash and the process won’t bomb out until I try to call a method on the hash which I was expecting as a particular type.
In legacy code, this has led to a lot of safety checks verifying the variable is actually the expected type.
Perl 6 does not have that problem. One can even bind an alias to non-existing keys in a hash (several levels deep) only to have vivification happen as soon as you assign to the alias.
my %h;
my $deep := %h<a><b><c>;
say %h<a>:exists; # False
say %h<a><b>:exists; # False
say %h<a><b><c>:exists; # False
$deep = 42;
say %h<a><b><c>:exists; # TrueAutovivifying properties of a dictionary could certaintly lead to some bugs, but as presented here, checking for existence won’t invoke autovivification.
The implementation provided in the article is at least a known property of that particular object type and not a property of all objects.
no autovivification; # switches off autoviv except for setting
no autovivification 'exists'; # just for exists checkssome_autoviv_variable = defaultdict(lambda: defaultdict(dict))
turtles = lambda: defaultdict(turtles)
some_autoviv_variable = defaultdict(turtles)
Have to confess I'm a polyglot type person, and even Im starting to twitch at "unpythonic" feels of having something as nuts as a recursive expression in a lambda with some assignment.Welcome to the Dark Side. Enjoy the cookies!
trie = defaultdict(lambda: defaultdict(trie))
and you have a 1-line trie data structure, which is super useful.The code below that paragraph actually does check on every access, though.
Fix on the way. Thanks for spotting the discrepancy!
I could be wrong, but I think a sufficiently clever JS engine (like v8) would remove that check at runtime, by realizing that half of the ternary operator is dead code. (If it's hot code and it gets optimized, anyway).