mirror of
https://github.com/justinethier/cyclone.git
synced 2025-05-23 20:15:05 +02:00
Merge pull request #175 from kozross/master
Documentation for new SRFIs, some small code changes
This commit is contained in:
commit
21f54914b5
8 changed files with 835 additions and 31 deletions
|
@ -32,19 +32,22 @@ This section of the Cyclone API is based on the [R<sup>7</sup>RS Scheme Specific
|
|||
|
||||
Cyclone supports the following [Scheme Requests for Implementation (SRFI)](http://srfi.schemers.org/) libraries. Detailed information is available in the linked SRFI page as well as the provided Cyclone API:
|
||||
|
||||
- [`srfi 1`](api/srfi/1.md) - [List Library](http://srfi.schemers.org/srfi-1/srfi-1.html)
|
||||
- [`srfi 1`](api/srfi/1.md) - [List library](http://srfi.schemers.org/srfi-1/srfi-1.html)
|
||||
- [`srfi 2`](api/srfi/2.md) - [`and-let*`](http://srfi.schemers.org/srfi-2/srfi-2.html)
|
||||
- [`srfi 8`](api/srfi/8.md) - [`receive`: Binding to multiple values](http://srfi.schemers.org/srfi-8/srfi-8.html) - Included as part of `scheme base`.
|
||||
- [`srfi 18`](api/srfi/18.md) - [Multithreading support](http://srfi.schemers.org/srfi-18/srfi-18.html)
|
||||
- [`srfi 27`](api/srfi/27.md) - [Sources of random bits](http://srfi.schemers.org/srfi-27/srfi-27.html)
|
||||
- [`srfi 28`](api/srfi/28.md) - [Basic format strings](http://srfi.schemers.org/srfi-28/srfi-28.html)
|
||||
- [`srfi 60`](api/srfi/60.md) - [Integers as bits](http://srfi.schemers.org/srfi-60/srfi-60.html)
|
||||
- [`srfi 69`](api/srfi/69.md) - [Basic hash tables](http://srfi.schemers.org/srfi-69/srfi-69.html)
|
||||
- [`srfi 106`](api/srfi/106.md) - [Basic socket interface](http://srfi.schemers.org/srfi-106/srfi-106.html)
|
||||
- [`srfi 111`](api/srfi/111.md) - [Boxes](http://srfi.schemers.org/srfi-111/srfi-111.html)
|
||||
- [`srfi 113`](api/srfi/113.md) - [Sets and bags](http://srfi.schemers.org/srfi-113/srfi-113.html)
|
||||
- [`srfi 117`](api/srfi/117.md) - [Mutable queues](http://srfi.schemers.org/srfi-117/srfi-117.html)
|
||||
- [`srfi 121`](api/srfi/121.md) - [Generators](http://srfi.schemers.org/srfi-121/srfi-121.html)
|
||||
- [`srfi 128`](api/srfi/128.md) - [Comparators](http://srfi.schemers.org/srfi-128/srfi-128.html)
|
||||
- [`srfi 132`](api/srfi/132.md) - [Sort Libraries](http://srfi.schemers.org/srfi-132/srfi-132.html)
|
||||
- [`srfi 133`](api/srfi/133.md) - [Vector Library (R7RS-compatible)](http://srfi.schemers.org/srfi-133/srfi-133.html)
|
||||
- [`srfi 132`](api/srfi/132.md) - [Sort libraries](http://srfi.schemers.org/srfi-132/srfi-132.html)
|
||||
- [`srfi 133`](api/srfi/133.md) - [Vector library (R7RS-compatible)](http://srfi.schemers.org/srfi-133/srfi-133.html)
|
||||
|
||||
# Cyclone Libraries
|
||||
|
||||
|
|
458
docs/api/srfi/121.md
Normal file
458
docs/api/srfi/121.md
Normal file
|
@ -0,0 +1,458 @@
|
|||
# SRFI 121 - Generators
|
||||
|
||||
Defines utility procedures that create, transform and consume generators. A
|
||||
'generator' is a procedure with no arguments (a 'thunk') that works as a source
|
||||
of values. Every time a generator is called, it yields a value.
|
||||
|
||||
Generators may be finite or infinite; a finite generator returns an end-of-file
|
||||
object to indicate that it is exhausted (has no more values to give). For
|
||||
example, ``read-char``, ``read-line`` and ``read`` are generators that produce
|
||||
characters, lines and objects from the current input port.
|
||||
|
||||
This library is designed to provide lightweight laziness.
|
||||
|
||||
See the [SRFI document][1] for more information.
|
||||
|
||||
## Definitions
|
||||
|
||||
Generators can be divided into two classes: *finite* and *infinite*. Both kinds
|
||||
of generator can be invoked an indefinite number of times. After a finite
|
||||
generator has produced all of its values, it will return an end-of-file object
|
||||
for all subsequent calls. A generator is said to be *exhausted* if calling it
|
||||
will return an end-of-file object. By definition, an infinite generator can
|
||||
never be exhausted.
|
||||
|
||||
A generator is said to be in an *undefined state* if it cannot be determined how
|
||||
many values it has produced. This arises because it is impossible to tell by
|
||||
inspection whether a generator is exhausted or not. For example,
|
||||
``(generator-fold + 0 (generator 1 2 3) (generator 1 2))`` will compute 0 + 1 +
|
||||
1 + 2 + 2 = 6, at which time the second generator will be exhausted. If the
|
||||
first generator is invoked, however, it may return either 3 or an end-of-file
|
||||
object, depending on whether the implementation of ``generator-fold`` invoked it
|
||||
or not. Therefore, the first generator is said to be in an undefined state.
|
||||
|
||||
Functions provided under [generator operations](#generator-operations) do not
|
||||
consume elements from their input generators. In general, they produce finite
|
||||
generators if their inputs are finite.
|
||||
|
||||
Functions provided udner [consuming generated
|
||||
values](#consuming-generated-values) consume all values from any generator
|
||||
passed to them, and will not return if any of their arguments are infinite.
|
||||
|
||||
## Generator constructors
|
||||
[`generator`](#generator)
|
||||
[`make-iota-generator`](#make-iota-generator)
|
||||
[`make-range-generator`](#make-range-generator)
|
||||
[`make-coroutine-generator`](#make-coroutine-generator)
|
||||
[`list->generator'](#list-generator)
|
||||
[`vector->generator'](#vector-generator)
|
||||
[`reverse-vector->generator'](#reverse-vector-generator)
|
||||
[`string->generator`](#string-generator)
|
||||
[`bytevector->generator`](#bytevector-generator)
|
||||
[`make-for-each-generator`](#make-for-each-generator)
|
||||
[`make-unfold-generator`](#make-unfold-generator)
|
||||
|
||||
## Generator operations
|
||||
[`gcons*`](#gcons)
|
||||
[`gappend`](#gappend)
|
||||
[`gcombine`](#gcombine)
|
||||
[`gfilter`](#gfilter)
|
||||
[`gremove`](#gremove)
|
||||
[`gtake`](#gtake)
|
||||
[`gdrop`](#gdrop)
|
||||
[`gtake-while`](#gtake-while)
|
||||
[`gdrop-while`](#gdrop-while)
|
||||
[`gdelete`](#gdelete)
|
||||
[`gdelete-neighbor-dups`](#gdelete-neighbor-dups)
|
||||
[`gindex`](#gindex)
|
||||
[`gselect`](#gselect)
|
||||
|
||||
## Consuming generated values
|
||||
[`generator->list`](#generator-list)
|
||||
[`generator->reverse-list`](#generator-reverse-list)
|
||||
[`generator->vector`](#generator-vector)
|
||||
[`generator->vector!`](#generator-vector!)
|
||||
[`generator->string`](#generator-string)
|
||||
[`generator-fold`](#generator-fold)
|
||||
[`generator-for-each`](#generator-for-each)
|
||||
[`generator-find`](#generator-find)
|
||||
[`generator-count`](#generator-count)
|
||||
[`generator-any`](#generator-any)
|
||||
[`generator-every`](#generator-every)
|
||||
[`generator-unfold`](#generator-unfold)
|
||||
|
||||
# generator
|
||||
|
||||
(generator arg ...)
|
||||
|
||||
Returns a generator which produces each of this function's arguments in turn.
|
||||
When given no arguments, returns an empty generator which provides no values.
|
||||
|
||||
# make-iota-generator
|
||||
|
||||
(make-iota-generator count)
|
||||
(make-iota-generator count start)
|
||||
(make-iota-generator count start step)
|
||||
|
||||
Returns a finite generator which produces a sequence of ``count`` numbers. The
|
||||
sequence begins with ``start`` (default 0) and increases by ``step`` (default
|
||||
1). If both ``start`` and ``step`` are exact, the generator produces exact
|
||||
values; otherwise, it produces inexact ones. The exactness of ``count`` does not
|
||||
affect the exactness of results.
|
||||
|
||||
Example: ``(generator->list (make-iota-generator 3 8))`` => (8 9 10)``
|
||||
|
||||
# make-range-generator
|
||||
|
||||
(make-range-generator start)
|
||||
(make-range-generator start end)
|
||||
(make-range-generator start end step)
|
||||
|
||||
Returns a generator which produces a sequence of numbers. The sequence begins
|
||||
with ``start``, increases by ``step`` (default 1), and continues while the
|
||||
number is less than ``end``, or forever if ``end`` is not provided. If both
|
||||
``start`` and ``step`` are exact, the generator produces exact values;
|
||||
otherwise, it produces inexact ones. The exactness of ``end`` does not affect
|
||||
the exactness of the results.
|
||||
|
||||
Example: ``(generator->list (make-range-generator 3) 4) => (3 4 5 6)``
|
||||
|
||||
# make-coroutine-generator
|
||||
|
||||
(make-coroutine-generator proc)
|
||||
|
||||
Creates a generator from a coroutine. The ``proc`` argument should be a
|
||||
procedure that takes a single argument ``yield``. When called,
|
||||
``make-coroutine-generator`` immediately returns a generator ``g``. When ``g``
|
||||
is called, ``proc`` runs until it calls ``yield``. Calling ``yield`` causes the
|
||||
execution of ``proc`` to be suspended, and ``g`` returns the value passed to
|
||||
``yield``.
|
||||
|
||||
Whether ``g`` is finite or infinite depends on the behaviour of ``proc``: if
|
||||
``proc`` returns, it is the end of the sequence, and ``g`` will return an
|
||||
end-of-file object from then on. The return value of ``proc`` is ignored.
|
||||
|
||||
# list->generator
|
||||
|
||||
(list->generator lis)
|
||||
|
||||
Returns a generator that produces each element of the list ``lis`` in turn.
|
||||
Mutating ``lis`` will affect the results of the generator.
|
||||
|
||||
``list->generator`` and ``generator->list`` (when given no arguments) are
|
||||
inverses up to ``equal?``; thus, for any list ``x``,
|
||||
``(equal? x (generator->list (list->generator x))) => #t``.
|
||||
|
||||
# vector->generator
|
||||
|
||||
(vector->generator vec)
|
||||
(vector->generator vec start)
|
||||
(vector->generator vec start end)
|
||||
|
||||
Returns a generator that produces elements of ``vec``, in turn, from the index
|
||||
``start`` (inclusive, default 0) to ``end`` (exclusive, default
|
||||
``(vector-length vec)``). Mutating ``vec`` will affect the results of the
|
||||
generator.
|
||||
|
||||
When given no arguments, ``vector->generator`` and ``generator->vector`` are
|
||||
inverses up to ``equal?``; thus, for any vector ``x``, ``(equal? x
|
||||
(generator->vector (vector->generator x))) => #t``.
|
||||
|
||||
# reverse-vector->generator
|
||||
|
||||
(reverse-vector->generator vec)
|
||||
(reverse-vector->generator vec start)
|
||||
(reverse-vector->generator vec start end)
|
||||
|
||||
Returns a generator that produces elements of ``vec``, in turn, from ``end``
|
||||
(exclusive, default ``(vector-length vec)``) to ``start`` (inclusive, default
|
||||
0), in reverse order of indices. Mutating ``vec`` will affect the results of the
|
||||
generator.
|
||||
|
||||
# string->generator
|
||||
|
||||
(string->generator str)
|
||||
(string->generator str start)
|
||||
(string->generator str start end)
|
||||
|
||||
Returns a generator that produces characters of ``str``, in turn, from ``start``
|
||||
(inclusive, default 0) to ``end`` (exclusive, default ``(string-length str)``).
|
||||
Mutating ``str`` will affect the results of the generator.
|
||||
|
||||
When given no arguments, ``string->generator`` and ``generator->string`` are
|
||||
inverses up to ``string=?``; thus, for any string ``s``, ``(string=? s
|
||||
(generator->string (string->generator s))) => #t``.
|
||||
|
||||
# bytevector->generator
|
||||
|
||||
(bytevector->generator bv)
|
||||
(bytevector->generator bv start)
|
||||
(bytevector->generator bv start end)
|
||||
|
||||
Returns a generator that produces bytes of ``bv``, in turn, from ``start``
|
||||
(inclusive, default 0) to ``end`` (exclusive, default ``(bytevector-length
|
||||
bv)``). Mutating ``bv`` will affect the results of the generator.
|
||||
|
||||
# make-for-each-generator
|
||||
|
||||
(make-for-each-generator for-each obj)
|
||||
|
||||
Constructs a generator over any collection ``obj``, using a ``for-each``
|
||||
procedure appropriate to ``obj``. This must be a procedure that, when called as
|
||||
``(for-each proc obj)`` calls ``proc`` on each element of ``obj``. Examples of
|
||||
such procedures are ``for-each``, ``string-for-each`` and ``vector-for-each``.
|
||||
The value returned by ``for-each`` is ignored. The generator is finite if the
|
||||
collection is finite.
|
||||
|
||||
``obj`` need not be a conventional one (such as a string, list, etc), as long as
|
||||
``for-each`` can invoke a procedure on everything that counts as a member.
|
||||
|
||||
# make-unfold-generator
|
||||
|
||||
(make-unfold-generator stop? mapper successor seed)
|
||||
|
||||
A generator similar to [SRFI 1][2]'s ``unfold``.
|
||||
|
||||
The ``stop?`` predicate takes a seed value and determines whether to stop. The
|
||||
``mapper`` procedure calculates a value to be returned by the generator from a
|
||||
seed value. The ``successor`` procedure calculates the next seed value from
|
||||
the current seed value.
|
||||
|
||||
For each call of the resulting generator, ``stop?`` is called with the current
|
||||
seed value. If it returns true, then the generator returns an end-of-file
|
||||
object. Otherwise, it applies ``mapper`` to the current seed value to get the
|
||||
value to return, and uses ``successor`` to update the seed value.
|
||||
|
||||
The generator is finite unless ``stop?`` is a constant function returning
|
||||
``#f``.
|
||||
|
||||
# gcons\*
|
||||
|
||||
(gcons\* item ... gen)
|
||||
|
||||
Returns a generator that adds ``item ...`` in front of ``gen``. Once each of
|
||||
``item ...`` has been produced, the generator is guaranteed to tail-call
|
||||
``gen``.
|
||||
|
||||
# gappend
|
||||
|
||||
(gappend gen ...)
|
||||
|
||||
Returns a generator that yields the items from the first argument generator, and
|
||||
once it is exhausted, the second generator, and so forth.
|
||||
|
||||
If any of the argument generators are infinite, subsequent argument generators
|
||||
will never be asked to produce any values.
|
||||
|
||||
# gcombine
|
||||
|
||||
(gcombine proc seed gen gen2 ...)
|
||||
|
||||
Returns a generator for mapping with state. It produces a sequence of sub-folds
|
||||
over ``proc``.
|
||||
|
||||
The ``proc`` argument is a procedure that takes as many arguments as there are
|
||||
argument generators, plus one. It is called as ``(proc v1 v2 ... seed)``, where
|
||||
``v1 v2 ...`` are the values produced by the argument generators, and ``seed``
|
||||
is the current seed value. It must return two values: the produced value and the
|
||||
next seed. The generator is exhausted when any of its argument generators are
|
||||
exhausted, at which time, the remaining argument generators are in an undefined
|
||||
state.
|
||||
|
||||
# gfilter
|
||||
|
||||
(gfilter pred gen)
|
||||
|
||||
Returns a generator that produces items from ``gen``, except those for which
|
||||
``pred`` would return ``#f``.
|
||||
|
||||
# gremove
|
||||
|
||||
(gremove pred gen)
|
||||
|
||||
Equivalent to ``(gfilter (lambda (x) (not (pred x))) gen)``.
|
||||
|
||||
# gtake
|
||||
|
||||
(gtake gen k)
|
||||
(gtake gen k padding)
|
||||
|
||||
A generator analogue to [SRFI 1][2]'s ``take``. Returns a generator that
|
||||
produces (at most) the first ``k`` items of ``gen``. If ``gen`` is exhausted
|
||||
before it can produce ``k`` items, the rest will be made up by producing the
|
||||
``padding`` value.
|
||||
|
||||
# gdrop
|
||||
|
||||
(gdrop gen k)
|
||||
|
||||
A generator analogue to [SRFI 1][2]'s ``drop``. Returns a generator that
|
||||
skips the first (at most) ``k`` items of ``gen``, then produces the rest. If
|
||||
``k`` is greater than, or equal to, the total number of items ``gen`` could
|
||||
produce, an empty generator is produced instead.
|
||||
|
||||
# gtake-while
|
||||
|
||||
(gtake-while pred gen)
|
||||
|
||||
A generator analogue to [SRFI 1][2]'s ``take-while``. Returns a generator that
|
||||
produces values from ``gen`` until ``pred`` returns ``#f`` on a value.
|
||||
|
||||
# gdrop-while
|
||||
|
||||
(gdrop-while pred gen)
|
||||
|
||||
A generator analogue to [SRFI 1][2]'s ``drop-while``. Returns a generator that
|
||||
discards values from ``gen`` until ``pred`` returns ``#t`` for a value, and then
|
||||
produces values from ``gen``.
|
||||
|
||||
# gdelete
|
||||
|
||||
(gdelete item gen)
|
||||
(gdelete item gen =)
|
||||
|
||||
Returns a generator which produces the same items as ``gen``, except any items
|
||||
that are the same as ``item`` up to ``=``, which defaults to ``equal?``. ``=``
|
||||
is passed exactly two arguments, one of which is the value produced by ``gen``.
|
||||
|
||||
# gdelete-neighbor-dups
|
||||
|
||||
(gdelete-neighbor-dups gen)
|
||||
(gdelete-neighbor-dups gen =)
|
||||
|
||||
Returns a generator which produces the same items as ``gen``, except any items
|
||||
that are the same as the preceding items up to ``=``, which defaults to
|
||||
``equal?``. ``=`` is passed exactly two arguments; the first of which is
|
||||
produced by ``gen`` before the second.
|
||||
|
||||
# gindex
|
||||
|
||||
(gindex value-gen index-gen)
|
||||
|
||||
Returns a generator that produces elements of ``value-gen`` specified by the
|
||||
indices (non-negative exact integers) produced by ``index-gen``. It is an error
|
||||
if the indices are not strictly increasing, or if any index exceeds the number
|
||||
of elements produced by ``value-gen``. The generator is exhausted when either of
|
||||
``value-gen`` or ``index-gen`` is exhausted, at which time the other is in an
|
||||
undefined state.
|
||||
|
||||
# gselect
|
||||
|
||||
(gselect value-gen truth-gen)
|
||||
|
||||
Returns a generator that produces elements of ``value-gen`` that correspond to
|
||||
the values produced by ``truth-gen``. If the current value of ``truth-gen`` is
|
||||
true, the current value of ``value-gen`` is produced; otherwise, the value is
|
||||
skipped. The generator is exhausted when either of ``value-gen`` or
|
||||
``truth-gen`` is exhausted, at which time the other is in an undefined state.
|
||||
|
||||
# generator->list
|
||||
|
||||
(generator->list gen)
|
||||
(generator->list gen k)
|
||||
|
||||
Calls ``gen`` repeatedly to produce its values, then collects them into a list
|
||||
and returns them. If ``k`` is omitted, ``gen`` will be asked to produce values
|
||||
until it is exhausted; otherwise, only at most ``k``-many values will be
|
||||
requested. It is an error for ``k`` to be anything other than a non-negative
|
||||
integer.
|
||||
|
||||
# generator->reverse-list
|
||||
|
||||
(generator->reverse-list gen)
|
||||
(generator->reverse-list gen k)
|
||||
|
||||
As ``generator->list``, but the returned list is in reverse order.
|
||||
|
||||
# generator->vector
|
||||
|
||||
(generator->vector gen)
|
||||
(generator->vector gen k)
|
||||
|
||||
As ``generator->list``, but the returned result is a vector.
|
||||
|
||||
# generator->vector!
|
||||
|
||||
(generator->vector! vec at gen)
|
||||
|
||||
Calls ``gen`` repeatedly to produce its values, and puts them into ``vec``,
|
||||
starting at index ``at``, until ``vec`` is full or ``gen`` is exhausted. Returns
|
||||
the number of elements produced from ``gen``.
|
||||
|
||||
# generator->string
|
||||
|
||||
(generator->string gen)
|
||||
(generator->string gen k)
|
||||
|
||||
Calls ``gen`` repeatedly to produce characters, and returns a newly-allocated
|
||||
string of them. It is an error if ``gen`` does not produce only characters. If
|
||||
``k`` is omitted, the generator will be asked to produce characters until it is
|
||||
exhausted; otherwise, at most ``k`` characters will be requested. It is an error
|
||||
for ``k`` to be anything other than a non-negative integer.
|
||||
|
||||
# generator-fold
|
||||
|
||||
(generator-fold proc seed gen1 gen2 ...)
|
||||
|
||||
An analogue of [SRFI 1][2]'s ``fold`` on values produced by the generator
|
||||
arguments.
|
||||
|
||||
When one generator argument ``gen`` is given, for each value ``v`` produced by
|
||||
``gen``, ``proc`` is called as ``(proc v r)``, where ``r`` is the current
|
||||
accumulated result; the initial value of ``r`` is ``seed``, and the return value
|
||||
from ``proc`` becomes the new accumulated result. When ``gen`` is exhausted, the
|
||||
accumulated result at the time is returned.
|
||||
|
||||
When more than one generator argument is given, ``proc`` is called on all the
|
||||
values produced by all the generator arguments, followed by the current
|
||||
accumulated result. The procedure returns when any of the generator arguments is
|
||||
exhausted, at which time the others are in an undefined state.
|
||||
|
||||
# generator-for-each
|
||||
|
||||
(generator-for-each proc gen1 gen2 ...)
|
||||
|
||||
A generator analogue of ``for-each`` that consumes produced values with side
|
||||
effects. ``proc`` is repeatedly applied to values produced by all the generator
|
||||
arguments, until any of them is exhausted. The values returned by ``proc`` are
|
||||
discarded. The procedure terminates when any of the argument generators is
|
||||
exhausted, at which time the others are in an undefined state.
|
||||
|
||||
# generator-find
|
||||
|
||||
(generator-find pred gen)
|
||||
|
||||
Returns the first value produced by ``gen`` that satisfies the predicate
|
||||
``pred``, or ``#f`` if no such value exists. If ``gen`` is infinite, this
|
||||
procedure will not return if it cannot find an appropriate item.
|
||||
|
||||
# generator-count
|
||||
|
||||
(generator-count pred gen)
|
||||
|
||||
Returns the number of values that gen can produce which satisfy the predicate
|
||||
``pred``. This procedure will not return if ``gen`` is infinite.
|
||||
|
||||
# generator-any
|
||||
|
||||
(generator-any pred gen)
|
||||
|
||||
Applies ``pred`` to each item produced by ``gen``. As soon as ``pred`` returns a
|
||||
true value, the value is returned without consuming the rest of ``gen``. If
|
||||
``gen`` is exhausted, returns ``#f``.
|
||||
|
||||
# generator-every
|
||||
|
||||
(generator-every pred gen)
|
||||
|
||||
Equivalent to ``(not (generator-any (lambda (x) (not (pred x))) gen))``.
|
||||
|
||||
# generator-unfold
|
||||
|
||||
(generator-unfold gen unfold arg ...)
|
||||
|
||||
Equivalent to ``(unfold eof-object? (lambda (x) x) (lambda (x) (gen)) arg
|
||||
...)``, where ``unfold`` is the [SRFI 1][2] procedure of the same name.
|
||||
|
||||
[1]: http://srfi.schemers.org/srfi-121/srfi-121.html
|
||||
[2]: http://srfi.schemers.org/srfi-1/srfi-1.html
|
|
@ -4,6 +4,12 @@ The `(srfi 18)` library provides multithreading support.
|
|||
|
||||
See the [Multithreading support SRFI documentation](http://srfi.schemers.org/srfi-18/srfi-18.html) for more information.
|
||||
|
||||
## Limitations
|
||||
|
||||
Currently, ``thread-join!`` is not provided. While this is not an essential
|
||||
primitive and can be worked around, code that relies on ``thread-join!`` being
|
||||
present in this implementation will fail to compile.
|
||||
|
||||
- [`thread?`](#thread)
|
||||
- [`make-thread`](#make-thread)
|
||||
- [`thread-name`](#thread-name)
|
||||
|
|
47
docs/api/srfi/28.md
Normal file
47
docs/api/srfi/28.md
Normal file
|
@ -0,0 +1,47 @@
|
|||
# SRFI 28 - Basic format strings
|
||||
|
||||
Specifies a method of interpreting a Scheme string which contains a number of
|
||||
escape sequences, into which other data is interpolated according to the
|
||||
semantics of each sequence.
|
||||
|
||||
See the [SRFI document][1] for more information.
|
||||
|
||||
## Limitations
|
||||
|
||||
Currently, this translates newline escape sequences into LF. This may cause
|
||||
issues if this is ever used on Windows (which expects CRLF instead). Given that
|
||||
Cyclone does not currently support Windows, this issue should not arise in
|
||||
practice.
|
||||
|
||||
## Interface
|
||||
|
||||
# format
|
||||
|
||||
(format format-string [obj ...])
|
||||
|
||||
Processes ``format-string``, replacing any escape sequences in order with one or
|
||||
more characters. These characters depend on the semantics of the escape
|
||||
sequence.
|
||||
|
||||
An 'escape sequence' is a two-character sequence in ``format-string``, where the
|
||||
first character is a tilde ('~'). The following are all of the valid escape
|
||||
codes, as well as their semantics:
|
||||
|
||||
- ``~a``: The corresponding value is inserted into the string as if printed by
|
||||
``display``.
|
||||
- ``~s``: The corresponding value is inserted into the string as if printed by
|
||||
``write``.
|
||||
- ``~%``: A newline is inserted.
|
||||
- ``~~``: A literal tilde is inserted.
|
||||
|
||||
``~a`` and ``~s``, when encountered, require a corresponding Scheme value to be
|
||||
present as an argument to ``format``. The values provided in ``obj ...`` are
|
||||
used by the escape sequences in order. It is an error if fewer values are
|
||||
provided than escape sequences which require them. ``~%`` and ``~~`` do not need
|
||||
a corresponding value.
|
||||
|
||||
Example: The call ``(format "This is the ~ast example: ~s~%" 1 '(foo bar 17))``
|
||||
would produce the string ``"This is the 1st example: (foo bar 17)
|
||||
"`` (note the newline).
|
||||
|
||||
[1]: http://srfi.schemers.org/srfi-28/srfi-28.html
|
247
docs/api/srfi/60.md
Normal file
247
docs/api/srfi/60.md
Normal file
|
@ -0,0 +1,247 @@
|
|||
# SRFI 60 - Integers as bits
|
||||
|
||||
Various operations designed to work on integers as strings of bits efficiently.
|
||||
|
||||
See the [SRFI document][1] for more information.
|
||||
|
||||
## Bitwise operations
|
||||
[`logand`](#logand)
|
||||
[`logior`](#logior)
|
||||
[`logxor`](#logxor)
|
||||
[`lognot`](#lognot)
|
||||
[`logtest`](#logtest)
|
||||
[`bitwise-and`](#bitwise-and)
|
||||
[`bitwise-ior`](#bitwise-ior)
|
||||
[`bitwise-xor`](#bitwise-xor)
|
||||
[`bitwise-not`](#bitwise-not)
|
||||
[`bitwise-if`](#bitwise-if)
|
||||
[`bitwise-merge`](#bitwise-merge)
|
||||
[`any-bits-set?`](#any-bits-set)
|
||||
|
||||
## Integer properties
|
||||
[`logcount`](#logcount)
|
||||
[`log2-binary-factors`](#log2-binary-factors)
|
||||
[`bit-count`](#bit-count)
|
||||
[`integer-length`](#integer-length)
|
||||
[`first-set-bit`](#first-set-bit)
|
||||
|
||||
## Bit within word
|
||||
[`logbit?`](#logbit)
|
||||
[`bit-set?`](#bit-set)
|
||||
[`copy-bit`](#copy-bit)
|
||||
|
||||
## Field of bits
|
||||
[`bit-field`](#bit-field)
|
||||
[`copy-bit-field`](#copy-bit-field)
|
||||
[`ash`](#ash)
|
||||
[`arithmetic-shift`](#ash)
|
||||
[`rotate-bit-field`](#rotate-bit-field)
|
||||
|
||||
## Bits as booleans
|
||||
[`integer->list`](#integer-list)
|
||||
[`list->integer`](#list-integer)
|
||||
[`booleans->integer`](#booleans-integer)
|
||||
|
||||
# logand
|
||||
|
||||
(logand n1 ...)
|
||||
|
||||
Returns the integer which is the bitwise-AND of the arguments.
|
||||
|
||||
Example: ``(number->string (logand #b1100 #b1010) 2) => "1000"``
|
||||
|
||||
# bitwise-and
|
||||
|
||||
Synonym for ``logand``.
|
||||
|
||||
# logior
|
||||
|
||||
(logior n1 ...)
|
||||
|
||||
Returns the integer which is the bitwise-OR of the arguments.
|
||||
|
||||
Example: ``(number->string (logior #b1100 #b1010) 2) => "1110"``
|
||||
|
||||
# bitwise-ior
|
||||
|
||||
Synonym for ``logior``.
|
||||
|
||||
# logxor
|
||||
|
||||
(logxor n1 ...)
|
||||
|
||||
Returns the integer which is the bitwise-XOR of the arguments.
|
||||
|
||||
Example: ``(number->string (logxor #b1100 #b1010) 2) => "110"``
|
||||
|
||||
# bitwise-xor
|
||||
|
||||
Synonym for ``logxor``.
|
||||
|
||||
# lognot
|
||||
|
||||
(lognot n)
|
||||
|
||||
Returns the integer which is the one's-complement of the argument.
|
||||
|
||||
# bitwise-not
|
||||
|
||||
Synonym for ``lognot``.
|
||||
|
||||
# bitwise-if
|
||||
|
||||
(bitwise-if mask n0 n1)
|
||||
|
||||
Returns an integer composed of some bits from ``n0`` and some bits from ``n1``.
|
||||
A bit of the result is taken from ``n0`` if the corresponding bit of ``mask`` is
|
||||
1, and from ``n1`` otherwise.
|
||||
|
||||
# bitwise-merge
|
||||
|
||||
Synonym for ``bitwise-if``.
|
||||
|
||||
# logtest
|
||||
|
||||
(logtest j k)
|
||||
|
||||
Equivalent to ``(not (zero? (logand j k)))``.
|
||||
|
||||
Example: ``(logtest #b0100 #b1011) => #f``
|
||||
|
||||
# any-bits-set?
|
||||
|
||||
Synonym for ``logtest``.
|
||||
|
||||
# logcount
|
||||
|
||||
(logcount n)
|
||||
|
||||
Returns the number of bits in ``n``. If ``n`` is positive, the 1-bits in its
|
||||
binary representation are counted. If negative, the 0-bits in its
|
||||
two's-complement binary representation are counted. If 0, then 0 is returned.
|
||||
|
||||
Example: ``(logcount #b10101010) => 4``
|
||||
|
||||
# bit-count
|
||||
|
||||
Synonym for ``logcount``.
|
||||
|
||||
# integer-length
|
||||
|
||||
(integer-length n)
|
||||
|
||||
Returns the number of bits necessary to represent ``n``.
|
||||
|
||||
Example: ``(integer-length #b1011) => 4``
|
||||
|
||||
# log2-binary-factors
|
||||
|
||||
(log2-binary-factors n)
|
||||
|
||||
Returns the bit-index of the least-significant 1-bit in ``n``. If ``n`` contains
|
||||
no 1-bits, -1 is returned.
|
||||
|
||||
Example: ``(log2-binary-factors 4) => 2``
|
||||
|
||||
# first-set-bit
|
||||
|
||||
Synonym for ``log2-binary-factors``
|
||||
|
||||
# logbit?
|
||||
|
||||
(logbit? index n)
|
||||
|
||||
Equivalent to ``(logtest (exact (expt 2 index)) n)``.
|
||||
|
||||
Example: ``(logbit? 1 #b1101) => #f``
|
||||
|
||||
# bit-set?
|
||||
|
||||
Synonym for ``logbit?``.
|
||||
|
||||
# copy-bit
|
||||
|
||||
(copy-bit index from bit)
|
||||
|
||||
Returns ``from``, except in the ``index``th bit, which is 1 if ``bit`` is #t,
|
||||
and 0 if ``bit`` is #f.
|
||||
|
||||
Example: ``(number->string (copy-bit 2 #b1111 #f) 2) => "1011"``
|
||||
|
||||
# bit-field
|
||||
|
||||
(bit-field n start end)
|
||||
|
||||
Returns the integer composed of the ``start`` (inclusive) through ``end``
|
||||
(exclusive) bits of ``n``. The ``start``th bit becomes the 0th bit in the
|
||||
result.
|
||||
|
||||
Example: ``(number->string (bit-field #b1101101010 0 4) 2) => "1010"``
|
||||
|
||||
# copy-bit-field
|
||||
|
||||
(copy-bit-field to from start end)
|
||||
|
||||
Returns ``to``, except possibly in the ``start`` (inclusive) through ``end``
|
||||
(exclusive) bits, which are the same as those of ``from``. The 0th bit of
|
||||
``from`` becomes the ``start``th bit of the result.
|
||||
|
||||
Example: ``(number->string (copy-bit-field #b1101101010 0 0 4) 2) =>
|
||||
"1101100000"``
|
||||
|
||||
# ash
|
||||
|
||||
(ash n count)
|
||||
|
||||
Equivalent to ``(exact (floor (* n (expt 2 count))))``.
|
||||
|
||||
Example: ``(number->string (ash #b1010 -1) 2) => "101"``
|
||||
|
||||
# arithmetic-shift
|
||||
|
||||
Synonym for ``ash``.
|
||||
|
||||
# rotate-bit-field
|
||||
|
||||
(rotate-bit-field n count start end)
|
||||
|
||||
Returns ``n`` with the bit-field from ``start`` to ``end`` cyclically permuted
|
||||
by ``count`` bits towards high-order.
|
||||
|
||||
Example: ``(number->string (rotate-bit-field #b0100 3 0 4) 2) => "10"``
|
||||
|
||||
# reverse-bit-field
|
||||
|
||||
(reverse-bit-field n start end)
|
||||
|
||||
Returns ``n`` with the order of bits ``start`` to ``end`` reversed.
|
||||
|
||||
Example: ``(number->string (reverse-bit-field #b10100111 0 8) 2) =>
|
||||
"11100101")``
|
||||
|
||||
# integer->list
|
||||
|
||||
(integer->list k)
|
||||
|
||||
(integer->list k len)
|
||||
|
||||
Returns a list of ``len`` booleans corresponding to each bit of the non-negative
|
||||
integer ``k``. ``#t`` is coded for each 1; ``#f`` for each 0. ``len`` defaults
|
||||
to ``(integer-length k)``.
|
||||
|
||||
# list->integer
|
||||
|
||||
(list->integer list)
|
||||
|
||||
Returns an integer formed from the booleans in ``list``, which must consist only
|
||||
of booleans. A 1 bit is coded for each ``#t``; a 0 bit for each ``#f``.
|
||||
``integer->list`` and ``list->integer`` are inverses up to ``equal?``: thus, for
|
||||
any ``x``, ``(equal x (integer->list (list->integer x))) => #t``.
|
||||
|
||||
# booleans->integer
|
||||
|
||||
(booleans->integer b1 ...)
|
||||
|
||||
Equivalent to ``(list->integer (list b1 ...))``.
|
||||
|
||||
[1]: http://srfi.schemers.org/srfi-60/srfi-60.html
|
|
@ -11,6 +11,18 @@ Hash tables are widely recognised as a fundamental data structure for a wide var
|
|||
|
||||
See the [SRFI document](http://srfi.schemers.org/srfi-69/srfi-69.html) for more information.
|
||||
|
||||
## Limitations
|
||||
|
||||
Hash table size must be strictly less than 536,870,909.
|
||||
|
||||
The default implementation of record hashing is severely suboptimal - if you
|
||||
want to store records in a hash table, use a custom hashing function.
|
||||
|
||||
This implementation does not distinguish ``hash`` and ``hash-by-identity``.
|
||||
Additionally, symbol hashing is done by string-hashing the result of
|
||||
``symbol->string`` on the symbol, making symbols identical to strings for the
|
||||
purpose of hash table key performance.
|
||||
|
||||
## Type constructors and predicate
|
||||
[`make-hash-table`](#make-hash-table)
|
||||
[`hash-table?`](#hash-table)
|
||||
|
|
83
srfi/60.scm
83
srfi/60.scm
|
@ -1,23 +1,32 @@
|
|||
;;; "60.scm", bit access and operations for integers for Scheme
|
||||
;;; Copyright (C) 1991, 1993, 2001, 2003, 2005 Aubrey Jaffer
|
||||
;;; Copyright (C) 2017 Koz Ross
|
||||
;
|
||||
;Permission to copy this software, to modify it, to redistribute it,
|
||||
;to distribute modified versions, and to use it for any purpose is
|
||||
;granted, subject to the following restrictions and understandings.
|
||||
;
|
||||
;1. Any copy made of this software must include this copyright notice
|
||||
;in full.
|
||||
;
|
||||
;2. I have made no warranty or representation that the operation of
|
||||
;this software will be error-free, and I am under no obligation to
|
||||
;provide any services, by way of maintenance, update, or otherwise.
|
||||
;
|
||||
;3. In conjunction with products arising from the use of this
|
||||
;material, there shall be no use of my name in any advertising,
|
||||
;promotional, or sales literature without prior written consent in
|
||||
;each case.
|
||||
|
||||
#|
|
||||
| Copyright (c) 1991, 1993, 2001, 2003, 2005 Aubrey Jaffer
|
||||
| Copyright (c) 2017, Koz Ross
|
||||
|
|
||||
| All rights reserved.
|
||||
|
|
||||
| Redistribution and use in source and binary forms, with or without
|
||||
| modification, are permitted provided that the following conditions are met:
|
||||
| * Redistributions of source code must retain the above copyright
|
||||
| notice, this list of conditions and the following disclaimer.
|
||||
| * Redistributions in binary form must reproduce the above copyright
|
||||
| notice, this list of conditions and the following disclaimer in the
|
||||
| documentation and/or other materials provided with the distribution.
|
||||
| * Neither the name of Cyclone nor the
|
||||
| names of its contributors may be used to endorse or promote products
|
||||
| derived from this software without specific prior written permission.
|
||||
|
|
||||
| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
| ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
| DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|#
|
||||
|
||||
(define-c raw-logand
|
||||
"(void* data, int argc, closure _, object k, object x, object y)"
|
||||
"Cyc_check_int(data, x);
|
||||
|
@ -99,16 +108,24 @@
|
|||
|
||||
(define bit-count logcount)
|
||||
|
||||
(define (integer-length x)
|
||||
(exact (ceiling (log (+ x 1) 2))))
|
||||
(define-c integer-length
|
||||
"(void* data, int argc, closure _, object k, object x)"
|
||||
"Cyc_check_int(data, x);
|
||||
int input = (int)unbox_number(x);
|
||||
int res = 0;
|
||||
while (input) {
|
||||
res++;
|
||||
input >>= 1;
|
||||
};
|
||||
return_closcall1(data, k, obj_int2obj(res));")
|
||||
|
||||
(define (log2-binary-factors n)
|
||||
(- (integer-length (logand n (- n))) 1))
|
||||
(- (integer-length (raw-logand n (- n))) 1))
|
||||
|
||||
(define first-set-bit log2-binary-factors)
|
||||
|
||||
(define (logbit? index n)
|
||||
(logtest (exact (expt 2 index)) n))
|
||||
(logtest (ash 1 index) n))
|
||||
|
||||
(define bit-set? logbit?)
|
||||
|
||||
|
@ -126,8 +143,22 @@
|
|||
(ash from start)
|
||||
to))
|
||||
|
||||
(define (ash x y)
|
||||
(exact (floor (* x (expt 2 y)))))
|
||||
(define-c ash
|
||||
"(void* data, int argc, closure _, object k, object x, object y)"
|
||||
"Cyc_check_int(data, x);
|
||||
Cyc_check_int(data,y);
|
||||
int bf = (int)unbox_number(x);
|
||||
int shift = (int)unbox_number(y);
|
||||
if (shift > 0) {
|
||||
for (int i = 0; i < shift; i++) {
|
||||
bf *= 2;
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < abs(shift); i++) {
|
||||
bf /= 2;
|
||||
}
|
||||
}
|
||||
return_closcall1(data, k, obj_int2obj(bf))")
|
||||
|
||||
(define arithmetic-shift ash)
|
||||
|
||||
|
|
|
@ -10,8 +10,8 @@
|
|||
;;;; doesn't have them yet. This will need to be modified accordingly once
|
||||
;;;; this support is provided.
|
||||
(define-library (srfi 60)
|
||||
(import (scheme base)
|
||||
(scheme inexact))
|
||||
(import
|
||||
(scheme base))
|
||||
(export
|
||||
any-bits-set? arithmetic-shift ash
|
||||
bit-count bit-field bit-set? bitwise-and bitwise-if bitwise-ior
|
||||
|
|
Loading…
Add table
Reference in a new issue