Merge pull request #175 from kozross/master

Documentation for new SRFIs, some small code changes
This commit is contained in:
Justin Ethier 2017-02-10 12:40:34 -05:00 committed by GitHub
commit 21f54914b5
8 changed files with 835 additions and 31 deletions

View file

@ -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
View 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

View file

@ -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
View 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
View 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

View file

@ -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)

View file

@ -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)

View file

@ -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