R7RS Compatibility
Sigil implements most of R7RS Small, with practical extensions. This page lists what works, what works with differences, and what is missing, as of Sigil 0.22.8.
Where R7RS Names Live
Sigil does not provide the (scheme ...) library names: (import (scheme base)) fails with "library not found". The R7RS procedures live in Sigil's own modules:
(sigil core), which every program and library sees without an import, has most of(scheme base),(scheme case-lambda),(scheme char),(scheme lazy)and(scheme write).(sigil io)has the port procedures that read and write characters, strings, bytes and bytevectors, string and bytevector ports, and file ports.(sigil math)has(scheme inexact):sqrt,exp,log, the trigonometric functions,finite?,infinite?andnan?. It also re-exports the(scheme base)math procedures that core has, such asfloorandquotient.(sigil string)has the case-insensitivestring-cicomparisons.(sigil process),(sigil time)and(sigil fs)have the process-context, time and file-system procedures.
Tables on this page say "in (sigil io)" and so on where a name is not in core.
R7RS Libraries
| Library | Status | Notes |
|---|---|---|
(scheme base) | Mostly supported | Gaps are listed in the tables below |
(scheme case-lambda) | Complete | |
(scheme char) | Partial | char-alphabetic?, char-numeric?, char-whitespace? and digit-value are ASCII-only; comparisons take exactly two arguments; string-ci comparisons are in (sigil string) |
(scheme complex) | Not provided | Sigil has no complex numbers |
(scheme cxr) | Partial | Only caadr, cadar, caddr, cdadr, cdddr and cadddr of the 24 |
(scheme eval) | Partial | eval works; environment is missing |
(scheme file) | Mostly supported | In (sigil io) and (sigil fs); with-input-from-file and with-output-to-file do not redirect the current ports |
(scheme inexact) | Complete | In (sigil math) |
(scheme lazy) | Complete | |
(scheme load) | Complete | |
(scheme process-context) | Partial | In (sigil process); get-environment-variable is missing (use getenv); exit and emergency-exit treat #f as success; exit does not run dynamic-wind after thunks |
(scheme read) | Complete | read is in (sigil io) |
(scheme time) | Complete | In (sigil time) |
(scheme write) | Mostly supported | write-shared and write-simple work; write prints floats with 6 digits and labels shared structure that has no cycle (see the notes under I/O) |
(scheme r5rs) | Not provided |
Import Modifiers
All R7RS import set modifiers are supported in both define-library and top-level import forms:
| Modifier | Description |
|---|---|
(only <import-set> <id> ...) | Import only the listed identifiers |
(except <import-set> <id> ...) | Import all except the listed identifiers |
(prefix <import-set> <prefix>) | Add a prefix to all imported names |
(rename <import-set> (<old> <new>) ...) | Rename specific identifiers |
Modifiers compose through nesting, e.g. (prefix (only (sigil math) sqrt exp) m:).
Intentionally Omitted
Sigil prioritizes practical utility over numeric tower completeness:
No Exact Rationals
Sigil has integers (fixnums and bignums) and floating-point numbers, but no rational number type:
;; Other Schemes:
(/ 1 3) ; => 1/3 (exact rational)
;; Sigil:
(/ 1 3) ; => 0.333... (inexact float)numerator, denominator and rationalize work on floats and return inexact results for fractional values.
No Complex Numbers
The (scheme complex) library is not provided. complex? and real? are the same as number?.
No R5RS Compatibility Library
The (scheme r5rs) library is not provided. The R5RS names exact->inexact and inexact->exact are in core.
(scheme base) Coverage
Control Flow
| Feature | Status |
|---|---|
if, and, or, when, unless, begin | Supported |
cond | Partial: a clause with only a test returns an undefined value instead of the test's value |
case | Partial: => in a clause is not supported |
let, let*, letrec | Supported |
letrec* | Partial: a lambda that refers to a later binding fails, as with let* |
do | Partial: a binding without a step fails to expand |
call/cc, call-with-current-continuation | Supported. Two call/cc forms in one expression whose receivers both return normally give a wrong result |
values | Supported |
call-with-values | Partial: a native procedure as the producer raises "apply: not a procedure" |
let-values, let*-values, define-values | Partial: proper formals only; dotted and single-symbol formals fail to expand |
guard, raise, raise-continuable | Supported |
with-exception-handler | Partial: when the handler returns from a non-continuable raise, raise returns the handler's value instead of raising a secondary exception |
dynamic-wind | Supported |
cond-expand | Partial: (and ...) with more than one requirement, (or ...) and (and) take the else branch |
syntax-error | Partial: the error happens at run time as "call: not a procedure", not at expansion |
features | Supported |
Procedures
| Feature | Status |
|---|---|
lambda, define | Supported |
apply | Supported |
map, for-each (multi-list) | Supported |
make-parameter | Supported |
parameterize | Partial: with a converter, the converter is applied again when the outer value is restored |
Numeric
| Feature | Status |
|---|---|
+, -, *, / | Supported |
=, <, >, <=, >= | Supported |
abs, remainder, modulo | Supported |
quotient, gcd, lcm | Partial: they reject inexact integers such as 7.0 |
floor, ceiling, truncate | Supported |
round | Partial: rounds halves away from zero ((round 2.5) is 3.0); R7RS rounds halves to even |
floor/, floor-quotient, floor-remainder | Supported |
truncate/, truncate-quotient, truncate-remainder | Supported |
max, min | Partial: no inexact contagion ((max 3 2.0) is 3) |
expt, square, exact-integer-sqrt | Supported |
exact, inexact, exact?, inexact?, exact-integer? | Supported |
number?, complex?, real?, rational? | Supported |
integer? | Supported |
numerator, denominator, rationalize | Supported, with inexact results for fractional values |
sqrt, exp, log, sin, cos, tan, asin, acos, atan | Supported, in (sigil math) |
number->string | Partial: a float with no fractional part loses its .0 ((number->string 1.0) is "1") |
string->number | Partial: radix prefixes are not parsed ((string->number "#xff") is #f) |
Lists and Pairs
| Feature | Status |
|---|---|
cons, car, cdr, set-car!, set-cdr! | Supported |
pair?, null?, list? | Supported |
list, make-list, length | Supported |
append, reverse, list-tail, list-ref | Supported |
list-set!, list-copy | Supported |
memq, memv, assq, assv | Supported |
member, assoc | Partial: the three-argument form with a comparison procedure is not supported |
Booleans and Symbols
| Feature | Status |
|---|---|
not, boolean?, boolean=? | Supported |
symbol?, symbol=? | Supported |
symbol->string, string->symbol | Supported |
Strings
| Feature | Status |
|---|---|
string, make-string, string-length | Supported |
string-ref, string-set! | Supported |
string<?, string<=?, string>?, string>=? | Supported |
string=? | Partial: exactly two arguments |
string-upcase, string-downcase, string-foldcase | Supported |
string-append, substring | Supported |
string->list | Partial: no start and end arguments |
list->string | Supported |
string-copy, string-copy! | Supported |
string-fill! | Supported |
string-map, string-for-each | Partial: one string only |
vector->string, string->vector | Supported |
Vectors
| Feature | Status |
|---|---|
vector, make-vector, vector-length | Supported |
vector-ref, vector-set! | Supported |
vector->list, list->vector | Supported |
vector-copy, vector-copy!, vector-append | Supported |
vector-fill! | Supported |
vector-map, vector-for-each | Partial: one vector only |
Bytevectors
| Feature | Status |
|---|---|
bytevector?, make-bytevector, bytevector | Supported |
bytevector-length | Supported |
bytevector-u8-ref, bytevector-u8-set! | Supported |
bytevector-copy, bytevector-copy! | Supported |
bytevector-append | Supported |
utf8->string, string->utf8 | Supported, in (sigil io) |
Error Objects
| Feature | Status |
|---|---|
error | Supported |
error-object? | Supported |
error-object-message | Supported |
error-object-irritants | Supported |
error-object-type | Supported |
file-error?, read-error? | Partial: both return #f for the errors that failing file opens and read raise |
I/O
| Feature | Status |
|---|---|
read-char, peek-char, write-char | Supported, in (sigil io) |
read-line, read-string | Supported, in (sigil io) |
read-u8, peek-u8, write-u8 | Supported, in (sigil io) |
read-bytevector, read-bytevector! | Supported, in (sigil io) |
write-string, write-bytevector | Partial, in (sigil io): no start and end arguments |
char-ready?, u8-ready? | Supported, in (sigil io) |
write, display, newline | Supported; see the notes on write below |
current-input-port, current-output-port, current-error-port | Supported |
open-input-file, open-output-file | Supported, in (sigil io) |
close-port, close-input-port, close-output-port | Supported |
call-with-port | Supported |
open-output-string, get-output-string | Supported |
open-input-string | Supported, in (sigil io) |
open-input-bytevector, open-output-bytevector, get-output-bytevector | Supported, in (sigil io) |
input-port?, output-port?, textual-port?, binary-port?, port? | Supported |
input-port-open?, output-port-open? | Supported |
eof-object, eof-object? | Supported |
flush-output-port | Supported, in (sigil io) |
Notes on write:
- It prints floats with 6 significant digits (
(write (/ 1.0 3))prints0.333333), so a written float may not read back as the same number.number->stringkeeps full precision. - It uses datum labels for shared structure even when there is no cycle: a list holding the same sublist twice prints as
(#0=(1 2) #0#).write-simpleprints no labels. - It writes printable non-ASCII text as itself, so
(write "λ")prints"λ". Control characters and invisible formatting characters (zero-width spaces, bidi controls, the byte order mark) print as one escape per character, such as\x1B;or\x202E;, and a byte that is not valid UTF-8 as\x<byte>;, which reads back as the character with that number. Everything elsewriteprints for a string reads back as the same string. Before 0.22.13 it wrote each UTF-8 byte as\xHHwith no;, whichreadrejected. #\λreads as one character; a non-ASCII character is written as#\x3BB.
Records
| Feature | Status |
|---|---|
define-record-type | Not implemented; (sigil record) has Sigil's record syntax |
Macros
| Feature | Status |
|---|---|
define-syntax, syntax-rules | Supported |
| Procedural macros (lambda transformers) | Supported |
let-syntax, letrec-syntax | Not implemented |
(scheme char) Coverage
| Feature | Status |
|---|---|
char? | Supported |
char=?, char<?, char>?, char<=?, char>=? | Partial: exactly two arguments |
char->integer, integer->char | Supported |
char-alphabetic?, char-numeric?, char-whitespace? | Partial: ASCII only ((char-alphabetic? #\λ) is #f, and a no-break space is not whitespace) |
char-upper-case?, char-lower-case? | Supported |
char-upcase, char-downcase, char-foldcase | Supported |
char-ci=?, char-ci<?, char-ci>?, char-ci<=?, char-ci>=? | Partial: exactly two arguments |
digit-value | Partial: ASCII digits only |
string-upcase, string-downcase, string-foldcase | Supported |
string-ci=?, string-ci<?, string-ci>?, string-ci<=?, string-ci>=? | Partial, in (sigil string): exactly two arguments |
Feature Identifiers
The features procedure returns a list of supported feature identifiers for use with cond-expand:
(features)
; => (r7rs sigil linux posix unix x86-64 lp64 64bit little-endian)Available features:
r7rs- R7RS compliancesigil- Sigil implementation- Platform:
linux,darwin,windows,freebsd,openbsd,netbsd - POSIX:
posix,unix(on Unix-like systems) - Architecture:
x86-64,aarch64,arm,i386,riscv - Data model:
ilp32,lp64 - Word size:
32bit,64bit - Endianness:
little-endian,big-endian
Sigil Extensions
Sigil provides additional features beyond R7RS:
Pattern Matching
(import (sigil match))
(match value
((a b c) (list a b c))
((x . rest) rest)
(_ 'default))Keywords
Keyword arguments in procedures:
(define (greet name: "World" times: 1)
(do ((i 0 (+ i 1)))
((= i times))
(display "Hello, ")
(display name)
(newline)))
(greet name: "Sigil" times: 3)Additional Modules
(sigil core)- Extended list operations,filter-map,fold-left, etc.(sigil json)- JSON parsing and generation(sigil http)- HTTP client and server(sigil socket)- TCP/UDP networking(sigil process)- Process spawning(sigil path)- Path manipulation(sigil fs)- File system operations(sigil time)- Date and time(sigil channels)- CSP-style concurrency
See the Library Reference for complete documentation.
Porting from Other Schemes
Replace (scheme ...) imports with Sigil modules. Most code needs no import at all for (scheme base), because (sigil core) is always available; add (sigil io), (sigil math) or (sigil string) for the names listed above.
From Guile
Guile modules map directly:
;; Guile
(use-modules (ice-9 match))
;; Sigil
(import (sigil match))From Racket
Racket's #lang is not supported. Convert to standard module syntax:
;; Racket
#lang racket
(define (foo x) x)
;; Sigil
(define-library (my-module)
(export foo)
(import (sigil core))
(begin
(define (foo x) x)))From Chicken
SRFI libraries are not bundled: (import (srfi srfi-1)) fails with "library not found". Core has list procedures with SRFI-1 names, but some differ from SRFI-1:
foldcalls its procedure as(proc acc elem), so(fold cons '() '(1 2 3))gives(((() . 1) . 2) . 3).removetakes an item to remove, not a predicate.anyreturns#t, not the true value its predicate returned.