While I find time to get round to trying to implement supcode, here are some of its features and quirks I've got planned!
Note
For a rundown of supcode’s design principles and axioms, see Axioms.
supcode uses kebab-case for identifiers:
set 'full-flavour' = trueYou can also use trailing ? and ! for conditions and in-place mutations:
func 'play-track!' (~Track 'track')
{
alt track.played? = true
alt track.total-plays + 1
}Functions accept primary parameters in (), partial parameters in [], and a block parameter in {}:
async func 'respond' (ctx) [
String 'message'
]You can partially apply a function’s partial parameters, which doesn’t call the function, but returns a modified version:
set 'items' = List(6, 9, 4, 2, 0)
filter(items)[pred = is-even]
\ equivalent to:
set 'filter-even' = filter[pred = is-even]
filter-even(items)A function with 1 or more primary parameters can be called as a method on its first argument:
\ these are equivalent:
attack(target)
target.attack()
\ these are equivalent:
add(inventory, item)
inventory.add(item)Chaining pipelines becomes fluid and follows their actual order!
take(skip(map(filter(players))))
\ equivalent to...
take(skip(map(players.filter())))
take(skip(players.filter().map()))
take(players.filter().map().skip())
players.filter().map().skip().take()
players.filter()
.map()
.skip()
.take()Functions accepting 1 primary parameter can be called without parentheses:
\ these are equivalent:
tokenise(text)
tokenise textMaking function application right-associative means you can call an entire pipeline without parentheses:
\ these are all equivalent:
parse(tokenise(text))
parse tokenise(text)
parse (tokenise text)
parse tokenise textHence supcode has barely any keywords or special syntax, because they can all be achieved through functions!
Like Rust, supcode can split a struct’s declaration and implementation, and also conditionally implement functionality!
struct 'Fruit-Salad' [T]
{
| List[T] tracks
}
evolve Fruit-Salad[Track]
{
func 'banana-breeze' (self)
{
self.play!()
}
}