## 11.3. idioms: Higher-order Orc programming idioms.

Higher-order Orc programming idioms. Many of these are standard functional-programming combinators borrowed from Haskell or Scheme.

### 11.3.1. `curry`

`def curry[A,B,C](lambda (A,B) :: C) :: lambda(A) :: lambda(B) :: C`

Curry a function of two arguments.

Implementation.

```
def curry[A,B,C](lambda (A,B) :: C) :: lambda(A) :: lambda(B) :: C
def curry(f) = lambda(x) = lambda(y) = f(x,y)

```

### 11.3.2. `curry3`

`def curry3[A,B,C,D](lambda (A,B,C) :: D) :: lambda(A) :: lambda(B) :: lambda(C) :: D`

Curry a function of three arguments.

Implementation.

```
def curry3[A,B,C,D](lambda (A,B,C) :: D) :: lambda(A) :: lambda(B) :: lambda(C) :: D
def curry3(f) = lambda(x) = lambda(y) = lambda(z) = f(x,y,z)

```

### 11.3.3. `uncurry`

`def uncurry[A,B,C](lambda (A) :: lambda(B) :: C) :: lambda(A, B) :: C`

Uncurry a function of two arguments.

Implementation.

```
def uncurry[A,B,C](lambda (A) :: lambda(B) :: C) :: lambda(A, B) :: C
def uncurry(f) = lambda(x,y) = f(x)(y)

```

### 11.3.4. `uncurry3`

`def uncurry3[A,B,C,D](lambda (A)(B)(C) :: D) :: lambda(A,B,C) :: D`

Uncurry a function of three arguments.

Implementation.

```
def uncurry3[A,B,C,D](lambda (A) :: lambda(B) :: lambda(C) :: D) :: lambda(A,B,C) :: D
def uncurry3(f) = lambda(x,y,z) = f(x)(y)(z)

```

### 11.3.5. `flip`

`def flip[A,B,C](lambda (A, B) :: C) :: lambda(B, A) :: C`

Flip the order of parameters of a two-argument function.

Implementation.

```
def flip[A,B,C](lambda (A, B) :: C) :: lambda(B, A) :: C
def flip(f) = lambda(x,y) = f(y,x)

```

### 11.3.6. `constant`

`def constant[A](A) :: lambda() :: A`

Create a function which returns a constant value.

Implementation.

```
def constant[A](A) :: lambda() :: A
def constant(x) = lambda() = x

```

### 11.3.7. `defer`

`def defer[A,B](lambda (A) :: B, A) :: lambda() :: B`

Given a function and its argument, return a thunk which applies the function.

Implementation.

```
def defer[A,B](lambda (A) :: B, A) :: lambda() :: B
def defer(f, x) = lambda() = f(x)

```

### 11.3.8. `defer2`

`def defer2[A,B,C](lambda (A,B) :: C, A, B) :: lambda() :: C`

Given a function and its arguments, return a thunk which applies the function.

Implementation.

```
def defer2[A,B,C](lambda (A,B) :: C, A, B) :: lambda() :: C
def defer2(f, x, y) = lambda() = f(x, y)

```

### 11.3.9. `ignore`

`def ignore[A](lambda () :: A) :: lambda(Top) :: B`

From a function of no arguments, create a function of one argument, which is ignored.

Implementation.

```
def ignore[A](lambda () :: A) :: lambda(Top) :: A
def ignore(f) = lambda(_) = f()

```

### 11.3.10. `ignore2`

`def ignore2[A,B,C](lambda () :: C) :: lambda(A, B) :: C`

From a function of no arguments, create a function of two arguments, which are ignored.

Implementation.

```
def ignore2[A,B,C](lambda () :: C) :: lambda(A, B) :: C
def ignore2(f) = lambda(_, _) = f()

```

### 11.3.11. `compose`

`def compose[A,B,C](lambda (B) :: C, lambda (A) :: B) :: lambda(A) :: C`

Compose two single-argument functions.

Implementation.

```
def compose[A,B,C](lambda (B) :: C, lambda (A) :: B) :: lambda (A) :: C
def compose(f,g) = lambda(x) = f(g(x))

```

### 11.3.12. `while`

`def while[A](lambda (A) :: Boolean, lambda (A) :: A) :: lambda(A) :: A`

Iterate a function while a predicate is satisfied, publishing each value passed to the function.

Example:

```-- Publishes: 0 1 2 3 4 5
while(
lambda (n) = (n <= 5),
lambda (n) = n+1
)(0)```

Implementation.

```
def while[A](lambda (A) :: Boolean, lambda (A) :: A) :: lambda(A) :: A
def while(p,f) =
def loop(A) :: A
def loop(x) = Ift(p(x)) >> ( x | loop(f(x)) )
loop

```

### 11.3.13. `repeat`

`def repeat[A](lambda () :: A) :: A`

Call a function sequentially, publishing each value returned by the function. The expression `repeat(f)` is equivalent to the infinite expression `f() >x> ( x | f() >x> ( x | f() >x> ... ) )`

Implementation.

```
def repeat[A](lambda () :: A) :: A
def repeat(f) = f() >x> (x | repeat(f))

```

### 11.3.14. `fork`

`def fork[A](List[lambda () :: A]) :: A`

Call a list of functions in parallel, publishing all values published by the functions.

The expression `fork([f,g,h])` is equivalent to the expression `f() | g() | h()`

Implementation.

```
def fork[A](List[lambda () :: A]) :: A
def fork([]) = stop
def fork(p:ps) = p() | fork(ps)

```

