What? You mean auto-verification? NO!
Vivification is when we directly assign a deeply nested attribute/property while the ones above don’t exist, and yet the entire hierarch is automatically created.
Take example of *nix mkdir command. It creates a new directories in a given directory
# Create a single directory in current directory
$ mkdir temp
$ tree
.
└── temp
But, we can also create sub-sub-sub directory
# Try to create a nested directory
# When outer ones don't exist
$ mkdir faltu/bakwaas/bekaar
mkdir: faltu/bakwaas: No such file or directory
See, no vivification! We are unable to create bekaar directory because faltu and bakwaas don’t exist.
We will be forced to create parent directories before the child and grandchild.
# Sigh! One at at ime
$ mkdir faltu
$ mkdir faltu/bakwaas
$ mkdir faltu/bakwaas/bekaar
$ tree
.
└── faltu
└── bakwaas
└── bekaar
Don’t we wish we could directly create bekaar without creating faltu and bakwaas first?
Welcome to Auto-vivification. Automatic creation of outer structure when directly creating a nested structure.
# Vivification in mkdir (watch the p)
$ mkdir -p good/bad/ugly
$ tree
.
└── good
└── bad
└── ugly
So now we understand auto-vivification, can we do this in programming languages as well?
Well, *some* of them, like perl
perl lnaguage has support auto-vivification. We can directly assign to $year and it would automatically create the chain of $college and $stream
my $univ;
my $college="SITS";
my $stream="BECS";
my $year=4;
$univ{$college}{$stream}{$year}="A+";
print($univ{$college}{$stream}{$year});
Let's do it in JavaScript
// No auto-vivification in JavaScript
// Create top level object
let univ = {};
// Now assign to a deeper level
univ.college.stream.year = "A+"; // ERROR
--------------------------------------------
Output
--------------------------------------------
univ.college.stream.year = "A+"; // ERROR
^
TypeError: Cannot read property 'stream' of undefined
Yep, that’s right. While we have an object called univ, currently we do not have a property called ‘college’ and ‘stream’ while trying to assign value to ‘year’
Let’s understand the problem first. When we try to assign to a nested property in JavaScript, it tries to “get” the parent property, which does not exist and we get an error.
How about if we intercept that and create the parent property on-the-fly? Hmm…
let univ = {
// If property exists return it
// Otherwise, create it and return it
get: (prop) => {
this[prop]
? this[prop]
: this[prop] = {} }
}
univ.college = "SITS"; // WORKS!!!
console.log(univ);
univ.college.stream.year = "BECS"; // ERROR
console.log(univ);
Well, our joy was short-lived. While it can create any property on the fly inside univ
univ.college = "ABCD";
univ.establised = 1884;
univ.name = "Amazing";
but we cannot do it at the next level, so this doesn’t work
univ.college.stream = "CS";
JavaScript Proxy
object to the rescue!
A Proxy object plugs-in another object and can be handler for certain functions/properties.
E.g. We can have a Proxy object which handles get
for the handled object.
// Use Proxy object and handler to create a new property on the fly
let AutoViv = () =>
// Proxy() object of JavaScript
new Proxy({}, // ANY blank object
{
// if property exists, return it
// Otherwise, create it
get: (obj, prop) =>
prop in obj
? obj[prop]
: obj[prop] = AutoViv()
}
)
Time to put this to test!
// Use Proxy object and handler to create a new property on the fly
let AutoViv = () =>
// Proxy() object of JavaScript
new Proxy({},
{
// Handler checks if prop does not exists, creates it
get: (obj, prop) =>
prop in obj
? obj[prop]
: obj[prop] = AutoViv()
}
)
// Create only TOP level
let univ = AutoViv();
// Now assign to deeper level
univ.college.stream.year = "A+";
console.log("univ", univ);
let univ2 = AutoViv();
univ2['college']['stream']['year'] = "A+";
// Bingo! It works
console.log("univ2", univ2);
Output
univ { college: { stream: { year: 'A+' } } }
univ2 { college: { stream: { year: 'A+' } } }
Congratulations! We have an Auto-Vivification object in JavaScript now, which allows us to create a nested property without first defining its parent property!
Can we do it in other languages too? Maybe next post.. AutoVivification in Python
Auto vivification Series
- Auto vivification in JavaScript
- Auto vivification in Python
- Auto vivification in JavaScript (Upgraded)