Happy App:   A Toolbox of Syntactic Shortcuts
1 Lambdas with placeholders
2 Arrow lambdas with [x -> x]
3 Arrow lambdas with [x ->* x] (discarding extra arguments)
4 Thunks with [-> x]
5 Thunk*s with [->* x]
6 Container access with [container index]
7 Curried functions with []
8 Binary infix expressions with {}
8.2

Happy App: A Toolbox of Syntactic Shortcuts

This package provides a whole bunch of syntactic shortcuts by redefining #%app. It makes me happy, and I hope it makes you happy too!

1 Lambdas with placeholders

Lambdas like this:

(lambda (x)
  (+ x 1))

can be shortened to this:

(+ _ 1)

Any parenthesized expression with at least one _ placeholder will be automatically converted into a lambda expression.

Examples:
> (map (+ 1 _) (list 1 2 3 4))

'(2 3 4 5)

> (map (+ _ 2) (list 1 2 3 4))

'(3 4 5 6)

The placeholder can be in any position, even initial position:

Example:
> (map (_ 2 3) (list + - * /))

'(5 -1 6 2/3)

This functionality is taken directly from Alex Knauth’s ugly-app package.

2 Arrow lambdas with [x -> x]

Lambdas like this:

(lambda (x)
  (+ x 1))

can be written this way:

[x -> (+ x 1)]

These are called "arrow lambdas". Function arguments go on the left side, and an expression to evaluate goes on the right side.

Examples:
> (map [x -> x] '(1 2 3 4))

'(1 2 3 4)

> (map [x -> (* x x)] '(1 2 3 4))

'(1 4 9 16)

> (map [x y z -> (x y z)]
       (list + - * /)
       (list 1 2 3 4)
       (list 4 5 6 7))

'(5 -3 18 4/7)

You can leave out the parentheses if there’s more than one term on the right, so the following examples are equivalent:

[x -> (+ x 1)]

[x -> + x 1]

Parentheses can’t be omitted from single-term expressions, because there’s no way to figure out if you mean [x -> x] or [x -> (x)].

Inspired by Haskell’s \x -> x lambda syntax.

3 Arrow lambdas with [x ->* x] (discarding extra arguments)

These are the same as with ->, but any extra arguments are discarded.

Example:
> ([x ->* x] 'hello 'world)

'hello

In the examples below, the lambda takes two arguments x and y; any extra arguments you pass in get thrown away.

Examples:
> ([x y ->* (* x y)] 5 6)

30

> ([x y ->* (* x y)] 5 6 7)

30

> ([x y ->* (* x y)] 5 6 7 8)

30

Just like with ->, parentheses can be omitted in multi-term expressions:

Example:
> ([x y ->* + x y] 5 6 7)

11

4 Thunks with [-> x]

These are simply arrow lambdas with no arguments (nullary functions). Rather than writing out a lambda like this:

(lambda () (+ 1 2 3))

You can shorten it to this:

[-> (+ 1 2 3)]

And just like before, you can leave out the parentheses:

[-> + 1 2 3]

Example:
> (call-with-values [-> values 2 3 4]
                    [x y z -> * x y z])

24

This functionality is like thunk from racket/function.

5 Thunk*s with [->* x]

Like the above, but the thunk accepts arguments and discards them.

Example:
> (build-list 10 [->* (random 100)])

'(85 65 20 40 89 45 54 38 26 62)

This functionality is like thunk* from racket/function.

6 Container access with [container index]

This is shorthand for either dict-ref or sequence-ref, depending on what you pass in. These are generic interfaces that work for all sorts of containers, including lists, vectors, strings, hashes, association lists, and so on.

Examples:
> ['(hello world) 1]

'world

> ['(a b c d e) 3]

'd

> [#(foo bar baz) 0]

'foo

> ["hello" 0]

#\h

> ['((color . blue)
     (shape . circle)) 'shape]

'circle

> [(hash 'color 'pink
         'shape 'rhombus) 'color]

'pink

Inspired by Greg Hendershott’s Rackjure.

7 Curried functions with []

Currying lets you express certain functions even more simply. For example, the arrow lambda:

[x -> + x 2]

could be written equivalently:

[+ 2]

Examples:
> ([+ 2] 3)

5

> ([+ 2 3] 5)

10

> (map [filter even?]
       '((1 2 3 4 5)
         (6 7 8 9)))

'((2 4) (6 8))

The choice between [+ 5] and [sequence index] is decided at run-time, because there’s no syntactic difference between the two. Although this should usually be unambiguous, happy-app checks dict? first, then sequence?, then procedure?; ambiguous cases will be resolved in that order.

This functionality is like curry from racket/function.

8 Binary infix expressions with {}

People sometimes have trouble understanding mathematical prefix expressions like this:

(< x 3)

To make it easier to understand, Racket has built-in "dotted infix" notation, which lets you rewrite it like this:

(x . < . 3)

But with this package, you can write infix expressions a bit more simply:

{x < 3}

These infix expressions must be binary – that is, they must have a function in the middle (called the "operator") and one argument on each side (called the "operands").

Examples:
> {2 < 3}

#t

> {5 + {10 * 3}}

35

> (map [x -> {x * x}]
       '(4 5 6 7))

'(16 25 36 49)

If an infix expression has placeholders, it’s automatically converted into a lambda expression:

Examples:
> ({2 _ 3} +)

5

> {5 + {10 * 3}}

35

> (filter {_ < 3}
          (range 10))

'(0 1 2)

Inspired by David Wheeler’s SRFI 105.