### 11.3.15. `forkMap`

`def forkMap[A,B](lambda (A) :: B, List[A]) :: B`

Apply a function to a list in parallel, publishing all values published by the applications.

The expression `forkMap(f, [a,b,c])` is equivalent to the expression `f(a) | f(b) | f(c)`

This function can be thought of as the following composition `fork(map(curry(defer)(f), xs))` (hence the name `forkMap`). It maps `f` over the list and then forks each of the resulting computations.

Implementation.

```
def forkMap[A,B](lambda (A) :: B, List[A]) :: B
def forkMap(f, []) = stop
def forkMap(f, x:xs) = f(x) | forkMap(f, xs)

```

### 11.3.16. `seq`

`def seq[A](List[lambda () :: A]) :: Signal`

Call a list of functions in sequence, publishing a signal whenever the last function publishes. The actual publications of the given functions are not published.

The expression `seq([f,g,h])` is equivalent to the expression `f() >> g() >> h() >> signal`

Implementation.

```
def seq[A](List[lambda () :: A]) :: Signal
def seq([]) = signal
def seq(p:ps) = p() >> seq(ps)

```

### 11.3.17. `seqMap`

`def seqMap[A,B](lambda (A) :: B, List[A]) :: Signal`

Apply a function to a list in sequence, publishing a signal whenever the last application publishes. The actual publications of the given functions are not published.

The expression `seqMap(f, [a,b,c])` is equivalent to the expression `f(a) >> f(b) >> f(c) >> signal`

This function can be thought of as the following composition `seq(map(curry(defer)(f), xs))` (hence the name `seqMap`). It maps `f` over the list and then runs each of the resulting computations in sequence. This is analogous to `foreach` in Scala or `iterate` in OCaml.

Implementation.

```
def seqMap[A,B](lambda (A) :: B, List[A]) :: Signal
def seqMap(f, []) = signal
def seqMap(f, x:xs) = f(x) >> seqMap(f, xs)

```

### 11.3.18. `join`

`def join[A](List[lambda () :: A]) :: Signal`

Call a list of functions in parallel and publish a signal once all functions have completed.

The expression `join([f,g,h])` is equivalent to the expression `(f(), g(), h()) >> signal`

Implementation.

```
def join[A](List[lambda () :: A]) :: Signal
def join([]) = signal
def join(p:ps) = (p(), join(ps)) >> signal

```

### 11.3.19. `joinMap`

`def joinMap[A](lambda (A) :: Top, List[A]) :: Signal`

Apply a function to a list in parallel and publish a signal once all applications have completed.

The expression `joinMap(f, [a,b,c])` is equivalent to the expression `(f(a), f(b), f(c)) >> signal`

This function can be thought of as the following composition `join(map(curry(defer)(f), xs))` (hence the name `joinMap`).

Implementation.

```
def joinMap[A](lambda (A) :: Top, List[A]) :: Signal
def joinMap(f, []) = signal
def joinMap(f, x:xs) = (f(x), joinMap(f, xs)) >> signal

```

### 11.3.20. `alt`

`def alt[A](List[lambda () :: A]) :: A`

Call each function in the list until one of them publishes (choosing the publishing alternative).

The expression `alt([f,g,h])` is equivalent to the expression `f() ; g() ; h()`

Implementation.

```
def alt[A](List[lambda () :: A]) :: A
def alt([]) = stop
def alt(p:ps) = p() ; alt(ps)

```

### 11.3.21. `altMap`

`def altMap[A,B](lambda (A) :: B, List[A]) :: B`

Apply the function to each element in the list until one publishes.

The expression `altMap(f, [a,b,c])` is equivalent to the expression `f(a) ; f(b) ; f(c)`

This function can be thought of as the following composition `alt(map(curry(defer)(f), xs))` (hence the name `altMap`).

Implementation.

```
def altMap[A,B](lambda (A) :: B, List[A]) :: B
def altMap(f, []) = stop
def altMap(f, x:xs) = f(x) ; altMap(f, xs)

```

### 11.3.22. `por`

`def por(List[lambda () :: Boolean]) :: Boolean`

Parallel or. Execute a list of boolean functions in parallel, publishing a value as soon as possible, and killing any unnecessary ongoing computation.

Implementation.

```
def por(List[lambda () :: Boolean]) :: Boolean
def por([]) = false
def por(p:ps) =
Let(
val b1 = p()
val b2 = por(ps)
Ift(b1) >> true | Ift(b2) >> true | (b1 || b2)
)

```

### 11.3.23. `pand`

`def pand(List[lambda () :: Boolean]) :: Boolean`

Parallel and. Execute a list of boolean functions in parallel, publishing a value as soon as possible, and killing any unnecessary ongoing computation.

Implementation.

```
def pand(List[lambda () :: Boolean]) :: Boolean
def pand([]) = true
def pand(p:ps) =
Let(
val b1 = p()
val b2 = pand(ps)
Iff(b1) >> false | Iff(b2) >> false | (b1 && b2)
)

```

### 11.3.24. `collect`

`def collect[A](lambda () :: A) :: List[A]`

Run a function, collecting all publications in a list. Publish the list when the function halts.

Example:

```-- Publishes: [signal, signal, signal, signal, signal]
collect(defer(signals, 5))```

Implementation.

```
def collect[A](lambda () :: A) :: List[A]
def collect(p) =
val b = Channel[A]()
p() >x> b.put(x) >> stop
; b.getAll()

```