Advanced features¶
Import statement¶
Hurdy includes a Python-like import statement, which can be used to quickly declare and assign local variables from the entries of a table:
from expr import x, y, test
is equivalent to
var x, y, test
{
var _hurdytemp1 = expr
x = _hurdytemp1.x
y = _hurdytemp1.y
test = _hurdytemp1.test
}
expr
need not be a variable name, but can be more generally an expression (function call, table indexing, etc.).
The following are all valid uses of the statement:
from x import x, y
from require("library") import x, y
from t.subtable import x, y
from a + b import x, y -- allowed, but needs methametods for it to make sense
from nil import x, y -- technically allowed, but will result in a runtime error
The variable names can optionally be changed with the extended version of the command
from expr import end, global, test as a, b, test
-- names must be provided for all entries
which is equivalent to
var a, b, test
{
var _hurdytemp1 = expr
a = _hurdytemp1["end"] -- bracket access because 'end' is a Lua keyword
b = _hurdytemp1.global
test = _hurdytemp1.test
}
Note
When using the as
version of the import statement, the fields of the table are allowed to be any
kind of identifier, including Hurdy and Lua keywords.
If statements with assignment¶
Hurdy allows the condition(s) inside an if statement to be assigned to a local variables that is in scope inside
the statement branches. This allows, for example, to quickly check if an object obtained through a function call or
table access is not nil
, and if it does access it without having to call the function/access the table again. For example:
if var x = t:get_object() {
do_stuff(x)
}
else {
print("no object!")
}
is equivalent to
{
var x = t:get_object()
if x {
do_stuff(x)
}
else {
print("no object!")
}
}
The assignment syntax is also available for the elseif
conditions, but when used in this case elseif
is
converted to else if
, that is a nested if statement is used. For example
if false {
-- do nothing
}
elseif y {
print("y")
}
elseif var x = f() {
do_stuff(x)
}
else {
print("no object!")
}
is equivalent to
if false {
-- do nothing
}
elseif y {
print("y")
}
else {
if var x = f() {
do_stuff(x)
}
else {
print("no object!")
}
}
Table comprehensions¶
Hurdy has Python-like comprehensions to quickly create arrays/tables through for loops. Table comprehensions, like table constructors, are expressions. There are three kinds of comprehensions syntaxes that can be used, described below.
Warning
This is the one feature in Hurdy that incurs in a performance cost compared to building the table in the regular verbose way, because it wraps the table creation loops in an anonymous function that is called immediately. The advantage of the syntax is that it makes things faster to write and easier to understand when reading the code.
Array comprehension¶
Arrays can be built with table comprehensions using braces containing a single expression followed by a for clause (both numeric and generic for are allowed) and optionally an if clause. For example
var array1 = { expr for i = 1, 10 }
var array2 = { expr for k, v in pairs(t) if k != 3 }
is equivalent to
var array1 = (function() {
var _hurdytemp1 = {}
var _hurdytemp2 = 0
for i = 1, 10 {
_hurdytemp2 += 1
_hurdytemp1[_hurdytemp2] = expr
}
return _hurdytemp1
})()
var array2 = (function() {
var _hurdytemp1 = {}
var _hurdytemp2 = 0
for k, v in pairs(t) {
if k != 3 {
_hurdytemp2 += 1
_hurdytemp1[_hurdytemp2] = expr
}
}
return _hurdytemp1
})()
Hash table comprehension¶
Hash tables can be built with table comprehensions using braces containing a two comma-separated expressions (a key/value pair) followed by a for clause (both numeric and generic for are allowed) and optionally an if clause. For example
var hash1 = { key_expr, value_expr for i = 1, 10 }
var hash2 = { key_expr, value_expr for k, v in pairs(t) if k != 3 }
is equivalent to
var hash1 = (function() {
var _hurdytemp1 = {}
for i = 1, 10 {
_hurdytemp1[key_expr] = value_expr
}
return _hurdytemp1
})()
var hash2 = (function() {
var _hurdytemp1 = {}
for k, v in pairs(t) {
if k != 3 {
_hurdytemp1[key_expr] = value_expr
}
}
return _hurdytemp1
})()
Hash table comprehension with single expression¶
In same cases it may be desirable for the key/value pair for the Hash table comprehension to be obtained as the outputs of a single function
call. A special syntax exists for this case, where the table is constructed using braces containing a question mark ?
followed by a
comma and a function/method call (returning a key/value pair) followed by a for clause (both numeric and generic for are allowed) and
optionally an if clause. For example
var hash1 = { ?, f() for i = 1, 10 }
var hash2 = { ?, t:get() for k, v in pairs(s) if k != 3 }
is equivalent to
var hash1 = (function() {
var _hurdytemp1 = {}
for i = 1, 10 {
var _hurdytemp2, _hurdytemp3 = f()
_hurdytemp1[_hurdytemp2] = _hurdytemp3
}
return _hurdytemp1
})()
var hash2 = (function() {
var _hurdytemp1 = {}
for k, v in pairs(s) {
if k != 3 {
var _hurdytemp2, _hurdytemp3 = t:get()
_hurdytemp1[_hurdytemp2] = _hurdytemp3
}
}
return _hurdytemp1
})()
Multiple for loops¶
Table comprehensions allow for multiple for clauses to be used, each with its own optional if clause. This allows the creation of tables that would require nested for loops. For example
var array1 = { M[i][j][k] for i = 1, 10 if i != 2 for j = 1, 10 for k = 1, 10 if k != 3 }
is equivalent to
var array1 = (function() {
var _hurdytemp1 = {}
var _hurdytemp2 = 0
for i = 1, 10 {
if i != 2 {
for j = 1, 10 {
for k = 1, 10 {
if k != 3 {
_hurdytemp2 += 1
_hurdytemp1[_hurdytemp2] = M[i][j][k]
}
}
}
}
}
return _hurdytemp1
})()
Note that the order in which the for loops and if clauses are nested is the same in which they are specified in the table comprehension.