Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>I can't speak to C#, but in layman's terms, Perl's autovivification is the process of creating a container object out of an undefined value as soon as it is needed.</p> <p>Despite most of Perl being quite dynamic, Perl's dereferencing syntax unambiguously specifies the type of the reference at compile time. This allows the interpreter to know what it needs out of a variable before the variable is ever defined.</p> <pre><code>my $var; # undefined # to autovivify to an array: @$var = 1..5; # @ here implies ARRAY $$var[4] = 5; # square brackets imply ARRAY $#$var; # $# implies ARRAY (returns the last index number) # to autovivify to a hash: %$var = (a =&gt; 1); # % implies HASH $$var{asdf} = 5; # curly braces imply HASH </code></pre> <p>This list could be longer, but should give you an idea.</p> <p>So basically, when you have a line like this:</p> <pre><code>my $var; $var-&gt;[1]{x}[3]{asdf} </code></pre> <p>Perl looks on the right side of the <code>-&gt;</code> and sees square braces. This means that the invocant <code>$var</code> must be an array reference. Since the invocant is undefined, Perl creates a new array and installs its reference into <code>$var</code>. This same process is then repeated for every subsequent dereferencing.</p> <p>So the line above really means:</p> <pre> (((($var //= [])->[1] //= {})->{x} //= [])->[3] //= {})->{asdf}; </pre> <p>which is fairly hideous, and hence autovivification. (<code>//=</code> is the defined-or assignment operator in perl 5.10+)</p> <p><strong>Update:</strong></p> <p>As per cjm's comment, to put this into general non-perl terms, to achieve autovivification in another language, you need a lazy object that supports indexing via <code>[...]</code> and <code>{...}</code>. When either of these indexing operations are performed, the object replaces itself with either an array or hash. Every time the object is then accessed, if the cell is empty, it should return another lazy object.</p> <pre><code>obj = new lazy_obj() level1 = obj[4] # sets obj to be an array, returns a new lazy_obj for level1 level2 = level1{asdf} # sets level1 (and obj[4]) to a hash, # returns a new lazy_obj for level2 </code></pre> <p>So basically you need two things, the ability to create an object that supports indexing with both array and hash subscripts (or the equivalent), and a mechanism such that an object can replace itself in memory with another object (or that can lock itself to one interpretation, and then store the new object internally.</p> <p>Something like the following pseudo-code could be a start:</p> <pre><code>class autoviv { private var content; method array_subscript (idx) { if (!content) { content = new Array(); } if (typeof content == Array) { if (exists content[idx]) return content[idx]; return content[idx] = new autoviv(); } else { throw error } } method hash_subscript (idx) { if (!content) { content = new Hash(); } if (typeof content == Hash) { if (exists content{idx}) return content{idx}; return content{idx} = new autoviv(); } else { throw error } } // overload all other access to return undefined, so that the value // still looks empty for code like: // // var auto = new autoviv(); // if (typeof auto[4] == autoviv) {should run} // if (auto[4]) {should not run} } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload