Seltzer
Seltzer is a programming language that provides less verbose syntax for JavaScript, while preserving JavaScript's semantics. Its core introduces absolutely no new functionality or changes in semantics, providing an exact one-to-one mapping to JavaScript.
Syntax
Variables
In Seltzer, variables can first be declared using the :=
operator. For instance:
x := 1
This is equivalent to, in JavaScript:
var x = 1;
Any further assignment modifying the variable x
can be done using the =
operator:
x = x + 1
Literals
Seltzer supports all the standard literals JavaScript does — numbers, strings, arrays and objects — with the same syntax JavaScript supplies.
aNumber = -1.2e-32
aString = "hello"
anArray = [1, 2, "hello"]
anObject = {
here: "are",
"some values": 1
}
Seltzer additionally supports multiline strings:
aMultilineString = """Hello, I can span
multiple lines!"""
Operators
Seltzer uses wordy operators instead of symbolic ones for logical operators, such as and
, or
and not
.
Comments
Single line comments are written using #
.
# This line will print "This is a string" to the console
console.log("This is a string")
Multi-line comments are written using triple quotes.
"""This is a multi-line comment
indicating that the following code
will print "This is a string" to
the console"""
console.log("This is a string")
Block Statements
Seltzer has the simple control flow statements if
, switch
, while
and for
.
if x > 2
console.log(x + " is bigger than 2!")
elif x > 1
console.log(x + " is bigger than 1!")
else
console.log(x + " is smaller than 1!")
end
Switch statements work as follows:
switch x
case 1
console.log("x is 1")
break
case 2
console.log("x is 2")
break
default
console.log("x is something else")
break
end
While loops can be used like so:
while x > 2
console.log(x + " is still bigger than 2!")
x -= 1
end
... and C-style for loops are used like so:
for i := 0, i < 2, i += 1
console.log(i)
end
The try
...catch
...finally
series of statements are also familiar:
try
# something
catch e
# oh no, an exception!
finally
# do some cleanup
end
Functions
Declaring functions is done with the def
keyword, for instance:
add = def (a, b)
return a + b
end
We can declare anonymous functions as function parameters as well:
product = def (xs)
return xs.reduce(def (acc, x)
return acc * x
end, 1)
end
Objects
Seltzer provides some shortcuts for object syntax — for instance, ::
is shorthand for .prototype
:
Cat = def (name)
this.name = name
end
Cat::speak = def (what)
console.log(this.name + " the cat says: " + what)
end
alfonso = new Cat("alfonso")
alfonso.speak("meow")
Extensions
Seltzer also proposes a variety of extensions. These are not part of the core language, merely pieces of syntactic sugar that are derived from the core features. As such, they are not enabled by default, but can be used when supplying the applicable -X ExtensionName1,ExtensionName2
flag to the compiler.
Additionally, they also require use of the Seltzer XRT library. This can be included in your HTML, or required at the top of your script file as __seltzer_xrt
.
DefaultArguments
Default Arguments Adds support for default arguments in function parameters.
foo = def (x=1)
# do something with x
end
Splats
Splats Adds support for variable argument lists, as well as destructuring assignments into lists.
foo = def (x, y, ys..., z)
# do something in here
end
NegativeIndexing
Negative Indexing Allow negative indexing on arrays to wrap around the list.
xs = [1, 2, 3]
xs[-1] # this is 3
This will incur extra branching for every access to an array via a numerical index, as the code will be transformed into:
xs[i < 0 ? xs.length - i : i]
DestructuringAssignment
Destructuring Assignment Unpack lists into individual variables during assignment, if applicable.
[a, b, c] = [1, 2, 3] # a=1, b=2, c=3
If Splats
is enabled, items can also be destructured via splats:
[a, bs..., c] = [1, 2, 3, 4, 5] # a=1, bs=[2, 3, 4], c=5
ArraySlices
Array Slices Python-style array slicing. Requires RangeLiterals
.
[1, 2, 3, 4, 5][[5:2:-1]] # this is [5, 4]
ChooseStatement
Choose Statement An alternative construct for the switch
statement.
choose x
when 1
console.log("x is 1")
when 2, 3
console.log("x is 2 or 3")
else
console.log("what is x?")
end
This safeguards against fall-through cases.
EnhancedFor
Enhanced For Provides an alternative syntax for for
loops:
for x : xs
# do for loop things in here
end
This exhibits the following properties:
for
loops will first check for the existence of an__iterator__
function attached to the object — if one exists, the iterator will be obtained from the object and the.next()
method will be invoked on it repeatedly untilStopIteration
is raised (this is JavaScript 1.7's behavior). This will incur additional branching.- With standard JavaScript arrays, this loops through each entry of the array by incrementing the index over the length of the array.
- With
DestructuringAssignment
support, it is possible to dofor [x, y] : xs
(and withSplats
support,for [x, y, ys..., z] : xs
.)
RangeLiterals
Range Literals Range literals provide a way to generate a sequential list of numbers.
for i : [1:10]
console.log(i)
end
This will print the numbers 1 through 10. It is also possible to specify a step.
for i : [2:10:2]
console.log(i)
end
This will print the numbers 2, 4, 6, 8 and 10. Ranges are inclusive. Both the beginning and end numbers will be included in the range. If the next step will be a number exceeding the maximum of the range, it will not be included.
Descending ranges are also supported.
for i : [10:1:-1]
console.log(i)
end
This will print the numbers 10 through 1 in descending order.
However, be careful with floating point ranges, as precision loss may result in unexpected results.
Generators
Generators Generators can transform functions into state machines with pausable execution.
makeCounter = def (n)
while true
n += 1
yield n
end
end
The generator can then be invoked like so:
countFromOne = makeCounter(1)
countFromOne.next() # this yields 2
countFromOne.next() # this yields 3
Comprehensions
Comprehensions Comprehensions provide a succint syntax for populating arrays.
[x + 1 for x : [1, 2, 3, 4, 5] if x > 2]
Iterator comprehensions are also possible:
(x + 1 for x : [1, 2, 3, 4, 5] if x > 2)
FunctionDecorators
Function Decorators Python-style function decorators.
logBeforeCall = def (f)
return def ()
console.log("calling some function")
f.apply(this, arguments)
end
end
@logBeforeCall
foo = def ()
console.log("calling foo")
end
foo() # this logs "calling some function", then "calling foo"