Fundamental sites and operators.
These declarations include both prefix and infix sites (operators). For
consistency, all declarations are written in prefix form, with the site name
followed by the operands. When the site name is surrounded in parentheses, as
in (+), it denotes an infix operator.
For a more complete description of the built-in operators and their syntax, see the Operators section of the User Guide.
|
When applied to no arguments, return a signal. |
|
When applied to a single argument, return that argument (behaving as the identity function). |
|
When applied to two or more arguments, return the arguments in a tuple. |
|
Fail silently if the argument is false. Otherwise return a signal. Example: -- Publishes: "Always publishes" if(false) >> "Never publishes" | if(true) >> "Always publishes" |
|
Halt with the given error message. Example, using def assert(b) = if b then signal else error("assertion failed") -- Fail with the error message: "assertion failed" assert(false) |
|
|
|
|
|
Return the additive inverse of the argument.
When this site appears as an operator, it is written in prefix form without the
zero, i.e. |
|
|
|
|
|
Example: 7/3 -- publishes 2 | 7/3.0 -- publishes 2.333... |
|
|
|
|
|
|
|
|
|
|
|
Two values with the same object identity are always considered equal. In addition, Cor constant values and data structures are considered equal if their contents are equal. Other types are free to implement their own equality relationship provided it conforms to the rules given here. Note that although values of different types may be compared with
|
|
|
|
Return the logical negation of the argument. |
|
Return the logical conjunction of the arguments. This is not a short-circuiting operator; both arguments must be evaluated and available before the result is computed. |
|
Return the logical disjunction of the arguments. This is not a short-circuiting operator; both arguments must be evaluated and available before the result is computed. |
|
The list Example: -- Publishes: (3, [4, 5]) 3:4:5:[] >x:xs> (x,xs) In patterns, the |
|
Return the absolute value of the argument. Implementation. def abs(Number) :: Number def abs(x) = if x < 0 then -x else x |
|
Implementation. def signum(Number) :: Number def signum(x) = if x < 0 then -1 else if x > 0 then 1 else 0 |
|
Return the lesser of the arguments. If the arguments are equal, return the first argument. Implementation. def min[A](A,A) :: A def min(x,y) = if y < x then y else x |
|
Return the greater of the arguments. If the arguments are equal, return the second argument. Implementation. def max[A](A,A) :: A def max(x,y) = if x > y then x else y |
|
Return the greatest integer less than or equal to this number. |
|
Return the least integer greater than or equal to this number. |
General-purpose supplemental data structures.
|
An optional value which is available. This site may also be used in a pattern. Example: -- Publishes: (3,4) Some((3,4)) >s> ( s >Some((x,y))> (x,y) | s >None()> signal ) | ||||||||||||||||||||
|
An optional value which is not available. This site may also be used in a pattern. | ||||||||||||||||||||
|
Return a semaphore with the given value. The semaphore maintains the invariant that its value is always non-negative. An example using a semaphore as a lock for a critical section: -- Prints: -- Entering critical section -- Leaving critical section val lock = Semaphore(1) lock.acquire() >> println("Entering critical section") >> println("Leaving critical section") >> lock.release()
| ||||||||||||||||||||
|
Create a new buffer (FIFO channel) of unlimited size. A buffer supports get, put and close operations. A buffer may be either empty or non-empty, and either open or closed. When
empty and open, calls to Example: -- Publishes: 10 val b = Buffer() Rtimer(1000) >> b.put(10) >> stop | b.get()
| ||||||||||||||||||||
|
Create a new buffer (FIFO channel) with the given number of slots. Putting an item into the buffer fills a slot, and getting an item opens a slot. A buffer with zero slots is equivalent to a synchronous channel. A bounded buffer may be empty, partly filled, or full, and either open or
closed. When empty and open, calls to Example: -- Publishes: "Put 1" "Got 1" "Put 2" "Got 2" val c = BoundedBuffer(1) c.put(1) >> "Put " + 1 | c.put(2) >> "Put " + 2 | Rtimer(1000) >> ( c.get() >n> "Got " + n | c.get() >n> "Got " + n )
| ||||||||||||||||||||
|
Create a synchronous channel, or rendezvous. Example: -- Publish: 10 val c = SyncChannel() c.put(10) | Rtimer(1000) >> c.get()
| ||||||||||||||||||||
|
Create a write-once storage location. Example: -- Publishes: 5 5 val c = Cell() c.write(5) >> c.read() | Rtimer(1) >> ( c.write(10) ; c.read() )
| ||||||||||||||||||||
|
Create a rewritable storage location without an initial value. Example: val r = Ref() Rtimer(1000) >> r := 5 >> stop | println(r?) >> r := 10 >> println(r?) >> stop
| ||||||||||||||||||||
|
Get the value held by a reference.
Implementation. def (?)[A](Ref[A]) :: A def (?)(r) = r.read() | ||||||||||||||||||||
|
Set the value held by a reference.
Implementation. def (:=)[A](Ref[A], A) :: Top def (:=)(r,v) = r.write(v) | ||||||||||||||||||||
|
Swap the values in two references. Implementation. def swap[A](Ref[A], Ref[A]) :: Top def swap(r,s) = (r?,s?) >(rval,sval)> (r := sval, s := rval) >> signal | ||||||||||||||||||||
|
Create a new native array of the given size. The array is initialized
to contain The resulting array can be called directly with an index, as if
its type were Simple example: -- Publishes: 3 val a = Array(1) a(0) := 3 >> a(0)? More complex example: -- Publishes: 0 1 2 val a = Array(3) for(0, a.length()) >i> a(i) := i >> stop ; a(0)? | a(1)? | a(2)?
| ||||||||||||||||||||
|
The call The user may also think of the call as returning an array whose
This function provides a simple form of memoisation; we avoid recomputing
the value of Example: val a = IArray(5, fib) -- Publishes the 4th number of the fibonnaci sequence: 5 a(3) Implementation. def IArray[A](Integer, lambda (Integer) :: A)(Integer) :: A def IArray(n, f) = val a = Array[A](n) def fill(Integer, lambda (Integer) :: A) :: Top def fill(i, f) = if i < 0 then signal else (a.set(i, f(i)), fill(i-1, f)) >> signal fill(n-1, f) >> a.get | ||||||||||||||||||||
|
Construct an empty mutable set. The set considers two
values
| ||||||||||||||||||||
|
Construct an empty mutable map from keys to values. Each key contained in the
map is associated with exactly one value. The mapping considers two keys
| ||||||||||||||||||||
|
Create a new counter initialized to the given value.
| ||||||||||||||||||||
|
Create a new dictionary (a mutable map from field names to values), initially empty. The first time each field of the dictionary is accessed (using dot notation), the dictionary creates and returns a new empty Ref which will also be returned on subsequent accesses of the same field. Dictionaries allow you to easily create object-like data structures. Example: -- Prints: 1 2 val d = Dictionary() println(d.one.read()) >> println(d.two.read()) >> stop | d.one.write(1) >> d.two.write(2) >> stop Here is the same example rewritten using Orc's reference syntax to improve clarity: -- Prints: 1 2 val d = Dictionary() println(d.one?) >> println(d.two?) >> stop | d.one := 1 >> d.two := 2 >> stop To create a multi-level dictionary, you must explicitly create sub-dictionaries for each field. For example: -- Prints: 2 val d = Dictionary() d.one := Dictionary() >> d.one?.two := 2 >> println(d.one?.two?) >> stop Note that you cannot write | ||||||||||||||||||||
|
Create a new record (an immutable map from field names to values). Arguments are consumed in pairs; the first argument of each pair is the key, and the second is the value for that key. To access the value in record -- Publishes: 1 val r = Record( "one", 1, "two", 2) r.one | ||||||||||||||||||||
|
Return the first element of a pair. Implementation. def fst[A,B]((A,B)) :: A def fst((x,_)) = x | ||||||||||||||||||||
|
Return the second element of a pair. Implementation. def snd[A,B]((A,B)) :: B def snd((_,y)) = y | ||||||||||||||||||||
|
| ||||||||||||||||||||
|
Return an empty set of intervals. An Intervals object is iterable; iterating over the set returns disjoint intervals in increasing order.
|
Higher-order Orc programming idioms. Many of these are standard functional-programming combinators borrowed from Haskell or Scheme.
|
Apply a function to a list of arguments. |
|
Curry a function of two arguments. Implementation. def curry[A,B,C](lambda (A,B) :: C)(A)(B) :: C def curry(f)(x)(y) = f(x,y) |
|
Curry a function of three arguments. Implementation. def curry3[A,B,C,D](lambda (A,B,C) :: D)(A)(B)(C) :: D def curry3(f)(x)(y)(z) = f(x,y,z) |
|
Uncurry a function of two arguments. Implementation. def uncurry[A,B,C](lambda (A)(B) :: C)(A, B) :: C def uncurry(f)(x,y) = f(x)(y) |
|
Uncurry a function of three arguments. Implementation. def uncurry3[A,B,C,D](lambda (A)(B)(C) :: D)(A,B,C) :: D def uncurry3(f)(x,y,z) = f(x)(y)(z) |
|
Flip the order of parameters of a two-argument function. Implementation. def flip[A,B,C](lambda (A, B) :: C)(B, A) :: C def flip(f)(x,y) = f(y,x) |
|
Create a function which returns a constant value. Implementation. def constant[A](A)() :: A def constant(x)() = x |
|
Given a function and its argument, return a thunk which applies the function. Implementation. def defer[A,B](lambda (A) :: B, A)() :: B def defer(f, x)() = f(x) |
|
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)() :: C def defer2(f, x, y)() = f(x, y) |
|
From a function of no arguments, create a function of one argument, which is ignored. Implementation. def ignore[A,B](lambda () :: B)(A) :: B def ignore(f)(_) = f() |
|
From a function of no arguments, create a function of two arguments, which are ignored. Implementation. def ignore2[A,B,C](lambda () :: C)(A, B) :: C def ignore2(f)(_, _) = f() |
|
Compose two single-argument functions. Implementation. def compose[A,B,C](lambda (B) :: C, lambda (A) :: B)(A) :: C def compose(f,g)(x) = f(g(x)) |
|
Iterate a function while a predicate is satisfied, publishing each value passed to the function. The exact behavior is specified by the following implementation:
def while(p,f) = def loop(x) = if(p(x)) >> ( x | loop(f(x)) ) loop 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)(A) :: A def while(p,f) = def loop(A) :: A def loop(x) = if(p(x)) >> ( x | loop(f(x)) ) loop |
|
Call a function sequentially, publishing each value returned by the function.
The expression Implementation. def repeat[A](lambda () :: A) :: A def repeat(f) = f() >x> (x | repeat(f)) |
|
Call a list of functions in parallel, publishing all values published by the functions. The expression Implementation. def fork[A](List[lambda () :: A]) :: A def fork([]) = stop def fork(p:ps) = p() | fork(ps) |
|
Apply a function to a list in parallel, publishing all values published by the applications. The expression 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) |
|
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 Implementation. def seq[A](List[lambda () :: A]) :: Top def seq([]) = signal def seq(p:ps) = p() >> seq(ps) |
|
Apply a function to a list in in sequence, publishing a signal whenever the last application publishes. The actual publications of the given functions are not published. The expression Implementation. def seqMap[A,B](lambda (A) :: B, List[A]) :: Top def seqMap(f, []) = signal def seqMap(f, x:xs) = f(x) >> seqMap(f, xs) |
|
Call a list of functions in parallel and publish a signal once all functions have completed. The expression Implementation. def join[A](List[lambda () :: A]) :: Top def join([]) = signal def join(p:ps) = (p(), join(ps)) >> signal |
|
Apply a function to a list in parallel and publish a signal once all applications have completed. The expression Implementation. def joinMap[A,B](lambda (A) :: B, List[A]) :: Top def joinMap(f, []) = signal def joinMap(f, x:xs) = (f(x), joinMap(f, xs)) >> signal |
|
Call each function in the list until one publishes. The expression Implementation. def alt[A](List[lambda () :: A]) :: A def alt([]) = stop def alt(p:ps) = p() ; alt(ps) |
|
Apply the function to each element in the list until one publishes. The expression 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) |
|
Parallel or. Evaluate a list of boolean functions in parallel, publishing a value as soon as possible, and terminating 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) if(b1) >> true | if(b2) >> true | (b1 || b2) ) |
|
Parallel and. Evaluate a list of boolean functions in parallel, publishing a value as soon as possible, and terminating 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) if(~b1) >> false | if(~b2) >> false | (b1 && b2) ) |
|
Run a function, collecting all publications in a list. Return the list when the function terminates. Example: -- Publishes: [signal, signal, signal, signal, signal] collect(defer(signals, 5)) Implementation. def collect[A](lambda () :: A) :: List[A] def collect(p) = val b = Buffer[A]() p() >x> b.put(x) >> stop ; b.getAll() |
Operations on lists. Many of these functions are similar to those in the Haskell prelude, but operate on the elements of a list in parallel.
|
Publish every value in a list, simultaneously. Implementation. def each[A](List[A]) :: A def each([]) = stop def each(h:t) = h | each(t) |
|
Apply a function to every element of a list (in parallel), returning a list of the results. Implementation. def map[A,B](lambda (A) :: B, List[A]) :: List[B] def map(f,[]) = [] def map(f,h:t) = f(h):map(f,t) |
|
Return the reverse of the given list. Implementation. def reverse[A](List[A]) :: List[A] def reverse(l) = def tailrev(List[A], List[A]) :: List[A] def tailrev([],x) = x def tailrev(h:t,x) = tailrev(t,h:x) tailrev(l,[]) |
|
Return a list containing only those elements which satisfy the predicate. The filter is applied to all list elements in parallel. Implementation. def filter[A](lambda (A) :: Boolean, List[A]) :: List[A] def filter(p,[]) = [] def filter(p,x:xs) = val fxs = filter(p, xs) if p(x) then x:fxs else fxs |
|
Return the first element of a list. Implementation. def head[A](List[A]) :: A def head(x:xs) = x |
|
Return all but the first element of a list. Implementation. def tail[A](List[A]) :: List[A] def tail(x:xs) = xs |
|
Return all but the last element of a list. Implementation. def init[A](List[A]) :: List[A] def init([x]) = [] def init(x:xs) = x:init(xs) |
|
Return the last element of a list. Implementation. def last[A](List[A]) :: A def last([x]) = x def last(x:xs) = last(xs) |
|
Is the list empty? Implementation. def empty[A](List[A]) :: Boolean def empty([]) = true def empty(_) = false |
|
Return the nth element of a list, counting from 0. Implementation. def index[A](List[A], Integer) :: A def index(h:t, 0) = h def index(h:t, n) = index(t, n-1) |
|
Return the first list concatenated with the second. Implementation. def append[A](List[A], List[A]) :: List[A] def append([],l) = l def append(h:t,l) = h:append(t,l) |
|
Reduce a list using the given left-associative binary operation and initial value.
Given the list Example using -- Publishes: [3, 2, 1] foldl(flip((:)), [], [1,2,3]) Implementation. def foldl[A,B](lambda (B, A) :: B, B, List[A]) :: B def foldl(f,z,[]) = z def foldl(f,z,x:xs) = foldl(f,f(z,x),xs) |
|
A special case of Implementation. def foldl1[A](lambda (A, A) :: A, List[A]) :: A def foldl1(f,x:xs) = foldl(f,x,xs) |
|
Reduce a list using the given right-associative binary operation and initial value.
Given the list Example summing the numbers in a list: -- Publishes: 6 foldr((+), 0, [1,2,3]) Implementation. def foldr[A,B](lambda (A, B) :: B, B, List[A]) :: B def foldr(f,z,xs) = foldl(flip(f),z,reverse(xs)) |
|
A special case of Implementation. def foldr1[A](lambda (A, A) :: A, List[A]) :: A def foldr1(f,xs) = foldl1(flip(f),reverse(xs)) |
|
Reduce a non-empty list using the given associative binary operation.
This function reduces independent subexpressions in parallel; the
calls exhibit a balanced tree structure, so the number of sequential
reductions performed is O(log n). For expensive reductions, this
is much more efficient than Implementation. def afold[A](lambda (A, A) :: A, List[A]) :: A def afold(f, [x]) = x {- Here's the interesting part -} def afold(f, xs) = def afold'(List[A]) :: List[A] def afold'([]) = [] def afold'([x]) = [x] def afold'(x:y:xs) = f(x,y):afold'(xs) afold(f, afold'(xs)) |
|
Reduce a non-empty list using the given associative and commutative binary operation.
This function opportunistically reduces independent subexpressions in parallel, so the number of
sequential reductions performed is as small as possible. For expensive reductions, this
is much more efficient than Implementation. def cfold[A](lambda (A, A) :: A, List[A]) :: A def cfold(f, []) = stop def cfold(f, [x]) = x def cfold(f, [x,y]) = f(x,y) def cfold(f, L) = val c = Buffer[A]() def work(Number, List[A]) :: A def work(i, x:y:rest) = c.put(f(x,y)) >> stop | work(i+1, rest) def work(i, [x]) = c.put(x) >> stop | work(i+1, []) def work(i, []) = if (i < 2) then c.get() else c.get() >x> c.get() >y> ( c.put(f(x,y)) >> stop | work(i-1,[]) ) work(0, L) |
|
Combine two lists into a list of pairs. The length of the shortest list determines the length of the result. Implementation. def zip[A,B](List[A], List[B]) :: List[(A,B)] def zip([],_) = [] def zip(_,[]) = [] def zip(x:xs,y:ys) = (x,y):zip(xs,ys) |
|
Split a list of pairs into a pair of lists. Implementation. def unzip[A,B](List[(A,B)]) :: (List[A], List[B]) def unzip([]) = ([],[]) def unzip((x,y):z) = (x:xs,y:ys) <(xs,ys)< unzip(z) |
|
Concatenate a list of lists into a single list. Implementation. def concat[A](List[List[A]]) :: List[A] def concat([]) = [] def concat(h:t) = append(h,concat(t)) |
|
Return the number of elements in a list. Implementation. def length[A](List[A]) :: Integer def length([]) = 0 def length(h:t) = 1 + length(t) |
|
Given a number Implementation. def take[A](Integer, List[A]) :: List[A] def take(0, _) = [] def take(n, x:xs) = if n > 0 then x:take(n-1, xs) else error("Cannot take(" + n + ", _)") |
|
Given a number Implementation. def drop[A](Integer, List[A]) :: List[A] def drop(0, xs) = xs def drop(n, x:xs) = if n > 0 then drop(n-1, xs) else error("Cannot drop(" + n + ", _)") |
|
Return true if the given item is a member of the given list, and false otherwise. Implementation. def member[A](A, List[A]) :: Boolean def member(item, []) = false def member(item, h:t) = if item = h then true else member(item, t) |
|
Merge two sorted lists. Example: -- Publishes: [1, 2, 2, 3, 4, 5] merge([1,2,3], [2,4,5]) Implementation. def merge[A](List[A], List[A]) :: List[A] def merge(xs,ys) = mergeBy((<), xs, ys) |
|
Merge two lists using the given less-than relation. Implementation. def mergeBy[A](lambda (A,A) :: Boolean, List[A], List[A]) :: List[A] def mergeBy(lt, xs, []) = xs def mergeBy(lt, [], ys) = ys def mergeBy(lt, x:xs, y:ys) = if lt(y,x) then y:mergeBy(lt,x:xs,ys) else x:mergeBy(lt,xs,y:ys) |
|
Sort a list. Example: -- Publishes: [1, 2, 3] sort([1,3,2]) Implementation. def sort[A](List[A]) :: List[A] def sort(xs) = sortBy((<), xs) |
|
Sort a list using the given less-than relation. Implementation. def sortBy[A](lambda (A,A) :: Boolean, List[A]) :: List[A] def sortBy(lt, []) = [] def sortBy(lt, [x]) = [x] def sortBy(lt, xs) = val half = floor(length(xs)/2) val front = take(half, xs) val back = drop(half, xs) mergeBy(lt, sortBy(lt, front), sortBy(lt, back)) |
|
Merge two sorted lists, discarding duplicates. Example: -- Publishes: [1, 2, 3, 4, 5] mergeUnique([1,2,3], [2,4,5]) Implementation. def mergeUnique[A](List[A], List[A]) :: List[A] def mergeUnique(xs,ys) = mergeUniqueBy((=), (<), xs, ys) |
|
Merge two lists, discarding duplicates, using the given equality and less-than relations. Implementation. def mergeUniqueBy[A](lambda (A,A) :: Boolean, lambda (A,A) :: Boolean, List[A], List[A]) :: List[A] def mergeUniqueBy(eq, lt, xs, []) = xs def mergeUniqueBy(eq, lt, [], ys) = ys def mergeUniqueBy(eq, lt, x:xs, y:ys) = if eq(y,x) then mergeUniqueBy(eq, lt, xs, y:ys) else if lt(y,x) then y:mergeUniqueBy(eq,lt,x:xs,ys) else x:mergeUniqueBy(eq,lt,xs,y:ys) |
|
Sort a list, discarding duplicates. Example: -- Publishes: [1, 2, 3] sortUnique([1,3,2,3]) Implementation. def sortUnique[A](List[A]) :: List[A] def sortUnique(xs) = sortUniqueBy((=), (<), xs) |
|
Sort a list, discarding duplicates, using the given equality and less-than relations. Implementation. def sortUniqueBy[A](lambda (A,A) :: Boolean, lambda (A,A) :: Boolean, List[A]) :: List[A] def sortUniqueBy(eq, lt, []) = [] def sortUniqueBy(eq, lt, [x]) = [x] def sortUniqueBy(eq, lt, xs) = val half = floor(length(xs)/2) val front = take(half, xs) val back = drop(half, xs) mergeUniqueBy(eq, lt, sortUniqueBy(eq, lt, front), sortUniqueBy(eq, lt, back)) |
|
Given a list of pairs, group together the second elements of consecutive pairs with equal first elements. Example: -- Publishes: [(1, [1, 2]), (2, [3]), (3, [4]), (1, [3])] group([(1,1), (1,2), (2,3), (3,4), (1,3)]) Implementation. def group[A,B](List[(A,B)]) :: List[(A,List[B])] def group(xs) = groupBy((=), xs) |
|
Given a list of pairs, group together the second elements of consecutive pairs with equal first elements, using the given equality relation. Implementation. def groupBy[A,B](lambda (A,A) :: Boolean, List[(A,B)]) :: List[(A,List[B])] def groupBy(eq, []) = [] def groupBy(eq, (k,v):kvs) = def helper(A, List[B], List[(A,B)]) :: List[(A,List[B])] def helper(k,vs, []) = [(k,vs)] def helper(k,vs, (k2,v):kvs) = if eq(k2,k) then helper(k, v:vs, kvs) else (k,vs):helper(k2, [v], kvs) helper(k,[v], kvs) |
|
Implementation. def rangeBy(Number, Number, Number) :: List[Number] def rangeBy(low, high, skip) = if low < high then low:rangeBy(low+skip, high, skip) else [] |
|
Generate a list of numbers in the given half-open range. Implementation. def range(Number, Number) :: List[Number] def range(low, high) = rangeBy(low, high, 1) |
|
Return true if any of the elements of the list match the predicate, and false otherwise. The predicate is applied to all elements of the list in parellel; the result is returned as soon as it is known and any unnecessary evaluation of the predicate terminated. Implementation. def any[A](lambda (A) :: Boolean, List[A]) :: Boolean def any(p, []) = false def any(p, x:xs) = let( val b1 = p(x) val b2 = any(p, xs) if(b1) >> true | if(b2) >> true | (b1 || b2) ) |
|
Return true if all of the elements of the list match the predicate, and false otherwise. The predicate is applied to all elements of the list in parellel; the result is returned as soon as it is known and any unnecessary evaluation of the predicate terminated. Implementation. def all[A](lambda (A) :: Boolean, List[A]) :: Boolean def all(p, []) = true def all(p, x:xs) = let( val b1 = p(x) val b2 = all(p, xs) if(~b1) >> false | if(~b2) >> false | (b1 && b2) ) |
|
Return the sum of all numbers in a list. The sum of an empty list is 0. Implementation. def sum(List[Number]) :: Number def sum(xs) = foldl( (+) :: lambda (Number, Number) :: Number, 0, xs) |
|
Return the product of all numbers in a list. The product of an empty list is 1. Implementation. def product(List[Number]) :: Number def product(xs) = foldl( (*) :: lambda (Number, Number) :: Number, 1, xs) |
|
Return the boolean conjunction of all boolean values in the list.
The conjunction of an empty list is Implementation. def and(List[Boolean]) :: Boolean def and([]) = true def and(false:xs) = false def and(true:xs) = and(xs) |
|
Return the boolean disjunction of all boolean values in the list.
The disjunction of an empty list is Implementation. def or(List[Boolean]) :: Boolean def or([]) = false def or(true:xs) = true def or(false:xs) = or(xs) |
|
Return the minimum element of a non-empty list. Implementation. def minimum[A](List[A]) :: A def minimum(xs) = -- this def appeases the typechecker def minA(x::A,y::A) = min(x,y) foldl1(minA, xs) |
|
Return the maximum element of a non-empty list. Implementation. def maximum[A](List[A]) :: A def maximum(xs) = -- this def appeases the typechecker def maxA(x::A,y::A) = max(x,y) foldl1(maxA, xs) |
Metalanguage operations.
|
This site promotes an Orc closure to a site; when the site is called, the closure is executed on those arguments. These executions behave like site calls; in particular, the following four properties hold:
The typical usage of Site looks like:
def foo(...) = ... val Foo = Site(foo) The typing of Site will enforce the side condition that the type A is an arrow type. |
Operations on strings.
|
Strings themselves have a set of methods associated with them. These methods can be invoked on any string literal or any variable bound to a string. The methods documented here are only a subset of those available in the Java
implementation. In practice, strings in the Java implementation support all
methods provided by Java's
| ||||||
|
Return the string representation of one or more values, concatenated.
For Java objects, this will call | ||||||
|
Print one or more values as strings, concatenated, to standard output.
For Java objects, this will call | ||||||
|
Print one or more values as strings, concatenated,
to standard output, with each value followed by a newline.
For Java objects, this will call | ||||||
|
Given a string representing an Orc value (using standard Orc literal syntax), return the corresponding value. If the argument does not conform to Orc literal syntax, halt with an error. Example: read("true") -- publishes the boolean true | read("1") -- publishes the integer 1 | read("(3.0, [])") -- publishes the tuple (3.0, []) | read("\"hi\"") -- publishes the string "hi" | ||||||
|
Given an Orc value, return its string representation using standard Orc literal syntax. If the value is of a type with no literal syntax, (for example, it is a site), return an arbitrary string representation which is intended to be human-readable. Example: write(true) -- publishes "true" | write(1) -- publishes "1" | write((3.0, [])) -- publishes "(3.0, [])" | write("hi") -- publishes "\"hi\"" | ||||||
|
Split a string into lines, which are substrings terminated by an endline or the end of the string. DOS, Mac, and Unix endline conventions are all accepted. Endline characters are not included in the result. Implementation. def lines(String) :: List[String] def lines(text) = ( val out = text.split("\n|\r\n|\r") if out.get(out.length()-1) = "" then out.split(0, out.length()-1) else out ) :!: List[String] | ||||||
|
Append a linefeed, "\n", to each string in the sequence and concatenate the results. Implementation. def unlines(List[String]) :: String def unlines(line:lines) = cat(line, "\n", unlines(lines)) def unlines([]) = "" | ||||||
|
Split a string into words, which are sequences of non-whitespace characters separated by whitespace. Implementation. def words(String) :: List[String] def words(text) = (text.trim().split("\\s+")) :!: List[String] | ||||||
|
Concatenate a sequence of strings with a single space between each string. Implementation. def unwords(List[String]) :: String def unwords([]) = "" def unwords([word]) = word def unwords(word:words) = cat(word, " ", unwords(words)) |
Real and logical time.
|
Publish a signal after the given number of milliseconds.
| ||
|
A call to Example: -- Publishes a value near 1000 val c = Clock() Rtimer(1000) >> c() | ||
|
Publish a signal after the given number of logical timesteps, as measured by the current logical clock. The logical time advances whenever the computation controlled by the logical clock is quiescent (i.e. cannot advance on its own).
| ||
|
Run the given thunk in the context of a new inner logical clock.
Within the computation represented by the thunk, calls to
| ||
|
Publish a signal at regular intervals, indefinitely. The period is given by the argument, in milliseconds. |
Miscellaneous utility functions.
|
Return a random Integer value chosen from the range of all possible 32-bit Integer values. |
|
Return a pseudorandom, uniformly distributed Integer value between 0 (inclusive) and the specified value (exclusive). If the argument is 0, halt. |
|
Returns a pseudorandom, uniformly distributed Double value between 0 and 1, inclusive. |
|
Return a random (type 4) UUID represented as a string. |
|
Given a site, return a new site which calls the original site in a separate thread. This is necessary when calling a Java site which does not cooperate with Orc's scheduler and may block for an unpredictable amount of time. A limited number of threads are reserved in a pool for use by this site, so there is a limit to the number of blocking, uncooperative sites that can be called simultaneously. |
|
Prompt the user for some input. The user may cancel the prompt, in which case the site fails silently. Otherwise their response is returned as soon as it is received. Example: -- Publishes the user's name Prompt("What is your name?") The user response is always taken to be a string. Thus, integer
3 as a response will be treated as "3". To convert the response
to its appropriate data type, use the library function
-- Prompts the user to enter an integer, then parses the response. Prompt("Enter an integer:") >r> read(r) |
|
Publish the given number of signals, simultaneously. Example: -- Publishes five signals signals(5) Implementation. def signals(Integer) :: Top def signals(n) = if n > 0 then (signal | signals(n-1)) |
|
Publish all values in the given half-open range, simultaneously. Example: -- Publishes: 1 2 3 4 5 for(1,6) Implementation. def for(Integer, Integer) :: Integer def for(low, high) = if low >= high then stop else ( low | for(low+1, high) ) |
|
Example: -- Publishes: 0 1 2 3 4 upto(5) Implementation. def upto(Integer) :: Integer def upto(high) = for(0, high) |
|
Given an array and a function from indices to values, populate the array by calling the function for each index in the array. For example, to set all elements of an array to zero: -- Publishes: 0 0 0 val a = fillArray(Array(3), lambda (_) = 0) a.get(0) | a.get(1) | a.get(2) Implementation. def fillArray[A](Array[A], lambda (Integer) :: A) :: Array[A] def fillArray(a, f) = val n = a.length() def fill(Integer, lambda(Integer) :: A) :: Bot def fill(i, f) = if i = n then stop else ( a.set(i, f(i)) >> stop | fill(i+1, f) ) fill(0, f) ; a |
|
Implementation. def takePubs[A](Integer, lambda () :: A) :: A def takePubs(n, f) = val out = Buffer[A]() val c = Counter(n) let( f() >x> if(c.dec() >> out.put(x) >> false ; out.closenb() >> true) ) >> stop | repeat(out.get) |
|
Acquire the semaphore and run a thunk which is expected to publish no more than one value. Publishes the value published by the thunk and releases the semaphore. Implementation. def withLock[A](Semaphore, lambda () :: A) :: A def withLock(s, f) = s.acquire() >> ( let(f()) >x> s.release() >> x ; s.release() >> stop ) |
|
Given a lock and thunk, return a new thunk which is serialized on the lock. Similar to Java's synchronized keyword. Implementation. def synchronized[A](Semaphore, lambda () :: A)() :: A def synchronized(s,f)() = withLock(s, f) |