Why NGS has no “undefined”

Since I know JavaScript, some Ruby and a bit of Perl which all have the concept of undefined it was a decision I had to make whether I implement undefined in NGS. This article shows why I decided not to have the undefined value/data type.

Update (thanks /u/EldritchSundae): what you observe in Ruby example below is nil, not undefined. In bash the undefined value is empty string. Ruby does not have undefined but it has the ability to read non-existing hash keys without causing an exception like JavaScript and Perl. In Ruby’s case the result is nil, not undef (Perl) or undefined (JavaScript).

Undefined in other languages

Showing here few common cases, not all possible usages.

JavaScript

> nodejs -e 'const a; console.log(a)'
undefined

> nodejs -e 'const h={}; console.log(h["xyz"])'
undefined

> nodejs -e '(function f(a,b) { console.log(a,b) })(1)'
1 undefined

Ruby

> ruby -e 'h={}; puts h["xyz"]' # outputs empty line

Perl

> perl -e '%h=(); print $h{"xyz"}' # outputs nothing

bash

> bash -c 'echo $a' # outputs empty line

Absence of undefined in NGS

Adding yet another data type to NGS needs justification. I can’t find any justification for undefined. I do consider the usages above bugs. Accessing a variable or a place that were not assigned any value is an error.

Conveying absence of a value in NGS is done similar to other languages with the special null value. There are also somewhat experimental Box, FullBox and EmptyBox types, similar to Option, Some and None in Scala.

Undefined as a hash value for non-existing keys

Having undefined returned when looking up non-existing hash key is a trade-off. It’s more convenient and more error-prone. I have chosen Python-like approach: it’s an error.

> ngs -e 'h={}; h["xyz"]'
... Exception of type KeyNotFound ...

# and added convenience method "get"
> ngs -p 'h={}; h.get("xyz", "NONE")'
NONE

Undefined when accessing unset variable

While bash gives you an empty string by default and Perl gives you undef, I do think accessing unset variable is definitely a bug. I guess it was understood at some point by the creators of bash and Perl so bash has -u flag that makes accessing undefined variable an error and Perl has use strict mode which does the same among other things.

> bash -c 'echo $a' # no error
> bash -c 'set -u; echo $a'
bash: a: unbound variable

> bash -c 'a=(); echo ${a[0]}' # no error, just horrible syntax :)
> bash -c 'set -u; a=(); echo ${a[0]}'
bash: a[0]: unbound variable

> perl -e 'print $a' # no error
> perl -e 'use strict; print $a;'
# no error - I have no idea why, probably some "special" variable

# Perl - take number two:
> perl -e 'print $abc' # no error
> perl -e 'use strict; print $abc;'
Global symbol "$abc" requires explicit package name
(did you forget to declare "my $abc"?) at -e line 1.
Execution of -e aborted due to compilation errors.

Undefined as value for parameters without arguments

Calling an NGS function with less arguments than it expects is an error as in most languages:

> ngs -e '(F (a,b) 10)(1)'
... Exception of type ArgsMismatch ..

By the way, I do cringe every time I see JavaScript code that explicitly uses undefined:

function f(optional_a, optional_b) { }
f(undefined, 10)

The programmer took a decision not to pass a value. How in the world is this undefined? Use null for f*ck sake!


Have a nice day!