Tarnish is an experimental programming language styled as a modern "scripting" language, a la Perl, Python or Ruby.
null
; algebraic data types + pattern matching
// booleans
true; false;
// numbers
1.23e45; 0xA9F4; 0b11001001;
// strings
"all strings are in double quotes";
"strings
can spread over
multiple lines";
"strings can have ${interpolated} values"
// functions
{|x| x + 1 }
// plain objects
{ x: 1, y: 2 }
// lists
["foo", "bar", "baz"]
let point = {
// properties
x: 0,
y: 1,
// methods
manhattan_distance (self, other) {
(self.x - other.x).abs() + (self.y - other.y).abs()
},
}
// accessing object properties & methods
point.x // => 0
point.manhattan_distance({ x: 2, y: 2 }) // => 3
// by default, objects are not mutable or extensible
point.x = 2 // panics
point.z = 2 // panics
// objects can have mutable properties
let mut_point = {
mut x: 0,
mut y: 0,
}
mut_point.x = 2
mut_point.x // => 2
// immutable objects are compared structurally, but mutable objects are compared by reference
{ x: 0, y: 0 } == { x: 0, y: 0 }
{ mut x: 0, mut y: 0 } != { mut x: 0, mut y: 0 }
// objects can be destructured & pattern_matched
let { x, y } = point // => x = 0, y = 1
match point {
case { x, y } {
x + y
}
case _ {
0
}
}
// => 1
let list = ["foo", "bar", "baz"]
// indexing into lists
list[0] // => "foo"
list[100] // panics
// calling list methods
list.length() // => 3
// lists are immutable
list[0] = "xyzzy" // panics
// lists can be destructured & pattern_matched
let [first, second | rest] = list // => first = "foo", second = "bar", rest = ["baz"]
// Array: a mutable list
let my_array = Array(["foo", "bar", "baz"])
my_array[2] = "quux" // => array(["foo", "bar", "quux"])
my_array.push("xyzzy") // => array(["foo", "bar", "quux", "xyzzy"])
let Array([first, second | rest ]) = my_array // => first = "foo", second = "bar", rest = Array(["quux", "xyzzy"])
// Map: a mutable key-value collection
let my_map = Map([["foo", 1], ["bar", 2], ["baz", 3]])
my_map["foo"] // => 1
my_map["bar"] = 200 // => map([["foo", 1], ["bar", 200], ["baz", 3]])
// map can insert new values, too
my_map["quux"] = 4 // => map([["foo", 1], ["bar", 200], ["baz", 3], ["quux", 4]])
let Map([["bar", bar_value]]) = my_map // => bar_value = 200
enum Option {
case None {
then (fn) {
Option.None
}
}
case Some (value) {
then (value, fn) {
fn(value)
}
}
}
let value = Option.Some(10)
value.then({|value| Some(value + 1)}) // => Option.Some(11)
None.then({|value| Some(value + 1)}) // => Option.None
match value {
case Option.Some(x) { x }
case Option.None { 0 }
} // => 10