-
Notifications
You must be signed in to change notification settings - Fork 41
Hush vs NGS
Focusing on differences, skipping aspects which are similar.
https://hush-shell.github.io/intro/type-system.html
As in Lua, Hush proposes only a handful of built-in types, and no user-defined types.
NGS:
- provides many built in types.
- supports user-defined types.
- supports inheritance.
- lacks the
char
type, most likely a mistake on my part
let pi = 3.14
NGS - pi = 3.14
String concatenation
++
NGS uses multiple dispatch. +
is used for adding numbers and concatenation of strings.
Hush:
let array = [
1 + 2,
3.0 * std.float(4), # explicit conversion to float.
21 % std.int(5.2), # explicit conversion to int.
false and not true, # will short circuit.
1 == 1.0, # false, int and float are always distinct.
"abc" > "def",
"hello" ++ " world",
]
std.assert(array[0] == 3)
NGS:
The commas at the end of line, separating the elements, are optional.
array = [
1 + 2
2.0 * Real(4)
21 % Int(5.2)
false and not(true)
"abc" > "def"
"hello" + " world"
]
assert(array[0] == 3)
Hush:
let dictionary = @[
age: 20,
height: 150,
greet: function()
std.print("hello!")
end,
]
std.assert(dictionary["age"] == 20)
std.assert(dictionary.height == 150)
dictionary.greet() # prints "hello!"
NGS:
Optional commas at ends of lines. Quoted keys. Very direct translation. In NGS the following would be implemented with user defined type and F greet(x:MyType) ...
, not a method in a dictionary.
assert()
in NGS takes a pattern as the second argument.
dictionary = {
'age': 20
'height': 150
'greet': { echo("hello!") }
}
assert(dictionary, {"age": 20, "height": 150})
dictionary::greet()
https://hush-shell.github.io/intro/control-flow.html
Functions are first class citizens
Same. Taken few steps forward though. Function defintion syntax is short, based on frequency of use:
-
F (...) ...
- anonymous -
F name(...) ...
- multiple dispatch -
{ ... }
- anonymous with 3 optional arguments:A
,B
andC
. -
my_func = some_func(X, 1, 2)
- partially applied function, call asmy_func(100)
.
They must declare how many arguments they expect, which is enforced when calling a function.
In NGS, parameters have types. These are also enforced when calling a function. Additionally, types serve multiple dispatch so:
Hush:
function takes_one(x)
# ...
end
function takes_two(x, y)
# ...
end
takes_one(1)
takes_two("a", 2)
NGS:
Sample, could be more like Hush but showing multiple dispatch here.
F takes(x) ...
F takes(x, y) ...
takes(1)
takes("a", 2)
Calling a function with less or more arguments than expected will result in a panic.
If no appropriate method found (among the candidate in multiple dispatch), an exception is thrown.
Hush provides one further facility for functions: the self keyword.
Nothing like this in NGS. There are types and methods. UFCS is supported, calling obj.meth(x)
is exactly the same as meth(obj, x)
.
For loops
Hush:
for item in iter(array) do
sum = sum + item
end
NGS:
Iter()
is automatically called so for item in array { ... }
https://hush-shell.github.io/error-handling.html
Panic
NGS uses exceptions thoroughly.
Optional type Box/EmptyBox/FullBox
and result type Result/Success/Failure
are also supported.
safe_div_mod(5, 0)?
The quesion mark is not needed as NGS uses exceptions.
- https://hush-shell.github.io/cmd/basic.html
- https://hush-shell.github.io/cmd/capture.html
- https://hush-shell.github.io/cmd/async.html
{ echo Hello world! }
NGS has multitude of mechanisms to run external commands and many controls
process_obj = $(...)
bg_process_obj = $(... &)
output = `...`
parsed_output = ``...`` (parses for example JSON)
Errors
Consistent with the rest of the language, NGS throws exception on errors.
Note that errors are not one-to-one with non-zero exit code. grep
for example returns 1 if nothing is found. That's false
in boolean context in NGS but it's not an exception.
For unknown commands, non-zero exit code is an exception but override is easy: $(ok:[0,1,4] my_command)
- lists the exit codes which would not throw an exception.
https://hush-shell.github.io/std.html
std.args()
ARGV
std.assert(value)
https://ngs-lang.org/doc/latest/generated/assert.html
std.contains(collection, value)
- https://ngs-lang.org/doc/latest/generated/has.html
- https://ngs-lang.org/doc/latest/generated/in.html
std.env(key)
ENV.get(key)
std.is_empty(collection)
not(collection)
- empty collection is false
in boolean context
std.iter(collection)
Iter(collection)
std.json.dump(value)
value.encode_json()
and higher level store("file_name.json", value)
std.json.parse(string)
string.decode_json()
and higher level fetch("file_name.json")
std.regex(pattern)
/pattern/
std.to_string(value)
value.Str()
std.typecheck(value, type)
assert(value, type)
- type must be the type object such as Arr
, Hash
, Bool
, etc.
std.try_typecheck(value, type)
value is type
- type must be the type object such as Arr
, Hash
, Bool
, etc.
std.type(value)
typeof(value)
- returns the type object
https://hush-shell.github.io/paradigms/index.html
NGS:
- has more typing features
- more ergonomuc functional programming
- supports multiple dispatch which is heavilty used across the language
https://hush-shell.github.io/paradigms/oop.html
Hush:
# This function acts like a combination of a class and a constructor. It'll take any
# arguments relevant to the construction of a `MyCounter` object, and will return an
# instance of such object, which is nothing but a dictionary.
let MyCounter = function(start)
@[
# A member field. Using the same convention as Python, a field starting with an
# underscore should be considered private.
_start: start,
# A method. Here, we can use the `self` keyword to access the object.
get: function()
self._start
end,
# Another method.
increment: function()
self._start = self._start + 1
end,
]
end
let counter = MyCounter(1) # object instantiation.
std.print(counter.get()) # 1
counter.increment()
std.print(counter.get()) # 2
NGS:
type MyCounter
F init(mc:MyCounter, start:Int) mc._start = start
F get(mc:MyCounter) mc._start
F increment(mc:MyCounter) mc._start += 1
counter = MyCounter(1)
echo(counter.get())
counter.increment()
echo(counter.get())
Inheritance
Hush:
let MySuperCounter = function (start, step)
# Instantiate an object of the base class. We'll then augment this object with
# derived functionality.
let counter = MyCounter(start)
counter._step = step # Add new fields to the object.
# Override a method. Make sure not to change the number of parameters here!
counter.increment = function ()
self._start = self._start + self._step
end
# In order to override a method and call the parent implementation, you'll need to
# bind it to the current object, and then store it to a variable:
let super_get = std.bind(counter, counter.get)
counter.get = function()
let value = super_get() # call the parent method.
std.print(value)
value
end
counter
end
let super_counter = MySuperCounter(2, 3)
super_counter.get() # 2
super_counter.increment()
super_counter.get() # 5
NGS:
type MySuperCounter(MyCounter)
echo(MySuperCounter)
F init(msc:MySuperCounter, start:Int, step:Int) {
super(msc, start)
msc._step = step
}
# Inherited: F get(...) ...
F increment(msc:MySuperCounter) msc._start += msc._step
# "super_counter" hits syntax bug, renamed to "sup_counter"
sup_counter = MySuperCounter(2, 3)
echo(sup_counter.get())
sup_counter.increment()
echo(sup_counter.get())
NGS, how I would really do it - use optional prameter step
:
type MyCounter
F init(mc:MyCounter, start:Int, step:Int=1) {
mc._start = start
mc._step = step
}
F get(mc:MyCounter) mc._start
F increment(mc:MyCounter) mc._start += mc._step
counter = MyCounter(1, 3)
echo(counter.get())
counter.increment()
echo(counter.get())
https://hush-shell.github.io/paradigms/fun.html
(Maybe later)
Meanwhile, see Iter
implementation for an array:
Noticable features that NGS has and were not mentioned in Hush:
- Automatic parsing of command line arguments (
F main(...) ...
in NGS) - Last statement in the program is converted to exit code
- Facility for preparing command line arguments when running external programs - https://ngs-lang.org/doc/latest/generated/Argv.html
- Common ops pieces of code factored out - log(), warn(), error(), retry()
NGS official website is at https://ngs-lang.org/