Impulse Programming Language

November 2005 · Mike Austin

Impusle is a language idea I've been toying with over the past few years. It's based upon block predicate dispatching, meaning that a block, or lexical closure, can have multiple definitions and dispatching on these blocks is based on predicates. Think of it as Smalltalk with functional pattern matching. I dislike special syntax such as pattern matching, list comprehension, etc., and Impulse tries to factor these ideas into the language, eliminating special syntax.

Blocks

A block is a lexical closure with the properties of a generic function. A block therefor can have multiple definitions, and a predicate decides which of these are executed. When used as higher order functions, these blocks can emulate list comprehension, pattern matching and more.

Simple Blocks

A simple block is defined by a list of arguments each optionally supporting a element separator (:), an arrow (->), and an expression.

a, b -> a * b					>> {block}

squared = n -> n * n
squared value: 10				>> 20

list sort: a, b -> a < b

pixels map: r:g:b -> (r + g + b) / 3

Predicate Blocks

A predicate block is defined by a list of arguments, followed by a list of predicates enclosed in square brackets ([]), an arrow (->), and an expression. Each predicate is scoped to it's corresponding argument, in addition to the local context in which it was defined. This allows you to simulate pattern matching such as [> 10, < 20], and to compare arbitrary values such as [a date < b date]. To allow nil return values, there is a concept of a non-value, as if the function was never called.

n [n > 0] -> n * n				>> {block}

x, y [> 10, < 20] -> x * y			>> {block}

evens-squared = 1..10 map: n
  [% 2 == 0] -> n * n				>> 4,16,36,64,100

Multiple Predicate Blocks

A multiple-predicate block is defined by a list of arguments, followed by a list of predicates enclosed in square brackets ([]), each with an arrow (->), and an expression. Child blocks are executed based on the predicate arguments supplied.

stream each: char
  [is-digit?] -> read-number
  [is-alpha?] -> read-identifier

n = if: [n < 0] -> -1 [n > 0] -> 1