Hacker News new | ask | show | jobs
by DougWebb 3151 days ago
Why would there be a warning? Your example does exactly what autovivification is supposed to do. Obviously you don't normally use it as obscurely as you've done here.

I hate C#'s way of assigning a value to a dictionary, without autovivification:

    if (dict.ContainsKey("yes"))
    {
        dict["yes"] = val;
    }
    else
    {
        dict.Add("yes", val);
    }
You also have to use ContainsKey before you try to use [] to retrieve a value, because [] throws an exception if the key doesn't exist in the dictionary. Perl's autovivification, which assumes you know what you're doing and expect the key to be there when you ask for the value rather than explicity check for the key, makes much more sense and is a lot easier to work with.
2 comments

>which assumes you know what you're doing

This is exactly my point, there should be no autovivification - I'd wager most people using perl these days don't know what they're doing, they're reluctantly editing some legacy code.

It's a dangerous default behaviour that can lead to very hard to debug errors. Most languages don't do this so people don't expect it; I don't know C# but can immediately tell what the code you wrote is doing. Explicit is better.

It's extra confusing because if you try and dereference undef without accessing a value it's an error:

  perl -Mstrict -WE 'my $test; say @{ $test };'
  Can't use an undefined value as an ARRAY reference at -e line 1.
What harm is there in a warning? You can disable classes of warnings in perl if you want to, or turn them off completely. I would much rather be explicit so I don't accidentally use some magic.
Explicit isn't better when the explicit boilerplate overwhelms and hides the intent of your code.

For the C# example, this can cause an exception:

   dict["yes"] = "val";
If the dictionary already contains an entry with the key "yes", the line will assign "val" to that entry. But if there is no entry with that key, an exception is thrown. The alternative is to use the Add() method, but that throws an exception if the key does exist, and works if it doesn't. I can't imagine any common use case of dictionaries where this behavior makes sense.

So what you're left with is a bunch of boilerplace and an if/else branch wrapped around every place you want to set a value in a dictionary. It makes dictionary use very cumbersome, which obscures the intention of code that uses dictionaries and, worse, discourages their use. C#'s design here takes away a very handy data structure that can make entire classes of problems easy to solve.

Perl's dictionaries, aka hash types, are used everywhere in Perl code. They're extremely useful and flexible, and a lot of that is due to the ease of use that autovivification brings.

I don't think it's fair to judge a language (or any tool) by how difficult it is to use by someone who rarely uses it and has no desire to learn, rather than by how usable it is for someone who uses it all of the time.

> than by how usable it is for someone who uses it all of the time.

Most of my career since 1996 has been in developing Perl. I'm a contractor who gets hired (and paid well) to help with Perl projects. By no stretch can you say I "rarely use it".

And I still consider Perl one of the more difficult languages to deal with because it's very easy to rely on implicit behaviour that - whilst perfectly clear as you develop it - makes life inordinately hard a year later when you're trying to debug an edge case because now, e.g., people can have two different delivery methods in the same basket (whoops, the second one overwrote the first one in the hash!)

> Perl's autovivification, which assumes you know what you're doing

Which is fine if you're the only person who will look at this code and we're talking about a timespan of a few hours.

When someone comes to deal with this code a year later, it makes life more difficult than it needs to be; at least the C# way is explicit - you can come back to that years later and know exactly what's happening.

(Which is the basic problem with most of Perl's magic - coming back to it hours/months/years later makes life harder for no actual gain.)