Shawn Wagner <shawnw.mobile@gmail.com>
While Racket comes with a number of SRFI libraries, it’s missing quite a lot of useful ones. This collection adds some.
A note on licensings: Most of the included SRFIs are the reference implementations adapted to Racket, and retain the original licenses.
Typical changes to the reference versions include adding contracts and removing now-redundant type checking, avoiding things Scheme allows that Racket doesn’t like if missing an else clause, reorganization of source files, etc.
Modules that are noted as providing an unsafe option have a submodule named unsafe that exports functions without contracts and potentially other run time checks. Passing those functions invalid or out of range arguments can have unpredictable results. Use with caution.
Imports SRFI-1 functions into a Shallow Typed Racket module. Circular and dotted lists aren’t always accepted where the documentation says they should be; I still need to work out if it’s even possible to represent a circular list in TR.
The linear update procedures ending with a ! are just aliases for the normal ones, thanks to Racket’s immutable cons cells. This behavior is allowed by the SRFI.
SRFI-1 for mutable lists. Procedures have the same name with an m prepended, except ones with list or pair in the name, which turns into mlist or mpair. So, for example, make-mlist, not-mpair? and mxcons.
Also available in an unsafe module with (require (submod srfi/1munsafe)).
lst:list?
procedure
( mlist->listmlst)→list?
mlst:proper-mlist?
Notes: While Racket comes with a SRFI-13 implementation, it’s only for normal Racket, not Typed Racket. This module can be used instead of having to "require/typed" specific functions from it that you might need in Typed Racket.
Notes: While Racket comes with a SRFI-27 implementation, it’s only for normal Racket, not Typed Racket. This module can be used instead of having to "require/typed" specific functions from it that you might need in Typed Racket.
Notes: The version of this module in srfi-lib is just the reference implementation and has, as of Racket 8.15, a serious bug in that the "native" endianness is always big-endian. This, besides being having a version written in Typed Racket, fixes that, and uses a more Racket-specific implementation. You should probably use always use this one, at least until the bug is fixed.
While Racket comes with a SRFI-87 implementation in srfi-lib, trying to use it causes syntax errors. This version actually works, and it follows the Racket convention of using equal? instead of eqv? to test values in case .
Racket natively supports SRFI-111 single-valued boxes, but this module re-exports SRFI-195 versions of functions to comply with that document.
Notes: (os-version) always returns #f, but the other functions are all implemented.
The SRFI uses normal lists, which are immutable in Racket. Therefore, this implemention uses mutable lists of mcons pairs. The single argument form of make-list-queue and two argument form of list-queue-set-list! can be passed normal lists, though. list-queue-list returns a mutable list.
Also available in an unsafe module with (require (submod srfi/117unsafe)).
procedure
( in-list-queuelq)→sequence?
lq:list-queue?
Notes: The lazy sequences described in the SRFI are built on normal, mutable Scheme cons cells. Racket cons cells are in theory immutable, so this implementation instead uses mcons cells; lists of which aren’t compatible with list functions. There’s a few extra functions to help make that easier to work with, as well as the srfi/1m module.
lst:list?
val:any/c
procedure
( in-lseqlseq)→sequence?
lseq:lseq?
Reference documentation. Also includes SRFI-162 Comparators sublibrary and SRFI-228 Composing Comparators routines and variables.
The make-eq-comparator, make-eqv-comparator, make-equal-comparator and make-equal-always functions return comparators using the standard Racket eq-hash-code etc. hash functions instead of default-hash.
make-comparator takes an optional keyword argument, "#:secondary-hash", whose value has the same signature as the "hash" one - either (-> any/c exact-integer? ) or #f. This is used for better compability with Racket’s custom hash tables, which take two hash functions. Hash functions can also return negative numbers, contrary to the SRFI spec.
Comparators can be used as flat contracts (And thus predicates) that test their argument against their type test predicate.
cmp:comparator?
procedure
( comparator-secondary-hashcmpobj)→exact-integer?
cmp:comparator?obj:any/c
vector-sort and vector-sort! conflict with the ones in racket/vector - the order of the vector and ordering predicate is reversed.
The side-effect-enabled list functions list-merge! and list-delete-neighbor-dups! currently use unsafe-immutable-set-cdr! to modify the lists in place. The test cases pass, but if this becomes an issue in practice (The function has lots of warnings attached), I’ll switch them to just being aliases for the non-side-effect versions.
Available as an unsafe module via (require (submod srfi/132unsafe)).
See also SRFI-43 included with Racket. Notable differences are functions that take callbacks not passing the current index like they do in 43.
Also available in a Typed Racket version and an unsafe version as (require (submod srfi/133unsafe)).
Notes:
Deques are equal? if they are the same length and all corresponding elements are equal? .
Deques are streams and sequences.
As of Racket 8.13, implemented with treelists instead of the banker’s deque reference implementation.
Extra functions:
procedure
( in-idequedq)→sequence?
dq:ideque?
procedure
( in-ideque-backwardsdq)→sequence?
dq:ideque?
Notes:
This module is equivalent to the R7RS (srfi140istrings) library. The other variations laid out in the SRFI are not present. The mutable string functions string-append! and string-replace!, which require resizable strings, are not provided.
Extra functions:
Stuff used by the UTF-16 conversion routines that might be more broadly useful.
procedure
( string-utf-16-lengths[startend])→exact-nonnegative-integer?
s:string?
b:bytes?
If big-endian? is ' check-bom and there is no BOM present, the native system endianness is used.
b:bytes?
Notes:
The functions in the typed version are constrained to only take and return exact integers. The regular package’s will accept inexact integers. The typed module also has Fixnum versions with a "fx" prefix - fxfloor/, for example.
struct
#:extra-constructor-namemake-exn:fail:contract:assume#:transparent)
mapping? objects are also ordered-dict? s and many functions in this module can be used with other ordered dicts or even unordered-ones for operations where order doens’t matter. The mapping implementation uses scapegoat trees.
The current make-mapping-comparator and mapping-comparator do not provide ordering.
The linear update versions of functions with names ending in !, if passed an external dict object that supports side effect operations, will update it in place and return it. If passed an immutable dict, they will just return a new object like the non-linear versions. Basically, as long as you follow the guideline of never using a particular dict object again after passing it to a linear update function, everything will Just Work no matter what.
Additional functions:
procedure
( in-ordered-dictod[starting-pos])→sequence?
procedure
( in-ordered-dict-keysod[starting-pos])→sequence?
procedure
( in-ordered-dict-valuesod[starting-pos])→sequence?
hashmap? objects are also dict? s and many functions in this module can be used with other types of dicts. The hashmap implementation uses Racket’s immutable hash tables, but also support mutable side-effect functionality.
Notes:
Written in Typed Racket. Hopefully the type signatures should be obvious and intuitive. If performance matters, code that uses these routines should also be written in Typed Racket.
Reference documentation. Also includes SRFI-221 Generator/accumulator sub-library routines.
These generators are not compatible with the ones in "racket/generator". There is an adaptor function provided to wrap Racket generators in SRFI-158 ones, but beware of conflicting generator identifiers in the two modules.
Available as an unsafe module via (require (submod srfi/158unsafe)).
procedure
( generator? obj)→boolean?
obj:any/c
procedure
( sequence->generator s)→(-> any/c )
Reference documentation. In addition to all the numeric types in the SRFI, functions for flvector and fxvector vectors are also provided, with a "fl" and "fx" prefix respectively. If Racket CS ever gains support for 80-bit extflonum? numbers on x86, I’ll add support for extflvector? and f80vector? vectors too (And might adjust the f32vector? contracts to explicitly work with single-flonum? values if CS ever gets them).
All these modules have an unsafe submodule.
Additional functions for converting between flvectors and SRFI-4 vectors:
procedure
( flvector->f32vectorfl[startend])→f32vector?
fl:flvector?
procedure
( flvector->f64vectorfl[startend])→f64vector?
fl:flvector?
procedure
( f32vector->flvectorf32[startend])→flvector?
f32:f32vector?
procedure
( f64vector->flvectorf64[startend])→flvector?
f64:f64vector?
Additional functions:
procedure
( in-@vectorvec[startend])→sequence?
vec:@vector?
Notes: The bytevector-u8-* functions have been renamed bytes-* to better match Racket conventions, though the original names are still available as aliases.
Available as an unsafe module via (require (submod srfi/171unsafe)).
Additional functions:
procedure
( set-transducexformfset)→any/c
xform:procedure?set:set?xform:procedure?identity:any/cset:set?
procedure
( treelist-transducexformftl)→any/c
xform:procedure?tl:treelist?xform:procedure?identity:any/ctl:treelist?
procedure
( hash-transducexformfht)→any/c
xform:procedure?ht:hash?xform:procedure?identity:any/cht:hash?
procedure
( sequence-transducexformfseq)→any/c
xform:procedure?seq:sequence?xform:procedure?identity:any/cseq:sequence?
Notes: A hook object is callable as a procedure; (hook-objargs... ) is the same as (hook-runhook-objargs... ).
Notes:
Implemented as a distinct type (A transparent structure), with the range of the seconds values the same as the range of Racket integers.
timespec-hash uses equal-hash-code and might return negative values contrary to the SRFI description of the function.
What the SRFI documentation calls a bytevector is what Racket calls a byte string.
Available as an unsafe module via (require (submod srfi/175unsafe)).
You can never have too many JSON parsers available for a language.
Notes: The yield syntax conflicts with "racket/generator".
Notes:
The heuristics for telling if a command or script or neither is being executed could probably stand to be improved.
The command-line procedure conflicts with the one in "racket/cmdline".
Notes:
Written in Typed Racket.
make-ellipsoid-generator, make-ball-generator and make-sphere-generator have variants flmake-ellipsoid-generator, flmake-ball-generator and flmake-sphere-generator that return flvectors. The ellipsoid generator functions can take a flvector or a vector of reals. The ball generator functions can take a flvector, vector of reals, or an integer.
Notes:
Native Racket single-valued boxes are accepted by these functions, and multiple-valued boxes of arity 1 created by this SRFI’s box use them.
Multiple-valued boxes can be compared and hashed with equal? . The usual caveats about modifying a box used as a key in a hash table apply.
A match expander to use multiple-valued boxes in match clauses.
procedure
( box-immutable arg...)→box?
arg:any/c
Notes: The "range" function from this module conflicts with the one from "racket/list".
procedure
( range-empty?r)→boolean?
r:range?
procedure
( in-range-objectr)→sequence?
r:range?
Notes:
The reference implementations for this SRFI include one for Racket, but this one is original, using syntax-parse macros. It’s also a lot simpler, which makes me wonder, but it passes all the test cases...
Uses match style pattern matching.
The u8"..." reader syntax and I/O functions are not supported.
Available in an unsafe version as (require (submod srfi/207unsafe)).
Notes:
Currently only works with double-precision flonums, though the SRFI allows for other floating point types. While Racket BC supports single precision flonums, Racket CS doesn’t, and I don’t have a version of CS installed that supports extflonums (maybe it doesn’t support them at all either?). If either condition changes I might go back and add support for those types.
The main difference between the untyped and typed versions are that the former includes NaN checking of arguments in the contracts; the typed one has an explicit check to raise an error if passed a non-NaN number. I might remove that check in the future and just say it’s undefined what happens when they’re passed a non-NaN.
Notes:
apply/mv, call/mv, and with-values have been extended to work with Racket’s keyword arguments by taking optional keyword+value arguments after the last documented ones that are passed to the consumer procedure. For example,
The forms and functions that take/return boxes use SRFI-195 multiple-value ones.
procedure
( bind/vectorvectransducer...)→any
vec:vector?transducer:procedure?
Notes: The impelmentation is built on "data/gvector" and flexvectors are also gvector s.
procedure
( flexvector->bytesfv[startend])→bytes?
procedure
( in-flexvectorfv)→sequence?
fv:flexvector?
"iset" objects also support the Racket gen:set interface and can be used with "racket/set" functions. The set-theory functions like set-union only work when all sets are isets (The same restriction applies to other types of sets).
They also support equal? and are hashable so they can be used as keys in hash tables and sets. The usual warnings about mutating such sets apply.
The reference implementation, using Patricia trees, is currently being used. I’m considering replacing it with one that can more compactly store ranges of numbers.
Available as an unsafe module via (require (submod srfi/217unsafe)).
Reference documentation. This and the following modules are written in Typed Racket.
SRFI-223 procedures specialized for byte strings.
SRFI-223 procedures specialized for flvectors.
SRFI-223 procedures specialized for fxvectors.
"fxmapping" objects support the gen:dict interface and can thus be used with "racket/dict" functions. They also support equal? and are hashable so they can be used as keys in hash tables and sets. The usual warnings about mutating values stored in such mappings apply.
Available as an unsafe module via (require (submod srfi/224unsafe)).
Notes:
The conjoin and disjoin functions conflict with the ones in "racket/function" and group-by with the one in "racket/list".
case-procedure uses equal? to compare values instead of eqv? to match Racket’s case .
Procedures that take or return procedures that take arbitary arguments will work with keyword arguments for the most part.
The only predefined codeset is ' errno with POSIX errno values.
Normally you’d use match in Racket, but this is a lightweight alternative when just dealing with lists.
Just repackages (And renames) standard Racket functions. Intended to help with porting code to Racket.
name : identifier?constructor-name : identifier?predicate-name : identifier?accessor-name : identifier?