From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mp10.migadu.com ([2001:41d0:8:6d80::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by ms0.migadu.com with LMTPS id 8Oz0IyCICWK2ywAAgWs5BA (envelope-from ) for ; Sun, 13 Feb 2022 23:37:20 +0100 Received: from aspmx1.migadu.com ([2001:41d0:8:6d80::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by mp10.migadu.com with LMTPS id QPbAHCCICWJBNwEAG6o9tA (envelope-from ) for ; Sun, 13 Feb 2022 23:37:20 +0100 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by aspmx1.migadu.com (Postfix) with ESMTPS id 3030E1ACA6 for ; Sun, 13 Feb 2022 23:37:18 +0100 (CET) Received: from localhost ([::1]:59004 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1nJMqZ-00073B-0L for larch@yhetil.org; Sun, 13 Feb 2022 16:55:55 -0500 Received: from eggs.gnu.org ([209.51.188.92]:43444) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1nJMp3-0005mf-Av for guix-patches@gnu.org; Sun, 13 Feb 2022 16:54:23 -0500 Received: from debbugs.gnu.org ([209.51.188.43]:45189) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1nJMoo-0001um-TO for guix-patches@gnu.org; Sun, 13 Feb 2022 16:54:14 -0500 Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1nJMoo-0003Eq-PT for guix-patches@gnu.org; Sun, 13 Feb 2022 16:54:06 -0500 X-Loop: help-debbugs@gnu.org Subject: [bug#53878] [PATCH 11/11] gnu: racket: Update to 8.4. Resent-From: Philip McGrath Original-Sender: "Debbugs-submit" Resent-CC: guix-patches@gnu.org Resent-Date: Sun, 13 Feb 2022 21:54:06 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 53878 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: 53878@debbugs.gnu.org Cc: Liliana Marie Prikler , Philip McGrath Received: via spool by 53878-submit@debbugs.gnu.org id=B53878.164478922112344 (code B ref 53878); Sun, 13 Feb 2022 21:54:06 +0000 Received: (at 53878) by debbugs.gnu.org; 13 Feb 2022 21:53:41 +0000 Received: from localhost ([127.0.0.1]:39077 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1nJMoP-0003D1-Bm for submit@debbugs.gnu.org; Sun, 13 Feb 2022 16:53:41 -0500 Received: from mail-qk1-f172.google.com ([209.85.222.172]:35416) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1nJMoM-0003CY-Si for 53878@debbugs.gnu.org; Sun, 13 Feb 2022 16:53:39 -0500 Received: by mail-qk1-f172.google.com with SMTP id 200so13028879qki.2 for <53878@debbugs.gnu.org>; Sun, 13 Feb 2022 13:53:38 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=philipmcgrath.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=/hZBy6HUA7KdRbSzAale2OMOdr/JyowG+AEK/cK3F+s=; b=P5iCuEc5W+u7r+y2JvEIjebfpI1eBczjYVgheFxh5+MBFiawInD1d+K857Hmbp/5lr GKx0gHRE69Zc3BB9zcVjM+5JhtPzcf0qwL+fwaurpdKLnEN6PUNKK9ugR3RYzbx2K7HC 6bTj1PkRwL1W+XBOslTVBVNEkggZmB6VsJwJ0TcQ9gwKbN7zjVcZnT8itsRFeKqSsG1Z ODXsnYNd7oU6CzEwhqbvh5goru1HwOK0UOk7ndakTINlcHVc31KDS1dGAJoZjn2V05Tp HK49yctVRCEeL5sO5CVcQ8RAr3+guT/uVbLQIRPMb94udXu2C0205cHoRVDicxb5IGd1 FF+Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=/hZBy6HUA7KdRbSzAale2OMOdr/JyowG+AEK/cK3F+s=; b=JiTxK8hFZ/BLRvaKVnNzPxDsRReMxI1fqQDGm238AS+iysVhpBUPef10m+9QkQ1cQ+ 2HS5fa4mhwF1xH6K2YnFWN+MLwkAL9IJqJN8WP5dg8wGZlU5n8PXt8LKJYn/37XWiFBz zUCW2OKekBQgRP5ZsUCeTPvdnP6woGIcQZ2me3JXtB0OlvrxGn0VPzKGRKt7zPpObzRe CHLy7kALDzSyNNRxK6aKT/5kZtrHXmfzIPa9WBt6Ve7QI6yT66mjI2+IgEa0NkXodXll zb+QSU4BJZHCj+hLqXCGWCbqCTbhH53AKxKt/zHv7RgDbWRVr/yRBEC52xE11syBxp7U 0L8g== X-Gm-Message-State: AOAM533YZiUIbleodljlGubOihL8dgqUR6iXFW/XY92Hr5Xl2Gg6GXWR jR94QUmS9ccvfZYYsNzfSmEBGzmGLQnFmxv4NuI= X-Google-Smtp-Source: ABdhPJxBD4R0h9sTxbML3pDtCrRunX8QnNdlzs64vhnKSMjAK88pzS0yyxyBmcN0gJcN1f8RMLQljQ== X-Received: by 2002:a37:6393:: with SMTP id x141mr5749019qkb.197.1644789210864; Sun, 13 Feb 2022 13:53:30 -0800 (PST) Received: from localhost (c-73-125-98-51.hsd1.fl.comcast.net. [73.125.98.51]) by smtp.gmail.com with UTF8SMTPSA id i12sm15592937qkn.83.2022.02.13.13.53.26 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Sun, 13 Feb 2022 13:53:28 -0800 (PST) From: Philip McGrath Date: Sun, 13 Feb 2022 16:51:27 -0500 Message-Id: <20220213215127.218952-12-philip@philipmcgrath.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20220213215127.218952-1-philip@philipmcgrath.com> References: <20220213215127.218952-1-philip@philipmcgrath.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: guix-patches@gnu.org List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guix-patches-bounces+larch=yhetil.org@gnu.org Sender: "Guix-patches" X-Migadu-Flow: FLOW_IN X-Migadu-Country: US ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=yhetil.org; s=key1; t=1644791840; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding:resent-cc: resent-from:resent-sender:resent-message-id:in-reply-to:in-reply-to: references:references:list-id:list-help:list-unsubscribe: list-subscribe:list-post:dkim-signature; bh=/hZBy6HUA7KdRbSzAale2OMOdr/JyowG+AEK/cK3F+s=; b=Ufq9RK7qi4zwo6MRnUugTSCz1BrJV9cz21FnheBNsxPowC3Gjwvtwm5VNf9yVIteOaJAUp OUJHi1b92w0WeBSkU//tZb8HODwx4S5Ke0RyWWseFljJMvRBe3r/TAqCnIEG1OaE7TaNbn 8KWyx64ilsqdpX1BHzBI3c6BwJ/g9umHwqJT8VxeJssgvMM8fTXTF2K0UTl1N1KckiebiR IEWpVRrt4jLRRwvbkcG0HEtG6eDco5wTHYsWePUQMpUTZhQCgGZDSjKs6sQi4l0ccS0N6T GDQFdmt9W2TNcWkBuPbtjhjf6n5IFAXNOV7qttdjX7rlnn/xdyIUs/LEm6aa+Q== ARC-Seal: i=1; s=key1; d=yhetil.org; t=1644791840; a=rsa-sha256; cv=none; b=hcxIYuOFL90+kH1/sNYJTlM0jL5R0Btj3vmyOQ84LRMJ1IQRHFefZga60jo1JdfuaoyEM6 HlegdSCnixZ4nAa5LhQ1D2TAr3W+98CIxQePQszDal9hU7kuF6mUOS9GA7SyO90vtzlLxd 6TebioV9IEnlVJyP3MigyewGZI1hdUnyzTWtIN9CBrdl6nVyPhv1zdpUn0cRMRHUFHYtwQ EmZABqiOnFaj5xpuR7ICs6spN9l/AenVMuA4PZe4nEduXJFxF4tVubJYyqg6y0Hup8siIf vgwWrcJufUe1SApbDB/dDTpCA4csBqDPVMJvxpL0RW62xXX3BDcmXtMp1ySbGQ== ARC-Authentication-Results: i=1; aspmx1.migadu.com; dkim=fail ("headers rsa verify failed") header.d=philipmcgrath.com header.s=google header.b=P5iCuEc5; dmarc=none; spf=pass (aspmx1.migadu.com: domain of "guix-patches-bounces+larch=yhetil.org@gnu.org" designates 209.51.188.17 as permitted sender) smtp.mailfrom="guix-patches-bounces+larch=yhetil.org@gnu.org" X-Migadu-Spam-Score: 5.37 Authentication-Results: aspmx1.migadu.com; dkim=fail ("headers rsa verify failed") header.d=philipmcgrath.com header.s=google header.b=P5iCuEc5; dmarc=none; spf=pass (aspmx1.migadu.com: domain of "guix-patches-bounces+larch=yhetil.org@gnu.org" designates 209.51.188.17 as permitted sender) smtp.mailfrom="guix-patches-bounces+larch=yhetil.org@gnu.org" X-Migadu-Queue-Id: 3030E1ACA6 X-Spam-Score: 5.37 X-Migadu-Scanner: scn1.migadu.com X-TUID: QVyu7yaBuf94 * gnu/packages/patches/racket-gui-tethered-launcher-backport.patch, gnu/packages/patcheches/racket-srfi-fsdg-backport.patch: New patches. * gnu/local.mk (dist_patch_DATA): Add them. * gnu/packages/chez-and-racket-bootstrap.scm (racket-vm-for-system): New procedure. * gnu/packages/racket.scm (racket-minimal, racket): Update to 8.4. Rewrite to use 'racket-vm-for-system', label-less inputs, G-expressions, and Git origins for main-distribution packages. --- gnu/local.mk | 4 +- gnu/packages/chez-and-racket-bootstrap.scm | 11 +- ...acket-gui-tethered-launcher-backport.patch | 26 + .../patches/racket-srfi-fsdg-backport.patch | 41622 ++++++++++++++++ gnu/packages/racket.scm | 1551 +- 5 files changed, 42688 insertions(+), 526 deletions(-) create mode 100644 gnu/packages/patches/racket-gui-tethered-launcher-backp= ort.patch create mode 100644 gnu/packages/patches/racket-srfi-fsdg-backport.patch diff --git a/gnu/local.mk b/gnu/local.mk index 8ffdd15ee2..ff72ad8565 100644 --- a/gnu/local.mk +++ b/gnu/local.mk @@ -41,7 +41,7 @@ # Copyright =C2=A9 2020 Vinicius Monego # Copyright =C2=A9 2021 Bj=C3=B6rn H=C3=B6fling # Copyright =C2=A9 2021 Greg Hogan -# Copyright =C2=A9 2021 Philip McGrath +# Copyright =C2=A9 2021, 2022 Philip McGrath # Copyright =C2=A9 2021 Arun Isaac # Copyright =C2=A9 2021 Sharlatan Hellseher # Copyright =C2=A9 2021 Dmitry Polyakov @@ -1788,7 +1788,9 @@ dist_patch_DATA =3D \ %D%/packages/patches/rpcbind-CVE-2017-8779.patch \ %D%/packages/patches/rtags-separate-rct.patch \ %D%/packages/patches/racket-enable-scheme-backport.patch \ + %D%/packages/patches/racket-gui-tethered-launcher-backport.patch \ %D%/packages/patches/racket-minimal-sh-via-rktio.patch \ + %D%/packages/patches/racket-srfi-fsdg-backport.patch \ %D%/packages/patches/remake-impure-dirs.patch \ %D%/packages/patches/restic-0.9.6-fix-tests-for-go1.15.patch \ %D%/packages/patches/retroarch-LIBRETRO_DIRECTORY.patch \ diff --git a/gnu/packages/chez-and-racket-bootstrap.scm b/gnu/packages/chez= -and-racket-bootstrap.scm index 669c54729d..89e659a397 100644 --- a/gnu/packages/chez-and-racket-bootstrap.scm +++ b/gnu/packages/chez-and-racket-bootstrap.scm @@ -46,7 +46,8 @@ (define-module (gnu packages chez-and-racket-bootstrap) #:use-module (gnu packages xorg) #:use-module ((guix licenses) #:prefix license:) - #:export (chez-scheme-for-system)) + #:export (chez-scheme-for-system + racket-vm-for-system)) =20 ;; Commentary: ;; @@ -216,6 +217,14 @@ (define* (chez-scheme-for-system #:optional chez-scheme-for-racket chez-scheme)) =20 +(define* (racket-vm-for-system #:optional + (system (or (%current-target-system) + (%current-system)))) + "Return 'racket-vm-cs' if it supports SYSTEM; 'racket-vm-bc' otherwise." + (if (nix-system->chez-machine system) + racket-vm-cs + racket-vm-bc)) + (define (chez-machine->unthreaded mach) "Given a string MACH naming a Chez Scheme machine type, returns a string naming the unthreaded machine type for the same architecture and OS as MAC= H. diff --git a/gnu/packages/patches/racket-gui-tethered-launcher-backport.pat= ch b/gnu/packages/patches/racket-gui-tethered-launcher-backport.patch new file mode 100644 index 0000000000..1e018eaa79 --- /dev/null +++ b/gnu/packages/patches/racket-gui-tethered-launcher-backport.patch @@ -0,0 +1,26 @@ +From aa792e707b1fbc5cc33691bfaee5828dc3fbebaa Mon Sep 17 00:00:00 2001 +From: Matthew Flatt +Date: Mon, 31 Jan 2022 15:31:22 -0700 +Subject: [PATCH] fix creation of tethered launchers + +Related to racket/racket#4133 + +(cherry picked from commit 563c68432f127729592f234ef30c31e92618b517) +--- + gui-lib/mred/installer.rkt | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/gui-lib/mred/installer.rkt b/gui-lib/mred/installer.rkt +index b1691472..9ef06c53 100644 +--- a/gui-lib/mred/installer.rkt ++++ b/gui-lib/mred/installer.rkt +@@ -72,4 +72,5 @@ + (list "-A" (path->string (find-system-path 'addon-dir))))) +=20 + (define (config-flags) +- (list "-G" (path->string (find-config-dir)))) ++ (list "-X" (path->string (find-collects-dir)) ++ "-G" (path->string (find-config-dir)))) +--=20 +2.32.0 + diff --git a/gnu/packages/patches/racket-srfi-fsdg-backport.patch b/gnu/pac= kages/patches/racket-srfi-fsdg-backport.patch new file mode 100644 index 0000000000..75a5f46960 --- /dev/null +++ b/gnu/packages/patches/racket-srfi-fsdg-backport.patch @@ -0,0 +1,41622 @@ +From 82076308af8aeda65283ba83779302304e1a25d1 Mon Sep 17 00:00:00 2001 +From: Philip McGrath +Date: Thu, 20 Jan 2022 01:20:04 -0500 +Subject: [PATCH] Backport FSDG fix for Racket 8.4. + +This is a squashed and somewhat reduced version of commits +46e11b7, 48f8fca, and a2d0199. For detailed discussion, see + and +. +--- + srfi-doc/info.rkt | 10 +- + .../srfi/scribblings/srfi-5-doc-free.scrbl | 164 + + srfi-doc/srfi/scribblings/srfi-std/index.html | 351 +- + .../srfi/scribblings/srfi-std/racket-srfi.css | 87 + + .../srfi/scribblings/srfi-std/srfi-1.html | 2893 ++++++++++------- + .../srfi/scribblings/srfi-std/srfi-11.html | 103 +- + .../srfi/scribblings/srfi-std/srfi-13.html | 2072 +++++++----- + .../srfi/scribblings/srfi-std/srfi-14.html | 1533 +++++---- + .../srfi/scribblings/srfi-std/srfi-16.html | 101 +- + .../srfi/scribblings/srfi-std/srfi-17.html | 137 +- + .../srfi/scribblings/srfi-std/srfi-19.html | 863 ++--- + .../srfi/scribblings/srfi-std/srfi-2.html | 180 +- + .../srfi/scribblings/srfi-std/srfi-23.html | 131 +- + .../srfi/scribblings/srfi-std/srfi-25.html | 188 +- + .../srfi/scribblings/srfi-std/srfi-26.html | 408 ++- + .../srfi/scribblings/srfi-std/srfi-27.html | 695 ++-- + .../srfi/scribblings/srfi-std/srfi-28.html | 78 +- + .../srfi/scribblings/srfi-std/srfi-29.html | 88 +- + .../srfi/scribblings/srfi-std/srfi-30.html | 121 +- + .../srfi/scribblings/srfi-std/srfi-31.html | 338 +- + .../srfi/scribblings/srfi-std/srfi-34.html | 230 +- + .../srfi/scribblings/srfi-std/srfi-35.html | 222 +- + .../srfi/scribblings/srfi-std/srfi-38.html | 207 +- + .../srfi/scribblings/srfi-std/srfi-39.html | 278 +- + .../srfi/scribblings/srfi-std/srfi-4.html | 277 +- + .../srfi/scribblings/srfi-std/srfi-40.html | 232 +- + .../scribblings/srfi-std/srfi-41/srfi-41.html | 2116 ++++++------ + .../srfi/scribblings/srfi-std/srfi-42.html | 2205 +++++++------ + .../srfi/scribblings/srfi-std/srfi-43.html | 1049 +++--- + .../srfi/scribblings/srfi-std/srfi-45.html | 303 +- + .../srfi/scribblings/srfi-std/srfi-48.html | 535 +-- + .../srfi/scribblings/srfi-std/srfi-54.html | 179 +- + .../srfi/scribblings/srfi-std/srfi-57.html | 458 +-- + .../srfi/scribblings/srfi-std/srfi-59.html | 314 +- + .../srfi/scribblings/srfi-std/srfi-6.html | 156 +- + .../srfi/scribblings/srfi-std/srfi-60.html | 998 +++--- + .../srfi/scribblings/srfi-std/srfi-61.html | 64 +- + .../srfi/scribblings/srfi-std/srfi-62.html | 130 +- + .../srfi/scribblings/srfi-std/srfi-63.html | 1586 ++++----- + .../srfi/scribblings/srfi-std/srfi-64.html | 408 +-- + .../srfi/scribblings/srfi-std/srfi-66.html | 335 +- + .../srfi/scribblings/srfi-std/srfi-69.html | 346 +- + .../srfi/scribblings/srfi-std/srfi-7.html | 124 +- + .../srfi/scribblings/srfi-std/srfi-71.html | 274 +- + .../srfi/scribblings/srfi-std/srfi-74.html | 485 ++- + .../srfi/scribblings/srfi-std/srfi-78.html | 445 +-- + .../srfi/scribblings/srfi-std/srfi-8.html | 77 +- + .../srfi/scribblings/srfi-std/srfi-86.html | 202 +- + .../srfi/scribblings/srfi-std/srfi-87.html | 118 +- + .../srfi/scribblings/srfi-std/srfi-9.html | 223 +- + .../srfi/scribblings/srfi-std/srfi-98.html | 137 +- + srfi-doc/srfi/scribblings/srfi.scrbl | 70 +- + srfi-doc/srfi/scribblings/util.rkt | 17 + + srfi-lib/info.rkt | 2 + + srfi-lib/srfi/5/let.rkt | 83 +- + srfi-test/tests/srfi/5/srfi-5-test.rkt | 163 +- + srfi/info.rkt | 6 +- + 57 files changed, 14542 insertions(+), 11053 deletions(-) + create mode 100644 srfi-doc/srfi/scribblings/srfi-5-doc-free.scrbl + create mode 100644 srfi-doc/srfi/scribblings/srfi-std/racket-srfi.css + +diff --git a/srfi-doc/info.rkt b/srfi-doc/info.rkt +index 59d9611..2ce76b3 100644 +--- a/srfi-doc/info.rkt ++++ b/srfi-doc/info.rkt +@@ -2,20 +2,18 @@ +=20 + (define collection 'multi) +=20 ++(define version "1.1") ++ + (define build-deps '("mzscheme-doc" + "scheme-lib" + "base" + "scribble-lib" + "srfi-lib" + "racket-doc" +- "r5rs-doc" +- "r6rs-doc" ++ "racket-index" + "compatibility-lib")) +=20 +-(define deps '("scheme-lib" +- "base" +- "scribble-lib" +- "compatibility-lib")) ++(define deps '("base")) +=20 + (define update-implies '("srfi-lib")) +=20 +diff --git a/srfi-doc/srfi/scribblings/srfi-5-doc-free.scrbl b/srfi-doc/sr= fi/scribblings/srfi-5-doc-free.scrbl +new file mode 100644 +index 0000000..5ecf3af +--- /dev/null ++++ b/srfi-doc/srfi/scribblings/srfi-5-doc-free.scrbl +@@ -0,0 +1,164 @@ ++#lang scribble/doc ++@(require "util.rkt" ++ scribble/manual ++ scribble/example ++ scriblib/render-cond ++ scribble/core ++ scribble/html-properties ++ (for-syntax scheme/base) ++ (for-label (except-in scheme/base let) ++ srfi/5 ++ racket/stream)) ++ ++@title[#:tag "srfi-5" #:style 'unnumbered]{ ++ SRFI 5: A compatible let form with signatures and rest arguments} ++@defmodule[srfi/5] ++ ++@begin[ ++ (define-syntax-rule (defrkt rkt-let) ++ (begin ++ (require (for-label racket/base)) ++ (define rkt-let (racket let)))) ++ (defrkt rkt-let) ++ (define reference-doc ++ '(lib "scribblings/reference/reference.scrbl")) ++ (define guide-doc ++ '(lib "scribblings/guide/guide.scrbl")) ++ (define srfi-nf-doc ++ '(lib "srfi/scribblings/srfi-nf.scrbl")) ++ ] ++ ++Original specification: ++@seclink[#:indirect? #t #:doc srfi-nf-doc srfi-5-std-taglet]{SRFI 5} ++ ++For @hyperlink[srfi-license-history-url]{historical ++ reasons}, the SRFI 5 specification document has a ++@seclink[#:indirect? #t #:doc srfi-nf-doc srfi-5-license-taglet]{ ++ restrictive license} and is not included in the main Racket distribution. ++ ++The implementation in @racketmodname[srfi/5] and this ++documentation are distributed under the same ++@racket-license-link{license} as Racket: only the original ++specification document is restrictively licensed. ++ ++@defform*[[(let ([id init-expr] ...) ++ body ...+) ++ (let ([id init-expr] ...+ rest-binding) ++ body ...+) ++ (let loop-id ([id init-expr] ... maybe-rest-binding) ++ body ...+) ++ (let (loop-id [id init-expr] ... maybe-rest-binding) ++ body ...+)] ++ #:grammar ++ ([maybe-rest-binding code:blank rest-binding] ++ [rest-binding (code:line rest-id rest-init-expr ...)])]{ ++ ++ Like @rkt-let from @racketmodname[racket/base], but ++ extended to support additional variants of ++ @tech[#:doc reference-doc]{named @rkt-let}. ++ ++ As with @rkt-let from @racketmodname[racket/base], SRFI 5's ++ @racket[let] form conceptually expands to the immediate ++ application of a function to the values of the ++ @racket[init-expr]s: the @racket[id]s are bound in the ++ @racket[body]s (but not in any @racket[init-expr]s or ++ @racket[rest-init-expr]s), and @racket[loop-id], if present, ++ is bound in the @racket[body]s to the function itself, ++ allowing it to be used recursively. An @racket[id] or a ++ @racket[rest-id] can shadow @racket[loop-id], but the ++ @racket[rest-id] (if given) and all @racket[is]s much be ++ distinct. ++ ++ SRFI 5's @racket[let] adds support for a syntax like ++ @racket[define]'s @seclink[#:doc guide-doc "Function_Shorthand"]{ ++ function shorthand}, which allows the bindings to be written in a ++ syntax resembling an application of the function bound to ++ @racket[loop-id]. ++ ++ Additionally, SRFI 5's @racket[let] adds support for ++ @tech[#:doc guide-doc]{rest arguments}. If a ++ @racket[rest-id] is present, the function bound to ++ @racket[loop-id] (or the conceptual anonymous function, if ++ @racket[loop-id] is not used) will accept an unlimited ++ number of additional arguments after its required ++ by-position arguments, and the @racket[rest-id] will be ++ bound in the @racket[body]s (but not in any ++ @racket[init-expr]s or @racket[rest-init-expr]s) to a list ++ of those additional arguments. The values of the ++ @racket[rest-init-expr]s are supplied as arguments to the ++ initial, implicit application when the @racket[let] form is ++ evaluated, so the initial value bound to @racket[rest-id] is ++ @racket[(list rest-init-expr ...)]. ++ ++ @margin-note{Unlike the @racket[_kw-formals] of ++ @racket[lambda] and @racket[define] or the @racket[_formals] ++ of @racket[case-lambda], the bindings of SRFI 5's ++ @racket[let], with or without a @racket[rest-binding], are ++ always a proper (syntactic) list.} ++ ++ A @racket[rest-binding] can be used with both the ++ @racket[define]-like and the ++ @tech[#:doc reference-doc]{named-@rkt-let}--like variants of ++ @racket[let]. It is also possible to use @racket[rest-id] ++ without any @racket[loop-id]; however, as specified in the ++ grammar, at least one @racket[id]--@racket[init-expr] pair ++ is required in that case. (Otherwise, there would be an ++ ambiguity with the @racket[define]-like variant). ++ ++ @examples[ ++ #:eval (make-base-eval '(require srfi/5)) #:once ++ (code:comment "define-like bindings") ++ (define (factorial n) ++ (let (fact [n n] [acc 1]) ++ (if (zero? n) ++ acc ++ (fact (sub1 n) (* n acc))))) ++ (eval:check (factorial 5) 120) ++ (eval:check (factorial 11) 39916800) ++ (code:comment "rest arguments with named-let--like bindings") ++ (eval:check (let reverse-onto ([lst '(a b c)] ++ tail) ++ (if (null? lst) ++ tail ++ (apply reverse-onto (cdr lst) (car lst) tail))) ++ '(c b a)) ++ (eval:check (let reverse-onto ([lst '(a b c)] ++ tail 'x 'y 'z) ++ (if (null? lst) ++ tail ++ (apply reverse-onto (cdr lst) (car lst) tail))) ++ '(c b a x y z)) ++ (eval:check (let no-evens (lst 1 2 3 4 5) ++ (cond ++ [(null? lst) ++ '()] ++ [(even? (car lst)) ++ (apply no-evens (cdr lst))] ++ [else ++ (cons (car lst) (apply no-evens (cdr lst)))])) ++ '(1 3 5)) ++ (code:comment "rest arguments with define-like bindings") ++ (eval:check (let (reverse-onto [lst '(a b c)] tail) ++ (if (null? lst) ++ tail ++ (apply reverse-onto (cdr lst) (car lst) tail))) ++ '(c b a)) ++ (eval:check (let (reverse-onto [lst '(a b c)] . [tail 'x 'y 'z]) ++ (if (null? lst) ++ tail ++ (apply reverse-onto (cdr lst) (car lst) tail))) ++ '(c b a x y z)) ++ (eval:check (let (loop [continue? 0] args 'a 'a1 'a2) ++ (case continue? ++ [(0) (cons args (loop 1 'b))] ++ [(1) (cons args (loop 2 'c 'd))] ++ [else (list args)])) ++ '((a a1 a2) (b) (c d))) ++ (code:comment "rest arguments without any loop-id") ++ (eval:check (let ([x 1] ++ [y 2] ++ z 3 4 5 6 7) ++ (list* x y z)) ++ '(1 2 3 4 5 6 7)) ++ ] ++} +diff --git a/srfi-doc/srfi/scribblings/srfi-std/index.html b/srfi-doc/srfi= /scribblings/srfi-std/index.html +index 6f03f9b..c46dd8b 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/index.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/index.html +@@ -1,258 +1,113 @@ +- +- ++ ++ ++ + ++ + SRFI documents inside Racket ++ ++ + +- + +

SRFI documents inside Racket

+- +-

Scheme Requests for Implementation

+- +-

The "Scheme Requests for Implementation" (SRFI) process +- is a new approach to helping Scheme users to write portable and +- yet useful code. It is a forum for people interested in +- coordinating libraries and other additions to the Scheme language +- between implementations.

+- +-

This manual includes the original= documentation of all +- the SRFIs already ported to Racket. For more information on +- the SRFI process, please follow +- this link.

+- +- +-

Loading

+- +-

To load a SRFI with name conflicts (currently SRFIs 1, 5, 13, 17, = 19, 43, +- 45, 48, 61, 63, 69 and 87) in a module,
+- please see the note below.
+-
+- To load a SRFI, use the following form:
+-
+-     (require srfi/N)
+-
+- if you know the number of the SRFI you want to load. This is the pref= erred +- method. Alternatively, use this one:
+-
+-     (require srfi/N/NAME)
+-
+- if you know the `informative name' of the SRFI.
+-
+- N, is a number corresponding to the sub-collection that holds a parti= cular +- SRFI, and NAME is a more descriptive name we assigned to the main fil= e in +- which the SRFI is defined. For instance, to load SRFI-34 you have to = do +- either one of:
+-
+-     (require srfi/34)
+-
+- or,
+-
+-     (require srfi/34/exception)
+-
+-

+- +- +

+- NOTE on SRFIs with name conflicts +-
+- Certain SRFIs (currently SRFIs 1, 5, 13, 17, 19, 43, 45, 48, 61, 63, = 69 and +- 87) provide names which conflict with names provided by the racke= t +- language. Attempting to require one of these SRFIs in a module writte= n in +- the racket language will result in an error.
+-
+- To address this problem, the Racket implementations of these SRFIs pr= ovide a +- different module which renames the problematic exports to avoid these +- conflicts. For SRFI 1, this library is called list, and should be +- required like this:
+-
+-     (require srfi/1/list)
+-
+- which supplies the colliding names with a prefix of 's:' (e.g. "= s:map", +- "s:reverse!") and is therefore suitable for requires in a m= odule.
+-
+- For SRFI 19, this library is called time, and should be required like +- this:
+-
+-     (require srfi/19/time)
+-
+- which supplies the colliding names with a prefix of 'srfi:' (e.g. +- "srfi:date?", "srfi:date-second") and is therefor= e
+- suitable for requires in a module.
+-
++ The information that used to be on this page has moved to ++ ../index.html. +

+- +- +

+- Supported SRFIs
++ If you do nothing, you should be redirected in five seconds. +

+- +- +-

SRFI           F= ile +- name           +- Sub-collection
+- SRFI-1         list.rkt =             +- 1
+- SRFI-2         and-let.rkt&nb= sp;         +- 2
+- SRFI-4(*1)     4.rkt
+- SRFI-5         let.rkt &= nbsp;            +- 5
+- SRFI-6(+)      6.rkt
+- SRFI-7         program.rkt&nb= sp;         +- 7
+- SRFI-8         receive.rkt&nb= sp;         +- 8
+- SRFI-9         record.rkt&nbs= p;          +- 9
+- SRFI-11(+)     11.rkt
+- SRFI-13        string.rkt &nb= sp;         +- 13
+- SRFI-14        char-set.rkt &= nbsp;       +- 14
+- SRFI-16(+)     16.rkt
+- SRFI-17        set.rkt  =             +- 17
+- SRFI-19(*2)    time.rkt     &= nbsp;       +- 19
+- SRFI-23(+)     23.rkt
+- SRFI-25        array.rkt &nbs= p;          +- 25
+- SRFI-26        cut.rkt  =             +- 26
+- SRFI-27        random-bits.rkt&nbs= p;     +- 27
+- SRFI-28(+)     28.rkt
+- SRFI-29        localization.rkt&nb= sp;    +- 29
+- SRFI-30(+)     30.rkt
+- SRFI-31        rec.rkt  =             +- 31
+- SRFI-32        sort.scm  = ;          +- 32
+- SRFI-34        exception.rkt =        +- 34
+- SRFI-35        condition.rkt =        +- 35
+- SRFI-38(+)     38.rkt
+- SRFI-39(+)     39.rkt
+- SRFI-40        stream.rkt &nb= sp;         +- 40
+- SRFI-42        comprehensions.rkt&= nbsp;  +- 42
+- SRFI-43        vector-lib.rkt = ;      +- 43
+- SRFI-45(*3)    lazy.rkt     &= nbsp;       +- 45
+- SRFI-48        format.rkt &nb= sp;         +- 48
+- SRFI-54        cat.rkt  =             +- 54
+- SRFI-57        records.rkt &n= bsp;        +- 57
+- SRFI-59        vicinity.rkt &= nbsp;       +- 59
+- SRFI-60        60.rkt  &= nbsp;            +- 60
+- SRFI-61        cond.rkt  &nbs= p;          +- 61
+- SRFI-62(+)
+- SRFI-63        63.rkt  &= nbsp;            +- 63
+- SRFI-64        testing.rkt &n= bsp;        +- 64
+- SRFI-66        66.rkt  &= nbsp;            +- 66
+- SRFI-67        compare.rkt &n= bsp;        +- 67
+- SRFI-69        hash.rkt  = ;           +- 69
+- SRFI-71        letvalues.rkt =        +- 71
+- SRFI-74        74.rkt  &= nbsp;            +- 74
+- SRFI-78        check.rkt &nbs= p;          +- 78
+- SRFI-86        86.rkt  &= nbsp;            +- 86
+- SRFI-87        case.rkt  = ;           +- 87
+-

+- +- +-

Notes:

+- +- +-

+ Supported by the Racket core
+-
+- *1 The functionality is all part of racket available +- via (require ffi/unsafe), the only missing part is the i/o +- syntax.
+-
+- *2 The time module does not export its time structure +- (you have to use the time-* procedures.) It renames all +- the date-* accessors to tm:date-* so that you won't get +- errors when including this code in other modules. Care +- most be taken NOT to confuse the internal date structure +- with the Racket one, they are not the same, and all +- procedures from this library expect the former.
+-
+- *3 This port also provides promise? / srfi-45-promise?.
+-

+- +- +-

Ported SRFIs: original documents

+- +- +- +- ++ + +diff --git a/srfi-doc/srfi/scribblings/srfi-std/racket-srfi.css b/srfi-doc= /srfi/scribblings/srfi-std/racket-srfi.css +new file mode 100644 +index 0000000..661e2cb +--- /dev/null ++++ b/srfi-doc/srfi/scribblings/srfi-std/racket-srfi.css +@@ -0,0 +1,87 @@ ++/* ++ This is a substitute for "srfi.css" from ++ https://github.com/scheme-requests-for-implementation/srfi-common ++*/ ++@import "../../scribble.css"; ++@import "../../manual-style.css"; ++@import "../../manual-racket.css"; ++/* NB doc-site.css is imported at the end of this file */ ++ ++a.eponymous { ++ /* based on upstream srfi.css */ ++ font-family: 'Fira-Mono', monospace; ++ overflow-wrap: break-word; ++ word-break: break-all; ++ word-wrap: break-word; ++} ++body > p:first-of-type { ++ /* this is the SRFI author */ ++ font-family: 'Fira', sans-serif; ++ font-size: 1.3em; ++} ++body { ++ /* like .maincolumn from manual-style.css */ ++ width: auto; ++ margin-top: 4rem; ++ margin-left: 17rem; ++ margin-right: 2rem; ++ margin-bottom: 10rem; /* to avoid fixed bottom nav bar */ ++ max-width: 700px; ++ min-width: 370px; /* below this size, code samples don't fit */ ++} ++@media (max-width:720px) { ++ /* adapt to narrow screens, like .maincolumn in manual-style.css */ ++ body { ++ margin-left: 1em; ++ margin-top: 7rem; ++ margin-bottom: 0rem; ++ } ++} ++.refpara.racket-srfi-note .refcolumn { ++ /* Overrides @media rule to put .refcolumn in the margin on wide ++ screens. This is necessary because some SRFIs (e.g. 14) include ++ inline stylesheets that interfere with the way it tries to use ++ `float`. ++ */ ++ margin: inherit; ++ float: inherit; ++ clear: inherit; ++ width: inherit; ++} ++h1 { ++ /* like h2 from manual-style.css */ ++ font-family: 'Cooper-Hewitt'; ++ font-size: 2.3rem; ++ font-weight: bold; ++ line-height: 1.2; ++ width: 90%; ++} ++h2 { ++ /* like h3 -- h8 in manual-style.css */ ++ margin-top: 2em; ++ padding-top: 0.1em; ++ margin-bottom: 0.75em; ++ font-size: 2rem; ++} ++h3, h4, h5, h6, h7, h8 { ++ border: none; ++} ++span.antispam { ++ display: none; ++} ++pre, dl, dd, ol, ul { ++ /* like p from manual-style.css */ ++ margin-bottom: 1em; ++} ++li { ++ /* slightly tighter than p */ ++ margin-bottom: 0.6em; ++} ++.srfi-plt-extension { ++ /* like the background color for .boxed (blue boxes), ++ but without the gradient */ ++ background-color: hsl(216, 78%, 95%); ++} ++ ++/* Goes last, so it can override everything. */ ++@import "../../doc-site.css"; +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-1.html b/srfi-doc/srf= i/scribblings/srfi-std/srfi-1.html +index 773c03b..f1ccc40 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-1.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-1.html +@@ -1,24 +1,41 @@ +- +- ++ ++ ++ ++ ++ + +- + +- +- +- +- ++ ++ ++ ++ + SRFI 1: List Library +=20 + + +=20 +- + +=20 + +=20 + +-

Title

+-SRFI-1: List Library +-
+- +- +-

Author

++

SRFI 1: List Library

+=20 +-Olin Shivers +- +-
+- http://www.ai.mit.edu/~= shivers/ / +- shivers@ai.mit.edu +-
++

by Olin Shivers

++

This copy of the SRFI 1 specifica= tion document ++is distributed as part of the Racket package ++srfi-doc.

= The canonical source of this document is ++https://srfi.sch= emers.org/srfi-1/srfi-1.html.

+=20 + +-

Status

+- +-This SRFI is currently in ``final'' status. To see an explanation of eac= h status that a SRFI can hold, see here. +-You can access the discussion via the archive of the mailing list. +-

+-

    +-
  • Received: 1998/11/08
  • +-
  • Draft: 1998/12/22-1999/03/09
  • +-
  • Revised: several times
  • +-
  • Final: 1999/10/09
  • +-
++

Status

++ ++

This SRFI is currently in final status. Here is an explanation of each stat= us that a SRFI can hold. To provide input on this SRFI, please send email = to = srfi-1 @nospamsrfi.schemers.org= . To subscribe to the list, follow these instructions. You can access previous me= ssages via the mailing list archive.

++
    ++
  • Received: 1998-11-08
  • ++
  • Draft: 1998-12-22--1999-03-09
  • ++
  • Revised: several times
  • ++
  • Final: 1999-10-09
  • ++
  • Revised to fix errata: ++
      ++
    • 2016-08-27 (Clarify Booleans.)
    • ++
    • 2018-10-08 (Remove extra parenthesis.)
    • ++
    • 2019-10-25 (Fix broken links.)
    • ++
    • 2020-06-02 (Add note ++ about order of arguments to lset=3D.)
    • ++
    ++
  • ++
+=20 + +-

Table of contents

++

Table of contents

+=20 + +-
    +-
  • Abstract +-
  • Rationale +-
  • Procedure index +-
  • General discussion +- +-
  • The procedures +- +-
  • Acknowledgements +-
  • References & links +-
  • Copyright ++ +=20 +=20 + +-

    Abstract

    ++

    Abstract

    +

    + R5RS Scheme has an impoverished set of list-processing utilities, which is a + problem for authors of portable code. This SRFI proposes a coherent and + comprehensive set of list-processing procedures; it is accompanied by a + reference implementation of the spec. The reference implementation is ++

    +
      +-
    • portable +-
    • efficient +-
    • completely open, public-domain source ++
    • portable
    • ++
    • efficient
    • ++
    • completely open, public-domain source
    • +
    +=20 + +-

    Rationale

    ++

    Rationale

    +

    + The set of basic list and pair operations provided by R4RS/R5RS Scheme is far + from satisfactory. Because this set is so small and basic, most +@@ -220,7 +245,7 @@ implementations provide additional utilities, such as = a list-filtering + function, or a "left fold" operator, and so forth. But, of course, this + introduces incompatibilities -- different Scheme implementations provide + different sets of procedures. +- ++

    +

    + I have designed a full-featured library of procedures for list processing. + While putting this library together, I checked as many Schemes as I could= get +@@ -228,43 +253,47 @@ my hands on. (I have a fair amount of experience wit= h several of these + already.) I missed Chez -- no on-line manual that I can find -- but I hit= most + of the other big, full-featured Schemes. The complete list of list-proces= sing + systems I checked is: +-

    +- R4RS/R5RS Scheme, MIT = Scheme, Gambit, RScheme, MzScheme, slib,=20 ++

    ++
    ++ R4RS/R5RS Scheme, MIT = Scheme, Gambit, RScheme, MzScheme, slib, + Common Lisp, Bigloo, guile, T, APL and th= e SML standard basis +
    +

    + As a result, the library I am proposing is fairly rich. ++

    +

    + Following this initial design phase, this library went through several + months of discussion on the SRFI mailing lists, and was altered in light + of the ideas and suggestions put forth during this discussion. ++

    +

    + In parallel with designing this API, I have also written a reference + implementation. I have placed this source on the Net with an unencumbered, + "open" copyright. A few notes about the reference implementation: +- ++

    +
      +
    • Although I got procedure names and specs from many Schemes, I wrote t= his +- code myself. Thus, there are no entanglements.=20 ++ code myself. Thus, there are no entanglements. + Any Scheme implementor + can pick this library up with no worries about copyright problems -- = both + commercial and non-commercial systems. +=20 +-
    • The code is written for portability and should be trivial to port to ++
    • The code is written for portability and should be trivial to por= t to + any Scheme. It has only four deviations from R4RS, clearly discussed + in the comments:
        +
      • Use of an error procedure; +-
      • Use of the R5RS values and a simple receive m= acro for producing ++
      • Use of the R5RS values and a simple receive macro for producing + and consuming multiple return values; +-
      • Use of simple :optional and let-optionals = macros for optional ++
      • Use of simple :optional and let-optionals macros for optional + argument parsing and defaulting; +-
      • Use of a simple check-arg procedure for argument checki= ng. +-
      ++
    • Use of a simple check-arg procedure for argument c= hecking. ++
    +=20 +-
  • It is written for clarity and well-commented. The current source is ++
  • It is written for clarity and well-commented. The current source= is + 768 lines of source code and 826 lines of comments and white space. +=20 +-
  • It is written for efficiency. Fast paths are provided for common ++
  • ++ It is written for efficiency. Fast paths are provided for common + cases. Side-effecting procedures such as filter! avoid u= nnecessary, + redundant set-cdr!s which would thrash a generational GC= 's write barrier + and the store buffers of fast processors. Functions reuse longest com= mon +@@ -272,227 +301,243 @@ implementation. I have placed this source on the N= et with an unencumbered, + possible. Constant-space iterations are used in preference to recursi= ons; + local recursions are used in preference to consing temporary intermed= iate + data structures. +-

    ++

    ++

    + This is not to say that the implementation can't be tuned up for + a specific Scheme implementation. There are notes in comments address= ing + ways implementors can tune the reference implementation for performan= ce. +-

++

+

+ In short, I've written the reference implementation to make it as painless + as possible for an implementor -- or a regular programmer -- to adopt this + library and get good results with it. +- ++

+=20 + +-

Procedure Index

++

Procedure Index

+

+ Here is a short list of the procedures provided by the list-lib package. +-R5RS procedures are shown in=20 +-bold; +-extended R5RS=20 +- procedures, in bold italic. +-

++R5RS procedures are shown in ++bold; ++extended R5RS ++ procedures, in bold italic. ++

++
+
+-
Constructors +-
+-
+-cons list=

+-xcons cons* make-list list-tabulate=20
++
Constructors ++
++
++cons li=
st
++xcons cons* make-list list-tabulate
+ list-copy circular-=
list iota
+ 
+=20 +-
Predicates +-
+-
+-pair? null?
+-proper-list? =
circular-list? dotted-list?=20
++
Predicates ++
++
++pair? null?
++proper-list? =
circular-list? dotted-list?
+ not-pair? null-list?=

+-list=3D
++list=3D
+ 
+=20 +-
Selectors +-
+-
+-car cdr=
 ... cddadr cddddr list-ref
++
Selectors ++
++
++car cdr ... cddadr cddddr list-ref
+ first second third fourth fifth=
 sixth seventh eighth ninth tenth
+-car+cdr
++car+cdr
+ take       drop
+ take-right drop-right=

+-take!      drop-right!=20
+-split-at   split-at!=
=20
++take!      drop-right!
++split-at   split-at!
+ last last-pair
+ 
+=20 +-
Miscellaneous: length, append, concatenate, rever= se, zip & count +-
+-
+-length length+
+-append  concatenate  reverse
++
Miscellaneous: length, append, concatenate= , reverse, zip & count ++
++
++length length+
++append  concatenate  reverse
+ append! concatenate! reverse!
+ append-reverse append-reverse!
+ zip unzip1 unzip2 unzip3 unzip4=
 unzip5
+ count
+ 
+=20 +-
Fold, unfold & map +-
+-
+-map f=
or-each
+-fold       unfold       pair-fold       reduce=20
+-fold-right unfold-r=
ight pair-fold-right reduce-right=20
++
Fold, unfold & map ++
++
++map for-each
++fold       unfold       pair-fold       reduce
++fold-right unfold-r=
ight pair-fold-right reduce-right
+ append-map append-ma=
p!
+ map! pair-for-each <=
a href=3D"#filter-map">filter-map map-in-orde=
r
+ 
+=20 +-
Filtering & partitioning +-
+-
++
Filtering & partitioning ++
++
+ filter  partition  remove
+-filter! partition! <=
a href=3D"#remove!">remove!=20
++filter! partition! <=
a href=3D"#remove!">remove!
+ 
+=20 +-
Searching +-
+-
+-member memq memv
+-find find-tail=20
++
Searching ++
++
++member memq memv
++find find-tail
+ any every
+ list-index
+ take-while drop-while=
 take-while!
+ span break span! break!
+ 
+=20 +-
Deleting +-
+-
+-delete  delete-dup=
licates=20
++
Deleting ++
++
++delete  delete-dup=
licates
+ delete! delete-d=
uplicates!
+ 
+=20 +-
Association lists +-
+-
+-assoc assq assv
++
Association lists ++
++
++assoc assq assv
+ alist-cons alist-copy=

+ alist-delete ali=
st-delete!
+ 
+=20 +-
Set operations on lists +-
+-
+-lset<=3D lset=3D lset-adjoin
++
Set operations on lists ++
++
++lset<=3D lset=3D =
lset-adjoin
+ lset-union			lset-un=
ion!
+ lset-intersection		lset-intersection!
+ lset-difference		        lset-difference!
+ lset-xor			lset-xor!
+-lset-diff+intersection	        lset-diff+intersection!
++lset-diff+intersection	        =
lset-diff+intersection!
+ 
+=20 +-
Primitive side-effects +-
+-
+-set-car! set-cdr!
++
Primitive side-effects ++
++
++set-car! set-cdr!
+ 
+-
++ +
+=20 +

+ Four R4RS/R5RS list-proc= essing procedures are extended by this library in + backwards-compatible ways: +-

+- +-
map for-each=20 +- (Extended to take lists of unequal length)=20 +-
member assoc=20 +- (Extended to take an optional comparison procedure.) +-
++

++
++ ++
map for-each ++ (Extended to take lists of unequal length) ++
member assoc ++ (Extended to take an optional comparison procedure.) ++
+
+=20 +

+ The following R4RS/R5RS li= st- and pair-processing procedures are also part of + list-lib's exports, as defined by the R5RS: +-

++

++
+
+ cons pair? null?
+-car cdr ... cdddar cddddr=20
+-set-car! set-cdr!=20
++car cdr ... cdddar cddddr
++set-car! set-cdr!
+ list append reverse
+ length list-ref
+ memq memv assq assv
+ 
+
+-=20=20=20=20 ++ +

+-The remaining two R4RS/= R5RS list-processing=20 ++The remaining two R4RS/= R5RS list-processing + procedures are not part of + this library: +-

+- +-
list-tail=20 +- (renamed drop) +-
list? +- (see proper-list?, +- circular-list? and=20 ++

++
++ ++
list-tail ++ (renamed drop) ++
list? ++ (see proper-list?, ++ circular-list? and + dotted-list?) +-
++
+
+=20 + +-

General discussion

++

General discussion

+

+=20 + A set of general criteria guided the design of this library. +=20 ++

+

+=20 +-I don't require "destructive" (what I call "linear update") procedures to= =20 ++I don't require "destructive" (what I call "linear update") procedures to + alter and recycle cons cells from the argument lists. They are allowed to= , but + not required to. (And the reference implementations I have written do= + recycle the argument lists.) +=20 ++

+

+ List-filtering procedures such as filter or delete do not disorder + lists. Elements appear in the answer list in the same order as they appea= r in + the argument list. This constrains implementation, but seems like a desir= able + feature, since in many uses of lists, order matters. (In particular, + disordering an alist is definitely a bad idea.) ++

+

+ Contrariwise, although the reference implementations of the list-filtering + procedures share longest common tails between argument and answer lists, + it not is part of the spec. ++

+

+ Because lists are an inherently sequential data structure (unlike, say, + vectors), list-inspection functions such as find, find= -tail, for-each, any + and every commit to a left-to-right traversal order of their= argument list. ++

+

+ However, constructor functions, such as list-tabulate<= /code> and the mapping + procedures (append-map, append-map!, map!= , pair-for-each, filter-map, + map-in-order), do not specify the dynamic order in = which their procedural + argument is applied to its various values. ++

+

+ Predicates return useful true values wherever possible. Thus any must return + the true value produced by its predicate, and every returns= the final true + value produced by applying its predicate argument to the last element of = its + argument list. ++

+

+ Functionality is provided both in pure and linear-update (potentially + destructive) forms wherever this makes sense. ++

+

+ No special status accorded Scheme's built-in equality functions. + Any functionality provided in terms of eq?, eqv?, equal? is also + available using a client-provided equality function. ++

+

+ Proper design counts for more than backwards compatibility, but I have tr= ied, +-ceteris paribus,=20 ++ceteris paribus, + to be as backwards-compatible as possible with existing + list-processing libraries, in order to facilitate porting old code to run= as a + client of the procedures in this library. Name choices and semantics are,= for + the most part, in agreement with existing practice in many current Scheme + systems. I have indicated some incompatibilities in the following text. ++

+

+ These procedures are not "sequence generic" -- i.e., pr= ocedures that + operate on either vectors and lists. They are list-specific. I prefer to + keep the library simple and focussed. ++

+

+ I have named these procedures without a qualifying initial "list-" lexeme, + which is in keeping with the existing set of list-processing utilities in +@@ -501,9 +546,11 @@ I follow the general Scheme convention (vector-length= , string-ref) of + placing the type-name before the action when naming procedures -- so + we have list-copy and pair-for-each rather than= the perhaps + more fluid, but less consistent, copy-list or for-each= -pair. ++

+

+ I have generally followed a regular and consistent naming scheme, composi= ng + procedure names from a set of basic lexemes. ++

+=20 + +

"Linear update" procedures

+@@ -520,18 +567,21 @@ of list1 to point to list= 2, and then + empty list, in which case it would simply return list2). However, append! may + also elect to perform a pure append operation -- this is a legal definiti= on + of append!: +-
++

++
+ (define append! append)
+ 
+

+ This is why we do not call these procedures "destructive" -- because they + aren't required to be destructive. They are potentially= destructive. ++

+

+ What this means is that you may only apply linear-update procedures to + values that you know are "dead" -- values that will never be used again + in your program. This must be so, since you can't rely on the value passed + to a linear-update procedure after that procedure has been called. It + might be unchanged; it might be altered. ++

+

+ The "linear" in "linear update" doesn't mean "linear time" or "linear spa= ce" + or any sort of multiple-of-n kind of meaning. It's a fancy term that +@@ -542,6 +592,7 @@ bound to no other variable. So when you use a= variable in a variable + reference, you "use it up." Knowing that no one else has a pointer to that + value means the a system primitive is free to side-effect its arguments to + produce what is, observationally, a pure-functional result. ++

+

+ In the context of this library, "linear update" means you, the programmer, + know there are no other live references to the value passed to t= he +@@ -549,11 +600,13 @@ procedure -- after passing the value to one of these= procedures, the + value of the old pointer is indeterminate. Basically, you are licensing + the Scheme implementation to alter the data structure if it feels like + it -- you have declared you don't care either way. ++

+

+ You get no help from Scheme in checking that the values you claim are "li= near" + really are. So you better get it right. Or play it safe and use the non-! + procedures -- it doesn't do any good to compute quickly if you get the wr= ong + answer. ++

+

+ Why go to all this trouble to define the notion of "linear update" and us= e it + in a procedure spec, instead of the more common notion of a "destructive" +@@ -572,16 +625,18 @@ algorithm. Linear-update operations are easily para= llelised. Going with a + linear-update spec doesn't close off these valuable alternative implement= ation + techniques. This list library is intended as a set of low-level, basic + operators, so we don't want to exclude these possible implementations. ++

+

+ The linear-update procedures in this library are +-

++

++
+ take! drop-right! split-at! + append! concatenate! reverse! append-reverse! + append-map! map! +-filter! partition! remove!=20 ++filter! partition! remove! + take-while! span! break! + delete! alist-delete! delete-duplicates! +-lset-adjoin! lset-union! lset-intersection!=20 ++lset-adjoin! lset-union! lset-intersection! + lset-difference! lset-xor! lset-diff+intersection! +
+=20 +@@ -597,26 +652,33 @@ treat these trees as lists. Further complications en= sue from the fact that + Scheme allows side-effects to these tuples, raising the possibility of li= sts + of unbounded length, and trees of unbounded depth (that is, circular data + structures). +- ++

+

+ However, there is a simple view of the world of Scheme values that consid= ers + every value to be a list of some sort. that is, every value is either ++

+
    +-
  • a "proper list" -- a finite, nil-terminated list, such as:
    +- (a b c)
    +- ()
    +- (32)
    +-
  • a "dotted list" -- a finite, non-nil terminated list, such as:
    +- (a b c . d)
    +- (x . y)
    +- 42
    +- george
    +-
  • or a "circular list" -- an infinite, unterminated list. ++
  • ++ a "proper list" -- a finite, nil-terminated list, such as:
    ++ (a b c)
    ++ ()
    ++ (32)
    ++
  • ++
  • ++ a "dotted list" -- a finite, non-nil terminated list, such as:
    ++ (a b c . d)
    ++ (x . y)
    ++ 42
    ++ george
    ++
  • ++
  • ++ or a "circular list" -- an infinite, unterminated list. ++
  • +
+

+ Note that the zero-length dotted lists are simply all the non-null, non-p= air + values. +- ++

+

+ This view is captured by the predicates proper-list?, = dotted-list?, and + circular-list?. List-lib users should note that dotted lists= are not commonly +@@ -624,7 +686,7 @@ used, and are considered by many Scheme programmers to= be an ugly artifact of + Scheme's lack of a true list type. However, dotted lists do play a notice= able + role in the syntax of Scheme, in the "rest" parameters used by n= -ary + lambdas: (lambda (x y . rest) ...). +- ++

+

+ Dotted lists are not fully supported by list-lib. Most procedure= s are + defined only on proper lists -- that is, finite, nil-terminated lists. T= he +@@ -632,8 +694,9 @@ procedures that will also handle circular or dotted li= sts are specifically + marked. While this design decision restricts the domain of possible argum= ents + one can pass to these procedures, it has the benefit of allowing the + procedures to catch the error cases where programmers inadvertently pass +-scalar values to a list procedure by accident,=20 ++scalar values to a list procedure by accident, + e.g., by switching the arguments to a procedure call. ++

+=20 + +

Errors

+@@ -645,6 +708,7 @@ do that." They are not a guarantee that a conforming i= mplementation will + Regrettably, R5RS Scheme requires no firmer guarantee even for basic operato= rs such + as car and cdr, so there's little point in requ= iring these procedures to do + more. Here is the relevant section of the R5RS: ++

+
+

+ When speaking of an error situation, this report uses the phrase "an +@@ -654,209 +718,235 @@ more. Here is the relevant section of the ++

+ For example, it is an error for a procedure to be passed an argument + that the procedure is not explicitly specified to handle, even though + such domain errors are seldom mentioned in this report. + Implementations may extend a procedure's domain of definition to + include such arguments. +-

++

+=20 +=20 + +

Not included in this library=

+

+ The following items are not in this library: ++

+
    +
  • Sort routines +-
  • Destructuring/pattern-matching macro +-
  • Tree-processing routines +-
++
  • Destructuring/pattern-matching macro ++
  • Tree-processing routines ++
  • +

    + They should have their own SRFI specs. +-

    ++

    +=20 +=20 + +-

    The procedures

    ++

    The procedures

    +

    +=20 + In a Scheme system that has a module or package system, these procedures + should be contained in a module named "list-lib". +- ++

    ++

    + The templates given below obey the following conventions for procedure fo= rmals: ++

    + +- +-
    list=09 +- A proper (finite, nil-terminated) list +-
    clist +- A proper or circular list +-
    flist +- A finite (proper or dotted) list +-
    pair +- A pair +-
    x, y, d, a +- Any value +-
    object, value +- Any value +-
    n, i +- A natural number (an integer >=3D 0) +-
    proc +- A procedure +-
    pred +- A procedure whose return value is treated as a boolean +-
    =3D +- A boolean procedure taking two arguments +-
    ++ list ++ A proper (finite, nil-terminated) list ++ clist ++ A proper or circular list ++ flist ++ A finite (proper or dotted) list ++ pair ++ A pair ++ ++ x, y, d, a<= /var> ++ Any value ++ object, = value ++ Any value ++ n, = i ++ A natural number (an integer >=3D 0) ++ proc ++ A procedure ++ pred ++ A procedure whose return value is treated as a boolean ++ =3D ++ A boolean procedure taking two arguments ++ +=20 +

    + It is an error to pass a circular or dotted list to a procedure not + defined to accept such an argument. +- ++

    + +-

    Constructors

    +-

    ++

    Constructors

    ++ +=20 +
    +=20 + +-
    ++
    + +-cons a d -> pair +-
    ++cons a d -> pair ++ ++
    ++

    + [R5RS] +- The primitive constructor. Returns a newly allocated pair whose car = is=20 +- a and whose cdr is d.=20=20 ++ The primitive constructor. Returns a newly allocated pair whose car = is ++ a and whose cdr is d. + The pair is guaranteed to be different (in the sense of eqv?) + from every existing object. +-

    +-(cons 'a '())        =3D> (a)
    +-(cons '(a) '(b c d)) =3D> ((a) b c d)
    +-(cons "a" '(b c))    =3D> ("a" b c)
    +-(cons 'a 3)          =3D> (a . 3)
    +-(cons '(a b) 'c)     =3D> ((a b) . c)
    ++

    ++
    ++(cons 'a '())        =3D> (a)
    ++(cons '(a) '(b c d)) =3D> ((a) b c d)
    ++(cons "a" '(b c))    =3D> ("a" b c)
    ++(cons 'a 3)          =3D> (a . 3)
    ++(cons '(a b) 'c)     =3D> ((a b) . c)
    + 
    +- ++
    + +-
    ++
    + +-list object ... -> list +-
    ++list object ... -> list ++ ++
    ++

    + [R5RS] + Returns a newly allocated list of its arguments. +-

    +-(list 'a (+ 3 4) 'c) =3D>  (a 7 c)
    +-(list)               =3D>  ()
    ++

    ++
    ++(list 'a (+ 3 4) 'c) =3D>  (a 7 c)
    ++(list)               =3D>  ()
    + 
    +- ++
    + +-
    ++
    + +-xcons d a -> pair +-
    ++xcons d a -> pair ++ ++
    +
    + (lambda (d a) (cons a d))
    + 
    +- Of utility only as a value to be conveniently passed to higher-order= =20 ++

    ++ Of utility only as a value to be conveniently passed to higher-order + procedures. +- +-

    ++

    ++
    + (xcons '(b c) 'a) =3D> (a b c)
    + 
    +- ++

    + The name stands for "eXchanged CONS." +- ++

    ++
    + +- +-
    cons* elt1 elt2 ... -> object +-
    +- +- Like list,=20 ++
    cons*= elt1 elt2 ... -> object ++
    ++
    ++

    ++ Like list, + but the last argument provides the tail of the constructed list, + returning +-

    ++

    ++
    + (cons elt1 (cons elt2 (cons .= .. eltn))) +
    +- This function is called list* in Common Lisp and about=20 ++

    ++ This function is called list* in Common Lisp and about + half of the Schemes that provide it, + and cons* in the other half. +-

    ++

    ++
    + (cons* 1 2 3 4) =3D> (1 2 3 . 4)
    + (cons* 1) =3D> 1
    + 
    +- ++
    + +- +-
    make-list n [fil= l] -> list +-
    +- Returns an n-element list,=20 ++
    make-li= st n [fill] -> list ++
    ++
    ++

    ++ Returns an n-element list, + whose elements are all the value fill. + If the fill argument is not given, the elements of the lis= t may + be arbitrary values. +-

    ++

    ++
    + (make-list 4 'c) =3D> (c c c c)
    + 
    +- ++
    + +- +-
    list-tabulate n i= nit-proc -> list +-
    ++
    list= -tabulate n init-proc -> list ++
    ++
    ++

    + Returns an n-element list. Element i of the lis= t, where 0 <=3D i < n, + is produced by (init-proc i). No g= uarantee is made about the dynamic + order in which init-proc is applied to these indices. +- +-

    ++

    ++
    + (list-tabulate 4 values) =3D> (0 1 2 3)
    + 
    +- ++
    + +- +-
    list-copy flist -= > flist +-
    ++
    list-cop= y flist -> flist ++
    ++
    ++

    + Copies the spine of the argument. +-=20=20=20=20 ++

    ++
    + +- +-
    circular-list elt= 1 elt2 ... -> list +-
    ++
    circ= ular-list elt1 elt2 ... -> list ++
    ++
    ++

    + Constructs a circular list of the elements. +-

    ++

    ++
    + (circular-list 'z 'q) =3D> (z q z q z q ...)
    + 
    +- ++
    + +- +-
    iota count [start= step] -> list +-
    ++
    iota count [start step] -> list ++
    ++
    ++

    + Returns a list containing the elements +-

    ++

    ++
    + (start start+step ... start+(=
    count-1)*step)
    + 
    ++

    + The start and step parameters default to 0 and = 1, respectively. + This procedure takes its name from the APL primitive. +- +-

    ++

    ++
    + (iota 5) =3D> (0 1 2 3 4)
    + (iota 5 0 -0.1) =3D> (0 -0.1 -0.2 -0.3 -0.4)
    + 
    ++
    +
    +=20 + +@@ -864,240 +954,282 @@ defined to accept such an argument. +

    + Note: the predicates proper-list?, circular-list?, and dotted-list? + partition the entire universe of Scheme values. +- ++

    +
    + +-
    +-proper-list? x -> boolean ++
    ++proper-list? x -> boolean + +-
    ++ ++
    ++

    + Returns true iff x is a proper list -- a finite, nil-termi= nated list. ++

    +

    +- More carefully: The empty list is a proper list. A pair whose cdr is = a=20 ++ More carefully: The empty list is a proper list. A pair whose cdr is a + proper list is also a proper list: ++

    +
    + <proper-list> ::=3D ()                            (Empty proper lis=
    t)
    +               |   (cons <x> <proper-list>)      (Proper-list =
    pair)
    + 
    ++

    + Note that this definition rules out circular lists. This + function is required to detect this case and return false. ++

    +

    + Nil-terminated lists are called "proper" lists by R5RS and Common Lisp. + The opposite of proper is improper. ++

    +

    + R5RS= binds this function to the variable list?. +-

    ++

    +
    + (not (proper-list? x)) =3D (or (dotted-list? x) (ci=
    rcular-list? x))
    + 
    +- ++
    + +- +-
    circular-list? x = -> boolean +-
    ++
    ci= rcular-list? x -> boolean ++
    ++
    ++

    + True if x is a circular list. A circular list is a value s= uch that + for every n >=3D 0, cdrn(x) is a pair. ++

    +

    + Terminology: The opposite of circular is finite. ++

    +
    + (not (circular-list? x)) =3D (or (proper-list? x) (=
    dotted-list? x))
    + 
    +- ++
    + +- +-
    dotted-list? x -&= gt; boolean +-
    ++
    dott= ed-list? x -> boolean ++
    ++
    ++

    + True if x is a finite, non-nil-terminated list. That is, t= here exists +- an n >=3D 0 such that cdrn(x= ) is neither a pair nor ().=20 ++ an n >=3D 0 such that cdrn(x= ) is neither a pair nor (). + This includes +- non-pair, non-() values (e.g. symbols, numbers),=20 ++ non-pair, non-() values (e.g. symbols, numbers), + which are considered to be dotted lists of length 0. ++

    +
    + (not (dotted-list? x)) =3D (or (proper-list? x) (ci=
    rcular-list? x))
    + 
    +- ++
    + +- +-
    pair? object ->= ; boolean +-
    ++
    pair? object -> boolean ++
    ++
    ++

    + [R5RS] + Returns #t if object is a pair; otherwise, #f. +-

    +-(pair? '(a . b)) =3D>  #t
    +-(pair? '(a b c)) =3D>  #t
    +-(pair? '())      =3D>  #f
    +-(pair? '#(a b))  =3D>  #f
    +-(pair? 7)        =3D>  #f
    +-(pair? 'a)       =3D>  #f
    ++

    ++
    ++(pair? '(a . b)) =3D>  #t
    ++(pair? '(a b c)) =3D>  #t
    ++(pair? '())      =3D>  #f
    ++(pair? '#(a b))  =3D>  #f
    ++(pair? 7)        =3D>  #f
    ++(pair? 'a)       =3D>  #f
    + 
    +- ++
    + +- +-
    null? object ->= ; boolean +-
    ++
    null? object -> boolean ++
    ++
    ++

    + [R5RS] + Returns #t if object is the empty list; otherwise, #f. +- ++

    ++
    + +- +-
    null-list? list -= > boolean +-
    ++
    null-l= ist? list -> boolean ++
    ++
    ++

    + List is a proper or circular list. This procedure returns = true if + the argument is the empty list (), and false otherwise. It is an + error to pass this procedure a value which is not a proper or + circular list. +- +- This procedure is recommended as the termination condition for=20 ++

    ++

    ++ This procedure is recommended as the termination condition for + list-processing procedures that are not defined on dotted lists. +- ++

    ++
    + +-
    ++
    + +-not-pair? x -> boolean +-
    +-
    (lambda (x) (not (pair? x)))
    ++not-pair? x -> boolean ++ ++
    ++
    (lambda (x) (not (pair? x)))
    ++

    + Provided as a procedure as it can be useful as the termination condit= ion + for list-processing procedures that wish to handle all finite lists, + both proper and dotted. +- ++

    ++
    + +-
    ++
    + +-list=3D elt=3D list1 ... -&= gt; boolean +-
    ++list=3D elt=3D list1 ... = -> boolean ++ ++
    ++

    + Determines list equality, given an element-equality procedure. +- Proper list A equals proper list B=20 ++ Proper list A equals proper list B + if they are of the same length, +- and their corresponding elements are equal,=20 +- as determined by elt=3D.=20 ++ and their corresponding elements are equal, ++ as determined by elt=3D. + If the element-comparison procedure's first argument is +- from listi,=20 +- then its second argument is from listi+1,=20 ++ from listi, ++ then its second argument is from listi+1, + i.e. it is always called as + (elt=3D a b) +- for a an element of list A,=20 ++ for a an element of list A, + and b an element of list B. ++

    +

    +- In the n-ary case,=20 +- every listi is compared to=20 +- listi+1=20 +- (as opposed, for example, to comparing=20 +- list1 to every listi,=20 +- for i>1).=20 +- If there are no list arguments at all,=20 ++ In the n-ary case, ++ every listi is compared to ++ listi+1 ++ (as opposed, for example, to comparing ++ list1 to every listi, ++ for i>1). ++ If there are no list arguments at all, + list=3D simply returns true. ++

    +

    + It is an error to apply list=3D to anything except prope= r lists. + While + implementations may choose to extend it to circular lists, note that = it + cannot reasonably be extended to dotted lists, as it provides no way = to + specify an equality procedure for comparing the list terminators. ++

    +

    + Note that the dynamic order in which the elt=3D procedure = is +- applied to pairs of elements is not specified.=20 ++ applied to pairs of elements is not specified. + For example, if list=3D is applied +- to three lists, A, B, and C,=20 ++ to three lists, A, B, and C, + it may first completely compare A to B, +- then compare B to C,=20 ++ then compare B to C, + or it may compare the first elements of A and B, +- then the first elements of B and C,=20 ++ then the first elements of B and C, + then the second elements of A and B, and so for= th. ++

    +

    +- The equality procedure must be consistent with eq?.=20 ++ The equality procedure must be consistent with eq?. + That is, it must be the case that +-

    +- (eq? x y) =3D> (elt= =3D x y). ++

    ++
    ++ (eq? x y) =3D> (= elt=3D x y). +
    +- Note that this implies that two lists which are eq?=20 ++

    ++ Note that this implies that two lists which are eq? + are always list=3D, as well; implementations may exploit t= his + fact to "short-cut" the element-by-element comparisons. +-

    +-(list=3D eq?) =3D> #t       ; Trivial cases
    +-(list=3D eq? '(a)) =3D> #t
    ++

    ++
    ++(list=3D eq?) =3D> #t       ; Trivial cases
    ++(list=3D eq? '(a)) =3D> #t
    + 
    +- ++
    +
    +=20 +=20 + +-

    Selectors

    ++

    Selectors

    +
    +=20 + +- +- +-
    car pair -> v= alue +-
    cdr pair -> v= alue +-
    ++
    car pair -> value ++
    ++
    cdr pair -> value ++
    ++
    ++

    + [R5RS] + These functions return the contents of the car and cdr field of their + argument, respectively. + Note that it is an error to apply them to the empty list. +-

    +-(car '(a b c))     =3D>  a             (cdr '(a b c))     =3D>  (b c)=20=
    =20
    +-(car '((a) b c d)) =3D>  (a)	     (cdr '((a) b c d)) =3D>  (b c d)
    +-(car '(1 . 2))     =3D>  1	     (cdr '(1 . 2))     =3D>  2=20=20=20=20=20=
    =20
    +-(car '())          =3D>  *error*	     (cdr '())          =3D>  *error*
    ++

    ++
    ++(car '(a b c))     =3D>  a             (cdr '(a b c))     =3D>  (b =
    c)
    ++(car '((a) b c d)) =3D>  (a)	     (cdr '((a) b c d)) =3D>  (b c d)
    ++(car '(1 . 2))     =3D>  1	     (cdr '(1 . 2))     =3D>  2
    ++(car '())          =3D>  *error*	     (cdr '())          =3D>  *err=
    or*
    + 
    +- ++
    +=20 +=20 + +- +- +- +- +-
    caar pair -> = value +-
    cadr pair -> = value +-
    : +-
    cdddar pair ->= ; value +-
    cddddr pair ->= ; value +-
    ++
    caar<= var> pair -> value ++
    ++
    cadr<= var> pair -> value ++
    ++
    : ++
    ++
    cddadr pair -> value ++
    ++
    cdddar pair -> value ++
    ++
    cddddr pair -> value ++
    ++
    ++

    + [R5RS] + These procedures are compositions of car and cdr, + where for example caddr could be defined by +-

    =20=20=20=20
    ++

    ++
    + (define caddr (lambda (x) (car (cdr (cdr x))))).
    + 
    ++

    + Arbitrary compositions, up to four deep, are provided. There are + twenty-eight of these procedures in all. +- ++

    ++
    + +- +-
    list-ref clist i = -> value +-
    ++
    list-ref<= /code> clist i -> value ++
    ++
    ++

    + [R5RS] +- Returns the ith element of clist.=20= =20 +- (This is the same as the car of=20 ++ Returns the ith element of clist. ++ (This is the same as the car of + (drop clist i).) +- It is an error if i >=3D n,=20 ++ It is an error if i >=3D n, + where n is the length of clist. +-

    =20=20=20=20
    +-(list-ref '(a b c d) 2) =3D> c
    +-
    =20=20=20=20 +- ++

    ++
    ++(list-ref '(a b c d) 2) =3D> c
    ++
    ++
    + +-
    ++
    + +-first   pair -> obje= ct +-
    ++first   pair -> ob= ject ++
    + +-second  pair -> object +-
    ++second  pair -> object = ++
    + +-third   pair -> obje= ct +-
    ++third   pair -> ob= ject ++
    + +-fourth  pair -> object +-
    ++fourth  pair -> object = ++
    + +-fifth   pair -> obje= ct +-
    ++fifth   pair -> ob= ject ++
    + +-sixth   pair -> obje= ct +-
    ++sixth   pair -> ob= ject ++
    + +-seventh pair -> object +-
    ++seventh pair -> object ++
    + +-eighth  pair -> object +-
    ++eighth  pair -> object = ++
    + +-ninth   pair -> obje= ct +-
    ++ninth   pair -> ob= ject ++
    + +-tenth   pair -> obje= ct +-
    +- Synonyms for car, cadr, caddr,= ...=20 ++tenth   pair -> ob= ject ++
    ++ Synonyms for car, cadr, caddr,= ... +=20 +-
    ++
    + (third '(a b c d e)) =3D> c
    + 
    +=20 + +-
    ++
    + +-car+cdr pair -> [x y] +-
    ++car+cdr pair -> [x y] ++
    + The fundamental pair deconstructor: +-
    ++
    + (lambda (p) (values (car p) (cdr p)))
    + 
    + This can, of course, be implemented more efficiently by a compiler. +- ++
    + +-
    ++
    + +-take x i -> list +-
    ++take x i -> list ++
    + +-drop x i -> object +-
    +- take returns the first i elements of list x.
    ++drop x i -> object ++
    ++ take returns the first i elements of list x.
    + drop returns all but the first i elements of = list x. +-
    ++
    + (take '(a b c d e)  2) =3D> (a b)
    + (drop '(a b c d e)  2) =3D> (c d e)
    + 
    + x may be any value -- a proper, circular, or dotted list: +-
    ++
    + (take '(1 2 3 . d) 2) =3D> (1 2)
    + (drop '(1 2 3 . d) 2) =3D> (3 . d)
    + (take '(1 2 3 . d) 3) =3D> (1 2 3)
    +@@ -1186,7 +1318,7 @@ partition the entire universe of Scheme values.
    + 
    + For a legal i, take and drop par= tition the list in a manner which + can be inverted with append: +-
    ++
    + (append (take x i) (drop x i)=
    ) =3D x
    + 
    + drop is exactly equivalent to performing i cd= r operations on x; +@@ -1195,114 +1327,138 @@ partition the entire universe of Scheme values. + If the argument is a list of non-zero length, take is gu= aranteed to + return a freshly-allocated list, even in the case where the entire + list is taken, e.g. (take lis (length lis)). +- ++
    + +-
    ++
    + +-take-right flist i -> object +-
    ++take-right flist i -> object ++
    ++
    + +-drop-right flist i -> list +-
    +- take-right returns the last i elements of flist.
    ++drop-right flist i -> list ++ ++
    ++

    ++ take-right returns the last i elements of flist.
    + drop-right returns all but the last i element= s of flist. +-

    ++

    ++
    + (take-right '(a b c d e) 2) =3D> (d e)
    + (drop-right '(a b c d e) 2) =3D> (a b c)
    + 
    ++

    + The returned list may share a common tail with the argument list. ++

    +

    + flist may be any finite list, either proper or dotted: +-

    ++

    ++
    + (take-right '(1 2 3 . d) 2) =3D> (2 3 . d)
    + (drop-right '(1 2 3 . d) 2) =3D> (1)
    + (take-right '(1 2 3 . d) 0) =3D> d
    + (drop-right '(1 2 3 . d) 0) =3D> (1 2 3)
    + 
    +- For a legal i, take-right and drop-righ= t partition the list in a manner=20 ++

    ++ For a legal i, take-right and drop-righ= t partition the list in a manner + which can be inverted with append: +-

    ++

    ++
    + (append (take flist i) (drop flist =
    i)) =3D flist
    + 
    ++

    + take-right's return value is guaranteed to share a commo= n tail with flist. +=20 + If the argument is a list of non-zero length, drop-right= is guaranteed to + return a freshly-allocated list, even in the case where nothing is + dropped, e.g. (drop-right lis 0). +- ++

    ++
    + +-
    ++
    + +-take! x i -> list +-
    ++take! x i -> list ++
    ++
    + +-drop-right! flist i -> list +-
    ++drop-right! flist i -> list ++ ++
    ++

    + take! and drop-right! are "linear-update" v= ariants of take and + drop-right: the procedure is allowed, but not required, = to alter the + argument list to produce the result. +-

    ++

    + If x is circular, take! may return a shorter-= than-expected list: +-

    ++

    ++
    + (take! (circular-list 1 3 5) 8) =3D> (1 3)
    + (take! (circular-list 1 3 5) 8) =3D> (1 3 5 1 3 5 1 3)
    + 
    +- ++
    +=20 + +-
    ++
    + +-split-at  x i -> [list object]= +-
    ++split-at  x i -> [list objec= t] ++
    ++
    + +-split-at! x i -> [list object] +-
    +- split-at splits the list x=20 +- at index i, returning a list of the=20 ++split-at! x i -> [list object] ++ ++
    ++

    ++ split-at splits the list x ++ at index i, returning a list of the + first i elements, and the remaining tail. It is equivalent + to +-

    ++

    ++
    + (values (take x i) (drop x i))
    + 
    ++

    + split-at! is the linear-update variant. It is allowed, b= ut not + required, to alter the argument list to produce the result. +-

    +-(split-at '(a b c d e f g h) 3) =3D>
    ++

    ++
    ++(split-at '(a b c d e f g h) 3) =3D>
    +     (a b c)
    +     (d e f g h)
    + 
    +- ++
    +=20 + +-
    ++
    + +-last pair -> object +-
    ++last pair -> object ++
    ++
    + +-last-pair pair -> pair +-
    +- last returns the last element of the non-empty,=20 ++last-pair pair -> pair ++ ++
    ++

    ++ last returns the last element of the non-empty, + finite list pair. + last-pair returns the last pair in the non-empty, + finite list pair. +- +-

    ++

    ++
    + (last '(a b c)) =3D> c
    + (last-pair '(a b c)) =3D> (c)
    + 
    +- ++
    +
    +=20 + +@@ -1313,174 +1469,208 @@ partition the entire universe of Scheme values. + =3D=3D=3D=3D length+ + =3D=3D=3D=3D length + =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D--> +-
    ++
    + +-length  list -> integer +-
    ++length  list -> integer= ++
    ++
    + +-length+ clist -> integer or #f= +-
    ++length+ clist -> integer or = #f ++ ++
    ++

    + Both length and length+ return the length o= f the argument. + It is an error to pass a value to length which is not a = proper + list (finite and nil-terminated). In particular, this means an + implementation may diverge or signal an error when length is + applied to a circular list. +-

    =20=20=20=20 ++

    ++

    + length+, on the other hand, returns #F when= applied to a circular + list. +-

    =20=20=20=20 +- The length of a proper list is a non-negative integer n su= ch that cdr=20 ++

    ++

    ++ The length of a proper list is a non-negative integer n su= ch that cdr + applied n times to the list produces the empty list. +- ++

    ++
    +=20 + +-
    ++
    + +-append  list1 ... ->= ; list +-
    ++append  list1 ... -&= gt; list ++
    ++
    + +-append! list1 ... -> lis= t +-
    ++append! list1 ... -> l= ist ++ ++
    ++

    + [R5RS] +- append returns a list consisting of the elements=20 ++ append returns a list consisting of the elements + of list1 + followed by the elements of the other list parameters. +-

    +-(append '(x) '(y))        =3D>  (x y)
    +-(append '(a) '(b c d))    =3D>  (a b c d)
    +-(append '(a (b)) '((c)))  =3D>  (a (b) (c))
    ++

    ++
    ++(append '(x) '(y))        =3D>  (x y)
    ++(append '(a) '(b c d))    =3D>  (a b c d)
    ++(append '(a (b)) '((c)))  =3D>  (a (b) (c))
    + 
    ++

    + The resulting list is always newly allocated, except that it +- shares structure with the final listi argument.= =20=20 +- This last argument may be any value at all;=20 ++ shares structure with the final listi argument. ++ This last argument may be any value at all; + an improper list results if it is not + a proper list. All other arguments must be proper lists. +-

    +-(append '(a b) '(c . d))  =3D>  (a b c . d)
    +-(append '() 'a)           =3D>  a
    +-(append '(x y))           =3D>  (x y)
    +-(append)                  =3D>  ()
    ++

    ++
    ++(append '(a b) '(c . d))  =3D>  (a b c . d)
    ++(append '() 'a)           =3D>  a
    ++(append '(x y))           =3D>  (x y)
    ++(append)                  =3D>  ()
    + 
    +- ++

    + append! is the "linear-update" variant of append + -- it is allowed, but not required, to alter cons cells in the argume= nt +- lists to construct the result list.=20 ++ lists to construct the result list. + The last argument is never altered; the result + list shares structure with this parameter. +- ++

    ++
    + +-
    ++
    + +-concatenate  list-of-lists -> = value +-
    ++concatenate  list-of-lists ->= ; value ++
    ++
    + +-concatenate! list-of-lists -> value= +-
    ++concatenate! list-of-lists -> val= ue ++ ++
    ++

    + These functions append the elements of their argument together. + That is, concatenate returns +-

    ++

    ++
    + (apply append list-of-lists)
    + 
    ++

    + or, equivalently, +-

    ++

    ++
    + (reduce-right append '() list-of-lists)
    + 
    +- ++

    + concatenate! is the linear-update variant, defined in + terms of append! instead of append. +-=20=20=20=20 ++

    +

    + Note that some Scheme implementations do not support passing more tha= n a +- certain number (e.g., 64) of arguments to an n-ary procedure= .=20=20 ++ certain number (e.g., 64) of arguments to an n-ary procedure. + In these implementations, the (apply append ...) idiom +- would fail when applied to long lists,=20 ++ would fail when applied to long lists, + but concatenate would continue to function properly. +- ++

    +

    +- As with append and append!,=20 ++ As with append and append!, + the last element of the input list may be any value at all. +- ++

    ++
    + +-
    ++
    + +-reverse  list -> list +-
    ++reverse  list -> list ++
    ++
    + +-reverse! list -> list +-
    ++reverse! list -> list ++ ++
    ++

    + [R5RS] +=20 + reverse returns a newly allocated list consisting of + the elements of list in reverse order. +-

    +-(reverse '(a b c)) =3D>  (c b a)
    ++

    ++
    ++(reverse '(a b c)) =3D>  (c b a)
    + (reverse '(a (b c) d (e (f))))
    +-    =3D>  ((e (f)) d (b c) a)
    ++    =3D>  ((e (f)) d (b c) a)
    + 
    ++

    + reverse! is the linear-update variant of reverse. +- It is permitted, but not required, to alter the argument's cons cells= =20 ++ It is permitted, but not required, to alter the argument's cons cells + to produce the reversed list. +- ++

    ++
    +=20 + +-
    ++
    + +-append-reverse  rev-head tai= l -> list +-
    ++append-reverse  rev-head t= ail -> list ++
    ++
    + +-append-reverse! rev-head tail -&g= t; list +-
    ++append-reverse! rev-head tail -= > list ++ ++
    ++

    + append-reverse returns + (append (reverse rev-head) tail). + It is provided because it is a common operation -- a common + list-processing style calls for this exact operation to transfer valu= es + accumulated in reverse order onto the front of another list, and beca= use + the implementation is significantly more efficient than the simple +- composition it replaces. (But note that this pattern of iterative=20 +- computation followed by a reverse can frequently be rewritten as a=20 +- recursion, dispensing with the reverse and append-= reverse steps, and=20 +- shifting temporary, intermediate storage from the heap to the stack,= =20 +- which is typically a win for reasons of cache locality and eager stor= age=20 ++ composition it replaces. (But note that this pattern of iterative ++ computation followed by a reverse can frequently be rewritten as a ++ recursion, dispensing with the reverse and append-= reverse steps, and ++ shifting temporary, intermediate storage from the heap to the stack, ++ which is typically a win for reasons of cache locality and eager stor= age + reclamation.) ++

    +

    + append-reverse! is just the linear-update variant -- it = is allowed, but + not required, to alter rev-head's cons cells to construct = the result. +- ++

    ++
    + +- +-
    zip clist1 clist2 ... -> list +-
    ++
    zip clist1 clist2 ... -> list ++
    ++
    +
    (lambda lists (apply map list lists))
    + 
    ++

    + If zip is passed n lists, it returns a list a= s long as the shortest + of these lists, each element of which is an n-element list= comprised + of the corresponding elements from the parameter lists. +- +-

    +-(zip '(one two three)=20
    ++

    ++
    ++(zip '(one two three)
    +      '(1 2 3)
    +      '(odd even odd even odd even odd even))
    +     =3D> ((one 1 odd) (two 2 even) (three 3 odd))
    +=20
    + (zip '(1 2 3)) =3D> ((1) (2) (3))
    + 
    ++

    + At least one of the argument lists must be finite: +-

    +-(zip '(3 1 4 1) (circular-list #f #t))=20
    +-    =3D> ((3 #f) (1 #t) (4 #f) (1 #t))
    ++

    ++
    ++(zip '(3 1 4 1) (circular-list #f #t))
    ++    =3D> ((3 #f) (1 #t) (4 #f) (1 #t))
    + 
    +- ++
    + +- +-
    unzip1 list -&= gt; list +- +-
    unzip2 list -&g= t; [list list] +- +-
    unzip3 list -&g= t; [list list list] +- +-
    unzip4 list -&g= t; [list list list list] +- +-
    unzip5 list -&g= t; [list list list list list] +-
    +- unzip1 takes a list of lists,=20 +- where every list must contain at least one element,=20 +- and returns a list containing the initial element of each such list.= =20 +- That is, it returns (map car lists).=20=20 ++
    unzip1 list -> list ++
    ++
    unzip2 list -> [list list] ++
    ++
    unzip3 list -> [list list list] ++
    ++
    unzip4 list -> [list list list list] ++
    ++
    unzip5 list -> [list list list list list] ++
    ++
    ++

    ++ unzip1 takes a list of lists, ++ where every list must contain at least one element, ++ and returns a list containing the initial element of each such list. ++ That is, it returns (map car lists). + unzip2 takes a list of lists, where every list must cont= ain at least + two elements, and returns two values: a list of the first elements, + and a list of the second elements. unzip3 does the same = for the first + three elements of the lists, and so forth. +- +-

    ++

    ++
    + (unzip2 '((1 one) (2 two) (3 three))) =3D>
    +-    (1 2 3)=20
    ++    (1 2 3)
    +     (one two three)
    + 
    +- ++
    + +-
    ++
    + +-count pred clist1 clist2 -> integer +-
    ++count pred clist1 clist2 -> integer ++ ++
    ++

    + pred is a procedure taking as many arguments as there +- are lists and returning a single value. It is applied=20 ++ are lists and returning a single value. It is applied + element-wise to the elements of the lists, and a count is + tallied of the number of elements that produce a true value. This cou= nt + is returned. count is "iterative" in that it is guarante= ed + to apply pred to the list elements in a + left-to-right order. + The counting stops when the shortest list expires. +-

    +-(count even? '(3 1 4 1 5 9 2 5 6)) =3D> 3
    +-(count < '(1 2 4 8) '(2 4 6 8 10 12 14 16)) =3D> 3
    ++

    ++
    ++(count even? '(3 1 4 1 5 9 2 5 6)) =3D> 3
    ++(count < '(1 2 4 8) '(2 4 6 8 10 12 14 16)) =3D> 3
    + 
    ++

    + At least one of the argument lists must be finite: +-

    +-(count < '(3 1 4 1) (circular-list 1 10)) =3D> 2
    ++

    ++
    ++(count < '(3 1 4 1) (circular-list 1 10)) =3D> 2
    + 
    +- ++
    + +=20 + +-

    Fold, unfold & map

    ++

    Fold, unfold & map

    +
    + +-
    ++
    + +-fold kons knil clist1 clist= 2 ... -> value +-
    +- The fundamental list iterator.=20 ++fold kons knil clist1 cli= st2 ... -> value ++ ++
    ++

    ++ The fundamental list iterator. ++

    +

    + First, consider the single list-parameter case. If clist1 =3D (e1 e2 ... = en), + then this procedure returns +-

    ++

    ++
    + (kons en ... (kons e2 (kons e1 knil)) ... ) +
    ++

    + That is, it obeys the (tail) recursion +-

    ++

    ++
    + (fold kons knil lis) =3D (fold kons=
     (kons (car lis) knil) (cdr lis=
    ))
    + (fold kons knil '()) =3D knil
    + 
    +- ++

    + Examples: +-

    ++

    ++
    + (fold + 0 lis)			; Add up the elements of LIS.
    +=20
    + (fold cons '() lis)		; Reverse LIS.
    +@@ -1581,297 +1784,357 @@ partition the entire universe of Scheme values.
    +       0
    +       lis)
    + 
    +- ++

    + If n list arguments are provided, then the kons= function must take + n+1 parameters: one element from each list, and the "seed"= or fold + state, which is initially knil. The fold operation termina= tes when + the shortest list runs out of values: +-

    ++

    ++
    + (fold cons* '() '(a b c) '(1 2 3 4 5)) =3D> (c 3 b 2 a 1)
    + 
    ++

    + At least one of the list arguments must be finite. +- ++

    ++
    + +-
    ++
    + +-fold-right kons knil clist1= clist2 ... -> value +-
    +- The fundamental list recursion operator.=20 ++fold-right kons knil clist1 clist2 ... -> value ++ ++
    +

    +- First, consider the single list-parameter case. If clist1 =3D (e1 e2 ...= en),=20 ++ The fundamental list recursion operator. ++

    ++

    ++ First, consider the single list-parameter case. If clist1 =3D (e1 e2 ...= en), + then this procedure returns +-

    ++

    ++
    + (kons e1 (kons e2 ... (kons en knil))) +
    ++

    + That is, it obeys the recursion +-

    ++

    ++
    + (fold-right kons knil lis) =3D (kon=
    s (car lis) (fold-right kons knil (c=
    dr lis)))
    + (fold-right kons knil '()) =3D knil
    + 
    +-=20=20=20=20=20=20=20=20 ++

    + Examples: +-

    ++

    ++
    + (fold-right cons '() lis)		; Copy LIS.
    +=20
    + ;; Filter the even numbers out of LIS.
    + (fold-right (lambda (x l) (if (even? x) (cons x l) l)) '() lis))
    + 
    +- ++

    + If n list arguments are provided, then the kons= function must take + n+1 parameters: one element from each list, and the "seed"= or fold + state, which is initially knil. The fold operation termina= tes when + the shortest list runs out of values: +-

    ++

    ++
    + (fold-right cons* '() '(a b c) '(1 2 3 4 5)) =3D> (a 1 b 2 c 3)
    + 
    ++

    + At least one of the list arguments must be finite. +- ++

    ++
    + +-
    ++
    + +-pair-fold kons knil clist1 = clist2 ... -> value +-
    +- Analogous to fold, but kons is applied to suc= cessive sublists of the=20 ++pair-fold kons knil clist1 clist2 ... -> value ++ ++
    ++

    ++ Analogous to fold, but kons is applied to suc= cessive sublists of the + lists, rather than successive elements -- that is, kons is= applied to the + pairs making up the lists, giving this (tail) recursion: +-

    ++

    ++
    + (pair-fold kons knil lis) =3D (let ((tai=
    l (cdr lis)))
    +                               (pair-fold kons (kons=
     lis knil) tail))
    + (pair-fold kons knil '()) =3D kni=
    l
    + 
    ++

    + For finite lists, the kons function may reliably apply + set-cdr! to the pairs it is given + without altering the sequence of execution. ++

    +

    + Example: +-

    ++

    ++
    + ;;; Destructively reverse a list.
    +-(pair-fold (lambda (pair tail) (set-cdr! pair tail) pair) '() lis))
    ++(pair-fold (lambda (pair tail) (set-cdr! pair tail) pair) '() lis)
    + 
    +- ++

    + At least one of the list arguments must be finite. +- +-=20=20=20=20 ++

    ++
    + +-
    ++
    + +-pair-fold-right kons knil clist1<= /sub> clist2 ... -> value +-
    ++pair-fold-right kons knil clist= 1 clist2 ... -> value ++ ++
    ++

    + Holds the same relationship with fold-right that p= air-fold holds with fold. + Obeys the recursion +-

    +-(pair-fold-right kons knil lis) =3D=20
    ++

    ++
    ++(pair-fold-right kons knil lis) =3D
    +     (kons lis (pair-fold-right kons knil (cdr lis)))
    + (pair-fold-right kons knil '()) =3D knil
    + 
    +-=20=20=20=20 ++

    + Example: +-

    ++

    ++
    + (pair-fold-right cons '() '(a b c)) =3D> ((a b c) (b c) (c))
    + 
    +- ++

    + At least one of the list arguments must be finite. +- ++

    ++
    + +-
    ++
    + +-reduce f ridentity list -> value +-
    +- reduce is a variant of fold.=20 ++reduce f ridentity list -> value<= /var> ++ ++
    +

    +- ridentity should be a "right identity" of the procedure f -- that is,=20 ++ reduce is a variant of fold. ++

    ++

    ++ ridentity should be a "right identity" of the procedure f -- that is, + for any value x acceptable to f, +-

    ++

    ++
    + (f x ridentity) =3D x
    + 
    +-=20=20=20=20 ++

    + reduce has the following definition: +-

    +-If list =3D (), return ridentity;
    ++

    ++
    ++If list =3D (), return ridentity;
    + Otherwise, return (fold f (car list) (cdr = list)). +
    +- ...in other words, we compute=20 ++

    ++ ...in other words, we compute + (fold f ridentity list). ++

    +

    + Note that ridentity is used only in the empty-lis= t case. + You typically use reduce when applying f is e= xpensive and you'd + like to avoid the extra application incurred when fold a= pplies + f to the head of list and the identity value, +- redundantly producing the same value passed in to f.=20 +- For example, if f involves searching a file directory or=20 +- performing a database query, this can be significant.=20 ++ redundantly producing the same value passed in to f. ++ For example, if f involves searching a file directory or ++ performing a database query, this can be significant. + In general, however, fold is useful in many contexts whe= re reduce is not + (consider the examples given in the fold definition -- o= nly one of the +- five folds uses a function with a right identity.=20 ++ five folds uses a function with a right identity. + The other four may not be performed with reduce). +- ++

    +

    + Note: MIT Scheme and Haskell flip F's arg order for their reduc= e and + fold functions. +- +-

    ++

    ++
    + ;; Take the max of a list of non-negative integers.
    + (reduce max 0 nums) ; i.e., (apply max 0 nums)
    + 
    +- ++
    + +-
    ++
    + +-reduce-right f ridentity list -> va= lue +-
    ++reduce-right f ridentity list -> = value ++ ++
    ++

    + reduce-right is the fold-right variant of reduce. + It obeys the following definition: +-

    ++

    ++
    + (reduce-right f ridentity '()) =3D ridentity
    + (reduce-right f ridentity '(e1)) =3D (f e1 ridentity) =3D e1
    + (reduce-right f ridentity '(e1 e2 ...)) =3D
    +     (f e1 (reduce f ride=
    ntity (e2 ...)))
    + 
    +- ...in other words, we compute=20 ++

    ++ ...in other words, we compute + (fold-right f ridentity list)<= /code>. +-=20=20=20=20 +-

    ++

    ++
    + ;; Append a bunch of lists together.
    + ;; I.e., (apply append list-of-lists)
    + (reduce-right append '() list-of-lists)
    + 
    +- ++
    + +-
    ++
    + +-unfold p f g seed [tail-gen] -> lis= t +-
    ++unfold p f g seed [tail-gen] -> l= ist ++ ++
    ++

    + unfold is best described by its basic recursion: +-

    +-(unfold p f g seed) =3D=20
    ++

    ++
    ++(unfold p f g seed) =3D
    +     (if (p seed) (tail-gen seed)
    +         (cons (f seed)
    +               (unfold p f g (g seed))))
    + 
    +
    +-
    p
    Determines when to stop unfolding. +-
    f
    Maps each seed value to the corresponding list ele= ment. +-
    g
    Maps each seed value to next seed value. +-
    seed
    The "state" value for the unfold. +-
    tail-gen
    Creates the tail of the list;=20 +- defaults to (lambda (x) '()) ++
    p
    ++
    Determines when to stop unfolding.
    ++
    f
    ++
    Maps each seed value to the corresponding list element.
    ++
    g
    ++
    Maps each seed value to next seed value.
    ++
    seed
    ++
    The "state" value for the unfold.
    ++
    tail-gen
    ++
    Creates the tail of the list; defaults to (lambda (x) '())
    +
    +

    + In other words, we use g to generate a sequence of seed va= lues +-

    ++

    ++
    + seed, g(seed), g2(= seed), g3(seed), ... +
    +- These seed values are mapped to list elements by f,=20 +- producing the elements of the result list in a left-to-right order.=20 ++

    ++ These seed values are mapped to list elements by f, ++ producing the elements of the result list in a left-to-right order. + P says when to stop. +- ++

    +

    +- unfold is the fundamental recursive list constructor,=20 +- just as fold-right is=20 ++ unfold is the fundamental recursive list constructor, ++ just as fold-right is + the fundamental recursive list consumer. + While unfold may seem a bit abstract + to novice functional programmers, it can be used in a number of ways: +- +-

    ++

    ++
    + ;; List of squares: 1^2 ... 10^2
    + (unfold (lambda (x) (> x 10))
    +         (lambda (x) (* x x))
    + 	(lambda (x) (+ x 1))
    + 	1)
    +-=09=09
    ++
    + (unfold null-list? car cdr lis) ; Copy a proper list.
    +=20
    + ;; Read current input port into a list of values.
    + (unfold eof-object? values (lambda (x) (read)) (read))
    +=20
    + ;; Copy a possibly non-proper list:
    +-(unfold not-pair? car cdr lis=20
    ++(unfold not-pair? car cdr lis
    +               values)
    +=20
    + ;; Append HEAD onto TAIL:
    +-(unfold null-list? car cdr head=20
    ++(unfold null-list? car cdr head
    +               (lambda (x) tail))
    + 
    +- +- Interested functional programmers may enjoy noting that=20 ++

    ++ Interested functional programmers may enjoy noting that + fold-right and unfold +- are in some sense inverses.=20 +- That is, given operations knull?, kar,=20 ++ are in some sense inverses. ++ That is, given operations knull?, kar, + kdr, kons, and knil satisfying +-

    ++

    ++
    + (kons (kar x) (kdr x)) =3D x +- and=20 ++ and + (knull? knil) =3D #t +
    ++

    + then +-

    ++

    ++
    + (fold-right kons knil (unfold knull? kar kdr x)) =3D x +
    ++

    + and +-

    ++

    ++
    + (unfold knull? kar kdr (fold-right= kons knil x)) =3D x. +
    +- ++

    + This combinator sometimes is called an "anamorphism;" when an + explicit tail-gen procedure is supplied, it is called an + "apomorphism." +- +- ++

    ++
    + +-
    ++
    + +-unfold-right p f g seed [tail] -> l= ist +-
    ++unfold-right p f g seed [tail] ->= list ++ ++
    ++

    + unfold-right constructs a list with the following loop: +-

    ++

    ++
    + (let lp ((seed seed) (lis tail))
    +   (if (p seed) lis
    +       (lp (g seed)
    +           (cons (f seed) lis))))
    + 
    +
    +-
    p
    Determines when to stop unfolding. +-
    f
    Maps each seed value to the corresponding list ele= ment. +-
    g
    Maps each seed value to next seed value. +-
    seed
    The "state" value for the unfold. +-
    tail
    list terminator; defaults to '(). ++
    p
    ++
    Determines when to stop unfolding.
    ++
    f
    ++
    Maps each seed value to the corresponding list element.
    ++
    g
    ++
    Maps each seed value to next seed value.
    ++
    seed
    ++
    The "state" value for the unfold.
    ++
    tail
    ++
    list terminator; defaults to '().
    +
    +

    + In other words, we use g to generate a sequence of seed va= lues +-

    ++

    ++
    + seed, g(seed), g2(= seed), g3(seed), ... +
    +- These seed values are mapped to list elements by f,=20 +- producing the elements of the result list in a right-to-left order.=20 ++

    ++ These seed values are mapped to list elements by f, ++ producing the elements of the result list in a right-to-left order. + P says when to stop. +- ++

    +

    +- unfold-right is the fundamental iterative list construct= or,=20 ++ unfold-right is the fundamental iterative list construct= or, + just as fold is the +- fundamental iterative list consumer.=20 ++ fundamental iterative list consumer. + While unfold-right may seem a bit abstract + to novice functional programmers, it can be used in a number of ways: +-

    ++

    ++
    + ;; List of squares: 1^2 ... 10^2
    +-(unfold-right zero?=20
    ++(unfold-right zero?
    +               (lambda (x) (* x x))
    +               (lambda (x) (- x 1))
    +               10)
    +-=09
    ++
    + ;; Reverse a proper list.
    + (unfold-right null-list? car cdr lis)
    +=20
    +@@ -1881,241 +2144,290 @@ Otherwise,    return (fold f (c=
    ar list) (cdr li
    + ;; (append-reverse rev-head tail)
    + (unfold-right null-list? car cdr rev-head tail)
    + 
    +- +- Interested functional programmers may enjoy noting that=20 ++

    ++ Interested functional programmers may enjoy noting that + fold and unfold-right +- are in some sense inverses.=20 +- That is, given operations knull?, kar,=20 ++ are in some sense inverses. ++ That is, given operations knull?, kar, + kdr, kons, and knil satisfying +-

    ++

    ++
    + (kons (kar x) (kdr x)) =3D x +- and=20 ++ and + (knull? knil) =3D #t +
    ++

    + then +-

    ++

    ++
    + (fold kons knil (unfold-right knull? kar kdr x)) =3D x +
    ++

    + and +-

    ++

    ++
    + (unfold-right knull? kar kdr (fold= kons knil x)) =3D x. +
    +- ++

    + This combinator presumably has some pretentious mathematical name; + interested readers are invited to communicate it to the author. +- ++

    ++
    + +-
    ++
    + +-map proc clist1 clist2= ... -> list +-
    +- [R5RS+] +- +- proc is a procedure taking as many arguments=20 +- as there are list arguments and returning a single value.=20=20 ++map proc clist1 clist2 ... -> list ++ ++
    ++

    ++ [R5RS+] ++ proc is a procedure taking as many arguments ++ as there are list arguments and returning a single value. + map applies proc element-wise to the elements +- of the lists and returns a list of the results,=20 +- in order.=20=20 +- The dynamic order in which proc=20 ++ of the lists and returns a list of the results, ++ in order. ++ The dynamic order in which proc + is applied to the elements of the lists is unspecified. +-=20=20=20=20 +-

    +-(map cadr '((a b) (d e) (g h))) =3D>  (b e h)
    ++

    ++
    ++(map cadr '((a b) (d e) (g h))) =3D>  (b e h)
    +=20
    + (map (lambda (n) (expt n n))
    +      '(1 2 3 4 5))
    +-    =3D>  (1 4 27 256 3125)
    ++    =3D>  (1 4 27 256 3125)
    +=20
    +-(map + '(1 2 3) '(4 5 6)) =3D>  (5 7 9)
    ++(map + '(1 2 3) '(4 5 6)) =3D>  (5 7 9)
    +=20
    + (let ((count 0))
    +   (map (lambda (ignored)
    +          (set! count (+ count 1))
    +          count)
    +-       '(a b))) =3D>  (1 2) or (2 1)
    ++       '(a b))) =3D>  (1 2) or (2 1)
    + 
    +- +- This procedure is extended from its=20 ++

    ++ This procedure is extended from its + R5RS= +- specification to allow the arguments to be of unequal length;=20 +- it terminates when the shortest list runs out.=20 ++ specification to allow the arguments to be of unequal length; ++ it terminates when the shortest list runs out. ++

    +

    + At least one of the argument lists must be finite: +-

    +-(map + '(3 1 4 1) (circular-list 1 0)) =3D> (4 1 5 1)
    ++

    ++
    ++(map + '(3 1 4 1) (circular-list 1 0)) =3D> (4 1 5 1)
    + 
    +- ++
    + +-
    ++
    + +-for-each proc clist1 clist<= sub>2 ... -> unspecified +-
    ++for-each proc clist1 clis= t2 ... -> unspecified ++ ++
    ++

    + [R5RS+] +- +- The arguments to for-each are like the arguments to=20 ++

    ++

    ++ The arguments to for-each are like the arguments to + map, but + for-each calls proc for its side effects rat= her +- than for its values.=20=20 +- Unlike map, for-each is guaranteed to call= =20 ++ than for its values. ++ Unlike map, for-each is guaranteed to call + proc on the elements of the lists in order from the first +- element(s) to the last,=20 ++ element(s) to the last, + and the value returned by for-each is unspecified. +-

    ++

    ++
    + (let ((v (make-vector 5)))
    +   (for-each (lambda (i)
    +               (vector-set! v i (* i i)))
    +             '(0 1 2 3 4))
    +-  v)  =3D>  #(0 1 4 9 16)
    ++  v)  =3D>  #(0 1 4 9 16)
    + 
    +-=20=20=20=20 ++

    + This procedure is extended from its + R5RS= +- specification to allow the arguments to be of unequal length;=20 +- it terminates when the shortest list runs out.=20 ++ specification to allow the arguments to be of unequal length; ++ it terminates when the shortest list runs out. ++

    +

    + At least one of the argument lists must be finite. +- ++

    ++
    + +-
    ++
    + +-append-map  f clist1 clist2 ... -> value +-
    ++append-map  f clist1<= /sub> clist2 ... -> value ++
    ++
    + +-append-map! f clist1 c= list2 ... -> value +-
    +- Equivalent to=20 +-
    ++append-map! f clist1= clist2 ... -> value ++ ++
    ++

    ++ Equivalent to ++

    ++
    + (apply append (map f clist1 clist<= sub>2 ...)) +
    ++

    + and +-

    ++

    ++
    + (apply append! (map f clist1 clist<= sub>2 ...)) +
    +- ++

    + Map f over the elements of the lists, just as in the map function. + However, the results of the applications are appended together to + make the final result. append-map uses append to append the results + together; append-map! uses append!. ++

    +

    + The dynamic order in which the various applications of f a= re made is + not specified. ++

    +

    + Example: +-

    ++

    ++
    + (append-map! (lambda (x) (list x (- x))) '(1 3 8))
    +     =3D> (1 -1 3 -3 8 -8)
    + 
    +- ++

    + At least one of the list arguments must be finite. +- ++

    ++
    + +-
    ++
    + +-map! f list1 clist2 ... -> list +-
    +- Linear-update variant of map -- map! is all= owed, but not required, to=20 ++map! f list1 clist2<= /sub> ... -> list ++ ++
    ++

    ++ Linear-update variant of map -- map! is all= owed, but not required, to + alter the cons cells of list1 to construct the = result list. ++

    +

    + The dynamic order in which the various applications of f a= re made is + not specified. +-=20=20=20=20 ++

    ++

    + In the n-ary case, clist2, clist3, ... must have at least as many + elements as list1. +- ++

    ++
    + +-
    ++
    + +-map-in-order f clist1<= /sub> clist2 ... -> list +-
    ++map-in-order f clist= 1 clist2 ... -> list ++ ++
    ++

    + A variant of the map procedure that guarantees to apply = f across + the elements of the listi arguments in a left-t= o-right order. This + is useful for mapping procedures that both have side effects and + return useful values. ++

    +

    + At least one of the list arguments must be finite. +- ++

    ++
    + +-
    ++
    + +-pair-for-each f clist1 clis= t2 ... -> unspecific +-
    ++pair-for-each f clist1 cl= ist2 ... -> unspecific ++ ++
    ++

    + Like for-each, but f is applied to successive= sublists of the argument + lists. That is, f is applied to the cons cells of the list= s, rather + than the lists' elements. These applications occur in left-to-right + order. ++

    +

    + The f procedure may reliably apply set-cdr! t= o the pairs it is given + without altering the sequence of execution. +- +-

    ++

    ++
    + (pair-for-each (lambda (pair) (display pair) (newline)) '(a b c)) =3D=3D&=
    gt;
    +     (a b c)
    +     (b c)
    +     (c)
    + 
    +- ++

    + At least one of the list arguments must be finite. +- ++

    ++
    + +-
    ++
    + +-filter-map f clist1 clist2 ... -> list +-
    ++filter-map f clist1 clist= 2 ... -> list ++ ++
    ++

    + Like map, but only true values are saved. +-

    ++

    ++
    + (filter-map (lambda (x) (and (number? x) (* x x))) '(a 1 b 3 c 7))
    +     =3D> (1 9 49)
    + 
    ++

    + The dynamic order in which the various applications of f a= re made is + not specified. ++

    +

    + At least one of the list arguments must be finite. ++

    ++
    +
    +=20 + +-

    Filtering & partitioning ++

    Filtering & partitioning

    +
    +=20 + +-
    ++
    + +-filter pred list -> list +-
    ++filter pred list -> list ++ ++
    ++

    + Return all the elements of list that satisfy predicate pred. + The list is not disordered -- elements that appear in the result list + occur in the same order as they occur in the argument list. + The returned list may share a common tail with the argument list. + The dynamic order in which the various applications of pred are made is + not specified. +-=20=20=20=20 +-

    ++

    ++
    + (filter even? '(0 7 8 8 43 -4)) =3D> (0 8 8 -4)
    + 
    +- ++
    + +-
    ++
    + +-partition pred list -> [list list]<= /var> +-
    ++partition pred list -> [list list= ] ++ ++
    ++

    + Partitions the elements of list with predicate pred, and returns two + values: the list of in-elements and the list of out-elements. + The list is not disordered -- elements occur in the result lists +@@ -2123,71 +2435,88 @@ Otherwise, return (fold f (car= list) (cdr li + The dynamic order in which the various applications of pred are made is + not specified. One of the returned lists may share a common tail with= the + argument list. +- +-

    +-(partition symbol? '(one 2 3 four five 6)) =3D>=20
    ++

    ++
    ++(partition symbol? '(one 2 3 four five 6)) =3D>
    +     (one four five)
    +     (2 3 6)
    + 
    +- ++
    + +-
    ++
    + +-remove pred list -> list +-
    ++remove pred list -> list ++ ++
    ++

    + Returns list without the elements that satisfy predicate <= var>pred: +-

    ++

    ++
    + (lambda (pred list) (filter (lambda (x) (not (pred x))) list))
    + 
    ++

    + The list is not disordered -- elements that appear in the result list + occur in the same order as they occur in the argument list. + The returned list may share a common tail with the argument list. +- The dynamic order in which the various applications of pred are made is=20 ++ The dynamic order in which the various applications of pred are made is + not specified. +-=20=20=20=20 +-

    ++

    ++
    + (remove even? '(0 7 8 8 43 -4)) =3D> (7 43)
    + 
    +- ++
    + +-
    ++
    + +-filter!    pred li= st -> list +-
    ++filter!    pred = list -> list ++
    ++
    + +-partition! pred list -> [list = list] +-
    ++partition! pred list -> [lis= t list] ++
    ++
    + +-remove!    pred li= st -> list +-
    ++remove!    pred = list -> list ++ ++
    ++

    + Linear-update variants of filter, partition= and remove. + These procedures are allowed, but not required, to alter the cons cel= ls + in the argument list to construct the result lists. +- ++

    ++
    +
    +=20 + +-

    Searching

    +-

    ++

    Searching

    +=20 ++

    + The following procedures all search lists for a leftmost element satisfyi= ng + some criteria. This means they do not always examine the entire list; thu= s, + there is no efficient way for them to reliably detect and signal an error= when + passed a dotted or circular list. Here are the general rules describing h= ow + these procedures work when applied to different kinds of lists: ++

    +=20 +
    +-
    Proper lists:=20 +-
    The standard, canonical behavior happens in this case. +- +-
    Dotted lists:=20 +-
    It is an error to pass these procedures a dotted list ++
    Proper lists: ++
    ++
    ++

    ++ The standard, canonical behavior happens in this case. ++

    ++
    ++
    Dotted lists: ++
    ++
    ++

    ++ It is an error to pass these procedures a dotted list + that does not contain an element satisfying the search + criteria. That is, it is an error if the procedure has + to search all the way to the end of the dotted list. +@@ -2200,23 +2529,31 @@ these procedures work when applied to different ki= nds of lists: + which is compliant with this SRFI may not rely on any + particular behavior. Future SRFI's may refine SRFI-1 + to define specific behavior in this case. +-

    ++

    ++

    + In brief, SRFI-1 compliant code may not pass a dotted + list argument to these procedures. +- +-

    Circular lists:=20 +-
    It is an error to pass these procedures a circular list ++

    ++
    ++
    Circular lists: ++
    ++
    ++

    ++ It is an error to pass these procedures a circular list + that does not contain an element satisfying the search +- criteria. Note that the procedure is not required to=20 ++ criteria. Note that the procedure is not required to + detect this case; it may simply diverge. It is, however, + acceptable to search a circular list if the search = is + successful -- that is, if the list contains an ele= ment + satisfying the search criteria. ++

    ++
    +
    +

    + Here are some examples, using the find and any = procedures as canonical + representatives: +-

    ++

    ++
    + ;; Proper list -- success
    + (find even? '(1 2 3))	=3D> 2
    + (any  even? '(1 2 3))	=3D> #t
    +@@ -2230,7 +2567,7 @@ representatives:
    + (any  even? '(1 3 . x))	=3D> error
    +=20
    + ;; The dotted list contains an element satisfying the search.
    +-;; This case is not specified -- it could be success, an error,=20
    ++;; This case is not specified -- it could be success, an error,
    + ;; or some third possibility.
    + (find even? '(1 2 . x))	=3D> error/undefined
    + (any  even? '(1 2 . x))	=3D> error/undefined ; success, error or other.
    +@@ -2248,17 +2585,19 @@ representatives:
    + 
    +-
    ++
    + +-find pred clist -> value +-
    ++find pred clist -> value ++ ++
    ++

    + Return the first element of clist that satisfies predicate= pred; + false if no element does. +- +-

    ++

    ++
    + (find even? '(3 1 4 1 5 9)) =3D> 4
    + 
    +- ++

    + Note that find has an ambiguity in its lookup semantics = -- if find + returns #f, you cannot tell (in general) if it found a <= code>#f element + that satisfied pred, or if it did not find any element at = all. In +@@ -2267,145 +2606,168 @@ representatives: + guaranteed to have an element satisfying pred. However, in= cases + where this ambiguity can arise, you should use find-tail= instead of + find -- find-tail has no such ambiguity: +-

    ++

    ++
    + (cond ((find-tail pred lis) =3D> (lambda (pair) ...)) ; Handle (CAR PA=
    IR)
    +       (else ...)) ; Search failed.
    + 
    +- ++
    + +-
    ++
    + +-find-tail pred clist -> pair or fal= se +-
    ++find-tail pred clist -> pair or f= alse ++ ++
    ++

    + Return the first pair of clist whose car satisfies pr= ed. If no pair does, + return false. ++

    +

    + find-tail can be viewed as a general-predicate variant o= f the member + function. ++

    +

    +- Examples:=20 +-

    ++    Examples:
    ++

    ++
    + (find-tail even? '(3 1 37 -8 -5 0 0)) =3D> (-8 -5 0 0)
    + (find-tail even? '(3 1 37 -5)) =3D> #f
    +=20
    + ;; MEMBER X LIS:
    + (find-tail (lambda (elt) (equal? x elt)) lis)
    + 
    +- ++

    + In the circular-list case, this procedure "rotates" the list. +- ++

    +

    +- Find-tail is essentially drop-while,=20 +- where the sense of the predicate is inverted:=20 ++ Find-tail is essentially drop-while, ++ where the sense of the predicate is inverted: + Find-tail searches until it finds an element satisfying +- the predicate; drop-while searches until it finds an=20 ++ the predicate; drop-while searches until it finds an + element that doesn't satisfy the predicate. +- ++

    ++
    + +-
    ++
    + +-take-while  pred clist -> list= +-
    ++take-while  pred clist -> li= st ++
    ++
    + +-take-while! pred clist -> list +-
    +- ++take-while! pred clist -> list ++ ++
    ++

    + Returns the longest initial prefix of clist whose elements all + satisfy the predicate pred. +- ++

    +

    + Take-while! is the linear-update variant. It is allowed, but= not + required, to alter the argument list to produce the result. +- +-

    +-(take-while even? '(2 18 3 10 22 9)) =3D> (2 18)
    ++

    ++
    ++(take-while even? '(2 18 3 10 22 9)) =3D> (2 18)
    + 
    +- ++
    + +-
    ++
    + +-drop-while pred clist -> list +-
    ++drop-while pred clist -> list ++ ++
    ++

    + Drops the longest initial prefix of clist whose elements all + satisfy the predicate pred, and returns the rest of the list. +- +-

    +-(drop-while even? '(2 18 3 10 22 9)) =3D> (3 10 22 9)
    ++

    ++
    ++(drop-while even? '(2 18 3 10 22 9)) =3D> (3 10 22 9)
    + 
    ++

    + The circular-list case may be viewed as "rotating" the list. +- ++

    ++
    +=20 + +-
    ++
    + +-span   pred clist -> [lis= t clist] +-
    ++span   pred clist -> [l= ist clist] ++
    ++
    + +-span!  pred list  -> [lis= t list] +-
    ++span!  pred list  -> [l= ist list] ++
    ++
    + +-break  pred clist -> [list cli= st] +-
    ++break  pred clist -> [list c= list] ++
    ++
    + +-break! pred list  -> [list lis= t] +-
    +- ++break! pred list  -> [list l= ist] ++ ++
    ++

    + Span splits the list into the longest initial prefix whose +-elements all satisfy pred, and the remaining tail.=20 +-Break inverts the sense of the predicate:=20 ++elements all satisfy pred, and the remaining tail. ++Break inverts the sense of the predicate: + the tail commences with the first element of the input list + that satisfies the predicate. +- ++

    +

    +-In other words:=20 +-span finds the initial span of elements=20 +-satisfying pred,=20 +-and break breaks the list at the first element satisfying=20 ++In other words: ++span finds the intial span of elements ++satisfying pred, ++and break breaks the list at the first element satisfying + pred. +- ++

    +

    +-Span is equivalent to=20 +-

    +-(values (take-while pred clist)=20
    ++Span is equivalent to
    ++

    ++
    ++(values (take-while pred clist)
    +         (drop-while pred clist))
    + 
    +- +

    +-Span! and break! are the linear-update variants= .=20 +-They are allowed, but not required,=20 ++Span! and break! are the linear-update variants. ++They are allowed, but not required, + to alter the argument list to produce the result. +- +-

    +-(span even? '(2 18 3 10 22 9)) =3D>
    ++

    ++
    ++(span even? '(2 18 3 10 22 9)) =3D>
    +   (2 18)
    +   (3 10 22 9)
    +=20
    +-(break even? '(3 1 4 1 5 9)) =3D>
    ++(break even? '(3 1 4 1 5 9)) =3D>
    +   (3 1)
    +   (4 1 5 9)
    + 
    +- ++
    +=20 + +-
    ++
    + +-any pred clist1 clist2= ... -> value +-
    ++any pred clist1 clist2 ... -> value ++ ++
    ++

    + Applies the predicate across the lists, returning true if the predica= te + returns true on any application. ++

    +

    + If there are n list arguments clist1= ... clistn, then pred must be a +- procedure taking n arguments and returning a boolean resul= t. ++ procedure taking n arguments ++ and returning a single value, interpreted as a boolean (that is, ++ #f means false, and any other value means true). ++

    +

    + any applies pred to the first elements of the= clisti parameters. + If this application returns a true value, any immediatel= y returns +@@ -2413,37 +2775,45 @@ to alter the argument list to produce the result. + elements of the clisti parameters, then the thi= rd, and so forth. + The iteration stops when a true value is produced or one of the lists= runs + out of values; in +- the latter case, any returns #f.=20 ++ the latter case, any returns #f. + The application of pred to the last element of the + lists is a tail call. ++

    +

    + Note the difference between find and any --= find returns the element + that satisfied the predicate; any returns the true value= that the + predicate produced. ++

    +

    + Like every, any's name does not end with a = question mark -- this is to + indicate that it does not return a simple boolean (#t or= #f), but a + general value. +- +-

    ++

    ++
    + (any integer? '(a 3 b 2.7))   =3D> #t
    + (any integer? '(a 3.1 b 2.7)) =3D> #f
    + (any < '(3 1 4 1 5)
    +        '(2 7 1 8 2)) =3D> #t
    + 
    +- ++
    + +-
    ++
    + +-every pred clist1 clist2 ... -> value +-
    ++every pred clist1 clist2 ... -> value ++ ++
    ++

    + Applies the predicate across the lists, returning true if the predica= te + returns true on every application. ++

    +

    + If there are n list arguments clist1= ... clistn, then pred must be a +- procedure taking n arguments and returning a boolean resul= t. ++ procedure taking n arguments ++ and returning a single value, interpreted as a boolean (that is, ++ #f means false, and any other value means true). ++

    +

    + every applies pred to the first elements of t= he clisti parameters. + If this application returns false, every immediately ret= urns false. +@@ -2451,27 +2821,36 @@ to alter the argument list to produce the result. + clisti parameters, then the third, and so forth= . The iteration stops + when a false value is produced or one of the lists runs out of values. + In the latter case, every returns +- the true value produced by its final application of pred.= =20 +- The application of pred to the last element of the lists=20 ++ the true value produced by its final application of pred. ++ The application of pred to the last element of the lists + is a tail call. ++

    +

    + If one of the clisti has no elements, eve= ry simply returns #t. ++

    +

    + Like any, every's name does not end with a = question mark -- this is to + indicate that it does not return a simple boolean (#t or= #f), but a + general value. +- ++

    ++
    + +-
    ++
    + +-list-index pred clist1 clis= t2 ... -> integer or false +-
    ++list-index pred clist1 cl= ist2 ... -> integer or false ++ ++
    ++

    + Return the index of the leftmost element that satisfies pred. ++

    +

    + If there are n list arguments clist1= ... clistn, then pred must be a +- function taking n arguments and returning a boolean result. ++ function taking n arguments ++ and returning a single value, interpreted as a boolean (that is, ++ #f means false, and any other value means true). ++

    +

    + list-index applies pred to the first elements= of the clisti parameters. + If this application returns true, list-index immediately= returns zero. +@@ -2479,139 +2858,154 @@ to alter the argument list to produce the result. + clisti parameters, then the third, and so forth= . When it finds a tuple of + list elements that cause pred to return true, it stops and= returns the + zero-based index of that position in the lists. ++

    +

    + The iteration stops when one of the lists runs out of values; in this + case, list-index returns #f. +- +-

    ++

    ++
    + (list-index even? '(3 1 4 1 5 9)) =3D> 2
    + (list-index < '(3 1 4 1 5 9 2 5 6) '(2 7 1 8 2)) =3D> 1
    + (list-index =3D '(3 1 4 1 5 9 2 5 6) '(2 7 1 8 2)) =3D> #f
    + 
    +- ++
    + +-
    ++
    + +-member x list [=3D] -> list +-
    ++member x list [=3D] -> list ++
    ++
    + +-memq x list -> list +-
    ++memq x list -> list ++
    ++
    + +-memv x list -> list +-
    +- [R5RS+] +- ++memv x list -> list ++ ++
    ++

    ++ [R5RS+] + These procedures return the first sublist of list whose ca= r is +- x, where the sublists of list are the=20 +- non-empty lists returned by=20 ++ x, where the sublists of list are the ++ non-empty lists returned by + (drop list i) +- for i less than the length of list.=20=20 ++ for i less than the length of list. + If x does +- not occur in list, then #f is returned.=20=20 ++ not occur in list, then #f is returned. + memq uses eq? to compare x +- with the elements of list,=20 ++ with the elements of list, + while memv uses eqv?, and + member uses equal?. +- +-

    +-    (memq 'a '(a b c))          =3D>  (a b c)
    +-    (memq 'b '(a b c))          =3D>  (b c)
    +-    (memq 'a '(b c d))          =3D>  #f
    +-    (memq (list 'a) '(b (a) c)) =3D>  #f
    ++

    ++
    ++    (memq 'a '(a b c))          =3D>  (a b c)
    ++    (memq 'b '(a b c))          =3D>  (b c)
    ++    (memq 'a '(b c d))          =3D>  #f
    ++    (memq (list 'a) '(b (a) c)) =3D>  #f
    +     (member (list 'a)
    +-            '(b (a) c))         =3D>  ((a) c)
    +-    (memq 101 '(100 101 102))   =3D>  *unspecified*
    +-    (memv 101 '(100 101 102))   =3D>  (101 102)
    ++            '(b (a) c))         =3D>  ((a) c)
    ++    (memq 101 '(100 101 102))   =3D>  *unspecified*
    ++    (memv 101 '(100 101 102))   =3D>  (101 102)
    + 
    +- +- member is extended from its=20 ++

    ++ member is extended from its + R5RS= + definition to allow the client to pass in +- an optional equality procedure =3D used to compare keys.=20 ++ an optional equality procedure =3D used to compare keys. +=20 ++

    +

    + The comparison procedure is used to compare the elements ei= of list + to the key x in this way: +-

    ++

    ++
    + (=3D x ei) ; list is (E1 ... En) +
    ++

    + That is, the first argument is always x, and the second ar= gument is + one of the list elements. Thus one can reliably find the first element + of list that is greater than five with + (member 5 list <) +- ++

    +

    + Note that fully general list searching may be performed with + the find-tail and find procedures, e.g.= +-

    ++

    ++
    + (find-tail even? list) ; Find the first elt with an even key.
    + 
    +- ++
    + +=20 + +-

    Deletion

    +-

    ++

    Deletion

    +=20 +
    + +-
    ++
    + +-delete  x list [=3D] -> l= ist +-
    ++delete  x list [=3D] ->= list ++
    ++
    + +-delete! x list [=3D] -> list +-
    ++delete! x list [=3D] -> list= ++ ++
    ++

    + delete uses the comparison procedure =3D, which defaults= to equal?, to find + all elements of list that are equal to x, and d= eletes them from list. The + dynamic order in which the various applications of =3D are= made is not + specified. +- ++

    +

    + The list is not disordered -- elements that appear in the result list + occur in the same order as they occur in the argument list. + The result may share a common tail with the argument list. +- ++

    +

    + Note that fully general element deletion can be performed with the remove + and remove! procedures, e.g.: +-

    ++

    ++
    + ;; Delete all the even elements from LIS:
    + (remove even? lis)
    + 
    +- ++

    + The comparison procedure is used in this way: + (=3D x ei). +- That is, x is always the first argument,=20 ++ That is, x is always the first argument, + and a list element is always the + second argument. The comparison procedure will be used to compare each + element of list exactly once; the order in which it is app= lied to the + various ei is not specified. Thus, one can rel= iably remove all the + numbers greater than five from a list with + (delete 5 list <) +- ++

    +

    + delete! is the linear-update variant of delete. + It is allowed, but not required, to alter the cons cells in +- its argument list to construct the result.=20=20=20=20 +- ++ its argument list to construct the result. ++

    ++
    + +-
    ++
    + +-delete-duplicates  list [=3D= ] -> list +-
    ++delete-duplicates  list [= =3D] -> list ++
    ++
    + +-delete-duplicates! list [=3D] -&g= t; list +-
    ++delete-duplicates! list [=3D] -= > list ++ ++
    ++

    + delete-duplicates removes duplicate elements from the + list argument. + If there are multiple equal elements in the argument list, the result= list +@@ -2619,19 +3013,22 @@ to alter the argument list to produce the result. + The order of these surviving elements is the same as in the original + list -- delete-duplicates does not disorder the list (he= nce it is useful + for "cleaning up" association lists). ++

    +

    + The =3D parameter is used to compare the elements of the l= ist; it defaults +- to equal?. If x comes before y in = list, then the comparison is performed=20 ++ to equal?. If x comes before y in = list, then the comparison is performed + (=3D x y). +- The comparison procedure will be used to compare each pair of element= s in=20 +- list no more than once;=20 ++ The comparison procedure will be used to compare each pair of element= s in ++ list no more than once; + the order in which it is applied to the various pairs is not specifie= d. ++

    +

    + Implementations of delete-duplicates + are allowed to share common tails + between argument and result lists -- for example, if the list argument + contains only unique elements, it may simply return exactly + this list. ++

    +

    + Be aware that, in general, delete-duplicates + runs in time O(n2) for n-element lists. +@@ -2639,12 +3036,13 @@ to alter the argument list to produce the result. + the list to bring equal elements together, then using a linear-time + algorithm to remove equal elements. Alternatively, one can use algori= thms + based on element-marking, with linear-time results. +- ++

    +

    + delete-duplicates! is the linear-update variant of delete-duplicates; it + is allowed, but not required, to alter the cons cells in its argument + list to construct the result. +-

    ++

    ++
    + (delete-duplicates '(a b a c a b c z)) =3D> (a b c z)
    +=20
    + ;; Clean up an alist:
    +@@ -2652,124 +3050,143 @@ to alter the argument list to produce the result.
    +                    (lambda (x y) (eq? (car x) (car y))))
    +     =3D> ((a . 3) (b . 7) (c . 1))
    + 
    ++
    +
    +=20 + +-

    Association lists

    ++

    Association lists

    +

    + An "association list" (or "alist") is a list of pairs. The car of each pa= ir + contains a key value, and the cdr contains the associated data value. The= y can + be used to construct simple look-up tables in Scheme. Note that associati= on + lists are probably inappropriate for performance-critical use on large da= ta; + in these cases, hash tables or some other alternative should be employed. +- ++

    +
    + +-
    ++
    + +-assoc key alist [=3D] -> pair or #f= +-
    ++assoc key alist [=3D] -> pair or = #f ++
    ++
    + +-assq key alist -> pair or #f +-
    ++assq key alist -> pair or #f ++
    ++
    + +-assv key alist -> pair or #f +-
    +- +- [R5RS+] +- alist must be an association list -- a list of pairs.=20=20 ++assv key alist -> pair or #f ++ ++
    ++

    ++ [R5RS+] ++ alist must be an association list -- a list of pairs. + These procedures +- find the first pair in alist whose car field is key,=20 +- and returns that pair.=20=20 +- If no pair in alist has key as its car,=20 +- then #f is returned.=20=20 +- assq uses eq? to compare key=20 +- with the car fields of the pairs in alist,=20 +- while assv uses eqv?=20 ++ find the first pair in alist whose car field is key, ++ and returns that pair. ++ If no pair in alist has key as its car, ++ then #f is returned. ++ assq uses eq? to compare key ++ with the car fields of the pairs in alist, ++ while assv uses eqv? + and assoc uses equal?. +-

    ++

    ++
    + (define e '((a 1) (b 2) (c 3)))
    +-(assq 'a e)                            =3D>  (a 1)
    +-(assq 'b e)                            =3D>  (b 2)
    +-(assq 'd e)                            =3D>  #f
    +-(assq (list 'a) '(((a)) ((b)) ((c))))  =3D>  #f
    +-(assoc (list 'a) '(((a)) ((b)) ((c)))) =3D>  ((a))
    +-(assq 5 '((2 3) (5 7) (11 13)))	   =3D>  *unspecified*
    +-(assv 5 '((2 3) (5 7) (11 13)))	   =3D>  (5 7)
    ++(assq 'a e)                            =3D>  (a 1)
    ++(assq 'b e)                            =3D>  (b 2)
    ++(assq 'd e)                            =3D>  #f
    ++(assq (list 'a) '(((a)) ((b)) ((c))))  =3D>  #f
    ++(assoc (list 'a) '(((a)) ((b)) ((c)))) =3D>  ((a))
    ++(assq 5 '((2 3) (5 7) (11 13)))	   =3D>  *unspecified*
    ++(assv 5 '((2 3) (5 7) (11 13)))	   =3D>  (5 7)
    + 
    +- +- assoc is extended from its=20 +-
    R5RS= =20 ++

    ++ assoc is extended from its ++ R5RS= + definition to allow the client to pass in + an optional equality procedure =3D used to compare keys. +- ++

    +

    + The comparison procedure is used to compare the elements ei= of list + to the key parameter in this way: +-

    ++

    ++
    + (=3D key (car ei)) ; list is (E1 ... En) +
    +- That is, the first argument is always key,=20 +- and the second argument is one of the list elements.=20 ++

    ++ That is, the first argument is always key, ++ and the second argument is one of the list elements. + Thus one can reliably find the first entry + of alist whose key is greater than five with + (assoc 5 alist <) +-=20=20=20=20=20 ++

    +

    + Note that fully general alist searching may be performed with + the find-tail and find procedures, e.g.= +-

    ++

    ++
    + ;; Look up the first association in alist with an even key:
    + (find (lambda (a) (even? (car a))) alist)
    + 
    +- ++
    +=20 + +-
    ++
    + +-alist-cons key datum alist -> alist= +-
    ++alist-cons key datum alist -> ali= st ++ ++
    +
    + (lambda (key datum alist) (cons (cons key datum) alist))
    + 
    ++

    + Cons a new alist entry mapping key -> datum = onto alist. +- ++

    ++
    + +-
    ++
    + +-alist-copy alist -> alist +-
    ++alist-copy alist -> alist ++ ++
    ++

    + Make a fresh copy of alist. This means copying each pair t= hat + forms an association as well as the spine of the list, i.e. ++

    +
    + (lambda (a) (map (lambda (elt) (cons (car elt) (cdr elt))) a))
    + 
    +- ++
    + +-
    ++
    + +-alist-delete  key alist [=3D= ] -> alist +-
    ++alist-delete  key alist [= =3D] -> alist ++
    ++
    + +-alist-delete! key alist [=3D] -&g= t; alist +-
    +- alist-delete deletes all associations from alist with the given key,=20 +- using key-comparison procedure =3D, which defaults to equal?.=20 +- The dynamic order in which the various applications of =3D= are made is not=20 +- specified.=20 ++alist-delete! key alist [=3D] -= > alist ++ ++
    ++

    ++ alist-delete deletes all associations from alist with the given key, ++ using key-comparison procedure =3D, which defaults to equal?. ++ The dynamic order in which the various applications of =3D= are made is not ++ specified. ++

    +

    + Return values may share common tails with the alist argume= nt. + The alist is not disordered -- elements that appear in the result ali= st + occur in the same order as they occur in the argument alist. ++

    +

    + The comparison procedure is used to compare the element keys ki of alist's + entries to the key parameter in this way: +@@ -2777,366 +3194,427 @@ in these cases, hash tables or some other altern= ative should be employed. + Thus, one can reliably remove all entries of alist whose k= ey is greater + than five with + (alist-delete 5 alist <) ++

    +

    + alist-delete! is the linear-update variant of alis= t-delete. + It is allowed, but not required, + to alter cons cells from the alist parameter to construct = the result. +- ++

    ++
    +
    +=20 +- + +-

    Set operations on lists

    ++

    Set operations on lists

    +

    + These procedures implement operations on sets represented as lists of ele= ments. +-They all take an =3D argument used to compare elements of list= s.=20 +-This equality procedure is required to be consistent with eq?.=20 ++They all take an =3D argument used to compare elements of list= s. ++This equality procedure is required to be consistent with eq?. + That is, it must be the case that +-

    +- (eq? x y) =3D> (=3D= x y). ++

    ++
    ++ (eq? x y) =3D> (= =3D x y). +
    ++

    + Note that this implies, in turn, that two lists that are eq?= are + also set-equal by any legal comparison procedure. This allows for + constant-time determination of set operations on eq? lists. +- ++

    +

    +-Be aware that these procedures typically run in time=20 +-O(n * m)=20 +-for n- and m-element list arguments.=20=20 ++Be aware that these procedures typically run in time ++O(n * m) ++for n- and m-element list arguments. + Performance-critical applications + operating upon large sets will probably wish to use other data + structures and algorithms. +- ++

    +
    + +-
    +- +-lset<=3D =3D list1 ... -= > boolean +-
    ++
    ++ ++lset<=3D =3D list1 ...= -> boolean ++
    ++
    ++

    + Returns true iff every listi is a subset of listi+1, using =3D for +- the element-equality procedure.=20 ++ the element-equality procedure. + List A is a subset of list B if every +- element in A is equal to some element of B.=20 +- When performing an element comparison,=20 ++ element in A is equal to some element of B. ++ When performing an element comparison, + the =3D procedure's first argument is an element + of A; its second, an element of B. +-

    ++

    ++
    + (lset<=3D eq? '(a) '(a b a) '(a b c c)) =3D> #t
    +=20
    +-(lset<=3D eq?) =3D> #t             ; Trivial cases
    +-(lset<=3D eq? '(a)) =3D> #t
    ++(lset<=3D eq?) =3D> #t             ; Trivial cases
    ++(lset<=3D eq? '(a)) =3D> #t
    + 
    +- ++
    + +-
    ++
    + +-lset=3D =3D list1 list= 2 ... -> boolean +-
    ++lset=3D =3D list1 list2 ... -> boolean ++ ++
    ++

    + Returns true iff every listi is set-equal to listi+1, using =3D for + the element-equality procedure. "Set-equal" simply means that + listi is a subset of listi+1, and listi+1 is a subset of listi= . + The =3D procedure's first argument is an element of l= isti; its second is an element of + listi+1. +-

    ++

    ++
    + (lset=3D eq? '(b e a) '(a e b) '(e e b a)) =3D> #t
    +=20
    +-(lset=3D eq?) =3D> #t               ; Trivial cases
    +-(lset=3D eq? '(a)) =3D> #t
    ++(lset=3D eq?) =3D> #t               ; Trivial cases
    ++(lset=3D eq? '(a)) =3D> #t
    + 
    +=20 ++

    ++Note added on 2020-06-02: ++The reference (sample) implementation ++had a bug that reversed the arguments to =3D. The ++implementation has been corrected to match the text above. ++

    ++
    + +-
    ++
    + +-lset-adjoin =3D list elt1 .= .. -> list +-
    +- Adds the elti elements not already in the list = parameter to the=20 ++lset-adjoin =3D list elt1= ... -> list ++ ++
    ++

    ++ Adds the elti elements not already in the list = parameter to the + result list. The result shares a common tail with the list parameter. + The new elements are added to the front of the list, but no guarantees + are made about their order. The =3D parameter is an equali= ty procedure +- used to determine if an elti is already a membe= r of list. Its first=20 ++ used to determine if an elti is already a membe= r of list. Its first + argument is an element of list; its second is one of the <= var>elti. ++

    +

    + The list parameter is always a suffix of the result -- even if the li= st + parameter contains repeated elements, these are not reduced. +-

    ++

    ++
    + (lset-adjoin eq? '(a b c d c e) 'a 'e 'i 'o 'u) =3D> (u o i a b c d c =
    e)
    + 
    +- ++
    + +-
    ++
    + +-lset-union =3D list1 ... -&= gt; list +-
    ++lset-union =3D list1 ... = -> list ++ ++
    ++

    + Returns the union of the lists, using =3D for the element-= equality + procedure. ++

    +

    + The union of lists A and B is constructed as fo= llows: ++

    +
      +-
    • If A is the empty list,=20 ++
    • If A is the empty list, + the answer is B (or a copy of B). +-
    • Otherwise, the result is initialised to be list A= =20 ++
    • Otherwise, the result is initialised to be list A<= /var> + (or a copy of A). +-
    • Proceed through the elements of list B=20 ++
    • Proceed through the elements of list B + in a left-to-right order. +- If b is such an element of B,=20 +- compare every element r of the current result lis= t=20 +- to b:=20 +- (=3D r b).=20 +- If all comparisons fail,=20 ++ If b is such an element of B, ++ compare every element r of the current result list ++ to b: ++ (=3D r b). ++ If all comparisons fail, + b is consed onto the front of the result. +-
    ++ ++

    + However, there is no guarantee that =3D will be applied to every pair +- of arguments from A and B.=20 +- In particular, if A is eq? to B,=20 ++ of arguments from A and B. ++ In particular, if A is eq? to B, + the operation may immediately terminate. +- ++

    +

    + In the n-ary case, the two-argument list-union operation is simply + folded across the argument lists. +- +-

    +-(lset-union eq? '(a b c d e) '(a e i o u)) =3D>=20
    ++

    ++
    ++(lset-union eq? '(a b c d e) '(a e i o u)) =3D>
    +     (u o i a b c d e)
    +=20
    + ;; Repeated elements in LIST1 are preserved.
    +-(lset-union eq? '(a a c) '(x a x)) =3D> (x a a c)
    ++(lset-union eq? '(a a c) '(x a x)) =3D> (x a a c)
    +=20
    + ;; Trivial cases
    +-(lset-union eq?) =3D> ()
    +-(lset-union eq? '(a b c)) =3D> (a b c)
    ++(lset-union eq?) =3D> ()
    ++(lset-union eq? '(a b c)) =3D> (a b c)
    + 
    +- ++
    + +-
    ++
    + +-lset-intersection =3D list1= list2 ... -> list +-
    +- Returns the intersection of the lists,=20 ++lset-intersection =3D list1 list2 ... -> list ++ ++
    ++

    ++ Returns the intersection of the lists, + using =3D for the element-equality procedure. ++

    +

    + The intersection of lists A and B +- is comprised of every element of A that is =3D= =20 +- to some element of B:=20 +- (=3D a b),=20 ++ is comprised of every element of A that is =3D ++ to some element of B: ++ (=3D a b), + for a in A, and b in B. +- Note this implies that an element which appears in B=20 ++ Note this implies that an element which appears in B + and multiple times in list A + will also appear multiple times in the result. ++

    +

    + The order in which elements appear in the result is the same as +- they appear in list1 --=20 +- that is, lset-intersection essentially filters=20 +- list1,=20 +- without disarranging element order.=20 ++ they appear in list1 -- ++ that is, lset-intersection essentially filters ++ list1, ++ without disarranging element order. + The result may + share a common tail with list1. ++

    +

    + In the n-ary case, the two-argument list-intersection operation is si= mply + folded across the argument lists. However, the dynamic order in which= the +- applications of =3D are made is not specified.=20 ++ applications of =3D are made is not specified. + The procedure may check an +- element of list1 for membership=20 ++ element of list1 for membership + in every other list before proceeding to +- consider the next element of list1,=20 ++ consider the next element of list1, + or it may completely intersect list1 +- and list2=20 +- before proceeding to list3,=20 ++ and list2 ++ before proceeding to list3, + or it may go about its work in some third order. +- +-

    ++

    ++
    + (lset-intersection eq? '(a b c d e) '(a e i o u)) =3D> (a e)
    +=20
    + ;; Repeated elements in LIST1 are preserved.
    +-(lset-intersection eq? '(a x y a) '(x a x z)) =3D> '(a x a)
    ++(lset-intersection eq? '(a x y a) '(x a x z)) =3D> '(a x a)
    +=20
    +-(lset-intersection eq? '(a b c)) =3D> (a b c)     ; Trivial case
    ++(lset-intersection eq? '(a b c)) =3D> (a b c)     ; Trivial case
    + 
    +- ++
    + +-
    ++
    + +-lset-difference =3D list1 l= ist2 ... -> list +-
    ++lset-difference =3D list1= list2 ... -> list ++ ++
    ++

    + Returns the difference of the lists, using =3D for the ele= ment-equality + procedure -- all the elements of list1 that are= not + =3D to any element from one of the +- other listi parameters.=20 ++ other listi parameters. ++

    +

    +- The =3D procedure's first argument is=20 +- always an element of list1;=20 ++ The =3D procedure's first argument is ++ always an element of list1; + its second is an element of one of the other listi. +- Elements that are repeated multiple times in the=20 +- list1 parameter=20 +- will occur multiple times in the result.=20 ++ Elements that are repeated multiple times in the ++ list1 parameter ++ will occur multiple times in the result. +=20 + The order in which elements appear in the result is the same as +- they appear in list1 --=20 ++ they appear in list1 -- + that is, lset-difference essentially +- filters list1, without disarranging element ord= er.=20 +- The result may share a common tail with list1.= =20 ++ filters list1, without disarranging element ord= er. ++ The result may share a common tail with list1. +=20 + The dynamic order in which the applications of =3D are mad= e is not +- specified.=20 ++ specified. + The procedure may check an element of list1 + for membership in every other list before proceeding to consider the + next element of list1, +- or it may completely compute the difference of=20 ++ or it may completely compute the difference of + list1 and list2 before +- proceeding to list3,=20 ++ proceeding to list3, + or it may go about its work in some third order. +- +-

    ++

    ++
    + (lset-difference eq? '(a b c d e) '(a e i o u)) =3D> (b c d)
    +=20
    +-(lset-difference eq? '(a b c)) =3D> (a b c) ; Trivial case
    ++(lset-difference eq? '(a b c)) =3D> (a b c) ; Trivial case
    + 
    +- ++
    + +-
    ++
    + +-lset-xor =3D list1 ... ->= ; list +-
    +- Returns the exclusive-or of the sets,=20 +- using =3D for the element-equality procedure.=20 ++lset-xor =3D list1 ... -&= gt; list ++ ++
    ++

    ++ Returns the exclusive-or of the sets, ++ using =3D for the element-equality procedure. + If there are exactly two lists, this is all the elements + that appear in exactly one of the two lists. The operation is associa= tive, + and thus extends to the n-ary case -- the elements that appear in an + odd number of the lists. The result may share a common tail with any = of + the listi parameters. ++

    +

    +- More precisely, for two lists A and B,=20 ++ More precisely, for two lists A and B, + A xor B is a list of ++

    +
      +
    • every element a of A + such that there is no element b of B + such that (=3D a b), and +-
    • every element b of B=20 ++
    • every element b of B + such that there is no element a of A + such that (=3D b a). +-
    ++ ++

    + However, an implementation is allowed to assume that =3D is + symmetric -- that is, that +-

    +- (=3D a b) =3D>=20 ++

    ++
    ++ (=3D a b) =3D> + (=3D b a). +
    +- This means, for example, that if a comparison=20 ++

    ++ This means, for example, that if a comparison + (=3D a b) produces +- true for some a in A=20 ++ true for some a in A + and b in B, + both a and b may be removed from + inclusion in the result. ++

    +

    + In the n-ary case, the binary-xor operation is simply folded across + the lists. +- +-

    ++

    ++
    + (lset-xor eq? '(a b c d e) '(a e i o u)) =3D> (d c b i o u)
    +=20
    + ;; Trivial cases.
    +-(lset-xor eq?) =3D> ()
    +-(lset-xor eq? '(a b c d e)) =3D> (a b c d e)
    ++(lset-xor eq?) =3D> ()
    ++(lset-xor eq? '(a b c d e)) =3D> (a b c d e)
    + 
    +- ++
    +=20 + +-
    ++
    + +-lset-diff+intersection =3D list1<= /sub> list2 ... -> [list list] +-
    ++lset-diff+intersection =3D list= 1 list2 ... -> [list list] ++ ++
    ++

    + Returns two values -- the difference and the intersection of the list= s. +- Is equivalent to=20 +-

    ++    Is equivalent to
    ++

    ++
    + (values (lset-difference =3D list1 =
    list2 ...)
    +         (lset-intersection =3D list1
    +                              (lset-union =3D list2 ...)))
    + 
    ++

    + but can be implemented more efficiently. ++

    +

    + The =3D procedure's first argument is an element of l= ist1; its second + is an element of one of the other listi. ++

    +

    +- Either of the answer lists may share a=20 ++ Either of the answer lists may share a + common tail with list1. + This operation essentially partitions list1. +- ++

    ++
    + +-
    ++
    + +-lset-union!      &nb= sp;      =3D list1 ...= -> list +-
    ++lset-union!      &= nbsp;      =3D list1 .= .. -> list ++
    ++
    + +-lset-intersection!     &n= bsp;=3D list1 list2 ... -> list +-
    ++lset-intersection!     =  =3D list1 list2 ... -> list ++
    ++
    + +-lset-difference!     &nbs= p;  =3D list1 list2 ... -> l= ist +-
    ++lset-difference!     &n= bsp;  =3D list1 list2 ... ->= list ++
    ++
    + +-lset-xor!       = ;        =3D list1= ... -> list +-
    ++lset-xor!      &nb= sp;        =3D list1 ... -> list ++
    ++
    + +-lset-diff+intersection! =3D list<= sub>1 list2 ... -> [list list] +-
    ++lset-diff+intersection! =3D lis= t1 list2 ... -> [list list] ++ ++
    ++

    + These are linear-update variants. They are allowed, but not required, + to use the cons cells in their first list parameter to construct their +- answer. lset-union! is permitted to recycle cons cells f= rom any=20 ++ answer. lset-union! is permitted to recycle cons cells f= rom any + of its list arguments. ++

    ++
    +
    +=20 + +-

    Primitive side-effects

    ++

    Primitive side-effects

    +

    +-These two procedures are the primitive,=20 +-R5RS=20 ++These two procedures are the primitive, ++R5RS + side-effect operations on pairs. +- ++

    +
    + +-
    ++
    + +-set-car! pair object -> unspecified= +-
    ++set-car! pair object -> unspecifi= ed ++
    ++
    + +-set-cdr! pair object -> unspecified= +-
    ++set-cdr! pair object -> unspecifi= ed ++ ++
    ++

    + [R5RS] + These procedures store object in the car and cdr field + of pair, respectively. + The value returned is unspecified. +-

    ++

    ++
    + (define (f) (list 'not-a-constant-list))
    + (define (g) '(constant-list))
    +-(set-car! (f) 3) =3D>  *unspecified*
    +-(set-car! (g) 3) =3D>  *error*
    ++(set-car! (f) 3) =3D>  *unspecified*
    ++(set-car! (g) 3) =3D>  *error*
    + 
    ++
    +
    +=20 + +-

    Acknowledgements

    ++

    Acknowledgements

    +

    + The design of this library benefited greatly from the feedback provided d= uring + the SRFI discuss= ion phase. Among those contributing thoughtful commentary and +@@ -3149,77 +3627,80 @@ Kelsey, Donovan Kolbly, Shriram Krishnamurthi, Dav= e Mason, Jussi Piitulainen, + David Pokorny, Duncan Smith, Mike Sperber, Maciej Stachowiak, Harvey J. S= tein, + John David Stone, and Joerg F. Wittenberger. I am grateful to them for th= eir + assistance. ++

    +

    + I am also grateful the authors, implementors and documentors of all the s= ystems + mentioned in the rationale. Aubrey Jaffer and Kent Pitman should be noted +-for their work in producing Web-accessible versions of the R5RS and=20 ++for their work in producing Web-accessible versions of the R5RS and + Common Lisp spec, which was a tremendous aid. ++

    +

    + This is not to imply that these individuals necessarily endorse the final +-results, of course.=20 +- ++results, of course. ++

    +=20 + +-

    References & links

    +-

    ++

    References & links

    +=20 +
    +-
    This document, in HTML: +-
    +- http://srfi.schemers.org/srfi-1/srfi-1.html ++
    This document, in HTML: ++
    ++ https://srfi.schemers.org/srfi-1/srfi-1.html +=20 +-
    Source code for the reference implementation: +-
    +- http://srfi.schemers.org/srfi-1/srfi-1-reference.scm ++
    Source code for the reference implementation: ++
    ++ https://srfi.schemers.org/srfi-1/srfi-1-reference.scm +=20 +-
    Archive of SRFI-1 discussion-list email: +-
    +- http://srfi.schemers.org/srfi-1/mail-archive/maillist.html ++
    Archive of SRFI-1 discussion-list email: ++
    ++ https://srfi-email.schemers.org/srfi-1 ++ ++
    SRFI web site: ++
    ++ https://srfi.schemers.org/ ++
    +=20 +-
    SRFI web site: +-
    +- http://srfi.schemers.org/ +- +=20 +-

    +=20 +

    +-
    [CommonLisp]
    +-
    Common Lisp: the Language
    +-Guy L. Steele Jr. (editor).
    +-Digital Press, Maynard, Mass., second edition 1990.
    +-Available at +-http://www.elwood.com/alu/table/references.htm#cltl2. ++
    [CommonLisp]
    ++
    ++

    ++Common Lisp: the Language
    ++Guy L. Steele Jr. (editor).
    ++Digital Press, Maynard, Mass., second edition 1990.
    ++(Wikip= edia entry) ++

    +

    +- + The Common Lisp "HyperSpec," produced by Kent Pitman, is essentially + the ANSI spec for Common Lisp: +- +-http://www.harlequin.com/education/books/HyperSpec/. +- +-

    [R5RS]
    +-
    Revised5 report on the algorithmic language Scheme.
    +- R. Kelsey, W. Clinger, J. Rees (editors).
    +- Higher-Order and Symbolic Computation, Vol. 11, No. 1, September, 199= 8.
    +- and ACM SIGPLAN Notices, Vol. 33, No. 9, October, 1998.
    ++http://www.lispworks.com/documentation/HyperSpec/Front/index.htm ++

    ++
    ++
    [R5RS]
    ++
    Revised5 report on the algorithmic language Scheme.
    ++ R. Kelsey, W. Clinger, J. Rees (editors).
    ++ Higher-Order and Symbolic Computation, Vol. 11, No. 1, September, 199= 8.
    ++ and ACM SIGPLAN Notices, Vol. 33, No. 9, October, 1998.
    + Available at + http://www.schemers.org/Documents/Standards/. +- ++
    +
    +=20 +=20 +=20 ++ + +-

    Copyright

    ++

    Copyright

    +

    +- + Certain portions of this document -- the specific, marked segments of text + describing the R5RS procedures -- were adapted with permission from the R= 5RS + report. ++

    +

    +-=20=20=20=20 +-All other text is copyright (C) Olin Shivers (1998, 1999).=20 +-All Rights Reserved.=20 ++All other text is copyright (C) Olin Shivers (1998, 1999). ++All Rights Reserved. ++

    +

    + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the +@@ -3242,5 +3723,7 @@ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WH= ETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +

    ++
    ++
    Editor: Michael Sperber
    + + +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-11.html b/srfi-doc/sr= fi/scribblings/srfi-std/srfi-11.html +index 987edd5..f100a02 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-11.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-11.html +@@ -1,55 +1,74 @@ +- +- ++ ++ + ++ ++ + SRFI 11: Syntax for receiving multiple values ++ ++ ++ + +=20 + +=20 +-

    Title

    ++

    SRFI 11: Syntax for receiving multiple values

    +=20 +-SRFI 11: Syntax for receiving multiple values ++

    by Lars T Hansen

    ++

    This copy of the SRFI 11 specific= ation document ++is distributed as part of the Racket package ++srfi-doc.

    = The canonical source of this document is ++https://srfi.s= chemers.org/srfi-11/srfi-11.html.

    +=20 +-

    Author

    ++

    Status

    +=20 +-Lars T Hansen ++

    This SRFI is currently in final status. Here is an explanation of each stat= us that a SRFI can hold. To provide input on this SRFI, please send email = to srfi-= 11@nospamsrfi.schemers.org. To = subscribe to the list, follow these instructions. You can access previous messages= via the mailing list a= rchive.

    ++
      ++
    • Received: 1999-09-10 ++
    • Draft: 1999-09-14--1999-11-12 ++
    • Revised: 1999-11-01 ++
    • Revised: 2000-03-15 ++
    • Final: 2000-03-15 ++
    +=20 +-

    Status

    +-This SRFI is currently in ``final'' status. To see an explanation of eac= h status=20 +-that a SRFI can hold, see here. +-You can access the discussion via the archive of=20 +-the mailing list. +-

      +-
    • Received: 1999/09/10 +-
    • Draft: 1999/09/14-1999/11/12 +-
    • Revised: 1999/11/01 +-
    • Revised: 2000/03/15 +-
    • Final: 2000/03/15 +-
    +- +-

    Abstract

    ++

    Abstract

    +=20 + The SRFI introduces syntactic forms LET-VALUES and LET*-VALUES that bind = the values of + expressions that return multiple values. +=20 +-

    Issues

    ++

    Issues

    +=20 + None. +=20 +-

    Rationale

    ++

    Rationale

    +=20 + LET-VALUES and LET*-VALUES reduce the clutter of the CALL-WITH-VALUES not= ation for + receiving multiple values. +=20 +=20 +-

    Specification

    ++

    Specification

    +=20 +
    +-
    ++
    + (LET-VALUES ((<formals> <expression>) ...) <body>)<= /tt> +-
    Syntax ++
    Syntax ++
    +
    +-

    Each <formals> should be a formal arguments list as for a LAMBDA= =20 ++

    Each <formals> should be a formal arguments list as for a LAMBDA + expression, cf section 4.1.4 of the R5RS.

    +=20 +

    The <expression>s are evaluated in the current environment, the= =20 +@@ -64,7 +83,6 @@ receiving multiple values. + error for an <expression> to return a number of values that does + not match its corresponding <formals>.

    +=20 +-

    +

    +              (let-values (((a b . c) (values 1 2 3 4)))
    +                (list a b c))            --> (1 2 (3 4))
    +@@ -74,13 +92,13 @@ receiving multiple values.
    +                             ((x y) (values a b)))
    +                  (list a b x y)))       --> (x y a b)
    + 
    +-

    +- +-
    ++
    ++
    + (LET*-VALUES ((<formals> <expression>) ...) <body>)= +-
    Syntax ++
    Syntax ++
    +
    +-

    Each <formals> should be a formal arguments list as for a LAMBDA= =20 ++

    Each <formals> should be a formal arguments list as for a LAMBDA + expression, cf section 4.1.4 of the R5RS.

    +=20 +

    LET*-VALUES is similar to LET-VALUES, but the bindings are performed +@@ -89,26 +107,25 @@ receiving multiple values. + expression to the right of the binding. Thus the second binding is do= ne in + an environment in which the first binding is visible, and so on.

    +=20 +-

    +

    +              (let ((a 'a) (b 'b) (x 'x) (y 'y))
    +                (let*-values (((a b) (values x y))
    +                              ((x y) (values a b)))
    +                  (list a b x y)))       --> (x y x y)
    + 
    +-

    ++
    + +=20 +-

    Implementation

    +=20 ++

    Implementation

    ++

    + The following implementation is written in R5RS Scheme. It is not + compatible with the IEEE Scheme standard because the IEEE standard does + not contain the high-level macro system. +- ++

    +

    The implementation assumes that some top-level names defined by the + R5RS are bound to their original values. +- +-

    ++

    +
    + ;; This code is in the public domain.
    +=20
    +@@ -148,9 +165,8 @@ R5RS are bound to their original values.
    +        (let*-values (?binding1 ...) ?body0 ?body1 ...)))))
    + 
    +=20 +-

    Copyright

    ++

    Copyright

    +

    Copyright (C) Lars T Hansen (1999). All Rights Reserved.

    +- +

    + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the +@@ -173,12 +189,11 @@ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WH= ETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +

    +- +-
    +-
    Editor: Mi= ke Sperber
    ++
    ++
    Editor: Mike Sperber
    + + +-Last modified: Tue Sep 28 10:59:57 MST 2004 ++Last modified: Sun Jan 28 13:40:20 MET 2007 + + + +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-13.html b/srfi-doc/sr= fi/scribblings/srfi-std/srfi-13.html +index 2f744dc..b519905 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-13.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-13.html +@@ -1,22 +1,39 @@ +- ++ ++ ++ ++ ++ + +- + +- +- +- +- ++ + SRFI 13: String Libraries +- ++ ++ ++ + + +=20 +- + +=20 + +=20 + +-

    Title

    ++

    SRFI 13: String Libraries

    +=20 +-
    SRFI 13: String Libraries
    ++

    by Olin Shivers

    ++

    This copy of the SRFI 13 specific= ation document ++is distributed as part of the Racket package ++srfi-doc.

    = The canonical source of this document is ++https://srfi.s= chemers.org/srfi-13/srfi-13.html.

    +=20 +- +-

    Author

    +- +-Olin Shivers +- +-

    Status

    +-This SRFI is currently in ``final'' status. To see an explanation of eac= h status that a SRFI can hold, see here. +-You can access the discussion via the archive of the mailing list. +-

      +-
    • Received: 1999/10/17 +-
    • Draft: 1999/10/18-1999/12/16 +-
    • Revised: 1999/10/31 +-
    • Revised: 1999/11/13 +-
    • Revised: 1999/11/22 +-
    • Revised: 2000/04/30 +-
    • Revised: 2000/06/09 +-
    • Revised: 2000/12/23 +-
    +- +-

    Table of contents

    ++

    Status

    ++ ++

    This SRFI is currently in final status. Here is an explanation of each stat= us that a SRFI can hold. To provide input on this SRFI, please send email = to srfi-= 13@nospamsrfi.schemers.org. To = subscribe to the list, follow these instructions. You can access previous messages= via the mailing list a= rchive.

    ++
      ++
    • Received: 1999-10-17 ++
    • Draft: 1999-10-18--1999-12-16 ++
    • Revised: 1999-10-31 ++
    • Revised: 1999-11-13 ++
    • Revised: 1999-11-22 ++
    • Revised: 2000-04-30 ++
    • Revised: 2000-06-09 ++
    • Revised: 2000-12-23 ++
    ++ ++

    Table of contents

    +=20 + +- ++ ++
  • Procedure specification + ++ ++
  • Low-level procedures + +- ++
  • Knuth-Morris-Pratt searching ++
  • ++ +=20 +-
  • Reference implementation +-
  • Acknowledgements +-
  • References & Links +-
  • Copyright +- ++
  • Reference implementation ++
  • Acknowledgements ++
  • References & Links ++
  • Copyright ++
  • +=20 + +-

    Abstract

    ++

    Abstract

    +

    +=20 + R5RS + Scheme has an impoverished set of string-processing utilities, which is a +-problem for authors of portable code. This SRFI proposes a coherent and comprehensive set of ++problem for authors of portable code. ++This SRFI propos= es ++a coherent and comprehensive set of + string-processing procedures; it is accompanied by a reference implementa= tion + of the spec. The reference implementation is ++

    +
      +
    • portable +-
    • efficient +-
    • open source +-
    ++
  • efficient ++
  • open source ++
  • +

    + The routines in this SRFI are backwards-compatible with the string-proces= sing + routines of + R5RS. +- ++

    + +-

    Procedure Index

    ++

    Procedure Index

    +

    + Here is a list of the procedures provided by the string-lib=20 + and string-lib-internals packages. + R5RS + procedures are shown in=20 +-bold; ++bold; + extended R5R= S +=20 +- procedures, in bold italic. +-

    ++ procedures, in bold italic. ++

    ++
    +
    +-
    Predicates +-
    +-
    +-string? string-null?=20
    ++
    Predicates ++
    ++
    ++string? string-null?=20
    + string-every string=
    -any
    + 
    +=20 +-
    Constructors +-
    +-
    +-make-string string string-tabulate=
    
    ++
    Constructors ++
    ++
    ++make-string string string-tabulat=
    e
    + 
    +=20 +-
    List & string conversion +-
    +-
    +-string->list=
     list->string
    +-reverse-list->string string-join
    ++
    List & string conversion ++
    ++
    ++string->list list->string
    ++reverse-list->string string-join
    + 
    +=20 +-
    Selection +-
    +-
    +-string-length
    ++
    Selection ++
    ++
    ++string-length
    + string-ref
    +-string-copy
    +-substring/shared
    ++string-copy
    ++substring/shared
    + string-copy!=20
    + string-take s=
    tring-take-right
    + string-drop s=
    tring-drop-right
    +@@ -288,24 +310,24 @@ extended =
    R5RSstring-trim s=
    tring-trim-right string-trim-both=20
    + 
    +=20 +-
    Modification +-
    +-
    +-string-set! <=
    span class=3Dr5rs-procx>string-fill!
    ++
    Modification ++
    ++
    ++string-set!=
     string-fill!
    + 
    +=20 +-
    Comparison +-
    +-
    ++
    Comparison ++
    ++
    + string-compare string-compare-ci
    +-">string<>     strin=
    g=3D    string<    ">str=
    ing>    string<=3D    =3D">string>=3D
    +-">string-ci<>  string-ci=3D string-ci< ">string-ci> string-ci<=3D =
    =3D">string-ci>=3D
    ++string<>     s=
    tring=3D    string<    string>    string<=3D    string>=3D
    ++string-ci<>  string-ci=3D string-ci< string-ci> string-ci=
    <=3D string-ci>=3D
    + string-hash  str=
    ing-hash-ci
    + 
    +=20 +-
    Prefixes & suffixes +-
    +-
    ++
    Prefixes & suffixes ++
    ++
    + string-prefix-length    string-suffix-length
    + string-prefix-length-ci string-suffix-length-ci
    +=20
    +@@ -313,65 +335,65 @@ extended =
    R5RSstring-prefix-ci? string-suffix-ci?=20
    + 
    +=20 +-
    Searching +-
    +-
    ++
    Searching ++
    ++
    + string-index string-index-right
    + string-skip  =
    string-skip-right=20
    + string-count=20
    + string-contains string-contains-ci
    + 
    +=20 +-
    Alphabetic case mapping +-
    +-
    ++
    Alphabetic case mapping ++
    ++
    + string-titlecase  string-upcase  string-downcase
    + string-titlecase! string-upcase! string-downcase!
    + 
    +=20 +-
    Reverse & append +-
    +-
    ++
    Reverse & append ++
    ++
    + string-reverse string-reverse!
    +-string-append
    ++string-append
    + string-concatenate
    +-string-concatenate/shared string-append/shared
    +-string-concatenate-reverse string-concatenate-reverse/sha=
    red
    ++string-concatenate/shared string-append/shared
    ++string-concatenate-reverse string-concatenate-reverse/s=
    hared
    + 
    +=20 +-
    Fold, unfold & map +-
    +-
    ++
    Fold, unfold & map ++
    ++
    + string-map      stri=
    ng-map!
    + string-fold     string-fold-right
    + string-unfold   string-unfold-right
    + string-for-each string-for-each-index
    + 
    +=20 +-
    Replicate & rotate +-
    +-
    ++
    Replicate & rotate ++
    ++
    + xsubstring string-=
    xcopy!
    + 
    +=20 +-
    Miscellaneous: insertion, parsing +-
    +-
    ++
    Miscellaneous: insertion, parsing ++
    ++
    + string-replace string-tokenize
    + 
    +=20 +-
    Filtering & deleting +-
    +-
    ++
    Filtering & deleting ++
    ++
    + string-filter s=
    tring-delete=20
    + 
    +=20 +-
    Low-level procedures +-
    +-
    +-string-parse-start+end
    +-string-parse-final-start+end
    +-let-string-start+end
    ++
    Low-level procedures ++
    ++
    ++string-parse-start+end
    ++string-parse-final-start+end<=
    /a>
    ++let-string-start+end
    +=20
    + check-substring-spec
    + substring-spec-ok?
    +@@ -379,35 +401,34 @@ extended =
    R5RSmake-kmp-restart-vector kmp-step string-k=
    mp-partial-search
    + 
    +=20 +-
    ++ +
    +=20 + +-

    Rationale

    ++

    Rationale

    +

    +- + This SRFI defines two libraries that provide a rich set of operations for + manipulating strings. These are frequently useful for scripting and other + text-manipulation applications. The library's design was influenced by the + string libraries found in MIT Scheme, Gambit, RScheme, MzScheme, slib, Co= mmon + Lisp, Bigloo, guile, Chez, APL, Java, and the SML standard basis. ++

    +

    +- + All procedures involving character comparison are available in + both case-sensitive and case-insensitive forms. ++

    +

    +- + All functionality is available in substring and full-string forms. +- ++

    + +-

    Strings are code-point sequences<= /a>

    ++

    Strings are code-point sequences

    +

    + This SRFI considers strings simply to be a sequence of "code points" or + character encodings. Operations such as comparison or reversal are always= done + code point by code point. See the comments below on super-ASCII character + types for implications that follow. ++

    +

    +- + It's entirely possible that a legal string might not be a sensible "text" + sequence. For example, consider a string comprised entirely of zero-width + Unicode accent characters with no preceding base character to modify -- +@@ -415,11 +436,10 @@ this is a legal string, albeit one that does not mak= e a great deal of sense + when interpreted as a sequence of natural-language text. The routines in + this SRFI do not handle these "text" concerns; they restrict themselves + to the underlying view of strings as merely a sequence of "code points." +- ++

    + +-

    String operations are locale- and context-indep= endent

    ++

    String operations are locale- and context-independen= t

    +

    +- + This SRFI defines string operations that are locale- and context-independ= ent. + While it is certainly important to have a locale-sensitive comparison or + collation procedure when processing text, it is also important to have a = suite +@@ -427,14 +447,13 @@ of operations that are reliably invariant for basic = string processing --- + otherwise, a change of locale could cause data structures such as hash ta= bles, + b-trees, symbol tables, directories of filenames, etc.=20 + to become corrupted. +- ++

    +

    + Locale- and context-sensitive text operations, such as collation, are + explicitly deferred to a subsequent, companion "text" SRFI. +- ++

    + +-

    Internationalisation & super-ASCII character = types

    +- ++

    Internationalisation & super-ASCII character types=

    +

    + The major issue confronting this SRFI is the existence of super-ASCII + character encodings, such as eight-bit Latin-1 or 16- and 32-bit Unicode.= It +@@ -443,13 +462,13 @@ implementations based on at least these three standa= rd encodings. + Unfortunately, this places strong limitations on the API design. Here are + some relevant issues. Be warned that life in a super-ASCII world is + significantly more complex; there are no easy answers for many of these i= ssues. +- ++

    + +-

    Case mapping and case-folding

    ++

    Case mapping and case-folding

    +=20 +

    + Upper- and lower-casing characters is complex in super-ASCII encodings. +- ++

    +
      +
    • Some characters case-map to more than one character. For example, + the Latin-1 German eszet character upper-cases to "SS."=20 +@@ -458,20 +477,22 @@ Upper- and lower-casing characters is complex in sup= er-ASCII encodings. + R5RS function char-upcase i= s not well-defined,=20 + since it is defined to produce a (single) character result.=20 +=20 +-
    • It means that an in-place string-upcase! procedure ca= nnot be reliably ++
    • It means that an in-place string-upcase! procedu= re cannot be reliably + defined, since the original string may not be long enough to contain + the result -- an N-character string might upcase to a 2N-character re= sult. +=20 +-
    • It means that case-insensitive string-matching or searching is qui= te ++
    • It means that case-insensitive string-matching or searching i= s quite + tricky. For example, an n-character string s might match a= 2N-character + string s'. +-
    ++ +=20 ++ +
  • Some characters case-map in different ways depending upon their surr= ounding + context. For example, the Unicode Greek capital sigma character downcas= es + differently depending upon whether or not it is the final character in a + word. Again, this spells trouble for the simple R5RS char-downcase function. +=20 ++
  • +
  • Unicode defines three cases: lowercase, uppercase and titlecase. The + distinction between uppercase and titlecase arises in the presence of + Unicode's compound characters. For example, Unicode has a single charac= ter +@@ -479,18 +500,22 @@ Upper- and lower-casing characters is complex in sup= er-ASCII encodings. + the compound character "DZ", while titlecasing (or, as Americans say, + capitalizing) it produces compound character "Dz". +=20 ++
  • +
  • Turkish actually has different case-mappings from other languages. ++
  • + +=20 +

    +-The Unicode Consortium's web site +-

    ++ The Unicode Consortium's web site ++

    ++ +-

    ++

    + has detailed discussions of the issues. See in particular technical report + 21 on case mappings +-

    ++

    ++ +=20 +@@ -498,24 +523,26 @@ has detailed discussions of the issues. See in parti= cular technical report + SRFI 13 makes no attempt to deal with these issues; it uses a simple 1-1 + locale- and context-independent case-mapping, specifically Unicode's 1-1 + case-mappings given in +-
    ++

    ++ +-

    ++

    + The format of this file is explained in +-

    ++

    ++ +-

    ++

    + Note that this means that German eszet upper-cases to itself, not "SS". +=20 +-

    ++

    + Case-mapping and case-folding operations in SRFI 13 are locale-independen= t so + that shifting locales won't wreck hash tables, b-trees, symbol tables, etc. +- ++

    +=20 + +-

    String equality & string normalisation

    ++

    String equality & string normalisation

    +=20 +

    + Comparing strings for equality is complicated because in some cases Unico= de +@@ -526,31 +553,32 @@ an acute accent. There is a single Unicode character= for this. However, + Unicode also allows one to represent this with a two-character sequence: = the + "e" character followed by a zero-width acute-accent character. As another + example, Unicode provides some Asian characters in "narrow" and "full" wi= dths. +- ++

    +

    + There are multiple ways we might want to compare strings for equality. In + (roughly) decreasing order of precision, +- ++

    +
      +
    • we might want a precise comparison of the actual encoding, so that + <e-acute> would not compare equal to <e, acute>. +- +-
    • We might want a "normalised" comparison, where these two sequences=20 ++
    • ++
    • We might want a "normalised" comparison, where these two sequences + would compare equal. +- ++
    • +
    • We might want an even more-permissive normalisation, where visually-= distinct + properties of "the same" character would be ignored. For example, we mi= ght + want narrow/full-width versions of the same Asian character to compare = equal. +- ++
    • +
    • We might want comparisons that are insensitive to accents and diacri= tical + marks. +- ++
    • +
    • We might want comparisons that are case-insensitive. +- ++
    • +
    • We might want comparisons that are insensitive to several of the abo= ve + properties. +- ++
    • +
    • We might want ways to "normalise" strings into various canonical for= ms. ++
    • +
    +=20 +

    +@@ -559,24 +587,26 @@ simply based upon comparing the encoding values used= for the characters. + Accent-insensitive and other types of comparison are not provided; only + a simple form of case-insensitive comparison is provided, which uses the + 1-1 case mappings specified by Unicode in +-

    ++

    ++ +-

    ++

    + These are adequate for "program" or "systems" use of strings (e.g., to=20 + manipulate program identifiers and operating-system filenames). +- ++

    + +-

    String inequality

    ++

    String inequality

    +=20 +

    + Above and beyond the issues arising in string-equality, when we attempt + to order strings there are even further considerations. +- ++

    +
      +
    • French orders accents with right-to-left significance -- the reverse= of + the significance of the characters. +=20 ++
    • +
    • Case-insensitive ordering is not well defined by simple "code-point" + considerations, even for simple ASCII: there are punctuation characters + between the ASCII's upper-case range of letters and its lower-case range +@@ -584,8 +614,10 @@ to order strings there are even further consideration= s. + Does left-bracket compare less-than or greater-than "a" in a + case-insensitive comparison?=20 +=20 ++
    • +
    • The German eszet character should sort as if it were the pair of + letters "ss". ++
    • +
    +=20 +

    +@@ -596,9 +628,9 @@ can be overlaid by additional domain- or language-spec= ific rules. Again, + this SRFI does not address these issues. SRFI 13 string ordering is stric= tly + based upon a character-by-character comparison of the values used for + representing the string. +- ++

    + +-

    Naming conventions

    ++

    Naming conventions

    +=20 +

    + This library contains a large number of procedures, but they follow +@@ -608,22 +640,25 @@ in a regular way that exposes the structure and rela= tionships between the + procedures. This should help the programmer to recall or reconstitute the= name + of the particular procedure that he needs when writing his own code. In + particular +- ++

    +
      +
    • Procedures whose names end in "-ci" are case-insensitive variant= s. +=20 ++
    • +
    • Procedures whose names end in "!" are side-effecting variants. + What values these procedures return is usually not specified. +=20 ++
    • +
    • The order of common parameters is consistent across the + different procedures. +=20 ++
    • +
    • Left/right/both directionality: + Procedures that have left/right directional variants + use the following convention: +-
      +- +- ++
      ++
      Direction
      ++ + + + +@@ -635,10 +670,11 @@ particular + This is a general convention that was established in SRFI 1. + The value of a convention is proportional to the extent of its=20 + use. ++ + +=20=20=20=20=20=20=20 + +-

      Shared storage

      ++

      Shared storage

      +=20 +

      + Some Scheme implementations, e.g. guile and T, provide ways to c= onstruct +@@ -651,12 +687,12 @@ property of these substrings -- the application assu= mes that if the underlying + storage is mutated, then all strings sharing that storage will show the + change. However, shared-text substrings are not a common feature; most S= cheme + implementations do not provide them. +- ++

      +

      + SRFI 13 takes a middle ground with respect to shared-text substrings. In + particular, a Scheme implementation does not need to have shared-text + substrings in order to implement this SRFI. +- ++

      +

      + There is an additional form of storage sharing enabled by some SRFI 13 + procedures, even without the benefit of shared-text substrings. In=20 +@@ -665,40 +701,44 @@ of the strings that was passed in as a parameter. Fo= r example, when + constructing a substring with the substring/shared procedure= , if the + requested substring is the entire string, the procedure is permitted + simply to return the original value. That is, +-

      ++

      ++
      + (eq? s (substring/shared s 0 (string-length s))) =3D> true or false
      + 
      +-

      ++

      + whereas the = R5RS=20 + substring function is required to allocate a fresh copy +-

      ++

      ++
      + (eq? s (substring s 0 (string-length s))) =3D> false.
      + 
      +

      + In keeping with SRFI 13's general approach to sharing, compliant + implementations are allowed, but not required, to provide this kind of + sharing. Hence, procedures may not rely upon sharing in these ca= ses. +-

      ++

      ++

      + Most procedures that permit results to share storage with inputs have + equivalent procedures that require allocating fresh storage for results.= =20 + If an application wishes to be sure a new, fresh string is allocated, the= n=20 + these "pure" procedures should be used. +-

      +-
      Direction  Suffix
      left-to-rightnone
      +- ++

      ++
      ++
      Fresh copy guaranteed
      ++ + + + + + + +- ++ + +- ++ + =20 + + ++ + + + +@@ -719,16 +759,16 @@ without this consideration -- if we had cheap shared= -text substrings, all the + start/end index parameters would vanish. However, since SRFI 13 does not + require implementations to provide shared-text substrings, the extended + API is provided. +- ++

      + +-

      R4RS/R5RS procedures

      ++

      R4RS/R5RS procedures

      +=20 +

      + The R4RS and R5RS reports define 22 string procedures. The string-lib + package includes 8 of these exactly as defined, 3 in an extended, + backwards-compatible way, and drops the remaining 11 (whose functionality + is available via other bindings). +- ++

      +

      + The 8 procedures provided exactly as documented in the reports are + string?, +@@ -739,7 +779,7 @@ The 8 procedures provided exactly as documented in the= reports are + string-set!, + string-append, and + list->string. +- ++

      +

      + The eleven functions not included are + string=3D?, string-ci=3D?, +@@ -749,37 +789,44 @@ The eleven functions not included are + string>=3D?, string-ci>=3D?, and + substring. + The string-lib package provides alternate bindings and extended functiona= lity. +- ++

      +

      + Additionally, the three extended procedures are +-

      ++

      ++
      + string-fill! s char [start end] -> unspecified
      + string->list s [start end] -> char-list
      + string-copy  s [start end] -> string
      + 
      +-

      ++

      + They are uniformly extended to take optional start/end parameters specify= ing + substring ranges. +- ++

      + +-

      Extra-SRFI recommendations

      ++

      Extra-SRFI recommendations

      +=20 +

      + This SRFI recommends the following +- ++

      +
        +-
      • A SRFI be defined for shared-text substrings, allowing programs to ++
      • ++

        ++ A SRFI be defined for shared-text substrings, allowing programs to + be written that actually rely on the shared-storage properties of these= data + structures. +- +-

      • A SRFI be defined for manipulating Unicode text -- various normalisa= tion ++

        ++
      • ++
      • ++

        ++ A SRFI be defined for manipulating Unicode text -- various normalisat= ion + operations, collation, searching, etc. Collation operations mi= ght be + parameterised by a "collation" structure representing collation rules + for a particular locale or language. Alternatively, a data structure + specifying collation rules could be activated with dynamic scope by + special procedures, possibly overridden by allowing collation rules + to be optional arguments to procedures that need to order strings, = e.g. +-

        ++    

        ++
        + (with-locale* denmark-locale
        +   (lambda ()=20
        +     (f x)
        +@@ -792,28 +839,32 @@ This SRFI recommends the following
        +=20
        + (set-locale! denmark-locale)
        + 
        +- +-
      • A SRFI be defined for manipulating characters that is portable across ++
      • ++
      • ++

        ++ A SRFI be defined for manipulating characters that is portable acro= ss + at least ASCII, Latin-1 and Unicode.=20 +- +-

          ++

          ++
            +
          • For backwards-compatibility, char-upcase and ch= ar-downcase should=20 + be defined to use the 1-1 locale- and context-insensitive case + mappings given by Unicode's UnicodeData.txt table. +-=20=20 ++
          • +
          • numeric codes for standard functions that map between characters a= nd + integers should be required to use the Unicode/Latin-1/ASCII mapping.= This + allows programmers to write portable code. +- ++
          • +
          • char-titlecase be added to char-upcase a= nd char-downcase. +- ++
          • +
          • char-titlecase? be added to char-upcase?= and char-downcase?. +- ++
          • +
          • Title/up/down-case functions be added to the character-processing = suite + which allow 1->n case maps by returning immutable, + possibly-multi-character strings instead of single characters. These = case + mappings need not be locale- or context-sensitive. +-
          ++ ++
        ++
      • +
      +=20 +

      +@@ -821,75 +872,83 @@ This SRFI recommends the following + requiring a Unicode/Latin-1/ASCII interface to integer/char mapping + functions does not imply anything about the actual underlying encodings= of + characters. +- ++

      +=20 + +-

      Procedure Specification

      ++

      Procedure Specification

      +=20 +

      + In the following procedure specifications: ++

      +
        +
      • An s parameter is a string. +- ++
      • +
      • A char parameter is a character. +- +-
      • Start and end parameters are half-open str= ing indices specifying=20 ++
      • ++
      • Start and end parameters are half-open str= ing indices specifying + a substring within a string parameter; when optional, they default + to 0 and the length of the string, respectively. When specified, it + must be the case that 0 <=3D start <=3D end=20 + <=3D (string-length s), for + the corresponding parameter s. They typically restrict a= procedure's + action to the indicated substring. +- +-
      • A pred parameter is a unary character predicate proce= dure, returning=20 ++
      • ++
      • A pred parameter is a unary character predicate proce= dure, returning + a true/false value when applied to a character. +- ++
      • +
      • A char/char-set/pred parameter is a value used to sel= ect/search + for a character in a string. If it is a character, it is used in + an equality test; if it is a character set, it is used as a + membership test; if it is a procedure, it is applied to the=20 + characters as a test predicate. +- ++
      • +
      • An i parameter is an exact non-negative integer speci= fying an index + into a string. +-=20=20=20=20 ++
      • +
      • Len and nchars parameters are exact non-ne= gative integers specifying a + length of a string or some number of characters. +- ++
      • +
      • An obj parameter may be any value at all. ++
      • +
      +-

      ++

      + Passing values to procedures with these parameters that do not satisfy th= ese + types is an error. +- ++

      +

      + Parameters given in square brackets are optional. Unless otherwise noted = in the + text describing the procedure, any prefix of these optional parameters may + be supplied, from zero arguments to the full list. When a procedure retur= ns + multiple values, this is shown by listing the return values in square + brackets, as well. So, for example, the procedure with signature +-

      +-halts? f [x init-store] -> [boolean integer]
      ++

      ++
      ++halts? f [x init-store] -> [boolean integer]
      + 
      ++

      + would take one (f), two (f, x)=20 + or three (f, x, init-store) input parame= ters,=20 + and return two values, a boolean and an integer. +- ++

      +

      + A parameter followed by "..." means zero-or-more elements.=20 + So the procedure with the signature +-

      +-sum-squares x ...  -> number
      ++

      ++
      ++sum-squares x ...  -> number
      + 
      ++

      + takes zero or more arguments (x ...),=20 + while the procedure with signature +-

      +-spell-check doc dict1 dict2 ... -> =
      string-list
      ++

      ++
      ++spell-check doc dict1 dict2 ... -> string-list
      + 
      ++

      + takes two required parameters=20 + (doc and dict1)=20 + and zero or more optional parameters (dict2 ...). +- ++

      +

      + If a procedure is said to return "unspecified," this means that nothing at + all is said about what the procedure returns. Such a procedure is not even +@@ -901,176 +960,207 @@ Note that in + R5RS= , + this restricts such a procedure to returning a single value;=20 + non-R5RS systems may not even provide this restriction. +- ++

      + +-

      Main procedures

      ++

      Main procedures

      +=20 +

      + In a Scheme system that has a module or package system, these procedures + should be contained in a module named "string-lib". +- ++

      + +-

      Predicates

      ++

      Predicates

      +=20 +
      + +-
      ++
      + +-string? obj -> boolean +-
      ++string? obj -> boolean ++ ++
      ++

      + [R5RS] + Returns #t if obj is a string, otherwise returns = #f. +- ++

      ++
      + +-
      ++
      + +-string-null? s -> boolean +-
      ++string-null? s -> boolean ++ ++
      + Is s the empty string? +
      +=20 + +-
      ++
      + + +-string-every char/char-set/pred s [sta= rt end] -> value +-
      string-any char/= char-set/pred s [start end] -> value +-
      ++string-every char/char-set/pred s [s= tart end] -> value ++ ++
      string-any c= har/char-set/pred s [start end] -> value ++
      ++
      ++

      + Checks to see if the given criteria is true of every / any character = in s, + proceeding from left (index start) to right (index en= d). +- ++

      +

      + If char/char-set/pred is a character, it is tested for equ= ality with + the elements of s. +- ++

      +

      + If char/char-set/pred is a character set, the elements of = s are tested + for membership in the set. +- ++

      +

      + If char/char-set/pred is a predicate procedure, it is appl= ied to the=20 + elements of s. The predicate is "witness-generating:" +- ++

      +
        +
      • If string-any returns true, the returned true val= ue is the one produced + by the application of the predicate. +-=20=20=20=20 ++
      • +
      • If string-every returns true, the returned true v= alue is the one +- produced by the final application of the predicate to s[end].=20 ++ produced by the final application of the predicate to s[end-1].=20 + If string-every is applied to an empty sequence of c= haracters,=20 + it simply returns #t. ++
      • +
      ++

      + If string-every or string-any apply the p= redicate to the final element + of the selected sequence (i.e., s[end-1]), that final application is a + tail call. +- ++

      +

      + The names of these procedures do not end with a question mark -- this= is to + indicate that, in the predicate case, they do not return a simple boo= lean + (#t or #f), but a general value. ++

      ++
      +
      +=20 +=20 + +-

      Constructors

      ++

      Constructors

      +=20 +
      + +-
      ++
      + +-make-string len [char] -> string +-
      ++make-string len [char] -> string<= /var> ++ ++
      ++

      + [R5RS<= /abbr>] + make-string returns a newly allocated string of length len. If + char is given, then all elements of the string are initializ= ed + to char, otherwise the contents of the string are unspecifie= d. +- ++

      ++
      + +-
      ++
      + +-string char1 ... -> string<= /var> +-
      ++string char1 ... -> st= ring ++ ++
      ++

      + [R5RS<= /abbr>] + Returns a newly allocated string composed of the argument characters. +-=20=20=20=20 ++

      ++
      + +-
      ++
      + +-string-tabulate proc len -> string +-
      +- Proc is an integer->char procedure. Construct a string of = size len ++string-tabulate proc len -> strin= g ++ ++
      ++

      ++ Proc is an integer->char procedure. Construct a string = of size len + by applying proc to each index to produce the correspondin= g string + element. The order in which proc is applied to the indices= is not + specified. +- ++

      ++
      +
      +=20 + +-

      List & string conversion

      ++

      List & string conversion

      +=20 +
      +=20 + +-
      ++
      + + +-string->list s [start end] -> char-= list +-
      list->string = char-list -> string +-
      ++string->list s [start end] -> = char-list ++ ++
      list->string char-list -> string ++
      ++
      ++

      + [R5RS+] +- string->list returns a newly allocated list of the chara= cters +- that make up the given string. list->string returns a n= ewly ++ string->list returns a newly allocated list of the ch= aracters ++ that make up the given string. list->string returns = a newly + allocated string formed from the characters in the list char-lis= t, +- which must be a list of characters. string->list and list->string=20 ++ which must be a list of characters. string->list and = list->string=20 + are inverses so far as equal? is concerned. +- +-

      +- string->list is extended from the R5RS definition to take o= ptional ++

      ++

      ++ string->list is extended from the R5RS definition to tak= e optional + start/end arguments. +- ++

      ++
      + +-
      ++
      + +-reverse-list->string char-list -> s= tring +-
      +- An efficient implementation of (compose list->string reverse): +-
      +-(reverse-list->string '(#\a #\B #\c)) -> "cBa"
      ++reverse-list->string char-list -&=
      gt; string
      ++
      ++
      ++

      ++ An efficient implementation of (compose list->string reverse= ): ++

      ++
      ++(reverse-list->string '(#\a #\B #\c)) -> "cBa"
      + 
      ++

      + This is a common idiom in the epilog of string-processing loops + that accumulate an answer in a reverse-order list. (See also + string-concatenate-reverse for the "chunked" variant.) +- ++

      ++
      + +-
      ++
      + +-string-join string-list [delimiter gra= mmar] -> string +-
      ++string-join string-list [delimiter g= rammar] -> string ++ ++
      ++

      + This procedure is a simple unparser --- it pastes strings together us= ing + the delimiter string.=20 +- +-

      ++

      ++

      + The grammar argument is a symbol that determines how the d= elimiter is + used, and defaults to 'infix. +-=20=20=20=20 ++

      +
        +
      • 'infix means an infix or separator grammar:=20 + insert the delimiter +@@ -1079,20 +1169,25 @@ Returns #t if obj is a str= ing, otherwise returns # + grammar is ambiguous. Is it an empty list, or a list of one eleme= nt, + the empty string? +=20=20=20=20=20 +-
      • 'strict-infix means the same as 'infix,=20 ++
      • ++
      • 'strict-infix means the same as 'infix, + but will raise an error if given an empty list. +=20=20=20=20=20 ++
      • +
      • 'suffix means a suffix or terminator grammar:=20 + insert the delimiter + after every list element. This grammar has no ambiguities. +=20 ++
      • +
      • 'prefix means a prefix grammar: insert the delimi= ter + before every list element. This grammar has no ambiguities. ++
      • +
      +- ++

      + The delimiter is the string used to delimit elements; it defaults to + a single space " ". +-

      ++

      ++
      + (string-join '("foo" "bar" "baz") ":")         =3D> "foo:bar:baz"
      + (string-join '("foo" "bar" "baz") ":" 'suffix) =3D> "foo:bar:baz:"
      +=20
      +@@ -1104,103 +1199,124 @@ Returns #t if obj is a s=
      tring, otherwise returns #
      + (string-join '()   ":" 'suffix) =3D> ""
      + (string-join '("") ":" 'suffix) =3D> ":"
      + 
      ++
      +
      +=20 +=20 + +-

      Selection

      ++

      Selection

      +=20 +
      + +-
      ++
      + +-string-length s -> integer +-
      ++string-length s -> integer ++ ++
      ++

      + [R5RS<= /abbr>] + Returns the number of characters in the string s. +- ++

      ++
      + +-
      ++
      + +-string-ref s i -> char +-
      ++string-ref s i -> char ++ ++
      ++

      + [R5RS<= /abbr>] + Returns character s[i] using zero-origin indexing. + I must be a valid index of s.=20=20 +- ++

      ++
      + +-
      ++
      + + +-string-copy s [start end] -> stri= ng +-
      substring/shared= s start [end] -> string +-
      ++string-copy s [start end] ->= string ++ ++
      substring/shared<= var> s start [end] -> string ++
      ++
      ++

      + [R5RS+] + substring/shared returns a string whose contents are the= characters of s + beginning with index start (inclusive) and ending with ind= ex end + (exclusive). It differs from the R5RS substring in two ways: ++

      +
        +
      • The end parameter is optional, not required. ++
      • +
      • substring/shared may return a value that shares m= emory with s or + is eq? to s. ++
      • +
      +- +-

      ++

      + string-copy is extended from its R5RS definition by the add= ition of + its optional start/end parameters. In contrast to su= bstring/shared, + it is guaranteed to produce a freshly-allocated string. +- +-

      ++

      ++

      + Use string-copy when you want to indicate explicitly in = your code that you + wish to allocate new storage; use substring/shared when = you don't care if=20 + you get a fresh copy or share storage with the original string. +-

      ++

      ++
      + (string-copy "Beta substitution") =3D> "Beta substitution"
      + (string-copy "Beta substitution" 1 10)=20
      +     =3D> "eta subst"
      + (string-copy "Beta substitution" 5) =3D> "substitution"
      + 
      +- ++
      + +-
      ++
      + +-string-copy! target tstart s [start en= d] -> unspecified +-
      ++string-copy! target tstart s [start = end] -> unspecified ++ ++
      ++

      + Copy the sequence of characters from index range [start,end) in + string s to string target, beginning at index <= var>tstart. The characters=20 + are copied left-to-right or right-to-left as needed -- the copy is + guaranteed to work, even if target and s are th= e same string. +- ++

      +

      + It is an error if the copy operation runs off the end of the target + string, e.g. +-

      ++    

      ++
      + (string-copy! (string-copy "Microsoft") 0
      +               "Regional Microsoft Operating Companies") =3D> error=
      
      + 
      +- ++
      +=20 + +-
      ++
      + + + + +-string-take s nchars -> string +-
      string-drop s nc= hars -> string +-
      string-take-right s nchars -> string +-
      string-drop-right s nchars -> string +-
      ++string-take s nchars -> string ++ ++
      string-drop = s nchars -> string ++
      ++
      string-take-right= s nchars -> string ++
      ++
      string-drop-right= s nchars -> string ++
      ++
      ++

      + string-take returns the first nchars of = s;=20 + string-drop returns all but the first nchars = of s. + string-take-right returns the last nchars of = s; +@@ -1208,133 +1324,157 @@ Returns #t if obj is a s= tring, otherwise returns # + If these procedures produce the entire string, they may return either + s or a copy of s; in some implementations, prop= er substrings may share + memory with s. +-

      ++

      ++
      + (string-take "Pete Szilagyi" 6) =3D> "Pete S"
      + (string-drop "Pete Szilagyi" 6) =3D> "zilagyi"
      +=20
      + (string-take-right "Beta rules" 5) =3D> "rules"
      + (string-drop-right "Beta rules" 5) =3D> "Beta "
      + 
      +- ++

      + It is an error to take or drop more characters than are in the string: +-

      ++

      ++
      + (string-take "foo" 37) =3D> error
      + 
      +- ++
      + +-
      ++
      + + +-string-pad s len [char start end= ] -> string +-
      string-pad-right= s len [char start end] -> string +-
      ++string-pad s len [char start e= nd] -> string ++ ++
      string-pad-right<= var> s len [char start end] -> string ++
      ++
      ++

      + Build a string of length len comprised of s pad= ded on the left (right) + by as many occurrences of the character char as needed. If= s has more + than len chars, it is truncated on the left (right) to len= gth len. Char + defaults to #\space. +- +-

      ++

      ++

      + If len <=3D end-start, the return= ed value is allowed to share storage + with s, or be exactly s (if len =3D = end-start). +-

      ++

      ++
      + (string-pad     "325" 5) =3D> "  325"
      + (string-pad   "71325" 5) =3D> "71325"
      + (string-pad "8871325" 5) =3D> "71325"
      + 
      +- ++
      + +-
      ++
      + + + +-string-trim       s [char/char-set/pred start end] -> string +-
      string-trim-right s [char/char-set/pred start end] -> string +-
      string-trim-both  s [char/char-set/pred start end] -> string +-
      ++string-trim      <= /code> s [char/char-set/pred start end] -> string ++ ++
      string-trim-right= s [char/char-set/pred start end] -> string ++
      ++
      string-trim-both  s [char/char-set/pred start end] -> string ++
      ++
      ++

      + Trim s by skipping over all characters on the left / on th= e right / + on both sides that satisfy the second parameter char/char-set/pr= ed: +-

        ++

        ++
          +
        • if it is a character char, characters equal to char are trimmed; ++
        • +
        • if it is a char set cs, characters contained in <= var>cs are trimmed; ++
        • +
        • if it is a predicate pred, it is a test predicate= that is applied + to the characters in s; a character causing it to re= turn true + is skipped. +-
        ++ ++
      ++

      + Char/char-set/pred defaults to the character set cha= r-set:whitespace + defined in SRFI 14. +- +-

      ++

      ++

      + If no trimming occurs, these functions may return either s= or a copy of s; + in some implementations, proper substrings may share memory with s. +- +-

      ++

      ++
      + (string-trim-both "  The outlook wasn't brilliant,  \n\r")
      +     =3D> "The outlook wasn't brilliant,"
      + 
      ++
      +
      +=20 +=20 + +-

      Modification

      ++

      Modification

      +=20 +
      +=20 + +-
      ++
      + +-string-set! s i char -> unspecified = +-
      ++string-set! s i char -> unspecifi= ed ++ ++
      ++

      + [R5RS<= /abbr>] + I must be a valid index of s. string-set!<= /code> stores char in + element i of s. Constant string literals appearin= g in code are=20 + immutable; it is an error to use them in a string-set!. +- +-

      ++

      ++
      + (define (f) (make-string 3 #\*))
      + (define (g) "***")
      + (string-set! (f) 0 #\?)                =3D=3D>  unspecified
      + (string-set! (g) 0 #\?)                =3D=3D>  error
      +-(string-set! (symbol->string 'immutable)
      ++(string-set! (symbol->string 'immutable)
      +              3
      +              #\?)                      =3D=3D>  error
      + 
      +- ++
      + +-
      ++
      + +-string-fill! s char [start end] -> uns= pecified +-
      ++string-fill! s char [start end] ->= ; unspecified ++ ++
      ++

      + [R5RS+] + Stores char in every element of s. +- +-

      ++

      ++

      + string-fill is extended from the R5RS definition to take op= tional + start/end arguments. +- ++

      ++
      +
      +=20 + +-

      Comparison

      ++

      Comparison

      +=20 +
      +=20 + +-
      ++
      + + +-string-compare    s1 s2= proc< proc=3D proc> [start1 end1 start2 end2] -> values +-
      string-compare-ci s1 s2 proc< proc=3D proc> [start1 end1 start2 end2] -> values +-
      ++string-compare    s1 = s2 proc< proc=3D proc> [start1 end1 start2 end2] -> values ++ ++
      string-compare-ci= s1 s2 proc< proc=3D proc> [start1 end1 start2 end2] -> value= s ++
      ++
      ++

      + Apply proc<, proc=3D, or proc> + to the mismatch index, depending + upon whether s1 is less than, equal to, or greater than s= 2. +@@ -1342,156 +1482,182 @@ The "mismatch index" is the largest index i= such that for + every 0 <=3D j < i,=20 + s1[j] =3D s2[j] + -- that is, i is the first position that doesn't match. +- ++

      +

      + string-compare-ci is the case-insensitive variant. Case-inse= nsitive + comparison is done by case-folding characters with the operation +-

      ++

      ++
      + (char-downcase (char-upcase c))
      + 
      ++

      + where the two case-mapping operations are assumed to be 1-1, locale- and + context-insensitive, and compatible with the 1-1 case mappings specified + by Unicode's UnicodeData.txt table: +-

      ++

      ++ +- +

      + The optional start/end indices restrict the comparison to the indicated + substrings of s1 and s2. The mismatch index is alwa= ys an index into s1; + in the case of proc=3D, it is always end1;=20 + we observe the protocol + in this redundant case for uniformity. +- +-

      ++

      ++
      + (string-compare "The cat in the hat" "abcdefgh"=20
      +                 values values values
      +                 4 6         ; Select "ca"=20
      +                 2 4)        ; & "cd"
      +     =3D> 5    ; Index of S1's "a"
      + 
      +- ++

      + Comparison is simply done on individual code-points of the string.=20 + True text collation is not handled by this SRFI. +- ++

      ++
      + +-
      ++
      + +-"> +- +-"> +- +-=3D"> +-string=3D  s1 s2 [start1 end1 sta= rt2 end2] -> boolean +-
      string<> s= 1 s2 [start1 end1 start2 end2] -> boolean +-
      string< = s1 s2 [start1 end1 start2 end2] -> boolean +-
      string> = s1 s2 [start1 end1 start2 end2] -> boolean +-
      string<=3D s1= s2 [start1 end1 start2 end2] -> boolean +-
      string>=3D s1= s2 [start1 end1 start2 end2] -> boolean +-
      ++ ++ ++ ++ ++ ++string=3D  s1 s2 [start1 end1 s= tart2 end2] -> boolean ++ ++
      string<> s1 s2 [start1 end1 start2 end2] -> boolean ++
      ++
      string< <= var> s1 s2 [start1 end1 start2 end2] -> boolean ++
      ++
      string> <= var> s1 s2 [start1 end1 start2 end2] -> boolean ++
      ++
      string<=3D s1 s2 [start1 end1 start2 end2] -> boolean ++
      ++
      string>=3D s1 s2 [start1 end1 start2 end2] -> boolean ++
      ++
      ++

      + These procedures are the lexicographic extensions to strings of the + corresponding orderings on characters. For example, string<= is the + lexicographic ordering on strings induced by the ordering char&= lt;? on + characters. If two strings differ in length but are the same up to=20 + the length of the shorter string, the shorter string is considered to= =20 + be lexicographically less than the longer string. +- +-

      ++

      ++

      + The optional start/end indices restrict the comparison to the indicat= ed + substrings of s1 and s2.=20 +- +-

      ++

      ++

      + Comparison is simply done on individual code-points of the string.=20 + True text collation is not handled by this SRFI. +- ++

      ++
      + +-
      ++
      + +-"> +- +-"> +- +-=3D"> +-string-ci=3D  s1 s2 [start1 end1 = start2 end2] -> boolean +-
      string-ci<> s1 s2 [start1 end1 start2 end2] -> boolean +-
      string-ci<  s1 s2 [start1 end1 start2 end2] -> boolean +-
      string-ci>  s1 s2 [start1 end1 start2 end2] -> boolean +-
      string-ci<=3D= s1 s2 [start1 end1 start2 end2] -> boolean +-
      string-ci>=3D= s1 s2 [start1 end1 start2 end2] -> boolean +-
      ++ ++ ++ ++ ++ ++string-ci=3D  s1 s2 [start1 end= 1 start2 end2] -> boolean ++ ++
      string-ci<>= s1 s2 [start1 end1 start2 end2] -> boolean ++
      ++
      string-ci<  s1 s2 [start1 end1 start2 end2] -> boolean ++
      ++
      string-ci>  s1 s2 [start1 end1 start2 end2] -> boolean ++
      ++
      string-ci<=3D<= var> s1 s2 [start1 end1 start2 end2] -> boolean ++
      ++
      string-ci>=3D<= var> s1 s2 [start1 end1 start2 end2] -> boolean ++
      ++
      ++

      + Case-insensitive variants. +- +-

      ++

      ++

      + Case-insensitive comparison is done by case-folding characters with=20 + the operation +-

      ++

      ++
      + (char-downcase (char-upcase c))
      + 
      ++

      + where the two case-mapping operations are assumed to be 1-1, locale- = and + context-insensitive, and compatible with the 1-1 case mappings specif= ied + by Unicode's UnicodeData.txt table: +-

      + +-
      ++
      + + +-string-hash    s [bound= start end] -> integer +-
      string-hash-ci s= [bound start end] -> integer +-
      ++string-hash    s [bou= nd start end] -> integer ++ ++
      string-hash-ci s [bound start end] -> integer ++
      ++
      ++

      + Compute a hash value for the string s.=20 + Bound is a non-negative + exact integer specifying the range of the hash function. A positive + value restricts the return value to the range [0,bound). +- ++

      +

      + If bound is either zero or not given, the implementation may u= se + an implementation-specific default value, chosen to be as large as + is efficiently practical. For instance, the default range might be chosen + for a given implementation to map all strings into the range of + integers that can be represented with a single machine word. +- ++

      +

      + The optional start/end indices restrict the hash operation to the=20 + indicated substring of s. +- ++

      +

      + string-hash-ci is the case-insensitive variant. Case-insensi= tive + comparison is done by case-folding characters with the operation +-

      ++

      ++
      + (char-downcase (char-upcase c))
      + 
      ++

      + where the two case-mapping operations are assumed to be 1-1, locale- and + context-insensitive, and compatible with the 1-1 case mappings specified + by Unicode's UnicodeData.txt table: +-

      ++

      ++ +- +

      + Invariants: +-

      +-(<=3D 0 (string-hash s b) (- b 1)) ; When B > 0.
      ++

      ++
      ++(<=3D 0 (string-hash s b) (- b 1)) ; When B > 0.
      + (string=3D    s1 s2)  =3D>  (=3D (string-hash s1 b)    (string-hash s2=
       b))
      + (string-ci=3D s1 s2)  =3D>  (=3D (string-hash-ci s1 b) (string-hash-ci=
       s2 b))
      + 
      +- +

      + A legal but nonetheless discouraged implementation: +-

      ++

      ++
      + (define (string-hash    s . other-args) 1)
      + (define (string-hash-ci s . other-args) 1)
      + 
      +- +

      + Rationale: allowing the user to specify an explicit bound simplifies = user + code by removing the mod operation that typically accompanies every h= ash +@@ -1502,231 +1668,274 @@ A legal but nonetheless discouraged implementati= on: + intermediate values never overflow into bignum integers, allowing the + implementor to provide a fixnum-specific "fast path" for computing the + common cases very rapidly. +- +- ++

      ++
      +
      +=20 + +-

      Prefixes & suffixes

      ++

      Prefixes & suffixes

      +=20 +
      + +-
      ++
      + + + + +-string-prefix-length   = s1 s2 [start1 end1 start2 end2] -> integer +-
      string-suffix-length &n= bsp;  s1 s2 [start1 end1 start2 end2] -> integer +-
      string-prefix-length-ci s1 s2 [start1 end1 start2 end2] -> integer +-
      string-suffix-length-ci s1 s2 [start1 end1 start2 end2] -> integer +-
      ++string-prefix-length    s1 s2 [start1 end1 start2 end2] -> integer ++ ++
      string-suffix-length&nbs= p;   s1 s2 [start1 end1 start2 end2] -> integer ++
      ++
      string-prefix-length-ci<= /code> s1 s2 [start1 end1 start2 end2] -> integer ++
      ++
      string-suffix-length-ci<= /code> s1 s2 [start1 end1 start2 end2] -> integer ++
      ++
      ++

      + Return the length of the longest common prefix/suffix of the two strings. + For prefixes, this is equivalent to the "mismatch index" for the strings + (modulo the starti index offsets). +- ++

      +

      + The optional start/end indices restrict the comparison to the indicated + substrings of s1 and s2. +- ++

      +

      + string-prefix-length-ci and string-suffix-length-ci are the + case-insensitive variants. Case-insensitive comparison is done by + case-folding characters with the operation +-

      ++

      ++
      + (char-downcase (char-upcase c))
      + 
      ++

      + where the two case-mapping operations are assumed to be 1-1, locale- and + context-insensitive, and compatible with the 1-1 case mappings specified + by Unicode's UnicodeData.txt table: +-

      ++

      ++ ++

      + Comparison is simply done on individual code-points of the string.=20 +- ++

      ++
      + +-
      ++
      + + + + +-string-prefix?    s1 s2= [start1 end1 start2 end2] -> boolean +-
      string-suffix?  &n= bsp; s1 s2 [start1 end1 start2 end2] -> boolean +-
      string-prefix-ci? s1 s2 [start1 end1 start2 end2] -> boolean +-
      string-suffix-ci? s1 s2 [start1 end1 start2 end2] -> boolean +-
      ++string-prefix?    s1 = s2 [start1 end1 start2 end2] -> boolean ++ ++
      string-suffix? &nbs= p;  s1 s2 [start1 end1 start2 end2] -> boolean ++
      ++
      string-prefix-ci?= s1 s2 [start1 end1 start2 end2] -> boolean ++
      ++
      string-suffix-ci?= s1 s2 [start1 end1 start2 end2] -> boolean ++
      ++
      ++

      + Is s1 a prefix/suffix of s2? +- ++

      +

      + The optional start/end indices restrict the comparison to the indicated + substrings of s1 and s2. +- ++

      +

      + string-prefix-ci? and string-suffix-ci? are the= case-insensitive variants. + Case-insensitive comparison is done by case-folding characters with the + operation +-

      ++

      ++
      + (char-downcase (char-upcase c))
      + 
      ++

      + where the two case-mapping operations are assumed to be 1-1, locale- and + context-insensitive, and compatible with the 1-1 case mappings specified + by Unicode's UnicodeData.txt table: +-

      ++

      ++ +- +

      + Comparison is simply done on individual code-points of the string.=20 +- ++

      ++
      +
      +=20 + +-

      Searching

      ++

      Searching

      +=20 +
      +=20 + +-
      ++
      + + + + +-string-index s char/char-set/pre= d [start end] -> integer or #f +-
      string-index-right s char/char-set/pred [start end] -> integer or #f +-
      string-skip s ch= ar/char-set/pred [start end] -> integer or #f +-
      string-skip-right s char/char-set/pred [start end] -> integer or #f +-
      ++string-index s char/char-set/p= red [start end] -> integer or #f ++ ++
      string-index-right s char/char-set/pred [start end] -> integer or #f ++
      ++
      string-skip = s char/char-set/pred [start end] -> integer or #f ++
      ++
      string-skip-right= s char/char-set/pred [start end] -> integer or #f ++
      ++
      ++

      + string-index (string-index-right) searches thro= ugh the string from the=20 + left (right), returning the index of the first occurrence of a character= =20 + which ++

      +
        +
      • equals char/char-set/pred (if it is a character); ++
      • +
      • is in char/char-set/pred (if it is a character set); ++
      • +
      • satisfies the predicate char/char-set/pred (if it is = a procedure). ++
      • +
      ++

      + If no match is found, the functions return false. +- ++

      +

      + The start and end parameters specify the beginning = and end indices of + the search; the search includes the start index, but not the end index. + Be careful of "fencepost" considerations: when searching right-to-left,=20 + the first index considered is +-

      ++

      ++
      + end-1 +
      ++

      + whereas when searching left-to-right, the first index considered is +-

      ++

      ++
      + start +
      ++

      + That is, the start/end indices describe a same half-open interval + [start,end) in these procedures that they do + in all the other SRFI 13 procedures. +- ++

      +

      + The skip functions are similar, but use the complement of the criteria: + they search for the first char that doesn't satisfy the test. E.g.,=20 + to skip over initial whitespace, say +-

      ++

      ++
      + (cond ((string-skip s char-set:whitespace) =3D>
      +        (lambda (i) ...)) ; s[i] is not whitespace.
      +       ...)
      + 
      +- ++
      + +-
      ++
      + +-string-count s char/char-set/pred [sta= rt end] -> integer +-
      ++string-count s char/char-set/pred [s= tart end] -> integer ++ ++
      ++

      + Return a count of the number of characters in s that satis= fy the + char/char-set/pred argument. If this argument is a procedu= re,=20 + it is applied to the character as a predicate; if it is a character s= et,=20 + the character is tested for membership; if it is a character, it is=20 + used in an equality test. +- ++

      ++
      + +-
      ++
      + + +-string-contains    s1 s= 2 [start1 end1 start2 end2] -> integer or false +-
      string-contains-ci s1 s2 [start1 end1 start2 end2] -> integer or false +-
      ++string-contains    s1= s2 [start1 end1 start2 end2] -> integer or false ++ ++
      string-contains-ci s1 s2 [start1 end1 start2 end2] -> integer or false ++
      ++
      ++

      + Does string s1 contain string s2? +- ++

      +

      + Return the index in s1 where s2 occurs as a substri= ng, or false. + The optional start/end indices restrict the operation to the + indicated substrings. +- ++

      +

      + The returned index is in the range [start1,end1).=20 + A successful match must lie entirely in the=20 + [start1,end1) range of s1. +- +-

      +-

      ++

      ++
      + (string-contains "eek -- what a geek." "ee"
      +                  12 18) ; Searches "a geek"
      +     =3D> 15
      + 
      +- +

      + string-contains-ci is the case-insensitive variant. Case-ins= ensitive + comparison is done by case-folding characters with the operation +-

      ++

      ++
      + (char-downcase (char-upcase c))
      + 
      ++

      + where the two case-mapping operations are assumed to be 1-1, locale- and + context-insensitive, and compatible with the 1-1 case mappings specified + by Unicode's UnicodeData.txt table: +-

      ++

      ++ +- +

      + Comparison is simply done on individual code-points of the string.=20 +- ++

      +

      + The names of these procedures do not end with a question mark -- this is = to + indicate that they do not return a simple boolean (#t or #f). Rather, + they return either false (#f) or an exact non-negative integ= er. +- ++

      ++
      +
      +=20 ++ + +-

      Alphabetic case mapping

      ++

      Alphabetic case mapping

      +=20 +
      +=20 + +-
      ++
      + + +-string-titlecase  s [start end] -= > string +-
      string-titlecase! s [start end] -> unspecified +-
      ++string-titlecase  s [start end]= -> string ++ ++
      string-titlecase!= s [start end] -> unspecified ++
      ++
      ++

      + For every character c in the selected range of s,=20 + if c is preceded by a cased character, it is downcased;=20 + otherwise it is titlecased. +- ++

      +

      + string-titlecase returns the result string and does not alte= r its s + parameter. string-titlecase! is the in-place side-effecting = variant. +- +-

      +-

      ++

      ++
      + (string-titlecase "--capitalize tHIS sentence.") =3D>
      +   "--Capitalize This Sentence."
      +=20
      +@@ -1736,70 +1945,80 @@ parameter. string-titlecase! is the i=
      n-place side-effecting variant
      + (string-titlecase "3com makes routers.") =3D>
      +   "3Com Makes Routers."
      + 
      +- +

      + Note that if a start index is specified, then the character + preceding s[start] has no effect on the titlecase d= ecision for + character s[start]: +-

      ++

      ++
      + (string-titlecase "greasy fried chicken" 2) =3D> "Easy Fried Chicken"
      + 
      +- +

      + Titlecase and cased information must be compatible with the Unicode + specification. +- ++

      ++
      + +-
      ++
      + + + + +-string-upcase  s [start end] -> s= tring +-
      string-upcase! s= [start end] -> unspecified +-
      string-downcase = s [start end] -> string +-
      string-downcase!= s [start end] -> unspecified +-
      ++string-upcase  s [start end] -&= gt; string ++ ++
      string-upcase! s [start end] -> unspecified ++
      ++
      string-downcase  s [start end] -> string ++
      ++
      string-downcase!<= var> s [start end] -> unspecified ++
      ++
      ++

      + Raise or lower the case of the alphabetic characters in the string. +- +-

      ++

      ++

      + string-upcase and string-downcase return th= e result string and do not + alter their s parameter. string-upcase! and <= code>string-downcase! are the +- in-place side-effecting variants.=20=20=20=20 +- +-

      ++ in-place side-effecting variants. ++

      ++

      + These procedures use the locale- and context-insensitive 1-1 case map= pings + defined by Unicode's UnicodeData.txt table: +-

      +
      +=20 ++ + +-

      Reverse & append

      ++

      Reverse & append

      +=20 +
      +=20 + +-
      ++
      + + +-string-reverse  s [start end] -> = string +-
      string-reverse! = s [start end] -> unspecified +-
      ++string-reverse  s [start end] -= > string ++ ++
      string-reverse! s [start end] -> unspecified ++
      ++
      ++

      + Reverse the string. +- ++

      +

      + string-reverse returns the result string=20 + and does not alter its s parameter.=20 + string-reverse! is the in-place side-effecting variant. +- +-

      ++

      ++
      + (string-reverse "Able was I ere I saw elba.")=20
      +     =3D> ".able was I ere I saw elbA"
      +=20
      +@@ -1810,49 +2029,58 @@ and does not alter its s parameter.
      +     (string-reverse! s i)
      +     (string-reverse! s)))
      + 
      +- +

      + Unicode note: Reversing a string simply reverses the sequence of + code-points it contains. So a zero-width accent character a=20 + coming after a base character b in string s=20 + would come out before b in the reversed result. +- ++

      ++
      + +-
      ++
      + +-string-append s1 ... -> str= ing +-
      ++string-append s1 ... ->= ; string ++ ++
      ++

      + [R5RS<= /abbr>] + Returns a newly allocated string whose characters form the + concatenation of the given strings. +- ++

      ++
      + +-
      ++
      + +-string-concatenate string-list -> stri= ng +-
      ++string-concatenate string-list ->= string ++ ++
      ++

      + Append the elements of string-list together into a singl= e string. + Guaranteed to return a freshly allocated string. +- +-

      ++

      ++

      + Note that the (apply string-append string-list) + idiom is + not robust for long lists of strings, as some Scheme implementations + limit the number of arguments that may be passed to an n-ary procedur= e. +- ++

      ++
      + +-
      ++
      + + +-string-concatenate/shared string-list = -> string +-
      string-append/shared<= var> s1 ... -> string +-
      ++string-concatenate/shared string-lis= t -> string ++ ++
      string-append/shared s1 ... -> string ++
      ++
      ++

      + These two procedures are variants of string-concatenate= =20 + and string-append + that are permitted to return results that share storage with their +@@ -1860,122 +2088,146 @@ would come out before b in t= he reversed result. + In particular, if string-append/shared is applied to jus= t=20 + one argument, it may return exactly that argument,=20 + whereas string-append is required to allocate a fresh st= ring. +- ++

      ++
      + +-
      ++
      + + +-string-concatenate-reverse stri= ng-list [final-string end] -> string +-
      string-concatenate-reverse/s= hared string-list [final-string end] -> string +-
      ++string-concatenate-reverse st= ring-list [final-string end] -> string ++ ++
      string-concatenate-rever= se/shared string-list [final-string end] -> string ++
      ++
      ++

      + With no optional arguments, these functions are equivalent to +-

      ++

      ++
      + (string-concatenate (reverse string-list))
      + 
      ++

      + and +-

      ++

      ++
      + (string-concatenate/shared (reverse string-list))
      + 
      ++

      + respectively. +- ++

      +

      + If the optional argument final-string is specified, it is cons= ed + onto the beginning of string-list + before performing the list-reverse and string-concatenate operations. +- +

      ++

      + If the optional argument end is given,=20 + only the first end characters + of final-string are added to the string list, thus producing +-

      ++

      ++
      + (string-concatenate=20
      +   (reverse (cons (substring/shared final-string 0 end)
      +                  string-list)))
      + 
      ++

      + E.g. +-

      ++

      ++
      + (string-concatenate-reverse '(" must be" "Hello, I") " going.XXXX" 7)
      +   =3D> "Hello, I must be going."
      + 
      +- +

      + This procedure is useful in the construction of procedures that=20 + accumulate character data into lists of string buffers, and wish to + convert the accumulated data into a single string when done. +- ++

      +

      + Unicode note: Reversing a string simply reverses the sequence of + code-points it contains.=20 + So a zero-width accent character ac coming after + a base character bc in string s would come out=20 + before bc in the reversed result. +- ++

      ++
      +
      +=20 ++ + +-

      Fold, unfold & map

      ++

      Fold, unfold & map

      +=20 +
      +=20 + +-
      ++
      + + +-string-map  proc s [start end] ->= string +-
      string-map! proc= s [start end] -> unspecified +-
      +- Proc is a char->char procedure; it is mapped over s. +-=20=20=20=20 +-

      ++string-map  proc s [start end] = -> string ++ ++

      string-map! = proc s [start end] -> unspecified ++
      ++
      ++

      ++ Proc is a char->char procedure; it is mapped over = s. ++

      ++

      + string-map returns the result string and does not alter = its s parameter. + string-map! is the in-place side-effecting variant. +- +-

      ++

      ++

      + Note: The order in which proc is applied to the elements of + s is not specified. +- ++

      ++
      + +-
      ++
      + + +-string-fold kons knil s [start e= nd] -> value +-
      string-fold-right kons knil s [start end] -> value +-
      ++string-fold kons knil s [start= end] -> value ++ ++
      string-fold-right= kons knil s [start end] -> value ++
      ++
      ++

      + These are the fundamental iterators for strings. +- ++

      +

      + The left-fold operator maps the kons procedure across the + string from left to right +-

      ++

      ++
      + (... (kons s[2] (kons s[1] (<=
      var>kons s[0] knil))))
      + 
      ++

      + In other words, string-fold obeys the (tail) recursion +-

      ++

      ++
      + (string-fold kons knil s start end) =3D
      +     (string-fold kons (kons s[start=
      ] knil) start+1 end)
      + 
      +- +

      + The right-fold operator maps the kons procedure across the + string from right to left +-

      ++

      ++
      + (kons s[0] (... (kons s[=
      end-3] (kons s[end-2] (kons s[end-1] knil)))))
      + 
      ++

      + obeying the (tail) recursion +-

      ++

      ++
      + (string-fold-right kons knil s star=
      t end) =3D
      +     (string-fold-right kons (kons s[end-1] knil) start end-1)
      + 
      +-=20=20=20=20 +

      + Examples:=20 +-

      ++

      ++
      + ;;; Convert a string to a list of chars.
      + (string-fold-right cons '() s)
      +=20
      +@@ -2001,39 +2253,46 @@ Examples:
      +                0 s)
      +   ans)
      + 
      +- +

      + The right-fold combinator is sometimes called a "catamorphism." +- ++

      ++
      + +-
      ++
      + +-string-unfold p f g seed [base make-fi= nal] -> string +-
      ++string-unfold p f g seed [base make-= final] -> string ++ ++
      ++

      + This is a fundamental constructor for strings.=20 ++

      +
        +
      • G is used to generate a series of "seed" values from the = initial seed: +-
        ++
        + seed, (g seed), (g2<= /var> seed), (g3 seed), ... +
        ++
      • +
      • P tells us when to stop -- when it returns true when appl= ied to one=20 + of these seed values. ++
      • +
      • F maps each seed value to the corresponding character=20 + in the result string. These chars are assembled into the + string in a left-to-right order. ++
      • +
      • Base is the optional initial/leftmost portion of the cons= tructed string; + it defaults to the empty string "". ++
      • +
      • Make-final is applied to the terminal seed value (on whic= h p returns + true) to produce the final/rightmost portion of the constructed string. + It defaults to (lambda (x) ""). ++
      • +
      +- +

      + More precisely, the following (simple, inefficient) definitions hold: +- +-

      ++

      ++
      + ;;; Iterative
      + (define (string-unfold p f g seed base make-final)
      +   (let lp ((seed seed) (ans base))
      +@@ -2053,18 +2312,20 @@ More precisely, the following (simple, inefficient=
      ) definitions hold:
      + string-unfold is a fairly powerful string constructor -- you=
       can use it to
      + convert a list to a string, read a port into a string, reverse a string,
      + copy a string, and so forth. Examples:
      +-
      +-(port->string p) =3D (string-unfold eof-object? values
      ++

      ++
      ++(port->string p) =3D (string-unfold eof-object? values
      +                                   (lambda (x) (read-char p))
      +                                   (read-char p))
      +=20
      +-(list->string lis) =3D (string-unfold null? car cdr lis)
      ++(list->string lis) =3D (string-unfold null? car cdr lis)
      +=20
      + (string-tabulate f size) =3D (string-unfold (lambda (i) (=3D i size)) f a=
      dd1 0)
      + 
      +

      + To map f over a list lis, producing a string: +-

      ++

      ++
      + (string-unfold null? (compose f car) cdr lis)
      + 
      +

      +@@ -2072,56 +2333,70 @@ Interested functional programmers may enjoy noting= that + string-fold-right=20 + and string-unfold are in some sense inverses. That is, given= operations=20 + knull?, kar, kdr, kons, and <= var>knil satisfying +-

      ++

      ++
      + (kons (kar x) (kdr x)) =3D x  and (=
      knull? knil) =3D #t
      + 
      ++

      + then +-

      ++

      ++
      + (string-fold-right kons knil (string-unfold kn=
      ull? kar kdr x)) =3D x
      + 
      ++

      + and +-

      ++

      ++
      + (string-unfold knull? kar kdr (string-fo=
      ld-right kons knil s)) =3D s.
      + 
      +- ++

      + The final string constructed does not share storage with either base= + or the value produced by make-final. +- ++

      +

      + This combinator sometimes is called an "anamorphism." +- ++

      +

      + Note: implementations should take care that runtime stack limits do not + cause overflow when constructing large (e.g., megabyte) strings = with + string-unfold. +- ++

      ++
      +=20 + +-
      ++
      + +-string-unfold-right p f g seed [base m= ake-final] -> string +-
      +- This is a fundamental constructor for strings.=20 ++string-unfold-right p f g seed [base= make-final] -> string ++ ++
      ++

      ++ This is a fundamental constructor for strings. ++

      +
        +
      • G is used to generate a series of "seed" values from = the initial seed: + seed, (g seed), (g2 seed), (g3 seed), ... ++
      • +
      • P tells us when to stop -- when it returns true when = applied to one=20 + of these seed values. ++
      • +
      • F maps each seed value to the corresponding character= =20 + in the result string. These chars are assembled into the + string in a right-to-left order. ++
      • +
      • Base is the optional initial/rightmost portion of the= constructed string; + it defaults to the empty string "". ++
      • +
      • Make-final is applied to the terminal seed value (on = which P returns + true) to produce the final/leftmost portion of the constructed stri= ng. + It defaults to (lambda (x) ""). ++
      • +
      +- +-

      ++

      + More precisely, the following (simple, inefficient) definitions hold: +-

      ++

      ++
      + ;;; Iterative
      + (define (string-unfold-right p f g seed base make-final)
      +   (let lp ((seed seed) (ans base))
      +@@ -2137,56 +2412,70 @@ cause overflow when constructing large (e.g., megabyte) strings with
      +                                       (string (f seed)))))
      +                  base))
      + 
      ++

      + Interested functional programmers may enjoy noting that=20 + string-fold + and string-unfold-right are in some sense inverses.=20 + That is, given operations knull?, kar, kdr= , kons, and knil satisfying +-

      ++

      ++
      + (kons (kar x) (kdr x)) =3D x and (knull? knil<= /var>) =3D #t +
      ++

      + then +-

      ++

      ++
      + (string-fold kons knil (string-unfold-right kn=
      ull? kar kdr x)) =3D x
      + 
      ++

      + and +-

      ++

      ++
      + (string-unfold-right knull? kar kdr (str=
      ing-fold kons knil s)) =3D s.
      + 
      +- ++

      + The final string constructed does not share storage with either = base + or the value produced by make-final. +- +-

      ++

      ++

      + Note: implementations should take care that runtime stack limits do n= ot + cause overflow when constructing large (e.g., megabyte) stri= ngs with + string-unfold-right. +- ++

      ++
      +=20 + +-
      ++
      + +-string-for-each proc s [start end] ->= unspecified +-
      ++string-for-each proc s [start end] = -> unspecified ++ ++
      ++

      + Apply proc to each character in s. + string-for-each is required to iterate from start to end + in increasing order. +- ++

      ++
      + +-
      ++
      + +-string-for-each-index proc s [start en= d] -> unspecified +-
      ++string-for-each-index proc s [start = end] -> unspecified ++ ++
      ++

      + Apply proc to each index of s, in order. The option= al start/end + pairs restrict the endpoints of the loop. This is simply a + method of looping over a string that is guaranteed to be safe + and correct. +- ++

      ++

      + Example: +-

      ++

      ++
      + (let* ((len (string-length s))
      +        (ans (make-string len)))
      +   (string-for-each-index
      +@@ -2194,109 +2483,127 @@ Example:
      +       s)
      +   ans)
      + 
      +- ++
      +
      +=20 ++ + +-

      Replicate & rotate

      ++

      Replicate & rotate

      +=20 +
      +=20 + +-
      ++
      + +-xsubstring s from [to start end] -> st= ring +-
      ++xsubstring s from [to start end] -&g= t; string ++ ++
      ++

      + This is the "extended substring" procedure that implements replicated + copying of a substring of some string. +- +-

      ++

      ++

      + S is a string; start and end are opt= ional arguments that demarcate + a substring of s, defaulting to 0 and the length of s= (i.e., the whole + string). Replicate this substring up and down index space, in both the + positive and negative directions. For example, if s =3D "a= bcdefg", start=3D3,=20 + and end=3D6, then we have the conceptual bidirectionally-i= nfinite string +-

      ++

      ++
      +
      Fresh copy guaranteedSharing permitted
      string-copysubstring/shared
      string-copystring-take string-take-right
      string-copystring-drop string-drop-right
      string-drop string-drop-right
      string-concatenatestring-concatenate/shared
      string-concatenate/shared
      string-appendstring-append/shared
      string-concatenate-reverse +- string-concatenate-reverse/shared
      string-concatenate-reverse/shared
      string-pad string-pad-right
      +- +- +- +- ++ ++f ++ ++= <= td>+2 +
      ... d e f d e f d e f <= td>d e f d e f d e f d ... +-
      ... -9 -8 -7 -6 -5 -4 -3 -2 -1 <= td>0 +1 +2 +3 +4 +5 +6 +7 +8 += 9 ... +-
      ... d e f d e f d e f d e d e f d e f= d ... ++
      ... -9 -8 -7 -6 -5 -4 -3 -2 -1 0 +1 +3 +4 +5 +6 +7 +8 +9 ... ++
      +
      +- ++

      + xsubstring returns the substring of this string beginnin= g at index from, + and ending at to=20 + (which defaults to from+(end-start)). +- +-

      ++

      ++

      + You can use xsubstring to perform a variety of tasks: ++

      +
        +
      • To rotate a string left: (xsubstring "abcdef" 2) = =3D> "cdefab" ++
      • +
      • To rotate a string right: (xsubstring "abcdef" -2) = =3D> "efabcd" ++
      • +
      • To replicate a string: (xsubstring "abc" 0 7) = =3D> "abcabca" ++
      • +
      +- +-

      +- Note that=20 ++

      ++ Note that ++

      +
        +
      • The from/to indices give a half-open ran= ge -- the characters from + index from up to, but not including, index to. ++
      • +
      • The from/to indices are not in terms of = the index space for string s. + They are in terms of the replicated index space of the substring + defined by s, start, and end. ++
      • +
      +- +-

      ++

      + It is an error if start=3Dend -- although this = is allowed by special + dispensation when from=3Dto. +- ++

      ++ + +-
      ++
      + +-string-xcopy! target tstart s sfrom [s= to start end] -> unspecified +-
      ++string-xcopy! target tstart s sfrom = [sto start end] -> unspecified ++ ++
      ++

      + Exactly the same as xsubstring, but the extracted text i= s written + into the string target starting at index tstart. + This operation is not defined if (eq? target s<= /var>) + or these two arguments + share storage -- you cannot copy a string on top of itself. +- ++

      ++
      + +=20 ++ + +-

      Miscellaneous: insertion, parsing

      ++

      Miscellaneous: insertion, parsing

      +=20 +
      +=20 + +-
      ++
      + +-string-replace s1 s2 start1 end1 [star= t2 end2] -> string +-
      ++string-replace s1 s2 start1 end1 [st= art2 end2] -> string ++ ++
      ++

      + Returns +-

      ++

      ++
      + (string-append (substring/shared s1 0 start1)
      +                (substring/shared s2 start2 end=
      2)
      +                (substring/shared s1 end1 (string-le=
      ngth s1)))
      + 
      +- ++

      + That is, the segment of characters in s1 from start1<= /var> to end1 + is replaced by the segment of characters in s2 from s= tart2 to end2. + If start1=3Dend1, this simply splices the = s2 characters into s1 at the + specified index. +- +-

      ++

      ++

      + Examples: +-

      ++

      ++
      + (string-replace "The TCL programmer endured daily ridicule."
      +                 "another miserable perl drone" 4 7 8 22 ) =3D>
      +     "The miserable perl programmer endured daily ridicule."
      +@@ -2309,74 +2616,82 @@ Example:
      + (string-insert "It's easy to code it up in Scheme." 5 "really ") =3D>
      +     "It's really easy to code it up in Scheme."
      + 
      +- ++
      + +-
      ++
      + +-string-tokenize s [token-set start end= ] -> list +-
      ++string-tokenize s [token-set start e= nd] -> list ++ ++
      ++

      + Split the string s into a list of substrings, where each su= bstring is + a maximal non-empty contiguous sequence of characters from the charact= er set + token-set. ++

      +
        +
      • token-set defaults to char-set:graphic=20 + (see SRFI 14=20 + for more on character sets and char-set:graphic). +-
      • If start or end indices are provided, t= hey restrict=20 ++
      • ++
      • If start or end indices are provided, t= hey restrict + string-tokenize to operating on the indicated subst= ring of s. ++
      • +
      +- +-

      ++

      + This function provides a minimal parsing facility for simple applicat= ions. + More sophisticated parsers that handle quoting and backslash effects = can + easily be constructed using regular-expression systems; be careful not + to use string-tokenize in contexts where more serious pa= rsing is needed. +- +-

      ++

      ++
      + (string-tokenize "Help make programs run, run, RUN!") =3D>
      +   ("Help" "make" "programs" "run," "run," "RUN!")
      + 
      +- ++
      +
      +=20 + +-

      Filtering & deleting

      ++

      Filtering & deleting

      +=20 +
      +=20 + +-
      ++
      + + +-string-filter char/char-set/pred s [st= art end] -> string +-
      string-delete ch= ar/char-set/pred s [start end] -> string +-
      ++string-filter char/char-set/pred s [= start end] -> string ++ ++
      string-delete char/char-set/pred s [start end] -> string ++
      ++
      ++

      + Filter the string s, retaining only those characters that + satisfy / do not satisfy the char/char-set/pred argument. = If + this argument is a procedure, it is applied to the character + as a predicate; if it is a char-set, the character is tested + for membership; if it is a character, it is used in an equality test. +- +-

      ++

      ++

      + If the string is unaltered by the filtering operation, these + functions may return either s or a copy of s. +- +- ++

      ++
      +
      +=20 ++ + +-

      Low-level procedures

      ++

      Low-level procedures

      +

      + The following procedures are useful for writing other string-processing + functions. In a Scheme system that has a module or package system, these + procedures should be contained in a module named "string-lib-internals". +- ++

      + +-

      Start/end optional-argument parsing & checki= ng utilities

      ++

      Start/end optional-argument parsing & checking ut= ilities

      +=20 +=20 +
      +@@ -2384,99 +2699,118 @@ procedures should be contained in a module named = "string-lib-internals". + +-
      ++
      + + +-string-parse-start+end proc s args -> = [rest start end] +-
      string-parse-final-start+end= proc s args -> [start end] +-
      ++string-parse-start+end proc s args -= > [rest start end] ++ ++
      string-parse-final-start= +end proc s args -> [start end] ++
      ++
      ++

      + string-parse-start+end may be used to parse a pair of op= tional start/end=20 + arguments from an argument list, defaulting them to 0 and the length = of=20 + some string s, respectively. Let the length of string s be slen. +-

        ++

        ++
          +
        • If args =3D (), the function returns=20 + (values '() 0 slen) ++
        • +
        • If args =3D (i), i is checked t= o ensure it is an exact integer, and + that 0 <=3D i <=3D slen.=20 + Returns (values (cdr args) i slen<= /var>). ++
        • +
        • If args =3D (i j ...),=20 + i and j are checked to ensure they are exa= ct + integers, and that 0 <=3D i <=3D j <= =3D + slen.=20 + Returns (values (cddr args) i j). +-
        +- +-

        ++ ++

      ++

      + If any of the checks fail, an error condition is raised, and pro= c is used + as part of the error condition -- it should be the client procedure w= hose + argument list string-parse-start+end is parsing. +-=20=20=20=20 +-

      ++

      ++

      + string-parse-final-start+end is exactly the same, except= that the args list + passed to it is required to be of length two or less; if it is longer, + an error condition is raised. It may be used when the optional s= tart/end=20 + parameters are final arguments to the procedure. +- +-

      ++

      ++

      + Note that in all cases, these functions ensure that s is a= string + (by necessity, since all cases apply string-length to s either to + default end or to bounds-check it). +- +-

      ++

      ++ ++
      + +-let-string-start+end (start end [rest]= ) proc-exp s-exp args-exp body ... -> value(s) +-
      +- ++let-string-start+end (start end [res= t]) proc-exp s-exp args-exp body ... -> value(s) ++ ++
      ++

      + [Syntax] ++

      ++

      + Syntactic sugar for an application of string-parse-start+end or + string-parse-final-start+end. +-=20=20=20=20=20=20 +-

      ++

      ++

      + If a rest variable is given, the form is equivalent to +-

      ++

      ++
      + (call-with-values
      +     (lambda () (string-parse-start+end proc-exp s-exp args-exp))
      +   (lambda (rest start end) body ...))
      + 
      +-=20=20=20=20=20=20=20=20 +-

      ++

      + If no rest variable is given, the form is equivalent to +-

      ++

      ++
      + (call-with-values
      +     (lambda () (string-parse-final-start+end proc-exp s-e=
      xp args-exp))
      +   (lambda (start end) body ...))
      + 
      +- ++
      + +-
      ++
      + + +-check-substring-spec proc s start end = -> unspecified +-
      substring-spec-ok? s start end -> boolean +-
      ++check-substring-spec proc s start en= d -> unspecified ++ ++
      substring-spec-ok? s start end -> boolean ++
      ++
      ++

      + Check values s, start and end to ens= ure they specify a valid substring. + This means that s is a string, start and e= nd are exact integers, and=20 + 0 <=3D start <=3D end <=3D=20 + (string-length s) +- +-

      ++

      ++

      + If the values are not proper ++

      +
        +
      • check-substring-spec raises an error condition.= proc is used + as part of the error condition, and should be the procedure who= se=20 + parameters we are checking. ++
      • +
      • substring-spec-ok? returns false. ++
      • +
      ++

      + Otherwise, substring-spec-ok? returns true, and ch= eck-substring-spec + simply returns (what it returns is not specified). +- ++

      ++
      +
      +=20 +=20 + +-

      Knuth-Morris-Pratt searching

      ++

      Knuth-Morris-Pratt searching

      +

      + The Knuth-Morris-Pratt string-search algorithm is a method of rapidly sca= nning + a sequence of text for the occurrence of some fixed string. It has the +@@ -2487,7 +2821,7 @@ the initialisation and searching phases of the algor= ithm for general use. They + also support searching through sequences of text that arrive in buffered + chunks, in that intermediate search state can be carried across applicati= ons + of the search loop from the end of one buffer application to the next. +- ++

      +

      + A second critical property of KMP search is that it requires the allocati= on of + auxiliary memory proportional to the length of the pattern, but const= ant +@@ -2495,22 +2829,24 @@ in the size of the character type. Alternate searc= hing algorithms frequently + require the construction of a table with an entry for every possible + character -- which can be prohibitively expensive in a 16- or 32-bit char= acter + representation. +- ++

      +
      + +-
      ++
      + +-make-kmp-restart-vector s [c=3D start = end] -> integer-vector +-
      ++make-kmp-restart-vector s [c=3D star= t end] -> integer-vector ++ ++
      ++

      + Build a Knuth-Morris-Pratt "restart vector," which is useful for quickly + searching character sequences for the occurrence of string s (= or the + substring of s demarcated by the optional start/end= parameters, if + provided). C=3D is a character-equality function used to const= ruct the + restart vector. It defaults to char=3D?; use char-ci= =3D? instead for + case-folded string search. +- ++

      +

      + The definition of the restart vector rv for string s is: + If we have matched chars 0..i-1 of s against some s= earch string ss, and +@@ -2519,13 +2855,13 @@ match ss[k]. + If rv[i] =3D -1,=20 + then punt ss[k] completely, and move on to + ss[k+1] and s[0]. +- ++

      +

      + In other words, if you have matched the first i chars of = s, but + the i+1'th char doesn't match,=20 + rv[i] tells you what the next-longest + prefix of s is that you have matched. +- ++

      +

      + The following string-search function shows how a restart vector is used to + search. Note the attractive feature of the search process: it is "on +@@ -2534,8 +2870,8 @@ data. It simply consumes characters one-at-a-time un= til declaring a complete + match or reaching the end of the sequence. Thus, it can be easily adapted= to + search other character sequences (such as ports) that do not provide rand= om + access to their contents. +- +-

      ++

      ++
      + (define (find-substring pattern source start end)
      +   (let ((plen (string-length pattern))
      +         (rv (make-kmp-restart-vector pattern)))
      +@@ -2558,7 +2894,6 @@ access to their contents.
      +                          (lp (+ si 1)  0   (- sj 1)  plen)  ; Punt.
      +                          (lp si        pi  sj        (- plen pi))))))))))
      + 
      +- +

      + The optional start/end parameters restrict the restart vector = to the + indicated substring of pat; rv is end - = start elements long. If start > 0, +@@ -2568,23 +2903,26 @@ pattern element pat[i + start]. + Elements of rv are themselves indices + that range just over [0, end-start),=20 + not [start, end). +- ++

      +

      + Rationale: the actual value of rv is "position independent" --= it + does not depend on where in the pat string the pattern occurs,= but + only on the actual characters comprising the pattern. +- ++

      ++
      + +-
      ++
      + +-kmp-step pat rv c i c=3D p-start -> in= teger +-
      ++kmp-step pat rv c i c=3D p-start -&g= t; integer ++ ++
      ++

      + This function encapsulates the work performed by one step of the + KMP string search; it can be used to scan strings, input ports, + or other on-line character sources for fixed strings.=20 +- ++

      +

      + Pat is the non-empty string specifying the text for which we a= re searching. + Rv is the Knuth-Morris-Pratt restart vector for the pattern,=20 +@@ -2593,7 +2931,7 @@ The pattern begins at pat[p-start], and is + (string-length rv) characters long. + C=3D is the character-equality function used to construct the + restart vector, typically char=3D? or char-ci=3D?. +- ++

      +

      + Suppose the pattern is N characters in length:=20 + pat[p-start, p-start + n). +@@ -2604,19 +2942,20 @@ We have already matched i characters: + returns the new i value -- that is, how much of the pattern we= have + matched, including character c.=20 + When i reaches n, the entire pattern has been match= ed. +- ++

      +

      + Thus a typical search loop looks like this: +-

      ++

      ++
      + (let lp ((i 0))
      +   (or (=3D i n)                           ; Win -- #t
      +       (and (not (end-of-stream))        ; Lose -- #f
      +            (lp (kmp-step pat rv (get-next-character) i char=3D? 0)))))
      + 
      +- +

      + Example: +-

      ++

      ++
      + ;; Read chars from IPORT until we find string PAT or hit EOF.
      + (define (port-skip pat iport)
      +   (let* ((rv (make-kmp-restart-vector pat))
      +@@ -2628,10 +2967,10 @@ Example:
      +                 (lp (kmp-step pat rv c i char=3D? 0) ; Continue
      +                     (+ nchars 1))))))))
      + 
      +- +

      + This procedure could be defined as follows: +-

      ++

      ++
      + (define (kmp-step pat rv c i c=3D p-start)
      +   (let lp ((i i))
      +     (if (c=3D c (string-ref pat (+ i p-start)))     ; Match =3D>
      +@@ -2640,27 +2979,29 @@ This procedure could be defined as follows:
      +           (if (=3D i -1) 0                          ; Can't back up more.
      +               (lp i)))))))                        ; Keep going.
      + 
      +- +

      + Rationale: this procedure takes no optional arguments because it + is intended as an inner-loop primitive and we do not want any + run-time penalty for optional-argument parsing and defaulting, + nor do we wish barriers to procedure integration/inlining. +- ++

      ++
      + +-
      ++
      + +-string-kmp-partial-search pat rv s i [= c=3D p-start s-start s-end] -> integer +-
      ++string-kmp-partial-search pat rv s i= [c=3D p-start s-start s-end] -> integer ++ ++
      ++

      + Applies kmp-step across s;=20 + optional s-start/s-end bounds parameters=20 + restrict search to a substring of s.=20 + The pattern is (vector-length rv) characters long= ;=20 + optional p-start index indicates non-zero start of pattern=20 + in pat. +- ++

      +

      + Suppose plen =3D (vector-length rv) + is the length of the pattern. +@@ -2668,38 +3009,41 @@ is the length of the pattern. + (that is, 0 <=3D i < plen) + indicating how much of the pattern has already been matched.=20 + (This means the pattern must be non-empty -- plen > 0.) +- ++

      +
        +
      • On success, returns -j,=20 + where j is the index in s bounding + the end of the pattern -- e.g., a value that could be= used as=20 + the end parameter in a call to substring/shared. +- +-
      • On continue, returns the current search state i'=20 ++
      • ++
      • On continue, returns the current search state i' + (an index into rv) + when the search reached the end of the string. This is a non-negative + integer. ++
      • +
      +- ++

      + Hence: ++

      +
        +
      • A negative return value indicates success, and says + where in the string the match occured. +- ++
      • +
      • A non-negative return value provides the i to use for + continued search in a following string. ++
      • +
      +- +

      + This utility is designed to allow searching for occurrences of a fixed + string that might extend across multiple buffers of text. This is + why, for example, we do not provide the index of the start of the + match on success -- it may have occurred in a previous buffer. +- ++

      +

      + To search a character sequence that arrives in "chunks," write a + loop of this form: +-

      ++

      ++
      + (let lp ((i 0))
      +   (and (not (end-of-data?))             ; Lose -- return #f.
      +        (let* ((buf (get-next-chunk))    ; Get or fill up the buffer.
      +@@ -2707,9 +3051,11 @@ loop of this form:
      +          (if (< i 0) (- i)              ; Win -- return end index.
      +              (lp i)))))                 ; Keep looking.
      + 
      ++

      + Modulo start/end optional-argument parsing, this procedure could + be defined as follows: +-

      ++

      ++
      + (define (string-kmp-partial-search pat rv s i c=3D p-start s-start s-end)
      +   (let ((patlen (vector-length rv)))
      +     (let lp ((si s-start)       ; An index into S.
      +@@ -2720,39 +3066,41 @@ be defined as follows:
      +                       (kmp-step pat rv (string-ref s si)
      +                                 vi c=3D p-start)))))))
      + 
      ++
      +
      +=20 + +-

      Reference implementation

      ++

      Reference implementation

      +=20 +

      + This SRFI comes with a reference implementation. It can be found at: +-

      +- http://srfi.= schemers.org/srfi-13/srfi-13.scm ++

      ++ +-

      ++

      + I have placed this source on the Net with an unencumbered, "open" copyrig= ht. + The prefix/suffix and comparison routines in this code had (extremely dis= tant) + origins in MIT Scheme's string lib, and were substantially reworked by my= self. + Being derived from that code, they are covered by the MIT Scheme copyrigh= t, + which is a generic BSD-style open-source copyright. See the source file f= or + details. +- ++

      +

      + The KMP string-search code was influenced by implementations written by + Stephen Bevan, Brian Denheyer and Will Fitzgerald. However, this version = was + written from scratch by myself. +- ++

      +

      + The remainder of the code was written by myself for scsh or for this SRFI= ; I + have placed this code under the scsh copyright, which is also a generic + BSD-style open-source copyright. +- ++

      +

      + The code is written for portability and should be straightforward to port= to + any Scheme. The source comments contains detailed notes describing the no= n-R5RS + dependencies. +- ++

      +

      + The library is written for clarity and well-commented; the current source= is + approximately 1000 lines of source code and 1000 lines of comments and wh= ite +@@ -2760,15 +3108,15 @@ space. It is also written for efficiency. Fast pat= hs are provided for common + cases. This is not to say that the implementation can't be tuned up for a + specific Scheme implementation. There are notes in the comments addressing + ways implementors can tune the reference implementation for performance. +- ++

      +

      + In short, I've written the reference implementation to make it as painless + as possible for an implementor -- or a regular programmer -- to adopt this + library and get good results with it. +- ++

      +=20 + +-

      Acknowledgements

      ++

      Acknowledgements

      +=20 +

      + The design of this library benefited greatly from the feedback provided d= uring +@@ -2782,137 +3130,175 @@ Kiselyov, Bengt Kleberg, Donovan Kolbly, Bruce K= orb, Shriram Krishnamurthi, + Bruce Lewis, Tom Lord, Brad Lucier, Dave Mason, David Rush, Klaus Schilli= ng, + Jonathan Sobel, Mike Sperber, Mikael Staldal, Vladimir Tsyshevsky, Donald + Welsh, and Mike Wilson. I am grateful to them for their assistance. +- ++

      +

      + I am also grateful the authors, implementors and documentors of all the s= ystems + mentioned in the introduction. Aubrey Jaffer and Kent Pitman should be no= ted + for their work in producing Web-accessible versions of the R5RS and Common + Lisp spec, which was a tremendous aid. +- ++

      +

      + This is not to imply that these individuals necessarily endorse the final + results, of course.=20 +- ++

      +

      + During this document's long development period, great patience was exhibi= ted + by Mike Sperber, who is the editor for the SRFI, and by Hillary Sullivan, + who is not. +- ++

      + +-

      References & links

      ++

      References & links

      +=20 +
      +=20 +-
      [Case-map] ++
      [Case-map] ++
      +
      +- Case mappings.
      +- Unicode Technical Report 21.
      ++

      ++ Case mappings.
      ++ Unicode Technical Report 21.
      + http://www.u= nicode.org/unicode/reports/tr21/ +- +-

      [CommonLisp]
      +-
      Common Lisp: the Language.
      +-Guy L. Steele Jr. (editor).
      +-Digital Press, Maynard, Mass., second edition 1990.
      ++

      ++
      ++
      [CommonLisp] ++
      ++
      ++

      ++Common Lisp: the Language.
      ++Guy L. Steele Jr. (editor).
      ++Digital Press, Maynard, Mass., second edition 1990.
      + Available at + http://www.elwood.com/alu/table/references.htm#cltl2. ++

      +

      +- + The Common Lisp "HyperSpec," produced by Kent Pitman, is essentially + the ANSI spec for Common Lisp: +- +-http://www.harlequin.com/education/books/HyperSpec/. +- +-

      [Java] ++ ++http://www.lispworks.com/documentation/HyperSpec/Front/index.htm. ++

      ++ ++
      [Java] ++
      +
      +- The following URLs provide documentation on relevant Java classes. ++

      ++ The following URLs provide documentation on relevant Java classes. +=20 + http://java.sun.com/products/jdk/1.2/docs/api/java/lang/Chara= cter.html +-
      ++
      + http://java.sun.com/products/jdk/1.2/docs/api/java/lang/String.h= tml +-
      ++
      + http://java.sun.com/products/jdk/1.2/docs/api/java/lang/St= ringBuffer.html +-
      ++
      + http://java.sun.com/products/jdk/1.2/docs/api/java/text/Collat= or.html +-
      ++
      + http://java.sun.com/products/jdk/1.2/docs/api/java/text= /package-summary.html +- +-

      [MIT-Scheme] ++

      ++ ++
      [MIT-Scheme] ++
      +
      ++

      + http://www.s= wiss.ai.mit.edu/projects/scheme/ +- +-

      [R5RS]
      +-
      Revised5 report on the algorithmic language Scheme.
      +- R. Kelsey, W. Clinger, J. Rees (editors).
      +- Higher-Order and Symbolic Computation, Vol. 11, No. 1, September, 199= 8.
      +- and ACM SIGPLAN Notices, Vol. 33, No. 9, October, 1998.
      ++

      ++
      ++
      [R5RS] ++
      ++
      ++

      ++ Revised5 report on the algorithmic language Scheme.
      ++ R. Kelsey, W. Clinger, J. Rees (editors).
      ++ Higher-Order and Symbolic Computation, Vol. 11, No. 1, September, 199= 8.
      ++ and ACM SIGPLAN Notices, Vol. 33, No. 9, October, 1998.
      + Available at + http://www.schemers.org/Documents/Standards/. +- +-

      [SRFI]
      ++

      ++ ++
      [SRFI] ++
      +
      +- The SRFI web site.
      +- http://srfi.schemers.org/ +- +-
      [SRFI-13]
      ++

      ++ The SRFI web site.
      ++ http://srfi.schemers.org/ ++

      ++ ++
      [SRFI-13] ++
      +
      +- SRFI-13: String libraries.
      +- http://srfi.schemers.or= g/srfi-13/ +- ++

      ++ SRFI-13: String libraries.
      ++ http://srfi.schemers.org/srfi-13/ ++

      +
      =20=20=20=20 +
      + This document, in HTML: +-
      +- http://srfi.schemers.org/srfi-13/srfi-13.html ++ ++
      ++ https://srfi.schemers.org/srfi-13/srfi-13.html +=20 ++
      +
      + This document, in plain text format: +-
      +- http://srfi.schemers.org/srfi-13/srfi-13.txt ++ ++
      ++ https://srfi.schemers.org/srfi-13/srfi-13.txt +=20 ++
      +
      Source code for the reference implementation: ++
      +
      +- +- http://srfi.schemers.org/srfi-13/srfi-13.scm ++ ++ https://srfi.schemers.org/srfi-13/srfi-13.scm +=20 ++
      +
      Scheme 48 module specification, with typings: ++
      +
      +- +- http://srfi.schemers.org/srfi-13/srfi-13-s48-module.scm ++ ++ https://srfi.schemers.org/srfi-13/srfi-13-s48-module.scm ++
      +
      +
      +=20 +-
      [SRFI-14] ++
      [SRFI-14] ++
      +
      +- SRFI-14: Character-set library.
      +- http://srfi.schemers.or= g/srfi-14/
      ++

      ++ SRFI-14: Character-set library.
      ++ http://srfi.schemers.org/srfi-14/
      + The SRFI 14 char-set library defines a character-set data type, + which is used by some procedures in this library. +- +-

      [Unicode] ++

      ++ ++
      [Unicode] ++
      +
      + http://www.unicode.org/ +- +-
      [UnicodeData] ++ ++
      [UnicodeData] ++
      +
      +- The Unicode character database.
      ++

      ++ The Unicode character database.
      + ftp:= //ftp.unicode.org/Public/UNIDATA/UnicodeData.txt +-
      ++
      + ftp= ://ftp.unicode.org/Public/UNIDATA/UnicodeData.html +- ++

      ++
      +
      +=20 ++ + +-

      Copyright

      ++

      Copyright

      +=20 +

      + Certain portions of this document -- the specific, marked segments of text + describing the R5RS procedures -- were adapted with permission from the R5RS + report. +-=20=20=20=20 ++

      +

      + All other text is copyright (C) Olin Shivers (1998, 1999, 2000).=20 + All Rights Reserved.=20 +- ++

      +

      + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the +@@ -2935,11 +3321,10 @@ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, = WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +

      +- ++
      ++
      Editor: Michael Sperber
      + +- +- +- ++ +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-14.html b/srfi-doc/sr= fi/scribblings/srfi-std/srfi-14.html +index 4167ab3..f42fc23 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-14.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-14.html +@@ -1,5 +1,23 @@ +- ++ ++ ++ ++ ++ + +- + +- +- +- +- ++ + SRFI 14: Character-set Library +- ++ ++ ++ + + +- +- + +- + +- + +-

      Title

      ++

      SRFI 14: Character-set Library

      +=20 +-
      SRFI 14: Character-set Library
      ++

      by Olin Shivers

      ++

      This copy of the SRFI 14 specific= ation document ++is distributed as part of the Racket package ++srfi-doc.

      = The canonical source of this document is ++https://srfi.s= chemers.org/srfi-14/srfi-14.html.

      +=20 +- +-

      Author

      +- +-Olin Shivers +- +-

      Status

      +-This SRFI is currently in ``final'' status. To see an explanation of eac= h status that a SRFI can hold, see here. +-You can access the discussion via the archive of the mailing list. +-

        +-
      • Received: 1999/10/17 +-
      • Draft: 1999/10/30-1999/12/30 +-
      • Revised: 2000/04/30 +-
      • Revised: 2000/04/30 +-
      • Revised: 2000/06/09 +-
      • Revised: 2000/12/23 +-
      ++

      Status

      ++ ++

      This SRFI is currently in final status. Here is an explanation of each stat= us that a SRFI can hold. To provide input on this SRFI, please send email = to srfi-= 14@nospamsrfi.schemers.org. To = subscribe to the list, follow these instructions. You can access previous messages= via the mailing list a= rchive.

      ++
        ++
      • Received: 1999-10-17
      • ++
      • Draft: 1999-10-30--1999-12-30
      • ++
      • Revised: 2000-04-30
      • ++
      • Revised: 2000-04-30
      • ++
      • Revised: 2000-06-09
      • ++
      • Revised: 2000-12-23
      • ++
      • Post-finalization notes: ++
          ++
        • ++ 2019-12-09 (In a ++ separate document, ++ added notes by John Cowan on relevant changes to Unicode ++ since publication of this SRFI. The author of SRFI 14, Olin Shive= rs, ++ has not yet expressed an opinion on the notes.) ++
        • ++
        ++
      • ++
      ++ +=20 + +-

      Table of contents

      ++

      Table of contents

      +=20 + +-
        +-
      • Abstract +-
      • Variable index +-
      • Rationale +- +- +-
      • Specification +- +- +-
      • Unicode, Latin-1 and ASCII definitio= ns of the standard character sets +-
      • Reference implementation +-
      • Acknowledgements +-
      • References & Links +-
      • Copyright ++ +=20 + +-

        Abstract

        ++

        Abstract

        +

        +- + The ability to efficiently represent and manipulate sets of characters is= an + unglamorous but very useful capability for text-processing code -- one th= at + tends to pop up in the definitions of other libraries. Hence it is usefu= l to + specify a general substrate for this functionality early. This SRFI defi= nes a + general library that provides this functionality.=20 +- ++

        ++

        + It is accompanied by a reference implementation for the spec. The referen= ce + implementation is fairly efficient, straightforwardly portable, and has a + "free software" copyright. The implementation is tuned for "small" 7 or 8 +@@ -216,90 +263,97 @@ bit character types, such as ASCII or Latin-1; the d= ata structures and + algorithms would have to be altered for larger 16 or 32 bit character typ= es + such as Unicode -- however, the specs have been carefully designed with t= hese + larger character types in mind. +- ++

        ++

        + Several forthcoming SRFIs can be defined in terms of this one: ++

        +
          +-
        • string library +-
        • delimited input procedures (e.g., read-line) +-
        • regular expressions ++
        • string library
        • ++
        • delimited input procedures (e.g., read-line)<= /li> ++
        • regular expressions
        • +
        +=20 +- + +-

        Variable Index

        ++

        Variable Index

        +

        + Here is the complete set of bindings -- procedural and otherwise -- + exported by this library. In a Scheme system that has a module or package= =20 + system, these procedures should be contained in a module named "char-set-= lib". +- +-

        ++

        ++
        +
        +-
        Predicates & comparison +-
        +-
        +-char-set? char-set=
        =3D char-set<=3D char-set-hash
        ++
        Predicates & comparison ++
        ++
        ++
        ++char-set? char-set=
        =3D char-set<=3D char-set-hash
        + 
        +- +-
        Iterating over character sets +-
        +-
        ++
        ++
        Iterating over character sets ++
        ++
        ++
        + char-set-cursor char-set-ref char-set-cursor-next end-of-char-set?=20
        + char-set-fold char-set-unfold char-set-unfold!
        + char-set-for-each char-set-map
        + 
        +- +-
        Creating character sets +-
        +-
        ++
        ++
        Creating character sets ++
        ++
        ++
        + char-set-copy char-s=
        et
        +=20
        +-char-set">list->char-set  char-=
        set">string->char-set
        +-char-set!">list->char-set! char=
        -set!">string->char-set!
        ++list->char-set  string->char-set
        ++list->char-set! string->char-set!
        +=20=20=20=20=20
        +-char-set-filter  =
        char-set">ucs-range->char-set 
        +-char-set-filter! char-set!">ucs-range->char-se=
        t!
        ++char-set-filter  ucs-range->char-set 
        ++char-set-filter! ucs-range->ch=
        ar-set!
        +=20
        +-char-set">->char-set
        ++->char-set
        + 
        +- +-
        Querying character sets +-
        +-
        +-list">char-set->list stri=
        ng">char-set->string
        ++
        ++
        Querying character sets ++
        ++
        ++
        ++char-set->list char-set->string
        + char-set-size =
        char-set-count char-set-contains?
        + char-set-every =
        char-set-any
        + 
        +- +-
        Character-set algebra +-
        +-
        ++
        ++
        Character-set algebra ++
        ++
        ++
        + char-set-adjoin  char-set-delete
        + char-set-adjoin! char-set-delete!
        +=20
        + char-set-complement  char-set-union  char-se=
        t-intersection
        + char-set-complement! char-set-union! char=
        -set-intersection!
        +=20
        +-char-set-difference  char-set-xor  char-s=
        et-diff+intersection
        +-char-set-difference! char-set-xor! cha=
        r-set-diff+intersection!
        ++char-set-difference  char-set-xor  char=
        -set-diff+intersection
        ++char-set-difference! char-set-xor! c=
        har-set-diff+intersection!
        + 
        +- +-
        Standard character sets +-
        +-
        +-char-set:lower-case  char-set:upper-case  char-set:title-case
        +-char-set:letter      char-set:digit       char-s=
        et:letter+digit
        +-char-set:graphic     char-set:printing    char=
        -set:whitespace
        +-char-set:iso-control char-set:punctuation c=
        har-set:symbol
        +-char-set:hex-digit   char-set:blank       char-set:a=
        scii
        +-char-set:empty       char-set:full
        ++
        ++
        Standard character sets ++
        ++
        ++
        ++char-set:lower-case  char-set:upper-case  char-set:title-case
        ++char-set:letter      char-set:digit       char-set:letter+digit
        ++char-set:graphic     char-set:printing    char-set:whitespace
        ++char-set:iso-control char-set:punctuation char-set:symbol
        ++char-set:hex-digit   char-set:blank       char=
        -set:ascii
        ++char-set:empty       char-set:full
        + 
        +=20 ++
        +
        +
        +=20 + +-

        Rationale

        ++

        Rationale

        +=20 +

        + The ability to efficiently manipulate sets of characters is quite +@@ -307,16 +361,16 @@ useful for text-processing code. Encapsulating this = functionality in + a general, efficiently implemented library can assist all such code. + This library defines a new data structure to represent these sets, called + a "char-set." The char-set type is distinct from all other types. +- ++

        +

        + This library is designed to be portable across implementations that use + different character types and representations, especially ASCII, Latin-1 + and Unicode. Some effort has been made to preserve compatibility with Java + in the Unicode case (see the definition of char-set:whitespace for the + single real deviation). +- ++

        + +-

        Linear-update operations

        ++

        Linear-update operations

        +=20 +

        + The procedures of this SRFI, by default, are "pure functional" -- they do= not +@@ -327,39 +381,43 @@ to construct their result. An implementation may leg= ally implement these + procedures as pure, side-effect-free functions, or it may implement them = using + side effects, depending upon the details of what is the most efficient or + simple to implement in terms of the underlying representation. +- ++

        +

        + The linear-update routines all have names ending with "!". +- ++

        +

        + Clients of these procedures may not rely upon these procedures w= orking by + side effect. For example, this is not guaranteed to work: +-

        ++

        ++
        + (let* ((cs1 (char-set #\a #\b #\c))      ; cs1 =3D {a,b,c}.
        +        (cs2 (char-set-adjoin! cs1 #\d))) ; Add d to {a,b,c}.
        +   cs1) ; Could be either {a,b,c} or {a,b,c,d}.
        + 
        +-

        ++

        + However, this is well-defined: +-

        ++

        ++
        + (let ((cs (char-set #\a #\b #\c)))
        +   (char-set-adjoin! cs #\d)) ; Add d to {a,b,c}.
        + 
        +- +

        + So clients of these procedures write in a functional style, but must + additionally be sure that, when the procedure is called, there are no oth= er + live pointers to the potentially-modified character set (hence the term + "linear update"). +- ++

        +

        + There are two benefits to this convention: ++

        +
          +
        • Implementations are free to provide the most efficient possible + implementation, either functional or side-effecting. ++
        • +
        • Programmers may nonetheless continue to assume that character sets + are purely functional data structures: they may be reliably shared + without needing to be copied, uniquified, and so forth. ++
        • +
        +=20 +

        +@@ -369,136 +427,151 @@ be represented in an ASCII Scheme with 4 32-bit wo= rds. Pure set-algebra + operations on such a representation are very fast and efficient. Programm= ers + who code using linear-update operations are guaranteed the system will + provide the best implementation across multiple platforms. +- ++

        +

        + In practice, these procedures are most useful for efficiently constructing + character sets in a side-effecting manner, in some limited local context,= =20 + before passing the character set outside the local construction scope to = be + used in a functional manner. +- ++

        +

        + Scheme provides no assistance in checking the linearity of the potentially + side-effected parameters passed to these functions --- there's no linear + type checker or run-time mechanism for detecting violations. (But + sophisticated programming environments, such as DrScheme, might help.) +- ++

        + +-

        Extra-SRFI recommendations

        ++

        Extra-SRFI recommendations

        +

        + Users are cautioned that the R5RS predicates=20 +-

        +-char-alphabetic?
        +-char-numeric?
        +-char-whitespace?
        +-char-upper-case?
        +-char-lower-case?
        ++

        ++
        ++char-alphabetic?
        ++char-numeric?
        ++char-whitespace?
        ++char-upper-case?
        ++char-lower-case?
        +
        +
        +-

        ++

        + may or may not be in agreement with the SRFI 14 base character sets +-

        ++

        ++
        + +-char-set:letter
        +-char-set:digit
        +-char-set:whitespace
        +-char-set:upper-case
        +-char-set:lower-case
        ++char-set:letter
        ++char-set:digit
        ++char-set:whitespace
        ++char-set:upper-case
        ++char-set:lower-case
        +
        +
        +-

        ++

        + Implementors are strongly encouraged to bring these predicates into + agreement with the base character sets of this SRFI; not to do so risks + major confusion. +- ++

        +=20 + +-

        Specification

        ++

        Specification

        +

        + In the following procedure specifications: ++

        +
          +
        • A cs parameter is a character set. +- ++
        • +
        • An s parameter is a string. +- ++
        • +
        • A char parameter is a character. +- ++
        • +
        • A char-list parameter is a list of characters. +- +-
        • A pred parameter is a unary character predicate proce= dure, returning=20 ++
        • ++
        • A pred parameter is a unary character predicate proce= dure, returning + a true/false value when applied to a character. +- ++
        • +
        • An obj parameter may be any value at all. ++
        • +
        +=20 +

        + Passing values to procedures with these parameters that do not satisfy th= ese + types is an error. +- ++

        +

        + Unless otherwise noted in the specification of a procedure, procedures + always return character sets that are distinct (from the point of view + of the linear-update operations) from the parameter character sets. For + example, char-set-adjoin is guaranteed to provide a fresh ch= aracter set, + even if it is not given any character parameters. +- ++

        +

        + Parameters given in square brackets are optional. Unless otherwise noted = in the + text describing the procedure, any prefix of these optional parameters may + be supplied, from zero arguments to the full list. When a procedure retur= ns + multiple values, this is shown by listing the return values in square + brackets, as well. So, for example, the procedure with signature +-

        +-halts? f [x init-store] -> [boolean integer]
        ++

        ++
        ++halts? f [x init-store] -> [boolean integer]
        + 
        ++

        + would take one (f), two (f, x)=20 + or three (f, x, init-store) input parame= ters,=20 + and return two values, a boolean and an integer. +- ++

        +

        + A parameter followed by "..." means zero-or-more elements.=20 + So the procedure with the signature +-

        +-sum-squares x ...  -> number
        ++

        ++
        ++sum-squares x ...  -> number
        + 
        ++

        + takes zero or more arguments (x ...),=20 + while the procedure with signature +-

        +-spell-check doc dict1 dict2 ... -> =
        string-list
        ++

        ++
        ++spell-check doc dict1 dict2 ... -> string-list
        + 
        ++

        + takes two required parameters=20 + (doc and dict1)=20 + and zero or more optional parameters (dict2 ...). +- ++

        +=20 + +-

        General procedures

        ++

        General procedures

        +
        +=20 + +-
        ++
        + +-char-set? obj -> boolean +-
        +- ++char-set? obj -> boolean ++ ++
        ++

        + Is the object obj a character set? +- ++

        ++
        + +-
        ++
        + +-char-set=3D cs1 ... -> bool= ean +-
        ++char-set=3D cs1 ... ->= boolean ++ ++
        ++

        + Are the character sets equal? ++

        +

        + Boundary cases: +-

        +-(char-set=3D) =3D> true
        +-(char-set=3D cs) =3D> true
        ++

        ++
        ++(char-set=3D) =3D> true
        ++(char-set=3D cs) =3D> true
        + 
        +- +

        + Rationale: transitive binary relations are generally extended to n-ary + relations in Scheme, which enables clearer, more concise code to be +@@ -506,15 +579,17 @@ and zero or more optional parameters (dict= 2 ...). + certainly not arise in first-order uses of such relations, they may w= ell + arise in higher-order cases or macro-generated code.=20 + E.g., consider +-

        ++

        ++
        + (apply char-set=3D cset-list)
        + 
        +-

        ++

        + This is well-defined if the list is empty or a singleton list. Hence + we extend these relations to any number of arguments. Implementors + have reported actual uses of n-ary relations in higher-order cases + allowing for fewer than two arguments. The way of Scheme is to handle= the + general case; we provide the fully general extension. ++

        +

        + A counter-argument to this extension is that=20 + R5RS= 's +@@ -523,63 +598,69 @@ and zero or more optional parameters (dict= 2 ...). + require at least two arguments, hence + this decision is a break with the prior convention -- although it is + at least one that is backwards-compatible. +- ++

        ++
        + +-
        +- +-char-set<=3D cs1 ... -> boo= lean +-
        ++
        ++ ++char-set<=3D cs1 ... -= > boolean ++
        ++
        ++

        + Returns true if every character set csi is=20 + a subset of character set csi+1. +- ++

        +

        + Boundary cases: +-

        +-(char-set<=3D) =3D> true
        +-(char-set<=3D cs) =3D> true
        ++

        ++
        ++(char-set<=3D) =3D> true
        ++(char-set<=3D cs) =3D> true
        + 
        +

        + Rationale: See char-set=3D for discussion of zero- and one-a= rgument + applications. Consider testing a list of char-sets for monotonicity +-with=20 +-

        +-(apply char-set<=3D cset-list)
        ++with
        ++

        ++
        ++(apply char-set<=3D cset-list)
        + 
        +- ++
        + +-
        ++
        + +-char-set-hash cs [bound] -> integer +-
        ++char-set-hash cs [bound] -> integ= er ++ ++
        ++

        + Compute a hash value for the character set cs.=20 + Bound is a non-negative + exact integer specifying the range of the hash function. A positive + value restricts the return value to the range [0,bound). +- +-

        ++

        ++

        + If bound is either zero or not given, the implementation m= ay use + an implementation-specific default value, chosen to be as large as + is efficiently practical. For instance, the default range might be ch= osen + for a given implementation to map all strings into the range of + integers that can be represented with a single machine word. +- +- +-

        ++

        ++

        + Invariant: +-

        +-(char-set=3D cs1 cs2) =3D> (=3D (char-set-hash cs1 b) (char-set-hash cs2 b))
        ++

        ++
        ++(char-set=3D cs1 cs2) =3D> (=3D (char-set-hash c=
        s1 b) (char-set-hash cs2 b))
        + 
        +- +-

        ++

        + A legal but nonetheless discouraged implementation: +-

        ++

        ++
        + (define (char-set-hash cs . maybe-bound) 1)
        + 
        +- +

        + Rationale: allowing the user to specify an explicit bound simplifies = user + code by removing the mod operation that typically accompanies every h= ash +@@ -590,29 +671,31 @@ with + intermediate values never overflow into bignum integers, allowing the + implementor to provide a fixnum-specific "fast path" for computing the + common cases very rapidly. +- ++

        ++
        +
        +=20 + +-

        Iterating over character sets

        ++

        Iterating over character sets

        +=20 +
        + +-
        +- +- +- +- +-char-set-cursor cset -> cursor +-
        +-char-set-ref cset cursor -> char +-
        +-char-set-cursor-next cset cursor -> cu= rsor +-
        +-end-of-char-set? cursor -> boolean +-
        ++
        ++char-set-cursor cset -> cursor ++
        ++
        ++char-set-ref cset cursor -> char<= /var> ++
        ++
        ++char-set-cursor-next cset cursor -&g= t; cursor ++
        ++
        ++end-of-char-set? cursor -> boolea= n ++
        ++
        ++

        + Cursors are a low-level facility for iterating over the characters in= a + set. A cursor is a value that indexes a character in a char set. + char-set-cursor produces a new cursor for a given char s= et.=20 +@@ -624,28 +707,29 @@ with + answers true to end-of-char-set?.=20 + It is an error to pass such a cursor to char-set-ref or = to + char-set-cursor-next. +- ++

        +

        + A cursor value may not be used in conjunction with a different charac= ter + set; if it is passed to char-set-ref or=20 + char-set-cursor-next with + a character set other than the one used to create it, the results and + effects are undefined. +- ++

        +

        + Cursor values are not necessarily distinct from other types.= =20 + They may be + integers, linked lists, records, procedures or other values. This lic= ense + is granted to allow cursors to be very "lightweight" values suitable = for + tight iteration, even in fairly simple implementations. +- ++

        +

        + Note that these primitives are necessary to export an iteration facil= ity + for char sets to loop macros. +- ++

        +

        + Example: +-

        ++

        ++
        + (define cs (char-set #\G #\a #\T #\e #\c #\h))
        +=20
        + ;; Collect elts of CS into a list.
        +@@ -653,16 +737,15 @@ with
        +   (if (end-of-char-set? cur) ans
        +       (lp (char-set-cursor-next cs cur)
        +           (cons (char-set-ref cs cur) ans))))
        +-  =3D> (#\G #\T #\a #\c #\e #\h)
        ++  =3D> (#\G #\T #\a #\c #\e #\h)
        +=20
        + ;; Equivalently, using a list unfold (from SRFI 1):
        + (unfold-right end-of-char-set?=20
        +               (curry char-set-ref cs)
        + 	      (curry char-set-cursor-next cs)
        + 	      (char-set-cursor cs))
        +-  =3D> (#\G #\T #\a #\c #\e #\h)
        ++  =3D> (#\G #\T #\a #\c #\e #\h)
        + 
        +- +

        + Rationale: Note that the cursor API's four functions "fit" the functi= onal + protocol used by the unfolders provided by the list, string and char-= set +@@ -674,26 +757,31 @@ with + character set, then this function returned false instead of the chara= cter + value, and another end-of-char-set cursor. In this way, the other thr= ee + functions of the current API were combined together. +- ++

        ++
        + +-
        ++
        + +-char-set-fold kons knil cs -> object +-
        ++char-set-fold kons knil cs -> obj= ect ++ ++
        ++

        + This is the fundamental iterator for character sets. Applies the fun= ction + kons across the character set cs using initial = state value knil. That is, + if cs is the empty set, the procedure returns knil. Otherwise, some + element c of cs is chosen;=20 + let cs' be the remaining, unchosen characters. + The procedure returns +-

        ++

        ++
        + (char-set-fold kons (kons c knil) cs')
        + 
        +-

        ++

        + Examples: +-

        ++

        ++
        + ;; CHAR-SET-MEMBERS
        + (lambda (cs) (char-set-fold cons '() cs))
        +=20
        +@@ -705,34 +793,39 @@ with
        +   (char-set-fold (lambda (c i) (if (vowel? c) (+ i 1) i))
        +                  0 cs))
        + 
        ++
        +=20 + +-
        +- +- +-char-set-unfold  f p g seed [base= -cs] -> char-set +-
        char-set-unfold!= f p g seed base-cs -> char-set +-
        ++
        ++char-set-unfold  f p g seed [ba= se-cs] -> char-set ++
        ++
        = char-set-unfold! f p g seed base-cs -> char-set ++
        ++
        ++

        + This is a fundamental constructor for char-sets.=20 ++

        +
          +
        • G is used to generate a series of "seed" values from = the initial seed: + seed, (g seed), (g2 seed), (g3 seed), ... +-
        • P tells us when to stop -- when it returns true when = applied to one=20 ++
        • ++
        • P tells us when to stop -- when it returns true when = applied to one + of these seed values. ++
        • +
        • F maps each seed value to a character. These characte= rs are added + to the base character set base-cs to form the result; base-cs defaults to + the empty set. char-set-unfold! adds the characters to= base-cs in a=20 + linear-update -- it is allowed, but not required, to side-effect + and use base-cs's storage to construct the result. ++
        • +
        +- +-

        ++

        + More precisely, the following definitions hold, ignoring the + optional-argument issues: +- +-

        ++

        ++
        + (define (char-set-unfold p f g seed base-cs)=20
        +   (char-set-unfold! p f g seed (char-set-copy base-cs)))
        +=20
        +@@ -742,31 +835,34 @@ with
        +             (lp (g seed)                                ; Loop on (G SEED=
        ).
        +                 (char-set-adjoin! cs (f seed))))))      ; Add (F SEED) to=
         set.
        + 
        +- ++

        + (Note that the actual implementation may be more efficient.) +- +-

        ++

        ++

        + Examples: +-

        =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=
        =20=20=20=20=20=20=20=20=20=20
        +-(port->char-set p) =3D (char-set-unfold eof-object? values
        ++

        ++
        =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=
        =20=20=20=20=20=20=20=20=20=20
        ++(port->char-set p) =3D (char-set-unfold eof-object? values
        +                                       (lambda (x) (read-char p))
        +                                       (read-char p))
        +=20
        +-(list->char-set lis) =3D (char-set-unfold null? car cdr lis)
        ++(list->char-set lis) =3D (char-set-unfold null? car cdr lis)
        + 
        ++
        + +-
        +- +-char-set-for-each proc cs -> unspecifi= ed +-
        ++
        ++char-set-for-each proc cs -> unsp= ecified ++
        ++
        ++

        + Apply procedure proc to each character in the character se= t cs. + Note that the order in which proc is applied to the charac= ters in the + set is not specified, and may even change from one procedure applicat= ion + to another. +- +-

        ++

        ++

        + Nothing at all is specified about the value returned by this procedur= e; it + is not even required to be consistent from call to call. It is simply + required to be a value (or values) that may be passed to a command +@@ -776,123 +872,137 @@ with + R5RS= , + this restricts the procedure to returning a single value;=20 + non-R5RS systems may not even provide this restriction. +- ++

        ++
        + +-
        +- +-char-set-map proc cs -> char-set +-
        +- proc is a char->char procedure. Apply it to all the charac= ters in ++
        ++char-set-map proc cs -> char-set<= /var> ++
        ++
        ++

        ++ proc is a char->char procedure. Apply it to all the cha= racters in + the char-set cs, and collect the results into a new charac= ter set. +- +-

        +- Essentially lifts proc from a char->char procedure to a ch= ar-set -> ++

        ++

        ++ Essentially lifts proc from a char->char procedure to a= char-set -> + char-set procedure. +- +-

        ++

        ++

        + Example: +-

        ++

        ++
        + (char-set-map char-downcase cset)
        + 
        ++
        +
        +=20 +- + +-

        Creating character sets

        ++

        Creating character sets

        +
        +=20 + +-
        +- +-char-set-copy cs -> char-set +-
        ++
        ++char-set-copy cs -> char-set ++
        ++
        ++

        + Returns a copy of the character set cs. "Copy" means that= if either the + input parameter or the result value of this procedure is passed to on= e of + the linear-update procedures described below, the other character set= is + guaranteed not to be altered.=20=20 +- +-

        ++

        ++

        + A system that provides pure-functional implementations of the + linear-operator suite could implement this procedure as the identity + function -- so copies are not guaranteed to be distinct by <= code>eq?. +- ++

        ++
        + +-
        +- +-char-set char1 ... -> char-= set +-
        ++
        ++char-set char1 ... -> = char-set ++
        ++
        ++

        + Return a character set containing the given characters. +- ++

        ++
        + +-
        +-char-set"> +-char-set!"> +-list->char-set  char-list [base-c= s] -> char-set +-
        list->char-set! = char-list base-cs -> char-set +-
        ++
        ++list->char-set  char-list [b= ase-cs] -> char-set ++
        ++
        list->char-set! char-list base-cs -> char-set ++
        ++
        ++

        + Return a character set containing the characters in the list of + characters char-list. +- +-

        ++

        ++

        + If character set base-cs is provided, the characters from = char-list +- are added to it. list->char-set! is allowed, but not req= uired, ++ are added to it. list->char-set! is allowed, but not = required, + to side-effect and reuse the storage in base-cs;=20 +- list->char-set produces a fresh character set. +- ++ list->char-set produces a fresh character set. ++

        ++
        + +-
        +-char-set"> +-char-set!"> +-string->char-set  s [base-cs] -> = char-set +-
        string->char-set! s base-cs -> char-set +-
        +- ++
        ++ ++ ++string->char-set  s [base-cs= ] -> char-set ++
        ++
        string->char-set! s base-cs -> char-set ++
        ++
        ++

        + Return a character set containing the characters in the string s= . +- +-

        ++

        ++

        + If character set base-cs is provided, the characters from = s are added to +- it. string->char-set! is allowed, but not required, to s= ide-effect and +- reuse the storage in base-cs; string->char-set produces a fresh character ++ it. string->char-set! is allowed, but not required, t= o side-effect and ++ reuse the storage in base-cs; string->char-set produces a fresh character + set. +- ++

        ++
        + +-
        ++
        + + +-char-set-filter  pred cs [base-cs= ] -> char-set +-
        char-set-filter!= pred cs base-cs -> char-set +-
        +- ++char-set-filter  pred cs [base-= cs] -> char-set ++ ++
        char-set-filter!<= var> pred cs base-cs -> char-set ++
        ++
        ++

        + Returns a character set containing every character c=20 + in cs such that (pred c)=20 + returns true. +- ++

        +

        + If character set base-cs is provided, the characters speci= fied=20 + by pred are added to it.=20 + char-set-filter! is allowed, but not required, + to side-effect and reuse the storage in base-cs;=20 + char-set-filter produces a fresh character set. +- ++

        +

        + An implementation may not save away a reference to pred and + invoke it after char-set-filter or=20 + char-set-filter! returns -- that is, "lazy," + on-demand implementations are not allowed, as pred may have + external dependencies on mutable data or have other side-effects. +- ++

        +

        + Rationale: This procedure provides a means of converting a character + predicate into its equivalent character set; the cs parame= ter +@@ -900,52 +1010,56 @@ with + be aware that filtering a character set such as char-set:full + could be a very expensive operation in an implementation that provide= d an + extremely large character type, such as 32-bit Unicode. An earlier dr= aft +- of this library provided a simple predicate->char-set ++ of this library provided a simple predicate->char-set + procedure, which was rejected in favor of char-set-filter for + this reason. +- ++

        ++
        +=20 + +-
        +-char-set"> +-char-set!"> +-ucs-range->char-set  lower upper = [error? base-cs] -> char-set +-
        ucs-range->char-set!<= var> lower upper error? base-cs -> char-set +-
        ++
        ++ ++ ++ucs-range->char-set  lower u= pper [error? base-cs] -> char-set ++
        ++
        ucs-range->char-set!<= /code> lower upper error? base-cs -> char-set ++
        ++
        ++

        + Lower and upper are exact non-negative integers= ;=20 +- lower <=3D upper. +- +-

        ++ lower <=3D upper. ++

        ++

        + Returns a character set containing every character whose ISO/IEC 10646 + UCS-4 code lies in the half-open range [lower,upper). +- ++

        +
          +
        • If the requested range includes unassigned UCS values, these are + silently ignored (the current UCS specification has "holes" in the + space of assigned codes). +-=20=20=20=20 ++
        • +
        • If the requested range includes "private" or "user space" codes,= these + are handled in an implementation-specific manner; however, a UCS- or + Unicode-based Scheme implementation should pass them through + transparently. +-=20=20=20=20 ++
        • +
        • If any code from the requested range specifies a valid, assigned + UCS character that has no corresponding representative in the + implementation's character type, then (1) an error is raised if error? + is true, and (2) the code is ignored if error? is false = (the default). + This might happen, for example, if the implementation uses ASCII + characters, and the requested range includes non-ASCII characters. ++
        • +
        +- +-

        ++

        + If character set base-cs is provided, the characters speci= fied by the +- range are added to it. ucs-range->char-set! is allowed, = but not required, ++ range are added to it. ucs-range->char-set! is allowe= d, but not required, + to side-effect and reuse the storage in base-cs;=20 +- ucs-range->char-set produces a fresh character set. +- +-

        ++ ucs-range->char-set produces a fresh character set. ++

        ++

        + Note that ASCII codes are a subset of the Latin-1 codes, which are in= turn + a subset of the 16-bit Unicode codes, which are themselves a subset o= f the + 32-bit UCS-4 codes. We commit to a specific encoding in this routine, +@@ -954,14 +1068,17 @@ with + implementation may use EBCDIC or SHIFT-JIS to encode characters; it m= ust + simply map the UCS characters from the given range into the native + representation when possible, and report errors when not possible. +- ++

        ++
        + +-
        +-char-set"> +-->char-set x -> char-set +-
        ++
        ++ ++->char-set x -> char-set ++
        ++
        ++

        + Coerces x into a char-set.=20 + X may be a string, character or + char-set. A string is converted to the set of its constituent charact= ers; +@@ -969,76 +1086,94 @@ with + as-is. + This procedure is intended for use by other procedures that want to=20 + provide "user-friendly," wide-spectrum interfaces to their clients. +- ++

        ++
        +
        +- + +-

        Querying character sets

        ++

        Querying character sets

        +
        +=20 + +-
        ++
        + +-char-set-size cs -> integer +-
        ++char-set-size cs -> integer ++ ++
        ++

        + Returns the number of elements in character set cs. +- ++

        ++
        + +-
        ++
        + +-char-set-count pred cs -> integer +-
        ++char-set-count pred cs -> integer= ++ ++
        ++

        + Apply pred to the chars of character set cs, an= d return the number + of chars that caused the predicate to return true. +- ++

        ++
        + +-
        +-list"> +-char-set->list cs -> character-list +-
        ++
        ++ ++char-set->list cs -> character= -list ++
        ++
        ++

        + This procedure returns a list of the members of character set cs= . + The order in which cs's characters appear in the list is n= ot defined, + and may be different from one call to another. +- ++

        ++
        + +-
        +-string"> +-char-set->string cs -> string +-
        ++
        ++ ++char-set->string cs -> string<= /var> ++
        ++
        ++

        + This procedure returns a string containing the members of character s= et cs. + The order in which cs's characters appear in the string is= not defined, + and may be different from one call to another. +- ++

        ++
        + +-
        ++
        + +-char-set-contains? cs char -> boolean<= /var> +-
        ++char-set-contains? cs char -> boo= lean ++ ++
        ++

        + This procedure tests char for membership in character set = cs. +- +-

        ++

        ++

        + The MIT Scheme character-set package called this procedure + char-set-member?, but the argument order isn't consistent = with the name. +- ++

        ++
        + +-
        ++
        + + +-char-set-every pred cs -> boolean +-
        char-set-any   pred cs -> boolean +-
        ++char-set-every pred cs -> boolean= ++ ++
        char-set-any  = pred cs -> boolean ++
        ++
        ++

        + The char-set-every procedure returns true if predicate <= var>pred + returns true of every character in the character set cs. + Likewise, char-set-any applies pred to every = character in +@@ -1046,169 +1181,171 @@ with + If no character produces a true value, it returns false. + The order in which these procedures sequence through the elements of + cs is not specified. +- +-

        ++

        ++

        + Note that if you need to determine the actual character on which a=20 + predicate returns true, use char-set-any and arrange for= the predicate=20 + to return the character parameter as its true value, e.g. +-

        ++

        ++
        + (char-set-any (lambda (c) (and (char-upper-case? c) c))=20
        +               cs)
        + 
        ++
        +
        +- + +-

        Character-set algebra

        ++

        Character-set algebra

        +
        +=20 + +-
        ++
        + + +-char-set-adjoin cs char1 ..= . -> char-set +-
        char-set-delete = cs char1 ... -> char-set +-
        ++char-set-adjoin cs char1 = ... -> char-set ++ ++
        char-set-delete cs char1 ... -> char-set ++
        ++
        ++

        + Add/delete the chari characters to/from charact= er set cs. +- ++

        ++
        + +-
        ++
        + + +-char-set-adjoin! cs char1 .= .. -> char-set +-
        char-set-delete!= cs char1 ... -> char-set +-
        +- ++char-set-adjoin! cs char1= ... -> char-set ++ ++
        char-set-delete!<= var> cs char1 ... -> char-set ++
        ++
        ++

        + Linear-update variants. These procedures are allowed, but not + required, to side-effect their first parameter. +- ++

        ++
        + +-
        ++
        + + + + + + +-char-set-complement cs = -> char-set +-
        char-set-union c= s1 ... -> char-set +-
        char-set-intersection= cs1 ... -> char-set +-
        char-set-difference cs1 cs2 ... -> char-set +-
        char-set-xor cs<= sub>1 ... -> char-set +-
        char-set-diff+intersection cs1 cs2 ... -> [char-set char-set] +-
        ++char-set-complement cs = -> char-set ++ ++
        char-set-union cs1 ... -> char-set ++
        ++
        char-set-intersection cs1 ... -> char-set ++
        ++
        char-set-difference cs1 cs2 ... -> char-set ++
        ++
        char-set-xor= cs1 ... -> char-set ++
        ++
        char-set-diff+intersecti= on cs1 cs2 ... -> [char-set char-set]<= /var> ++
        ++
        ++

        + These procedures implement set complement, union, intersection, + difference, and exclusive-or for character sets. The union, intersect= ion + and xor operations are n-ary. The difference function is also n-ary, + associates to the left (that is, it computes the difference between + its first argument and the union of all the other arguments), + and requires at least one argument. +- +-

        ++

        ++

        + Boundary cases: +-

        +-(char-set-union) =3D> char-set:empty
        +-(char-set-intersection) =3D> char-set:full
        +-(char-set-xor) =3D> char-set:empty
        +-(char-set-difference cs) =3D> cs
        ++

        ++
        ++(char-set-union) =3D> char-set:empty
        ++(char-set-intersection) =3D> char-set:full
        ++(char-set-xor) =3D> char-set:empty
        ++(char-set-difference cs) =3D> cs
        + 
        +- +-

        ++

        + char-set-diff+intersection returns both the difference a= nd the + intersection of the arguments -- it partitions its first parameter. + It is equivalent to=20 +-

        ++

        ++
        + (values (char-set-difference cs1 cs2 ...)
        +         (char-set-intersection cs1 (char-set-union =
        cs2 ...)))
        + 
        ++

        + but can be implemented more efficiently. +- ++

        +

        + Programmers should be aware that char-set-complement cou= ld potentially + be a very expensive operation in Scheme implementations that provide + a very large character type, such as 32-bit Unicode. If this is a + possibility, sets can be complimented with respect to a smaller + universe using char-set-difference. +- +- ++

        ++
        + +-
        +- +- +- +- +- +- +-char-set-complement! cs = -> char-set +-
        char-set-union! = cs1 cs2 ... -> char-set +-
        char-set-intersection! cs1 cs2 ... -> char-set +-
        char-set-difference!<= var> cs1 cs2 ... -> char-set +-
        char-set-xor! c= s1 cs2 ... -> char-set +-
        char-set-diff+intersection!<= /code> cs1 cs2 cs3 ... -> [char-set = char-set] +-
        ++
        ++char-set-complement! cs = -> char-set ++
        ++
        c= har-set-union! cs1 cs2 ... = -> char-set ++
        ++
        char-set-intersection! cs1 cs2 ...= -> char-set ++
        ++
        char-set-difference! cs1 cs2 ... = -> char-set ++
        ++
        cha= r-set-xor! cs1 cs2 ... = -> char-set ++
        ++
        char-set-diff+intersection! cs1 cs2= cs3 ... -> [char-set char-set] ++
        ++
        ++

        + These are linear-update variants of the set-algebra functions. + They are allowed, but not required, to side-effect their first (requi= red) + parameter. +- +-

        ++

        ++

        + char-set-diff+intersection! is allowed to side-effect bo= th + of its two required parameters, cs1 + and cs2. ++

        ++
        +
        +=20 + +-

        Standard character sets

        ++

        Standard character sets

        +

        + Several character sets are predefined for convenience: +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +-

        +- +-= +-= +-= +- +- +- +- +- +- +- +- +- +- +- +- +- +- ++

        ++
        ++
        char-set:lower-case Lower-case letters
        char-set:upper-case Upper-case letters
        char-set:title-case Title-case letters
        char-set:letter Letters
        char-set:digit Digits
        char-set:letter+digit Letters and digits
        char-set:graphic Printing characters except= spaces
        char-set:printing Printing characters inclu= ding spaces
        char-set:whitespace Whitespace characters <= /td>
        char-set:iso-control The ISO control charac= ters
        char-set:punctuation Punctuation characters=
        char-set:symbol Symbol characters
        char-set:hex-digit A hexadecimal digit: 0-9= , A-F, a-f
        char-set:blank Blank characters -- horizont= al whitespace
        char-set:ascii All characters in the ASCII = set.
        char-set:empty Empty set
        char-set:full All characters
        ++= ++= ++= ++ ++ ++ ++ ++ ++= ++ ++ ++ ++A hexadecimal digit: 0-9, A-F, a-f ++ ++ ++ ++ +
        char-set:lower-case Lower-case letters
        char-set:upper-case Upper-case letters
        char-set:title-case Title-case letters
        char-set:letter Lett= ers
        char-set:digit Digits=
        char-set:letter+digit <= /td>Letters and digits
        char-set:graphic Pr= inting characters except spaces
        char-set:printing = Printing characters including spaces
        char-set:whitespace Whitespace characters
        char-set:iso-control The ISO control characters
        char-set:punctuation Punctuation characters
        char-set:symbol Symb= ol characters
        char-set:hex-digit
        char-set:blank Blank = characters -- horizontal whitespace
        char-set:ascii All ch= aracters in the ASCII set.
        char-set:empty Empty = set
        char-set:full All char= acters
        +
        +- +

        + Note that there may be characters in char-set:letter that ar= e neither upper or + lower case---this might occur in implementations that use a character type +@@ -1216,8 +1353,9 @@ richer than ASCII, such as Unicode. A "graphic chara= cter" is one that would + put ink on your page. While the exact composition of these sets may vary + depending upon the character type provided by the underlying Scheme syste= m, + here are the definitions for some of the sets in an ASCII implementation: +-

        +- ++

        ++
        ++
        + + + +@@ -1232,76 +1370,93 @@ here are the definitions for some of the sets in a= n ASCII implementation: + +
        char-set:lower-case a-z
        char-set:upper-case A-Z
        char-set:letter A-Z and a-z
        char-set:iso-control ASCII 0-31 and 127
        +
        +- +

        + Note that the existence of the char-set:ascii set implies th= at the underlying + character set is required to be at least as rich as ASCII (including + ASCII's control characters). +- ++

        +

        + Rationale: The name choices reflect a shift from the older "alphabetic/nu= meric" + terms found in=20 + R5RS + and Posix to newer, Unicode-influenced "letter/digit" lexemes. +- ++

        + +-

        +- Unicode, Latin-1 and ASCII definitions of the standard character sets= +-

        ++

        ++ Unicode, Latin-1 and ASCII definitions of the standard character sets ++

        +

        + In Unicode Scheme implementations, the base character sets are compatible= with +-Java's Unicode specifications. For ASCII or Latin-1, we simply restrict t= he ++Java's Unicode specifications. ++ ++

        ++

        For ASCII or Latin-1, we simply restrict the + Unicode set specifications to their first 128 or 256 codes, respectively. + Scheme implementations that are not based on ASCII, Latin-1 or Unicode sh= ould + attempt to preserve the sense or spirit of these definitions. +- ++

        +

        + The following descriptions frequently make reference to the "Unicode char= acter + database." This is a file, available at URL +-

        ++

        ++ +-

        ++

        + Each line contains a description of a Unicode character. The first + semicolon-delimited field of the line gives the hex value of the characte= r's + code; the second field gives the name of the character, and the third fie= ld + gives a two-letter category. Other fields give simple 1-1 case-mappings f= or + the character and other information; see +-

        ++

        ++ +-

        ++

        + for further description of the file's format. Note in particular the +-two-letter category specified in the third field, which is referenced ++two-letter category specified in the the third field, which is referenced + frequently in the descriptions below. +- ++

        + +-

        char-set:lower-case

        ++

        char-set:lower-case

        +

        + For Unicode, we follow Java's specification: a character is lowercase if ++

        +
          +-
        • it is not in the range [U+2000,U+2FFF], and +-
        • the Unicode attribute table does not give a lowercase mapping for it= , and +-
        • at least one of the following is true: +-
            +-
          • the Unicode attribute table gives a mapping to uppercase=20 +- for the character, or +-
          • the name for the character in the Unicode attribute table contains ++
          • it is not in the range [U+2000,U+2FFF], and ++
          • ++
          • the Unicode attribute table does not give a lowercase mapping for = it, and ++
          • ++
          • at least one of the following is true: ++
              ++
            • the Unicode attribute table gives a mapping to uppercase ++ for the character, or ++
            • ++
            • the name for the character in the Unicode attribute table cont= ains + the words "SMALL LETTER" or "SMALL LIGATURE". +-
            ++
          • ++
          ++
        • +
        +=20 +

        + The lower-case ASCII characters are=20 +-

        ++

        ++
        + abcdefghijklmnopqrstuvwxyz +
        +-

        ++

        + Latin-1 adds another 33 lower-case characters to the ASCII set: +-

        +- ++

        ++
        ++
        + + + +@@ -1337,38 +1492,41 @@ Latin-1 adds another 33 lower-case characters to t= he ASCII set: + +
        00B5 MICRO SIGN
        00DF LATIN SMALL LETTER SHARP S
        00E0 LATIN SMALL LETTER A WITH GRAVE
        00FF LATIN SMALL LETTER Y WITH DIAERESIS
        +
        +-

        ++

        + Note that three of these have no corresponding Latin-1 upper-case charact= er: +-

        +- ++

        ++
        ++
        + + + +
        00B5 MICRO SIGN
        00DF LATIN SMALL LETTER SHARP S
        00FF LATIN SMALL LETTER Y WITH DIAERESIS
        +
        +-

        ++

        + (The compatibility micro character uppercases to the non-Latin-1 Greek ca= pital + mu; the German sharp s character uppercases to the pair of characters "SS= ," + and the capital y-with-diaeresis is non-Latin-1.) +- ++

        +

        + (Note that the Java spec for lowercase characters given at +-

        ++

        ++ +-

        ++

        + is inconsistent. U+00B5 MICRO SIGN fulfills the requirements for a lower-= case + character (as of Unicode 3.0), but is not given in the numeric list of + lower-case character codes.) +- ++

        +

        + (Note that the Java spec for isLowerCase() given at +-

        ++

        ++ +-

        ++

        + gives three mutually inconsistent definitions of "lower case." The first = is + the definition used in this SRFI. Following text says "A character is + considered to be lowercase if and only if it is specified to be lowercase= by +@@ -1377,33 +1535,41 @@ file)." The former spec excludes U+00AA FEMININE O= RDINAL INDICATOR and + U+00BA MASCULINE ORDINAL INDICATOR; the later spec includes them. Finally, + the spec enumerates a list of characters in the Latin-1 subset; this list + excludes U+00B5 MICRO SIGN, which is included in both of the previous spe= cs.)=20 +- ++

        + +-

        char-set:upper-case

        ++

        char-set:upper-case

        +

        + For Unicode, we follow Java's specification: a character is uppercase if ++

        +
          +-
        • it is not in the range [U+2000,U+2FFF], and +-
        • the Unicode attribute table does not give an uppercase mapping for it ++
        • it is not in the range [U+2000,U+2FFF], and ++
        • ++
        • the Unicode attribute table does not give an uppercase mapping for= it + (this excludes titlecase characters), and +-
        • at least one of the following is true: +-
            +-
          • the Unicode attribute table gives a mapping to lowercase=20 ++
          • ++
          • at least one of the following is true: ++
              ++
            • the Unicode attribute table gives a mapping to lowercase + for the character, or +-
            • the name for the character in the Unicode attribute table contains ++
            • ++
            • the name for the character in the Unicode attribute table cont= ains + the words "CAPITAL LETTER" or "CAPITAL LIGATURE". +-
            ++
          • ++
          ++
        • +
        +=20 +

        + The upper-case ASCII characters are=20 +-

        ++

        ++
        + ABCDEFGHIJKLMNOPQRSTUVWXYZ +
        +-

        ++

        + Latin-1 adds another 30 upper-case characters to the ASCII set: +-

        +- ++

        ++
        ++
        + + + +@@ -1437,109 +1603,112 @@ Latin-1 adds another 30 upper-case characters to= the ASCII set: +
        00C0 LATIN CAPITAL LETTER A WITH GRAVE
        00C1 LATIN CAPITAL LETTER A WITH ACUTE
        00C2 LATIN CAPITAL LETTER A WITH CIRCUMFLEX
        +
        + +-

        char-set:title-case

        ++

        char-set:title-case

        +

        + In Unicode, a character is titlecase if it has the category Lt in + the character attribute database. There are very few of these characters; + here is the entire 31-character list as of Unicode 3.0: +-

        +- +-
        01C5 LATIN CAPITAL LETTER D WITH SMALL LETTER Z = WITH CARON ++

        ++
        ++ ++ +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +
        01C5 LATIN CAPITAL LETTER D WITH SMAL= L LETTER Z WITH CARON +
        01C8 LATIN CAPITAL LETTER L WITH SMALL LETTER J ++
        01C8 LATIN CAPITAL LETTER L WITH SMAL= L LETTER J +
        01CB LATIN CAPITAL LETTER N WITH SMALL LETTER J ++
        01CB LATIN CAPITAL LETTER N WITH SMAL= L LETTER J +
        01F2 LATIN CAPITAL LETTER D WITH SMALL LETTER Z ++
        01F2 LATIN CAPITAL LETTER D WITH SMAL= L LETTER Z +
        1F88 GREEK CAPITAL LETTER ALPHA WITH PSILI AND P= ROSGEGRAMMENI ++
        1F88 GREEK CAPITAL LETTER ALPHA WITH = PSILI AND PROSGEGRAMMENI +
        1F89 GREEK CAPITAL LETTER ALPHA WITH DASIA AND P= ROSGEGRAMMENI ++
        1F89 GREEK CAPITAL LETTER ALPHA WITH = DASIA AND PROSGEGRAMMENI +
        1F8A GREEK CAPITAL LETTER ALPHA WITH PSILI AND VA= RIA AND PROSGEGRAMMENI ++
        1F8A GREEK CAPITAL LETTER ALPHA WITH P= SILI AND VARIA AND PROSGEGRAMMENI +
        1F8B GREEK CAPITAL LETTER ALPHA WITH DASIA AND V= ARIA AND PROSGEGRAMMENI ++
        1F8B GREEK CAPITAL LETTER ALPHA WITH = DASIA AND VARIA AND PROSGEGRAMMENI +
        1F8C GREEK CAPITAL LETTER ALPHA WITH PSILI AND O= XIA AND PROSGEGRAMMENI ++
        1F8C GREEK CAPITAL LETTER ALPHA WITH = PSILI AND OXIA AND PROSGEGRAMMENI +
        1F8D GREEK CAPITAL LETTER ALPHA WITH DASIA AND O= XIA AND PROSGEGRAMMENI ++
        1F8D GREEK CAPITAL LETTER ALPHA WITH = DASIA AND OXIA AND PROSGEGRAMMENI +
        1F8E GREEK CAPITAL LETTER ALPHA WITH PSILI AND P= ERISPOMENI AND PROSGEGRAMMENI ++
        1F8E GREEK CAPITAL LETTER ALPHA WITH = PSILI AND PERISPOMENI AND PROSGEGRAMMENI +
        1F8F GREEK CAPITAL LETTER ALPHA WITH DASIA AND P= ERISPOMENI AND PROSGEGRAMMENI ++
        1F8F GREEK CAPITAL LETTER ALPHA WITH = DASIA AND PERISPOMENI AND PROSGEGRAMMENI +
        1F98 GREEK CAPITAL LETTER ETA WITH PSILI AND PRO= SGEGRAMMENI ++
        1F98 GREEK CAPITAL LETTER ETA WITH PS= ILI AND PROSGEGRAMMENI +
        1F99 GREEK CAPITAL LETTER ETA WITH DASIA AND PRO= SGEGRAMMENI ++
        1F99 GREEK CAPITAL LETTER ETA WITH DA= SIA AND PROSGEGRAMMENI +
        1F9A GREEK CAPITAL LETTER ETA WITH PSILI AND VAR= IA AND PROSGEGRAMMENI ++
        1F9A GREEK CAPITAL LETTER ETA WITH PS= ILI AND VARIA AND PROSGEGRAMMENI +
        1F9B GREEK CAPITAL LETTER ETA WITH DASIA AND VAR= IA AND PROSGEGRAMMENI ++
        1F9B GREEK CAPITAL LETTER ETA WITH DA= SIA AND VARIA AND PROSGEGRAMMENI +
        1F9C GREEK CAPITAL LETTER ETA WITH PSILI AND OXI= A AND PROSGEGRAMMENI ++
        1F9C GREEK CAPITAL LETTER ETA WITH PS= ILI AND OXIA AND PROSGEGRAMMENI +
        1F9D GREEK CAPITAL LETTER ETA WITH DASIA AND OXI= A AND PROSGEGRAMMENI ++
        1F9D GREEK CAPITAL LETTER ETA WITH DA= SIA AND OXIA AND PROSGEGRAMMENI +
        1F9E GREEK CAPITAL LETTER ETA WITH PSILI AND PER= ISPOMENI AND PROSGEGRAMMENI ++
        1F9E GREEK CAPITAL LETTER ETA WITH PS= ILI AND PERISPOMENI AND PROSGEGRAMMENI +
        1F9F GREEK CAPITAL LETTER ETA WITH DASIA AND PER= ISPOMENI AND PROSGEGRAMMENI ++
        1F9F GREEK CAPITAL LETTER ETA WITH DA= SIA AND PERISPOMENI AND PROSGEGRAMMENI +
        1FA8 GREEK CAPITAL LETTER OMEGA WITH PSILI AND P= ROSGEGRAMMENI ++
        1FA8 GREEK CAPITAL LETTER OMEGA WITH = PSILI AND PROSGEGRAMMENI +
        1FA9 GREEK CAPITAL LETTER OMEGA WITH DASIA AND P= ROSGEGRAMMENI ++
        1FA9 GREEK CAPITAL LETTER OMEGA WITH = DASIA AND PROSGEGRAMMENI +
        1FAA GREEK CAPITAL LETTER OMEGA WITH PSILI AND V= ARIA AND PROSGEGRAMMENI ++
        1FAA GREEK CAPITAL LETTER OMEGA WITH = PSILI AND VARIA AND PROSGEGRAMMENI +
        1FAB GREEK CAPITAL LETTER OMEGA WITH DASIA AND V= ARIA AND PROSGEGRAMMENI ++
        1FAB GREEK CAPITAL LETTER OMEGA WITH = DASIA AND VARIA AND PROSGEGRAMMENI +
        1FAC GREEK CAPITAL LETTER OMEGA WITH PSILI AND O= XIA AND PROSGEGRAMMENI ++
        1FAC GREEK CAPITAL LETTER OMEGA WITH = PSILI AND OXIA AND PROSGEGRAMMENI +
        1FAD GREEK CAPITAL LETTER OMEGA WITH DASIA AND O= XIA AND PROSGEGRAMMENI ++
        1FAD GREEK CAPITAL LETTER OMEGA WITH = DASIA AND OXIA AND PROSGEGRAMMENI +
        1FAE GREEK CAPITAL LETTER OMEGA WITH PSILI AND P= ERISPOMENI AND PROSGEGRAMMENI ++
        1FAE GREEK CAPITAL LETTER OMEGA WITH = PSILI AND PERISPOMENI AND PROSGEGRAMMENI +
        1FAF GREEK CAPITAL LETTER OMEGA WITH DASIA AND P= ERISPOMENI AND PROSGEGRAMMENI ++
        1FAF GREEK CAPITAL LETTER OMEGA WITH = DASIA AND PERISPOMENI AND PROSGEGRAMMENI +
        1FBC GREEK CAPITAL LETTER ALPHA WITH PROSGEGRAMM= ENI ++
        1FBC GREEK CAPITAL LETTER ALPHA WITH = PROSGEGRAMMENI +
        1FCC GREEK CAPITAL LETTER ETA WITH PROSGEGRAMMENI ++
        1FCC GREEK CAPITAL LETTER ETA WITH PR= OSGEGRAMMENI +
        1FFC GREEK CAPITAL LETTER OMEGA WITH PROSGEGRAMM= ENI ++
        1FFC GREEK CAPITAL LETTER OMEGA WITH = PROSGEGRAMMENI +
        +
        +

        + There are no ASCII or Latin-1 titlecase characters. +- ++

        +=20 + +-

        char-set:letter

        ++

        char-set:letter

        +

        + In Unicode, a letter is any character with one of the letter categories + (Lu, Ll, Lt, Lm, Lo) in the Unicode character database.=20 +- ++

        +

        + There are 52 ASCII letters +-

        +- abcdefghijklmnopqrstuvwxyz
        +- ABCDEFGHIJKLMNOPQRSTUVWXYZ
        ++

        ++
        ++ abcdefghijklmnopqrstuvwxyz
        ++ ABCDEFGHIJKLMNOPQRSTUVWXYZ
        +
        +

        + There are 117 Latin-1 letters. These are the 115 characters that are + members of the Latin-1 char-set:lower-case and char-se= t:upper-case sets,=20 + plus +-

        +- ++

        ++
        ++
        + + +
        00AA FEMININE ORDINAL INDICATOR
        00BA MASCULINE ORDINAL INDICATOR
        +
        +-

        ++

        + (These two letters are considered lower-case by Unicode, but not by + Java or SRFI 14.) +- ++

        + +-

        char-set:digit

        ++

        char-set:digit

        +=20 +

        + In Unicode, a character is a digit if it has the category Nd in +@@ -1547,26 +1716,27 @@ the character attribute database. In Latin-1 and A= SCII, the only + such characters are 0123456789. In Unicode, there are other digit + characters in other code blocks, such as Gujarati digits and Tibetan + digits. +- ++

        +=20 + +-

        char-set:hex-digit

        ++

        char-set:hex-digit

        +

        + The only hex digits are 0123456789abcdefABCDEF. +- ++

        +=20 + +-

        char-set:letter+digit

        ++

        char-set:letter+digit

        +

        + The union of char-set:letter and char-set:digit. +- ++

        + +-

        char-set:graphic

        ++

        char-set:graphic

        +

        + A graphic character is one that would put ink on paper. The ASCII and Lat= in-1 + graphic characters are the members of +-

        +- ++

        ++
        ++
        + + + +@@ -1575,30 +1745,38 @@ graphic characters are the members of + +=20 + +-

        char-set:printing

        ++

        char-set:printing

        +

        + A printing character is one that would occupy space when printed, i.e= ., + a graphic character or a space character. char-set:printing = is the union + of char-set:whitespace and char-set:graphic. +- ++

        + +-

        char-set:whitespace

        ++

        char-set:whitespace

        +

        + In Unicode, a whitespace character is either ++

        +
          +
        • a character with one of the space, line, or paragraph separator ca= tegories + (Zs, Zl or Zp) of the Unicode character database. ++
        • +
        • U+0009 Horizontal tabulation (\t control-I) ++
        • +
        • U+000A Line feed (\n control-J) ++
        • +
        • U+000B Vertical tabulation (\v control-K) ++
        • +
        • U+000C Form feed (\f control-L) ++
        • +
        • U+000D Carriage return (\r control-M) ++
        • +
        +=20 +

        + There are 24 whitespace characters in Unicode 3.0: +-

        +-
        char-set:letter
        char-set:digit
        char-set:punctuation
        ++

        ++
        ++
        + = + + +@@ -1630,11 +1808,12 @@ The ASCII whitespace characters are the first six = characters in the above list + -- line feed, horizontal tabulation, vertical tabulation, form feed, carr= iage + return, and space. These are also exactly the characters recognised by the + Posix isspace() procedure. Latin-1 adds the no-break space. +- ++

        +

        + Note: Java's isWhitespace() method is incompatible, including +-

        +-
        0009 HORIZONTAL TABULATION \t control-I
        000A LINE FEED \n control-J
        000B VERTICAL TABULATION \v control-K
        ++

        ++
        ++
        + + + +@@ -1642,10 +1821,11 @@ Note: Java's isWhitespace() method is= incompatible, including + +
        0009 HORIZONTAL TABULATION (\t control-I)
        001C FILE SEPARATOR (control-\)
        001D GROUP SEPARATOR (control-])
        001F UNIT SEPARATOR (control-_)
        +
        +-

        ++

        + and excluding +-

        +- ++

        ++
        ++
        + +
        00A0 NO-BREAK SPACE
        +
        +@@ -1654,67 +1834,71 @@ Java's excluding the no-break space means that tok= enizers can simply break + character streams at "whitespace" boundaries. However, the exclusion intr= oduces + exceptions in other places, e.g. char-set:printing = is no longer simply the + union of char-set:graphic and char-set:whitespace. +- ++

        +=20 + +-

        char-set:iso-control

        ++

        char-set:iso-control

        +

        + The ISO control characters are the Unicode/Latin-1 characters in the rang= es + [U+0000,U+001F] and [U+007F,U+009F]. +- ++

        +

        + ASCII restricts this set to the characters in the range [U+0000,U+001F]=20 + plus the character U+007F. +- ++

        +

        + Note that Unicode defines other control characters which do not belong to= this + set (hence the qualifying prefix "iso-" in the name). This restriction is + compatible with the Java IsISOControl() method. +- ++

        +=20 + +-

        char-set:punctuation

        ++

        char-set:punctuation

        +

        + In Unicode, a punctuation character is any character that has one of the + punctuation categories in the Unicode character database (Pc, Pd, Ps, + Pe, Pi, Pf, or Po.) +- ++

        +

        + ASCII has 23 punctuation characters: +-

        ++

        ++
        + !"#%&'()*,-./:;?@[\]_{}
        + 
        +

        + Latin-1 adds six more: +-

        +- ++

        ++
        ++
        +
        00A1 INVERTED EXCLAMATION MARK +-
        00AB LEFT-POINTING DOUBLE ANGLE QUOTATION MARK +-
        00AD SOFT HYPHEN +-
        00B7 MIDDLE DOT +-
        00BB RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK +-
        00BF INVERTED QUESTION MARK +-
        ++
        00AB LEFT-POINTING DOUBLE ANGLE QUOTATION MA= RK ++
        00AD SOFT HYPHEN ++
        00B7 MIDDLE DOT ++
        00BB RIGHT-POINTING DOUBLE ANGLE QUOTATION M= ARK ++
        00BF INVERTED QUESTION MARK ++
        +
        +=20 +

        +-Note that the nine ASCII characters $+<=3D>^`|~ are not<= /em> ++Note that the nine ASCII characters $+<=3D>^`|~ are not + punctuation. They are "symbols." +- ++

        +=20 + +-

        char-set:symbol

        ++

        char-set:symbol

        +

        + In Unicode, a symbol is any character that has one of the symbol categori= es + in the Unicode character database (Sm, Sc, Sk, or So). There + are nine ASCII symbol characters: +-

        ++

        ++
        + $+<=3D>^`|~
        + 
        +

        + Latin-1 adds 18 more: +-

        +- ++

        ++
        ++
        + + + +@@ -1737,20 +1921,24 @@ Latin-1 adds 18 more: + +=20 + +-

        char-set:blank

        ++

        char-set:blank

        +=20 +

        + Blank chars are horizontal whitespace. In Unicode, a blank character is e= ither ++

        +
          +
        • a character with the space separator category (Zs) in the Unicode= =20 + character database. ++
        • +
        • U+0009 Horizontal tabulation (\t control-I) ++
        • +
        +=20 +

        + There are eighteen blank characters in Unicode 3.0: +-

        +-
        00A2 CENT SIGN
        00A3 POUND SIGN
        00A4 CURRENCY SIGN
        ++

        ++
        ++
        + + + +@@ -1774,21 +1962,22 @@ There are eighteen blank characters in Unicode 3.0: +

        + The ASCII blank characters are the first two characters above -- + horizontal tab and space. Latin-1 adds the no-break space. +- ++

        +

        + Java doesn't have the concept of "blank" characters, so there are no + compatibility issues. +- ++

        +=20 + +-

        Reference implementation

        ++

        Reference implementation

        +

        + This SRFI comes with a reference implementation. It resides at: +-

        +- +-http://srfi.schemers.org/srfi-14/srfi-14.scm ++

        ++ +-

        ++

        + I have placed this source on the Net with an unencumbered, "open" copyrig= ht. + Some of the code in the reference implementation bears a distant family + relation to the MIT Scheme implementation, and being derived from that co= de, +@@ -1797,37 +1986,45 @@ open-source copyright -- see the source file for d= etails). The remainder of + the code was written by myself for scsh or for this SRFI; I have placed t= his + code under the scsh copyright, which is also a generic BSD-style open-sou= rce + copyright. +- ++

        +

        + The code is written for portability and should be simple to port to + any Scheme. It has only the following deviations from R4RS, clearly + discussed in the comments: ++

        +
          +
        • an error procedure; ++
        • +
        • the R5RS values procedure for producing multiple retu= rn values; ++
        • +
        • a simple check-arg procedure for argument checking; ++
        • +
        • let-optionals* and :optional macros for = for parsing, checking and defaulting + optional arguments from rest lists; ++
        • +
        • The SRFI-19 define-record-type form; ++
        • +
        • bitwise-and for the hash function; +-
        • %latin1->char and %char->latin1. ++
        • ++
        • %latin1->char and %char->latin1. ++
        • +
        +=20 +

        + The library is written for clarity and well-commented; the current source= is + about 375 lines of source code and 375 lines of comments and white space. + It is also written for efficiency. Fast paths are provided for common cas= es. +- ++

        +

        + This is not to say that the implementation can't be tuned up for + a specific Scheme implementation. There are notes in comments addressing + ways implementors can tune the reference implementation for performance. +- ++

        +

        + In short, I've written the reference implementation to make it as painless + as possible for an implementor -- or a regular programmer -- to adopt this + library and get good results with it. +- ++

        +

        + The code uses a rather simple-minded, inefficient representation for + ASCII/Latin-1 char-sets -- a 256-character string. The character whose co= de is +@@ -1836,15 +2033,15 @@ not in the set if s[i] =3D ASCII 0 (nul= ). + A much faster and denser representation would be 16 or 32 bytes worth + of bit string. A portable implementation using bit sets awaits standards = for + bitwise logical-ops and byte vectors. +- ++

        +

        + "Large" character types, such as Unicode, should use a sparse representat= ion, + taking care that the Latin-1 subset continues to be represented with a + dense 32-byte bit set. +- ++

        +=20 + +-

        Acknowledgements

        ++

        Acknowledgements

        +

        + The design of this library benefited greatly from the feedback provided d= uring + the SRFI discussion phase. Among those contributing thoughtful commentary= and +@@ -1857,114 +2054,127 @@ Kiselyov, Bengt Kleberg, Donovan Kolbly, Bruce K= orb, Shriram Krishnamurthi, + Bruce Lewis, Tom Lord, Brad Lucier, Dave Mason, David Rush, Klaus Schilli= ng, + Jonathan Sobel, Mike Sperber, Mikael Staldal, Vladimir Tsyshevsky, Donald + Welsh, and Mike Wilson. I am grateful to them for their assistance. +- ++

        +

        + I am also grateful the authors, implementors and documentors of all the + systems mentioned in the introduction. Aubrey Jaffer should be noted for = his + work in producing Web-accessible versions of the R5RS spec, which was a + tremendous aid. +- ++

        +

        + This is not to imply that these individuals necessarily endorse the final + results, of course.=20 +- ++

        +

        + During this document's long development period, great patience was exhibi= ted + by Mike Sperber, who is the editor for the SRFI, and by Hillary Sullivan, + who is not. +- ++

        + +-

        References & links

        ++

        References & links

        +=20 +
        +-
        [Java] ++
        [Java] ++
        +
        +- The following URLs provide documentation on relevant Java classes. ++ The following URLs provide documentation on relevant Java classes. +=20 + http://java.sun.com/products/jdk/1.2/docs/api/java/lang/Chara= cter.html +-
        ++
        + http://java.sun.com/products/jdk/1.2/docs/api/java/lang/String.h= tml +-
        ++
        + http://java.sun.com/products/jdk/1.2/docs/api/java/lang/St= ringBuffer.html +-
        ++
        + http://java.sun.com/products/jdk/1.2/docs/api/java/text/Collat= or.html +-
        ++
        + http://java.sun.com/products/jdk/1.2/docs/api/java/text= /package-summary.html +=20 +-
        [MIT-Scheme] ++ ++
        [MIT-Scheme] ++
        +
        + http://www.s= wiss.ai.mit.edu/projects/scheme/ +=20 +-
        [R5RS]
        +-
        Revised5 report on the algorithmic language Scheme.
        +- R. Kelsey, W. Clinger, J. Rees (editors).
        +- Higher-Order and Symbolic Computation, Vol. 11, No. 1, September, 199= 8.
        +- and ACM SIGPLAN Notices, Vol. 33, No. 9, October, 1998.
        ++
        ++
        [R5RS]
        ++
        Revised5 report on the algorithmic language Scheme.
        ++ R. Kelsey, W. Clinger, J. Rees (editors).
        ++ Higher-Order and Symbolic Computation, Vol. 11, No. 1, September, 199= 8.
        ++ and ACM SIGPLAN Notices, Vol. 33, No. 9, October, 1998.
        + Available at + http://www.schemers.org/Documents/Standards/. +=20 +-
        [SRFI]
        ++ ++
        [SRFI]
        +
        +- The SRFI web site.
        +- http://srfi.schemers.org/ ++ The SRFI web site.
        ++ http://srfi.schemers.org/ +=20 +-
        [SRFI-14]
        ++ ++
        [SRFI-14]
        +
        +- SRFI-14: String libraries.
        +- http://srfi.schemers.or= g/srfi-14/ +- ++ SRFI-14: String libraries.
        ++ http://srfi.schemers.org/srfi-14/ +
        =20=20=20=20 +
        + This document, in HTML: +-
        +- http://srfi.schemers.org/srfi-14/srfi-14.html +- ++ ++
        ++ https://srfi.schemers.org/srfi-14/srfi-14.html ++
        +
        + This document, in plain text format: +-
        +- http://srfi.schemers.org/srfi-14/srfi-14.txt +- ++ ++
        ++ https://srfi.schemers.org/srfi-14/srfi-14.txt ++
        +
        Source code for the reference implementation: ++
        +
        +- +- http://srfi.schemers.org/srfi-14/srfi-14.scm +- ++ ++ https://srfi.schemers.org/srfi-14/srfi-14.scm ++
        +
        Scheme 48 module specification, with typings: ++
        +
        +- +- http://srfi.schemers.org/srfi-14/srfi-14-s48-module.scm +- ++ ++ https://srfi.schemers.org/srfi-14/srfi-14-s48-module.scm ++
        +
        Regression-test suite: +-
        +- http://srfi.schemers.org/srfi-14/srfi-14-tests.scm +- ++ ++
        ++ https://srfi.schemers.org/srfi-14/srfi-14-tests.scm ++
        +
        +
        +=20 +-
        [Unicode] ++
        [Unicode] ++
        +
        + http://www.unicode.org/ +- +-
        [UnicodeData] ++ ++
        [UnicodeData] ++
        +
        +- The Unicode character database.
        ++ The Unicode character database.
        + ftp:= //ftp.unicode.org/Public/UNIDATA/UnicodeData.txt +-
        ++
        + ftp= ://ftp.unicode.org/Public/UNIDATA/UnicodeData.html ++
        +
        +=20 + +-

        Copyright

        ++

        Copyright

        +=20 +

        + Certain portions of this document -- the specific, marked segments of text + describing the R5RS procedures -- were adapted with permission from the R5RS + report. +-=20=20=20=20 ++

        +

        + All other text is copyright (C) Olin Shivers (1998, 1999, 2000).=20 + All Rights Reserved.=20 +- ++

        +

        + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the +@@ -1987,10 +2197,10 @@ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, = WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +

        +- ++
        ++
        Editor: Michael Sperber
        + +- +- ++ +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-16.html b/srfi-doc/sr= fi/scribblings/srfi-std/srfi-16.html +index a335320..81f4963 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-16.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-16.html +@@ -1,57 +1,78 @@ +- +- ++ ++ + ++ ++ + SRFI 16: Syntax for procedures of variable arity ++ ++ + +=20 + +=20 +-

        Title

        ++

        SRFI 16: Syntax for procedures of variable arity.

        +=20 +-SRFI 16: Syntax for procedures of variable arity. ++

        by Lars T Hansen

        ++

        This copy of the SRFI 16 specific= ation document ++is distributed as part of the Racket package ++srfi-doc.

        = The canonical source of this document is ++https://srfi.s= chemers.org/srfi-16/srfi-16.html.

        +=20 +-

        Author

        ++

        Status

        +=20 +-Lars T Hansen +- +-

        Status

        +-This SRFI is currently in ``final'' status. To see an explanation of eac= h status that a SRFI can hold, see here. +-You can access the discussion via the archive of the mailing list. +-

          +-
        • Received: 1999/11/01 +-
        • Draft: 1999/11/06-2000/01/07 +-
        • Final: 2000/03/10 +-
        +- +-

        Abstract

        ++

        This SRFI is currently in final status. Here is an explanation of each stat= us that a SRFI can hold. To provide input on this SRFI, please send email = to srfi-= 16@nospamsrfi.schemers.org. To = subscribe to the list, follow these instructions. You can access previous messages= via the mailing list a= rchive.

        ++
          ++
        • Received: 1999-11-01
        • ++
        • Draft: 1999-11-06--2000-01-07
        • ++
        • Final: 2000-03-10
        • ++
        +=20 ++

        Abstract

        ++

        + CASE-LAMBDA, a syntax for procedures with a variable number of arguments, + is introduced. ++

        +=20 +-

        Rationale

        +- ++

        Rationale

        ++

        + CASE-LAMBDA reduces the clutter of procedures that execute different + code depending on the number of arguments they were passed; it is=20 + a pattern-matching mechanism that matches on the number of arguments. + CASE-LAMBDA is available in some Scheme systems. +- ++

        +

        While CASE-LAMBDA can be implemented as a macro using only facilities + available in R5RS Scheme, it admits considerable implementation-specific + optimization. ++

        +=20 +- +-

        Specification

        ++

        Specification

        +=20 +
        +-
        ++
        + (CASE-LAMBDA <clause> ...) +-
        Syntax ++
        Syntax ++
        +
        +-

        Each <clause> should have the form (<formals> <body>= ), where=20 ++

        Each <clause> should have the form (<formals> <body>= ), where + <formals> is a formal arguments list as for LAMBDA, cf section + 4.1.4 of the R5RS. Each <body> is a <tail-body>, cf secti= on + 3.5 of the R5RS. +- ++

        +

        A CASE-LAMBDA expression evaluates to a procedure that accepts + a variable number of arguments and is lexically scoped in the + same manner as procedures resulting from LAMBDA expressions.=20=20 +@@ -63,10 +84,10 @@ optimization. + locations, the <body> is evaluated in the extended environment, + and the results of <body> are returned as the results of the=20 + procedure call. +- ++

        +

        It is an error for the arguments not to agree with the <formals> + of any <clause>. +- ++

        +
        +              (define plus
        +                (case-lambda=20
        +@@ -85,23 +106,26 @@ optimization.
        +                ((a b) (* a b)))
        +               1 2 3)                    --> error
        + 
        ++
        +
        +=20 +-

        Implementation

        +- ++

        Implementation

        ++

        + The following implementation is written in R5RS Scheme. It is not + compatible with the IEEE Scheme standard because the IEEE standard does + not contain the high-level macro system. +- ++

        +

        The implementation assumes that some top-level names defined by the + R5RS are bound to their original values. +- +-

        ++

        +
        + ;; This code is in the public domain.
        +=20
        + (define-syntax case-lambda
        +   (syntax-rules ()
        ++    ((case-lambda)
        ++     (lambda args
        ++       (error "CASE-LAMBDA without any clauses.")))
        +     ((case-lambda=20
        +       (?a1 ?e1 ...)=20
        +       ?clause1 ...)
        +@@ -135,15 +159,14 @@ R5RS are bound to their original values.
        +       ?clause1 ...))
        +     ((case-lambda "IMPROPER" ?args ?l ?k ?al (?ar ?e1 ...)=20
        +       ?clause1 ...)
        +-     (if (>=3D ?l ?k)
        ++     (if (>=3D ?l ?k)
        +          (apply (lambda ?al ?e1 ...) ?args)
        +          (case-lambda "CLAUSE" ?args ?l=20
        +            ?clause1 ...)))))
        + 
        +=20 +-

        Copyright

        ++

        Copyright

        +

        Copyright (C) Lars T Hansen (1999). All Rights Reserved.

        +- +

        + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the +@@ -167,11 +190,11 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF= OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +

        +=20 +-
        +-
        Editor: Mike Sp= erber
        ++
        ++
        Editor: Mike Sperber
        + + +-Last modified: Mon Apr 19 20:38:48 CEST 2004 ++Last modified: Fri Sep 18 18:34:31 MST 2009 + + + +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-17.html b/srfi-doc/sr= fi/scribblings/srfi-std/srfi-17.html +index dc06d9d..e21b0b6 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-17.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-17.html +@@ -1,41 +1,63 @@ +- +- ++ ++ + ++ ++ + SRFI 17: Generalized set! ++ ++ ++ + +=20 + +=20 +-

        Title

        +- +-SRFI 17: Generalized set! +- +-

        Author

        ++

        SRFI 17: Generalized set!

        +=20 +-Per Bothner ++

        by Per Bothner

        ++

        This copy of the SRFI 17 specific= ation document ++is distributed as part of the Racket package ++srfi-doc.

        = The canonical source of this document is ++https://srfi.s= chemers.org/srfi-17/srfi-17.html.

        +=20 +-

        Status

        ++

        Status

        +=20 +-This SRFI is currently in ``final'' status. To see an explanation of eac= h status that a SRFI can hold, see here. +-You can access the discussion via the archive of the mailing list. +-

          +-
        • Received: 1999/12/08 +-
        • Draft: 2000/01/16-2000/03/17 +-
        • Revised: 2000/04/28 +-
        • Final: 2000/07/24 +-
        +- +-

        Abstract

        ++

        This SRFI is currently in final status. Here is an explanation of each stat= us that a SRFI can hold. To provide input on this SRFI, please send email = to srfi-= 17@nospamsrfi.schemers.org. To = subscribe to the list, follow these instructions. You can access previous messages= via the mailing list a= rchive.

        ++
          ++
        • Received: 1999-12-08
        • ++
        • Draft: 2000-01-16--2000-03-17
        • ++
        • Revised: 2000-04-28
        • ++
        • Final: 2000-07-24
        • ++
        +=20 ++

        Abstract

        ++

        + This is a proposal to allow procedure calls that evaluate + to the "value of a location" to be used to set + the value of the location, when used as the first + operand of set!. + For example: ++

        +
        + (set! (car x) (car y))
        + 
        ++

        + becomes equivalent to ++

        +
        + (set-car! x (car y))
        + 
        +@@ -49,14 +71,16 @@ which can be used in setf and some other = special forms. + However, the Common Lisp concept is based on the idea of + compile-time recognition of special "location-producing" functions; + this does not seem to be in the "spirit of Scheme". ++

        +

        + This SRFI proposes an extension of set! + so that it provides similar functionality as Common Lisp's setf, + except that the updater is associated with a procedure value, + rather than a name. ++

        +=20 +-

        Rationale

        +- ++

        Rationale

        ++

        + There is ample precedent for general "lvalues" on the + left-hand side of an assignment. This includes most statically + typed languages, and many dynamically typed languages (including APL +@@ -66,6 +90,7 @@ Another is that it becomes visually clearer which expres= sion is the new value, + and which are parameters. Also, the visual consistency between + an expression evaluated for its value and one evaluated to yield + a location seems natural to people. ++

        +

        + For most languages, the set of lvalue-producing operators is limited + (typically array indexing and field selection). Some languages have +@@ -77,19 +102,21 @@ mutable variables are first-class "cells", and access= ing the + contents of a cell requires an explicit operator. This is also not + compatible with Scheme. Instead we need to stick to the model + where using a variable in most contexts means using its value, +-but referring to a variable in certain lvalue contexts (lhs of ++but refering to a variable in certain lvalue contexts (lhs of + assignment) refers to its actual location. Sticking to this model + for general "lvalue expressions" in set! means + that "evaluation" must be done differently from normal + evaluation when in an "lvalue context". That is what this proposal does. ++

        +

        + This is a controversial issue. This srfi does not wish to imply that + all Scheme implementations should support this feature; it only + requests that implementations that do implement + generalized set! should be compatible with this srfi. ++

        +=20 +-

        Specification

        +- ++

        Specification

        ++

        + The special form set! is extended so the first operand + can be a procedure application, and not just a variable. + The procedure is typically one that extracts a component from +@@ -97,10 +124,13 @@ some data structure. Informally, when the procedure = is called + in the first operand of set!, it causes the corresponding + component to be replaced by the second operand. + For example, ++

        +
        + (set (vector-ref x i) v)
        + 
        ++

        + would be equivalent to: ++

        +
        + (vector-set! x i v)
        + 
        +@@ -109,12 +139,16 @@ Each procedure that may be used as the first operand= to set! + must have a corresponding "setter" procedure. + The builtin procedure setter takes a procedure and returns t= he + corresponding setter procedure. ++

        +

        + We define: ++

        +
        + (set! (proc arg ...) value)
        + 
        ++

        + as: ++

        +
        + ((setter proc) arg ... value)
        + 
        +@@ -124,9 +158,11 @@ the existing Scheme convention for setter procedures,= where + the new value is given last. For example we can define + (setter car) to be set-car!. + An alternative definition would be: ++

        +
        + ((setter proc) value arg ...) ;; Not the actual definition.
        + 
        ++

        + This definition would work better when you consider + procedures that take a variable number of arguments. + This is because it is straight-forward to add one extra +@@ -135,10 +171,12 @@ argument to the end of an argument list that has + a "rest" parameter, then things get more messy. + However, consistency with the existing new-value-last convention + seems more valuable. ++

        +=20 +-

        Standard setters

        +- ++

        Standard setters

        ++

        + The following standard procedures have pre-defined setters: ++

        +
        + (set! (car x) v) =3D=3D (set-car! x v)
        + (set! (cdr x) v) =3D=3D (set-cdr! x v)
        +@@ -161,20 +199,23 @@ One useful addition:
        + variable-length mutable strings.)
        + -->
        +=20
        +-

        Setting setters; properties

        +- ++

        Setting setters; properties

        ++

        + A setter procedure is a special case of the concept of procedures having + associated properties. Other properties might include + the procedures's name or usage documentation. + As a hypothetical example (i.e. not part of this SRFI), + we can use the Common Lisp documentation function, + where for example: ++

        +
        + (documentation sqrt)
        + 
        ++

        + returns the "documentation string" (if defined) for sqrt. + Such properties should also be settable using generalized set!. + For example: ++

        +
        + (set! (documentation sqrt) "Calculates the square root.")
        + 
        +@@ -184,19 +225,24 @@ This SRFI does + not propose a general "procedure properties" feature, but it + should be compatible with it. It does specify the special case + for the setter property. This is defined such that: ++

        +
        + (set! (setter proc) setter)
        + 
        ++

        + sets the setter procedure associated with proc + to setter. + For example, we can assume ++

        +
        + (set! (setter car) set-car!)
        + 
        ++

        + has been executed by the Scheme prologue. ++

        +=20 +-

        Efficiency Issues

        +- ++

        Efficiency Issues

        ++

        + If (set! (foo ..) ...) is to be the preferred idiom, + we want to make ((setter foo) ...) as efficient + as (set-foo! ...). +@@ -216,32 +262,42 @@ compilation more difficult. However, the next secti= on does define + a way to inherently tie a setter to a procedure, which does reduce + the problem of inlining generalized set! to the + standard inlining problem. ++

        +=20 +-

        getter-with-setter

        ++

        getter-with-setter

        +

        The function getter-with-setter can be used + to define a procedure with associated properties.=20 +-Specifically: ++Specifically: ++

        +
        + (getter-with-setter getter setter)
        + 
        ++

        + This evaluates to a new anonymous procedure which when=20 + applied invokes getter, and whose setter is setter. + It is an error for a program to subsequently try to modify + the setter of the resulting compound. ++

        +

        + For example, we could define: ++

        +
        + (define car (getter-with-setter %primitive-car %primitive-set-car!))
        + (define set-car! %primitive-set-car!)
        + 
        ++

        + The advantage of this approach that whenever a compiler can inline + car, it can also inline (setter car). ++

        +=20 +-

        Implementation

        +- +-Here = is a sample implementation ++

        Implementation

        ++

        ++Here= is a sample implementation + for Twobit. +-

        Here is a sample definition of getter-with-setter: ++

        ++

        ++Here is a sample definition of getter-with-setter: ++

        +
        + (define (getter-with-setter get set)
        +   (let ((proc (lambda args (apply get args))))
        +@@ -249,9 +305,8 @@ for Twobit.
        +     proc))
        + 
        +=20 +-

        Copyright

        ++

        Copyright

        +

        Copyright (C) Per Bothner (1999, 2000). All Rights Reserved.

        +- +

        + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the +@@ -275,11 +330,11 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF= OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +

        +=20 +-
        +-
        Editor: Mike Sp= erber
        ++
        ++
        Editor: Mike Sperber
        + + +-Last modified: Mon Jul 24 12:00:06 MST 2000 ++Last modified: Fri Sep 18 17:00:11 MST 2009 + + + +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-19.html b/srfi-doc/sr= fi/scribblings/srfi-std/srfi-19.html +index b2a612e..c7acadd 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-19.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-19.html +@@ -1,13 +1,32 @@ +- +- ++ ++ + ++ ++ + SRFI 19: Time Data Types and Procedures +- ++ ++ ++ ++ + + +- +- + +=20 + +=20 +-

        Title

        +- +-SRFI 19: Time Data Types and Procedures +- +-

        Author

        +- +-Will Fitzgerald +- +-

        Status

        ++

        SRFI 19: Time Data Types and Procedures

        +=20 +-

        This SRFI is currently in ``final'' status. To see an explanation of +-each status that a SRFI can hold, see here. You can +-access the discussion via +-the archive of the mailing list. ++

        by Will Fitzgerald

        ++

        This copy of the SRFI 19 specific= ation document ++is distributed as part of the Racket package ++srfi-doc.

        = The canonical source of this document is ++https://srfi.s= chemers.org/srfi-19/srfi-19.html.

        +=20 ++

        Status

        +=20 +-
          +-
        • Draft: 2000-02-28 to 2000-08-28
        • +-
        • Final: 2000-08-31
        • +-
        • Fixed reference implementation: 2003-02-28
        • +-
        • Documentation bug for ~D fixed: 2003-05-30
        • +-
        • Various Documentation bugs fixed: 2004-03-15
        • +-
        +- +-

        Abstract

        +- +-Points in time are represented a the number of seconds (with ++

        This SRFI is currently in final status. Here is an explanation of each stat= us that a SRFI can hold. To provide input on this SRFI, please send email = to srfi-= 19@nospamsrfi.schemers.org. To = subscribe to the list, follow these instructions. You can access previous messages= via the mailing list a= rchive.

        ++
          ++
        • Draft: 2000-02-28 to 2000-08-28
        • ++
        • Final: 2000-08-31
        • ++
        • Revised to fix errata: ++
            ++
          • 2003-02-28 (Fixed reference implementation.)
          • ++
          • 2003-05-30 (Fixed documentation bug for ~D.)
          • ++
          • 2004-03-15 (Fixed various documentation bugs.)
          • ++
          • 2017-05-05 (Fixed definition of Julian Day and Modified Julian Da= y.)
          • ++
          • 2019-6-11 (Fixed week number definitions in Table 1. Note that t= his was an incompatible change to the API.)
        ++ ++

        Abstract

        ++

        ++Points in time are represented as the number of seconds (with + nanosecond precision) since "the epoch," a zero point in time. Several + standard variants are defined, including UTC (universal coordinated + time), TAI (international atomic time), and monotonic time. A point in ti= me can also be +@@ -160,45 +177,49 @@ routines are provided. The procedure CURRENT-TIME qu= eries the current + time in a specified variant, with a system-dependent + resolution. Procedures for time arithmetic and time comparisons are + also provided.=20 +- +-

        A date is a representation of a point in time in the Gregorian ++

        ++

        ++A date is a representation of a point in time in the Gregorian + calendar, a 24 hour clock (with nanosecond precision) and a + time zone offset from UTC. Procedures for=20 + converting between time and dates are provided, as well as for reading + and writing string representations of dates. ++

        +=20 +-

        Issues

        [None currently] +- ++

        Issues

        ++

        [None currently]

        +=20 +-

        Rationale

        +=20 ++

        Rationale

        ++

        + R5RS Scheme does not provide standard data types for time. This + SRFI addresses this lack by specifying data types for time and + associated procedures. ++

        +=20 +- +-

        Specification

        ++

        Specification

        +=20 +

        A Time object, which is distinct from all existing types, + defines a point in time or a time duration in some standard time +-system. The standard time systems are: +- ++system. The standard time systems are: ++

        +
          +
        • Universal Coordinated Time (UTC), +-
        • International Atomic Time (TAI), +-
        • monotonic time (a monotonically increasing point in time from some ++
        • International Atomic Time (TAI), ++
        • monotonic time (a monotonically increasing point in time from = some + epoch, which is implementation-dependent),=20 +-
        • CPU time in current thread (implementation dependent), +-
        • CPU time in current process (implementation dependent), +-
        • Time duration. +-
        +- ++
      • CPU time in current thread (implementation dependent), ++
      • CPU time in current process (implementation dependent), ++
      • Time duration. ++
      • ++

        + Implementations are required to implement UTC, monotonic time, CPU + time in current process, and time duration. Implementations are + allowed to create extensions (for example, amount of time spent in + garbage collection). +- +-

        A time object consists of three components:= =20 ++

        ++

        A time object consists of three compone= nts: ++

        +
          +
        • Time type, a symbol representing the time system + representation used. The constants TIME-TAI, +@@ -207,100 +228,110 @@ garbage collection). + TIME-DURATION must be provided for these + symbols. Implementations should provide constants for time type + extensions.=20=20 +-
        • Second, an integer representing the number ++
        • Second, an integer representing the number + of whole seconds from "the epoch."=20=20 +-
        • Nanosecond, an ++
        • Nanosecond, an + integer of the number of nanoseconds in the fractional + portion. Although a time object has nanosecond precision, clocks + may have a lower resolution. +-
        ++ +=20 +-

        A Date object, which is distinct fro= m all existing ++

        A Date object, which is distinct from all exi= sting + types, represents a point in time as represented by the Gregorian + calendar as well as by a time zone. Dates are immutable. A date + consists of the following components: +-=20=20 ++

        +
          +
        • Nanosecond, an integer between 0 and 9,999,999, inclusive. +-
        • Second, an integer 0 and 60, inclusive,=20 ++
        • ++
        • Second, an integer 0 and 60, inclusive, + (60 represents a leap second) ++
        • +
        • Minute, an integer between 0 and 59, inclusive, ++
        • +
        • Hour, an integer between 0 and 23, inclusive, ++
        • +
        • Day, an integer between 0 and 31, inclusive, the upper limit d= epending + on the month and year of the point in time, ++
        • +
        • Month, an integer between 1 and 12, inclusive; in which 1 means + January, 2 February, and so on. ++
        • +
        • Year, an integer representing the year. ++
        • +
        • Time zone, an integer representing the number of seconds east = of GMT for this timezone. ++
        • +
        ++

        ++A Julian Day represents a point in time as a real number of days=20 ++since -4713-11-24T12:00:00Z (midday UT on 24 November 4714 BC in the=20 ++proleptic Gregorian calendar (1 January 4713 BC in the proleptic Julian = calendar)). ++

        ++

        ++A Modified Julian Day represents a point in time as a real number = of ++days since 1858-11-17T00:00:00Z (midnight UT on 17 November AD 1858). ++

        +=20 +-

        A Julian Day represents a point in time as a real number +-of days since -4714-11-24T12:00:00Z (November 24, -4714 at noon, +-UTC). +- +-

        A Modified Julian Day represents a point in time as a +-real number of days since 1858-11-17T00:00:00Z (November 17, +-1858 at midnight, UTC). +- +-

        Constants

        +-

        The following constants are required:=20 +- +-

        +-
        t= ime-duration=20 +-
        Symbol representing Time duration. +-
        = time-monotonic +-
        Symbol representing monotonic time. +-
        ti= me-process +-
        Symbol representing time spent in current process. +-
        time-t= ai +-
        Symbol representing TAI time. +-
        tim= e-thread +-
        Symbol representing time spent in current thread. +-
        time-u= tc +-
        Symbol representting UTC time. +-
        +-

        Current time and clock resolution

        +-

        The following procedures are required: +- +-

        +-
        cu= rrent-date [tz-offset] -> date +-
        Date corresponding to the current UTC time.=20 +-
        current-julian-day -> jdn +-
        Current Julian Day. +-
        current-modified-julian-day -> mjdn +-
        Current Modified Julian Day. +-
        cu= rrent-time [time-type] -> time +-
        Current time, of type time-type syste= m, which defaults to TIME-UTC. +-
        time-resolution [time-type] -> integer +-
        Clock resolution, in nanoseconds, of the system cl= ock of type type time-type system, which defaults to TIM= E-UTC. +-
        +-

        Time object and accessors

        +-

        The following procedures are required: +-

        +-
        make-= time type nanosecond second -> time +-
        Creates a time object. +-
        time? object -> boolean +-
        #t if object is a time object, otherw= ise, #f. +-
        time-= type time -> time-type +-
        Time type. +-
        time-nanosecond time -> integer +-
        Time nanosecond. +-
        tim= e-second time -> integer +-
        Time second. +-
        = set-time-type! time time-type +-
        Changes time type. Note: This changes the semantic= s of the time object. To convert a time to another ++

        Constants

        ++

        The following constants are required: ++

        ++
        ++
        ti= me-duration ++
        Symbol representing Time duration. ++
        time-monotonic ++
        Symbol representing monotonic time. ++
        time-process ++
        Symbol representing time spent in current p= rocess. ++
        ti= me-tai ++
        Symbol representing TAI time. ++
        time-thread ++
        Symbol representing time spent in current t= hread. ++
        ti= me-utc ++
        Symbol representing UTC time. ++
        ++

        Current time and clock resolution

        ++

        The following procedures are required: ++

        ++
        ++
        cur= rent-date [tz-offset] -> date ++
        Date corresponding to the current UTC time.= =20 ++
        current-julian-day -> jdn ++
        Current Julian Day. ++
        current-modified-julian-day -> mjdn ++
        Current Modified Julian Day. ++
        current-time [time-type] -> time ++
        Current time, of type time-type system, which defaults to TIME-UTC. ++
        time-resolution [time-type] -> integer ++
        Clock resolution, in nanoseconds, of the sy= stem clock of type type time-type system, which defaults to TIME-UTC. ++
        ++

        Time object and accessors

        ++

        The following procedures are required: ++

        ++
        ++
        make-t= ime type nanosecond second -> time ++
        Creates a time object. ++
        time= ? object -> boolean ++
        #t if object is a time object,= otherwise, #f. ++
        t= ime-type time -> time-type ++
        Time type. ++
        time-nanosecond time -> integer ++
        Time nanosecond. ++
        time-second time -> integer ++
        Time second. ++
        set-time-type! time time-type ++
        Changes time type. Note: This changes the s= emantics of the time object. To convert a time to another + system of representation, use one of the conversion = procedures. +-
        set-time-nanosecond! time integer +-
        Changes time nanosecond. +-
        set-time-second! time integer +-
        Changes time second. +-
        copy-= time time1 -> time2 +-
        Creates a new time object, with the same time type= , nanosecond, and second as time1. +-
        ++
        set-time-nanosecond! time integer ++
        Changes time nanosecond. ++
        set-time-second! time integer ++
        Changes time second. ++
        c= opy-time time1 -> time2 ++
        Creates a new time object, with the same ti= me type, nanosecond, and second as time1. ++
        +=20 +-

        Time comparison procedures

        ++

        Time comparison procedures

        +=20 +-

        All of the time comparison procedures require the time objects to ++

        All of the time comparison procedures require the time objects to + be of the same type. It is an error to use these procedures on time + objects of different types. For the point-in-time measurements (e.g., + TIME-TAI and TIME-UTC), the semantics are +@@ -308,243 +339,259 @@ described in plain text. For durations, (e.g., + TIME-DURATION, TIME-CPU, the semantics are + described in parentheses. +=20 +-

        The following procedures are required: +-

        +-
        time= <=3D? time1 time2 -> boolean +-
        #t if time1 is before or a= t (less than or equal to) time2, #f otherwise.=20 +-
        time<= ;? time1 time2 -> boolean +-
        #t if time1 is before (les= s than) time2, #f otherwise.=20 +-
        time= =3D? time1 time2 -> boolean +-
        #t if time1 at (equal) time2, #f otherwise.=20 +-
        =3D-p">time= >=3D? time1 time2 -> boolean +-
        #t if time1 is at or after= (greater than or equal to) time2, #f otherwise.=20 +-
        -p">time>= ;? time1 time2 -> boolean +-
        #t if time1 is after (grea= ter than) time2, #f otherwise.=20 +-
        +- +-

        Time arithmetic procedures

        +- +-

        The following procedures are required. +-

        +-
        time-difference time1 time2 -> time-duration +-
        The TIME-DURATION between time1<= /VAR> and time2. It is an error if time1 and tim= e2 are of different time types. A new time object is created. +-
        time-difference! time1 time2 -> time-duration<= /VAR> +-
        The TIME-DURATION between time1<= /VAR> and time2. It is an error if time1 and tim= e2 are of different time types. Time1 may be used to creat= e the resulting TIME-DURATION object. +-
        ad= d-duration time1 time-duration -> time +-
        The time resulting from adding time-duration<= /VAR> to time1, which is a time object of the same time type as= time1. A new time object is created. +-
        a= dd-duration! time1 time-duration -> time +-
        The time resulting from adding time-duration<= /VAR> to time1, which is a time object of the same time type as= time1. Time1 may used to create the resulting time = object. +-
        subtract-duration time1 time-duration -> time= +-
        The time resulting from subtracting time-dura= tion to time1, which is a time object of the same time ty= pe as time1. A new time object is created. +-
        subtract-duration! time1 time-duration -> ti= me +-
        The time resulting from subtracting time-dura= tion to time1, which is a time object of the same time ty= pe as time1. Time1 may used to create the resulting = time object. +-
        +- +-

        Date object and accessors

        +- +-

        Date objects are immutable once created. The following procedures are = required. +-

        +- +-
        make-= date nanosecond second minute hour day month year zone-offs= et -> date +-
        Creates a date object. +-
        date? date -> boolean +-
        #t if object is a time object, otherw= ise, #f. +-
        date-nanosecond date -> integer +-
        Date nanosecond. +-
        dat= e-second date -> integer +-
        Date second. +-
        dat= e-minute date -> integer +-
        Date minute. +-
        date-= hour date -> integer +-
        Date hour. +-
        date-d= ay date -> integer +-
        Date day. +-
        date= -month date -> integer +-
        Date month. +-
        date-= year date -> integer +-
        Date year. +-
        date-zone-offset date -> integer +-
        Date time zone offset. +-
        d= ate-year-day date -> integer +-
        The ordinal day of the year of this date. January = 1 is 1, etc. +-
        d= ate-week-day date -> integer +-
        The day of the week of this date, where Sunday=3D0= , Monday=3D1, etc. +-
        date-week-number date day-of-week-starting-week -> = integer +-
        The ordinal week of the year which holds this date= , ignoring a first partial week. 'Day-of-week-starting-week' is the integer= corresponding to the day of the week which is to be considered the first d= ay of the week (Sunday=3D0, Monday=3D1, etc.). +-
        +- +-

        Time/Date/Julian Day/Modified Julian Day Converters

        ++

        The following procedures are required: ++

        ++
        ++
        ti= me<=3D? time1 time2 -> boolean ++
        #t if time1 is befo= re or at (less than or equal to) time2, #f otherwis= e.=20 ++
        = time<? time1 time2 -> boolean ++
        #t if time1 is befo= re (less than) time2, #f otherwise.=20 ++
        t= ime=3D? time1 time2 -> boolean ++
        #t if time1 at (equ= al) time2, #f otherwise.=20 ++
        time>=3D? time1 time2 -> boolean ++
        #t if time1 is at o= r after (greater than or equal to) time2, #f otherw= ise.=20 ++
        = time>? time1 time2 -> boolean ++
        #t if time1 is afte= r (greater than) time2, #f otherwise.=20 ++
        ++ ++

        Time arithmetic procedures

        ++ ++

        The following procedures are required. ++

        ++
        ++
        = time-difference time1 time2 -> time-duration ++
        The TIME-DURATION between time1 and time2. It is an error if time1 and <= var>time2 are of different time types. A new time object is created. ++
        time-difference! time1 time2 -> time-durati= on ++
        The TIME-DURATION between time1 and time2. It is an error if time1 and <= var>time2 are of different time types. Time1 may be used t= o create the resulting TIME-DURATION object. ++
        add-duration time1 time-duration -> time ++
        The time resulting from adding time-du= ration to time1, which is a time object of the same time = type as time1. A new time object is created. ++
        add-duration! time1 time-duration -> time ++
        The time resulting from adding time-du= ration to time1, which is a time object of the same time = type as time1. Time1 may used to create the resultin= g time object. ++
        subtract-duration time1 time-duration -> t= ime ++
        The time resulting from subtracting ti= me-duration to time1, which is a time object of the same = time type as time1. A new time object is created. ++
        subtract-duration! time1 time-duration -> time ++
        The time resulting from subtracting ti= me-duration to time1, which is a time object of the same = time type as time1. Time1 may used to create the res= ulting time object. ++
        ++ ++

        Date object and accessors

        ++ ++

        Date objects are immutable once created. The following procedures are = required. ++

        ++
        ++
        make-d= ate nanosecond second minute hour day month year zone-offset -> date ++
        Creates a date object. ++
        date= ? date -> boolean ++
        #t if object is a time object,= otherwise, #f. ++
        date-nanosecond date -> integer ++
        Date nanosecond. ++
        date-second date -> integer ++
        Date second. ++
        date-minute date -> integer ++
        Date minute. ++
        d= ate-hour date -> integer ++
        Date hour. ++
        da= te-day date -> integer ++
        Date day. ++
        = date-month date -> integer ++
        Date month. ++
        d= ate-year date -> integer ++
        Date year. ++
        date-zone-offset date -> integer ++
        Date time zone offset. ++
        date-year-day date -> integer ++
        The ordinal day of the year of this date. J= anuary 1 is 1, etc. ++
        date-week-day date -> integer ++
        The day of the week of this date, where Sun= day=3D0, Monday=3D1, etc. ++
        date-week-number date day-of-week-starting-week -&g= t; integer ++
        The ordinal week of the year which holds th= is date, ignoring a first partial week. 'Day-of-week-starting-week' is the = integer corresponding to the day of the week which is to be considered the = first day of the week (Sunday=3D0, Monday=3D1, etc.). ++
        ++ ++

        Time/Date/Julian Day/Modified Julian Day Converters

        +=20 + The following conversion procedures are required. +-
        +-
        julian-day= ">date->julian-day date -> jd +-
        Convert date to Julian Day. +-
        modified-j= ulian-day">date->modified-julian-day date -> mjd= +-
        Convert date to Modified Julian Day. +-
        time-monot= onic">date->time-monotonic date -> time-monotoni= c +-
        Convert date to monotonic time. +-
        time-tai">= date->time-tai date -> time-tai +-
        Convert date to TAI time. +-
        time-utc">= date->time-utc date -> time-utc +-
        Convert date to UTC time. +-
        date= ">julian-day->date jd [tz-offset] -> date +-
        Convert Julian Day to date, , using time zone offs= et, which defaults to the local time zone. +-
        time= -monotonic">julian-day->time-monotonic jd -> tim= e-monotonic +-
        Convert Julian Day to monotonic time. +-
        time= -tai">julian-day->time-tai jd -> time-tai +-
        Convert Julian Day to TAI time. +-
        time= -utc">julian-day->time-utc jd -> time-utc +-
        Convert Julian Day to UTC time. +-
        date">modified-julian-day->date mjd [tz-off= set] -> date +-
        Convert Modified Julian Day to date, using time zo= ne offset, which defaults to the local time zone. +-
        time-monotonic">modified-julian-day->time-monotonic mj= d -> time-monotonic +-
        Convert Modified Julian Day to monotonic time. +-
        time-tai">modified-julian-day->time-tai mjd -> <= VAR>time-tai +-
        Convert Modified Julian Day to TAI time. +-
        time-utc">modified-julian-day->time-utc mjd -> <= VAR>time-utc +-
        Convert Modified Julian Day to UTC time. +-
        = date">time-monotonic->date time-monotonic [tz-of= fset] -> date +-
        Convert monotonic time to date, using time zone of= fset, which defaults to the local time zone. +-
        = julian-day">time-monotonic->julian-day time-monotonic= -> jd +-
        Convert monotonic time to Julian Day. +-
        = modified-julian-day">time-monotonic->modified-julian-day ti= me-monotonic -> mjd +-
        Convert monotonic time to Modified Julian Day. +-
        = time-tai">time-monotonic->time-tai time-monotonic -> = time-tai +-
        Convert monotonic time to TAI time. +-
        = time-tai!">time-monotonic->time-tai! time-monotonic -= > time-tai +-
        Convert monotonic time to TAI time. The time struc= ture may be reused. +-
        = time-utc">time-monotonic->time-utc time-monotonic -> = time-utc +-
        Convert monotonic time to UTC time. +-
        = time-utc!">time-monotonic->time-utc! time-monotonic -= > time-utc +-
        Convert monotonic time to UTC time. The time stru= cture may be reused. +-
        date">= time-tai->date time-tai [tz-offset] -> date +-
        Convert TAI time to date, using time zone offset, = which defaults to the local time zone. +-
        julian= -day">time-tai->julian-day time-tai -> jd +-
        Convert TAI time to Julian Day. +-
        modifi= ed-julian-day">time-tai->modified-julian-day time-tai= -> mjd +-
        Convert TAI time to Modified Julian Day. +-
        time-m= onotonic">time-tai->time-monotonic time-tai -> t= ime-monotonic +-
        Convert TAI time to monotonic time. +-
        time-m= onotonic!">time-tai->time-monotonic! time-tai -> time-monotonic +-
        Convert TAI time to monotonic time. The time struc= ture may be reused. +-
        time-u= tc">time-tai->time-utc time-tai -> time-utc +-
        Convert TAI time to monotonic time. +-
        time-u= tc!">time-tai->time-utc! time-tai -> time-utc +-
        Convert TAI time to monotonic time. The time struc= ture may be reused. +-
        date">= time-utc->date time-utc [tz-offset] -> time-utc<= /VAR> +-
        Convert UTC time to date, using time zone offset, = which defaults to the local time zone. +-
        julian= -day">time-utc->julian-day time-utc -> jd +-
        Convert UTC time to Julian Day +-
        modifi= ed-julian-day">time-utc->modified-julian-day time-utc= -> mjd +-
        Convert UTC time to Modified Julian Day. +-
        time-m= onotonic">time-utc->time-monotonic time-utc -> t= ime-monotonic +-
        Convert UTC time to monotonic time. +-
        time-m= onotonic!">time-utc->time-monotonic! time-utc -> time-monotonic +-
        Convert UTC time to monotonic time. The time struc= ture may be reused. +-
        time-t= ai">time-utc->time-tai time-utc -> time-tai +-
        Convert UTC time to TAI time. +-
        time-t= ai!">time-utc->time-tai! time-utc -> time-tai +-
        Convert UTC time to TAI time. The time structure m= ay be reused. +-
        +- +-

        Date to String/String to Date Converters

        ++
        ++
        date->julian-day date -> jd ++
        Convert date to Julian Day. ++
        date->modified-julian-day date ->= mjd ++
        Convert date to Modified Julian Day. ++
        date->time-monotonic date -> tim= e-monotonic ++
        Convert date to monotonic time. ++
        date->time-tai date -> time-tai ++
        Convert date to TAI time. ++
        date->time-utc date -> time-utc ++
        Convert date to UTC time. ++
        julian-day->date jd [tz-offset] -= > date ++
        Convert Julian Day to date, , using time zo= ne offset, which defaults to the local time zone. ++
        julian-day->time-monotonic jd ->= time-monotonic ++
        Convert Julian Day to monotonic time. ++
        julian-day->time-tai jd -> time-= tai ++
        Convert Julian Day to TAI time. ++
        julian-day->time-utc jd -> time-= utc ++
        Convert Julian Day to UTC time. ++
        modified-julian-day->date mjd [= tz-offset] -> date ++
        Convert Modified Julian Day to date, using = time zone offset, which defaults to the local time zone. ++
        modified-julian-day->time-monotonic <= var>mjd -> time-monotonic ++
        Convert Modified Julian Day to monotonic ti= me. ++
        modified-julian-day->time-tai mjd -> time-tai ++
        Convert Modified Julian Day to TAI time. ++
        modified-julian-day->time-utc mjd -> time-utc ++
        Convert Modified Julian Day to UTC time. ++
        time-monotonic->date time-monotonic [tz-offset] -> date ++
        Convert monotonic time to date, using time = zone offset, which defaults to the local time zone. ++
        time-monotonic->julian-day time-monotonic= -> jd ++
        Convert monotonic time to Julian Day. ++
        time-monotonic->modified-julian-day <= var>time-monotonic -> mjd ++
        Convert monotonic time to Modified Julian D= ay. ++
        time-monotonic->time-tai time-monotonic -> time-tai ++
        Convert monotonic time to TAI time. ++
        time-monotonic->time-tai! time-monotonic -> time-tai ++
        Convert monotonic time to TAI time. The tim= e structure may be reused. ++
        time-monotonic->time-utc time-monotonic -> time-utc ++
        Convert monotonic time to UTC time. ++
        time-monotonic->time-utc! time-monotonic -> time-utc ++
        Convert monotonic time to UTC time. The ti= me structure may be reused. ++
        time-tai->date time-tai [tz-offset] -> = date ++
        Convert TAI time to date, using time zone o= ffset, which defaults to the local time zone. ++
        time-tai->julian-day time-tai -> jd ++
        Convert TAI time to Julian Day. ++
        time-tai->modified-julian-day time-tai= -> mjd ++
        Convert TAI time to Modified Julian Day. ++
        time-tai->time-monotonic time-tai -&g= t; time-monotonic ++
        Convert TAI time to monotonic time. ++
        time-tai->time-monotonic! time-tai -= > time-monotonic ++
        Convert TAI time to monotonic time. The tim= e structure may be reused. ++
        time-tai->time-utc time-tai -> time= -utc ++
        Convert TAI time to monotonic time. ++
        time-tai->time-utc! time-tai -> = time-utc ++
        Convert TAI time to monotonic time. The tim= e structure may be reused. ++
        time-utc->date time-utc [tz-offset] -> = time-utc ++
        Convert UTC time to date, using time zone o= ffset, which defaults to the local time zone. ++
        time-utc->julian-day time-utc -> jd ++
        Convert UTC time to Julian Day ++
        time-utc->modified-julian-day time-utc= -> mjd ++
        Convert UTC time to Modified Julian Day. ++
        time-utc->time-monotonic time-utc -&g= t; time-monotonic ++
        Convert UTC time to monotonic time. ++
        time-utc->time-monotonic! time-utc -= > time-monotonic ++
        Convert UTC time to monotonic time. The tim= e structure may be reused. ++
        time-utc->time-tai time-utc -> time= -tai ++
        Convert UTC time to TAI time. ++
        time-utc->time-tai! time-utc -> = time-tai ++
        Convert UTC time to TAI time. The time stru= cture may be reused. ++
        ++ ++

        Date to String/String to Date Converters

        +=20 + These procedures provide conversion to and from strings. They are require= d. The specification below describes a 'locale;' the + specification of locales is beyond this SRFI. +=20 +-
        +-
        string">da= te->string date [format-string] -> st= ring +-
        Converts a date to a string, using the format stri= ng. The format string is copied as is; except +-escape characters (indicated by the tilde) are replaced with specific con= versions. Table 1 lists the required conversion specifiers; +-implementations are free to extend this list. +-
        date">st= ring->date input-string template-string -> date<= /VAR> +-
        Converts an input string to a date, using the temp= late string. The input string must match the template +-sting as is; except escape characters (indicate by the tilde) indicate sp= ecial converters which (1) move to the next character in the input string f= ulfilling a criterion; (2) read a value, and (3) act on this value in some = way. Table 2 lists the required=20 +-converters; implementations are free to extend this list. +-
        +- +-

        PLT-specific extensions

        +- +-

        The ~? wildcard is specific to the PLT implementation of = string->date: it parses 1 and 2 digit years like ~y and 3 and 4 digit years like ~Y.

        +- +-
        0009 HORIZONTAL TABULATION \t control-I <= /td>
        0020 SPACE Zs
        00A0 NO-BREAK SPACE Zs
        STRING conversion = specifiers"> +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +-<= /TR> +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +-

        ChConversion

        ~~a literal ~
        ~alocale's abbre= viated weekday name (Sun...Sat)
        ~Alocale's full = weekday name (Sunday...Saturday)
        ~blocale's abbre= viate month name (Jan...Dec)
        ~Blocale's full = month day (January...December)
        ~clocale's date = and time (e.g., "Fri Jul 14 20:28:42-0400 2000")
        ~dday of month, = zero padded (01...31)
        ~Ddate (mm/dd/yy= )
        ~eday of month, = blank padded ( 1...31)
        ~fseconds+fracti= onal seconds, using locale's decimal separator (e.g. 5.2).
        ~hsame as ~b
        ~Hhour, zero pad= ded, 24-hour clock (00...23)
        ~Ihour, zero pad= ded, 12-hour clock (01...12)
        ~jday of year, z= ero padded
        ~khour, blank pa= dded, 24-hour clock (00...23)
        ~lhour, blank pa= dded, 12-hour clock (01...12)
        ~mmonth, zero pa= dded (01...12)
        ~Mminute, zero p= added (00...59)
        ~nnew line
        ~Nnanosecond, ze= ro padded
        ~plocale's AM or= PM
        ~rtime, 12 hour = clock, same as "~I:~M:~S ~p"
        ~snumber of full= seconds since "the epoch" (in UTC)
        ~Ssecond, zero p= added (00...60)
        ~thorizontal tab=
        ~Ttime, 24 hour = clock, same as "~H:~M:~S"
        ~Uweek number = of year with Sunday as first day of week (00...53)
        ~Vweek number of= year with Monday as first day of week (01...52)
        ~w day of week (= 0...6)
        ~Wweek number = of year with Monday as first day of week (01...52)
        ~xweek number = of year with Monday as first day of week (00...53)
        ~Xlocale's date = representation, for example: "07/31/00"
        ~ylast two digit= s of year (00...99)
        ~Yyear
        ~ztime zone in R= FC-822 style
        ~Zsymbol time zo= ne (not-implemented)
        ~1ISO-8601 year-= month-day format
        ~2ISO-8601 hour-= minute-second-timezone format
        ~3ISO-8601 hour-= minute-second format
        ~4ISO-8601 year-= month-day-hour-minute-second-timezone format
        ~5ISO-8601 year-= month-day-hour-minute-second format

        Table 1: DATE->STRING conversion speci= fiers

        +- +-

        +-DATE conversion = specifiers"> +- +- +- +-<= /TR> +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +-= +- +- +- +-

        ChSkip toReadSet

        ~~anyread literal ~nothing
        ~achar-alphabeti= c?abbreviated weekday in localenothing
        ~Achar-alphabeti= c?full weekday in localenothi= ng
        ~bchar-alphabeti= c?abbreviated month name in localenothing
        ~Bchar-alphabeti= c?full month name in localeno= thing
        ~dchar-numeric?<= /TD>day of monthdate-day
        ~eanyday of month, blank paddeddate-day=
        ~hchar-alphabeti= c?same as ~bnothing
        ~Hchar-numeric?<= /TD>hourdate-hour
        ~kanyhour, blank paddeddate-hour=
        ~mchar-numeric?<= /TD>monthdate-month
        ~Mchar-numeric?<= /TD>minutedate-minute=
        ~Schar-numeric?<= /TD>seconddate-second=
        ~yany2-digit yeardate-year withi= n 50 years
        ~Ychar-numeric?<= /TD>yeardate-year
        ~zanytime zonedate-zone-offset
        ~?char-numeric?<= /TD>2-digit or 4-digit year (PLT-specific extension)date-year

        Table 2: STRING->DATE conversion speci= fiers

        +- +-

        Implementation

        ++
        ++
        = date->string date [format-string] -> string ++
        ++
        ++

        ++ Converts a date to a string, using the format string. The format st= ring ++ is copied as is; except escape characters (indicated by the tilde) = are ++ replaced with specific conversions. Table 1 lists the required ++ conversion specifiers; implementations are free to extend this list. ++

        ++
        ++
        = string->date input-string template-string -> d= ate ++
        ++
        ++

        ++ Converts an input string to a date, using the template string. The = input ++ string must match the template sting as is; except escape characters ++ (indicate by the tilde) indicate special converters which (1) move = to ++ the next character in the input string fulfilling a criterion; (2) = read ++ a value, and (3) act on this value in some way. Table 2 lists the ++ required converters; implementations are free to extend this list. ++

        ++

        PLT-specific extension: The ~? wildcard is ++specific to the PLT implementation of string->date: ++it parses 1 and 2 digit years like ~y and 3 and 4 ++digit years like ~Y.

        ++
        ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++<= /tr> ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++

        ChConversion

        ~~a literal ~
        ~alocale's abbre= viated weekday name (Sun...Sat)
        ~Alocale's full = weekday name (Sunday...Saturday)
        ~blocale's abbre= viate month name (Jan...Dec)
        ~Blocale's full = month day (January...December)
        ~clocale's date = and time (e.g., "Fri Jul 14 20:28:42-0400 2000")
        ~dday of month, = zero padded (01...31)
        ~Ddate (mm/dd/yy= )
        ~eday of month, = blank padded ( 1...31)
        ~fseconds+fracti= onal seconds, using locale's decimal separator (e.g. 5.2).
        ~hsame as ~b
        ~Hhour, zero pad= ded, 24-hour clock (00...23)
        ~Ihour, zero pad= ded, 12-hour clock (01...12)
        ~jday of year, z= ero padded
        ~khour, blank pa= dded, 24-hour clock ( 0...23)
        ~lhour, blank pa= dded, 12-hour clock ( 1...12)
        ~mmonth, zero pa= dded (01...12)
        ~Mminute, zero p= added (00...59)
        ~nnew line
        ~Nnanosecond, ze= ro padded
        ~plocale's AM or= PM
        ~rtime, 12 hour = clock, same as "~I:~M:~S ~p"
        ~snumber of full= seconds since "the epoch" (in UTC)
        ~Ssecond, zero p= added (00...60)
        ~thorizontal tab=
        ~Ttime, 24 hour = clock, same as "~H:~M:~S"
        ~Uweek number = of year with Sunday as first day of week (00...53)
        ~VISO 8601 week = number of the year with Monday as first day of week (01..53)[1]
        ~w day of week (= 0...6)
        ~Wweek number = of year with Monday as first day of week (01...52)
        ~xlocale's date = representation[1]
        ~Xlocale's time = representation[1]
        ~ylast two digit= s of year (00...99)
        ~Yyear
        ~ztime zone in R= FC-822 style
        ~Zsymbol time zo= ne (not-implemented)
        ~1ISO-8601 year-= month-day format
        ~2ISO-8601 hour-= minute-second-timezone format
        ~3ISO-8601 hour-= minute-second format
        ~4ISO-8601 year-= month-day-hour-minute-second-timezone format
        ~5ISO-8601 year-= month-day-hour-minute-second format

        Table 1: DATE->STRING conversion sp= ecifiers

        ++ ++

        [1] Th= ese lines were changed as part of a fix to errata on 2009-06-11.

        ++ ++ ++ ++ ++ ++<= /tr> ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++char-numeric?<= /tr> ++ ++ ++ ++

        ChSkip toReadSet

        ~~anyread literal ~nothing
        ~achar-alphabeti= c?abbreviated weekday in localenothing
        ~Achar-alphabeti= c?full weekday in localenothi= ng
        ~bchar-alphabeti= c?abbreviated month name in localenothing
        ~Bchar-alphabeti= c?full month name in localeno= thing
        ~dchar-numeric?<= /td>day of monthdate-day
        ~eanyday of month, blank paddeddate-day=
        ~hchar-alphabeti= c?same as ~bnothing
        ~Hchar-numeric?<= /td>hourdate-hour
        ~kanyhour, blank paddeddate-hour=
        ~mchar-numeric?<= /td>monthdate-month
        ~Mchar-numeric?<= /td>minutedate-minute=
        ~Schar-numeric?<= /td>seconddate-second=
        ~yany2-digit yeardate-year withi= n 50 years
        ~Ychar-numeric?<= /td>yeardate-year
        ~zanytime zonedate-zone-offset
        ~?2-digit or 4-digit year = (PLT-specific extension)date-year

        Table 2: STRING->DATE conversion sp= ecifiers

        ++ ++

        Implementation

        +=20 + This SRFI cannot be written in completely standard Scheme. In + particular, there must be some system-independent method of finding +@@ -553,34 +600,31 @@ the values for CURRENT-TIME. The GNU C = function, +=20 +

        The difference between TAI and UTC is not determinate, and + implementations must provide some method for getting TAI. A procedure +-is provided in the accompany implmentation for reading the leap second ++is provided in the accompany implementation for reading the leap second + table provided by the Time Service of the US Naval Observatory +-(available at ftp://maia.usno.navy.m= il/ser7/tai-utc.dat).=20 +- +-

        The accompanying implementation assumes SRFI 6 Basic String Ports. +-The accompanying implementation also assumes an error +-procedure. The accompanying implementation also assumes SRFI 8 RECEIVE: Binding to ++(available at ftp:/= /maia.usno.navy.mil/ser7/tai-utc.dat). ++ ++

        The accompanying implementation assumes SR= FI 6 Basic String Ports. ++The accompanying implementation also assumes an error ++procedure. The accompanying implementation also assumes SRFI 8 RECEIVE: Binding to + multiple values. which is easy to implement with the following + syntax: +- +- +-

        ++

        ++
        + (define-syntax receive
        +   (syntax-rules ()
        +     ((receive formals expression body ...)
        +      (call-with-values (lambda () expression)
        +                        (lambda formals body ...)))))
        +-
        +-
        +- +-

        Note that it contains TAI-UTC.DAT reader. ++

        +=20 +-

        The accompany= ing=20 ++

        ++Note that it contains TAI-UTC.DAT reader. ++

        ++

        ++The accompanying + implementation is written in MzScheme. MzScheme provides the procedu= re=20 +-current-seconds, which returns the number of seconds (UTC) ++current-seconds, which returns the number of seconds (UTC) + since 1970-01-01T00:00:00Z+00:00, and + current-milliseconds, which is a monotonic time + clock. Combining these provides an implementation of +@@ -590,46 +634,51 @@ UTC are resolved through a leap second table. Accord= ing to the + International Earth Rotation Service, there will be no leap second in + December, 2000. Thus, the leap second table is guaranteed to be + correct through June, 2000.=20 +- +-

        Also, MzScheme (as of version 102, I believe) provides a method for ++

        ++

        ++Also, MzScheme (as of version 102, I believe) provides a method for + returning the current time zone offset, via its SECONDS->DATE and +-CURRENT-DATE procedures.=20 +- +-

        MzScheme's DEFINE-STRUCT was used to define the time +-and date objects. SRFI 9, Defining Record ++CURRENT-DATE procedures. ++

        ++

        ++MzScheme's DEFINE-STRUCT was used to define the time ++and date objects. SRFI 9, Defining Record + Types, could be used instead. +- +-

        Procedures meant to be used internally have names beginning with ++

        ++

        ++Procedures meant to be used internally have names beginning with + TM:. Locale-related constants and procedures have + locale in their name; if a 'locale' SRFI is ever written, + it might be good to use that code instead. ++

        ++

        ++From this, the rest of the implementation was built. ++

        ++

        ++There is also a test suite. ++

        +=20 +-

        From this, the rest of the implementation was built.=20 +- +-

        There is also a test suite. +- +-

        Acknowledgements

        +- +-Claus T=C3=B8ndering's Frequently Asked Questions about calendars was a very ++

        Acknowledgements

        ++

        ++Claus ++T=C3=B8ndering's = Frequently Asked Questions about calendars was a very + useful resource. The implementation of Julian Day, Modified Julian +-Day, and Year Day comes from his FAQ. Markus Kuhn has a useful +-description of the ISO Standard 8601 for +-Date/Time notation; The W3 Consortium also has a useful Note. +- +-

        Mike Sperber, Marc Feely, Dave Mason, and "Prfnoff" all made useful ++Day, and Year Day comes from his FAQ. Markus Kuhn has a useful ++description of the ISO= Standard 8601 for ++Date/Time notation; The W3 Consortium also has a useful Note. ++

        ++

        ++Mike Sperber, Marc Feeley, Dave Mason, and "Prfnoff" all made useful + comments on previous versions of this draft. Thanks to Shriram=20 + Krishnamurthi for his editing help. +- +-

        The DATE->STRING procedure uses a format string, based on ++

        ++

        ++The DATE->STRING procedure uses a format string, based on + GNU C's date procedure, as well as scsh's + FORMAT-DATE procedure.=20 ++

        +=20 +- +-

        Copyright

        ++

        Copyright

        +=20 +

        Copyright (C) Neodesic Corporation (2000). All Rights Reserved.

        +=20 +@@ -656,11 +705,11 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF= OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +

        +=20 +-
        ++
        +=20 +-
        Editor: Shrira= m=20 +-Krishnamurthi
        ++
        Editor: Shriram=20 ++Krishnamurthi
        + Last=20 +-modified by the author:
        (display (date->string (current-date 0) +-"~4")): 2004-03-15T02:21:15Z +- ++modified by the author:
        (display (date->string (current-dat= e 0) ++"~4")): 2017-05-05T21:42:17Z ++ +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-2.html b/srfi-doc/srf= i/scribblings/srfi-std/srfi-2.html +index 18b6ba7..3c51824 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-2.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-2.html +@@ -1,38 +1,70 @@ +- +- +- SRFI 2: AND-LET*: an AND with local bindings, a guarded LE= T* special form ++ ++ ++ ++ ++ ++ SRFI 2: AND-LET*: an AND with local bindings, a guarded LET* s= pecial form ++ ++ ++ ++ +=20 + +-

        Title

        +- +-SRFI-2: AND-LET*: an AND with local bindings, a guarded LET* special form +- +-

        Author

        +- +-Oleg Kiselyov +- +-

        Status

        +-This SRFI is currently in ``final'' status. To see an explanation of eac= h status that a SRFI can hold, see here. +-You can access the discussion on this SRFI via the archive of the mailing lis= t. +-

          +-
        • Received: 1998/12/28 +-
        • Revised: 1999/02/09 +-
        • Draft: 1998/12/28-1999/02/28 +-
        • Final: 1999/03/01 +-
        +- +-

        Abstract

        +- +-

        Like an ordinary AND, an AND-LET* special form evaluates its arguments= -- ++

        SRFI 2: AND-LET*: an AND with local bindings, a guarded LET* special = form

        ++ ++

        by Oleg Kiselyov

        ++

        This copy of the SRFI 2 specifica= tion document ++is distributed as part of the Racket package ++srfi-doc.

        = The canonical source of this document is ++https://srfi.sch= emers.org/srfi-2/srfi-2.html.

        ++ ++

        Status

        ++ ++

        This SRFI is currently in final status. Here is an explanation of each stat= us that a SRFI can hold. To provide input on this SRFI, please send email = to srfi-2= @nospamsrfi.schemers.org. To su= bscribe to the list, follow these instructions. You can access previous messages v= ia the mailing list arch= ive.

        ++
          ++
        • Received: 1998-12-28 ++
        • Revised: 1999-02-09 ++
        • Draft: 1998-12-28--1999-02-28 ++
        • Final: 1999-03-01 ++
        • Revised to fix errata: ++
            ++
          • 2020-06-08 (Fixed: Variables bound by AND-LET* needn't ++ be unique. This requirement was based on the mistaken ++ impression that LET* imposed that requirement, which it ++ doesn't. Also, updated link to sample implementation to ++ point to a more recent version by Oleg.)
          • ++
          • 2020-10-26 (Clarified what is meant by BODY in (and-let* ++ (CLAWS) BODY).)
        • ++
        ++ ++

        Abstract

        ++ ++

        Like an ordinary AND, an AND-LET* special form evaluates its arguments= -- + expressions -- one after another in order, till the first one that + yields #f. Unlike AND, however, a non-#f result of one expression can + be bound to a fresh variable and used in the subsequent expressions. + AND-LET* is a cross-breed between LET* and AND. ++

        +=20 +-

        Rationale

        ++

        Rationale

        +=20 +-

        In case of an ordinary AND formed of proper boolean expressions:
        +-(AND E1 E2 ...)
        ++

        In case of an ordinary AND formed of proper boolean expressions:
        ++(AND E1 E2 ...)
        + expression E2, if it gets to be evaluated, knows that E1 has returned + non-#f. Moreover, E2 knows exactly what the result of E1 was -- #t -- + which E2 can use to its advantage. If E1 however is an extended +@@ -44,8 +76,8 @@ not an #f, and throws it away. If E2 needs it, it has to= compute that + value anew. This proposed AND-LET* special form lets constituent + expressions get hold of the results of already evaluated expressions, + without re-doing their work. +- +-

        AND-LET* can be thought of as a combination of LET* and AND, or a ++

        ++

        AND-LET* can be thought of as a combination of LET* and AND, or a + generalization of COND's send operator =3D>. An AND-LET* form can also= be + considered a sequence of guarded expressions. In a regular program, + forms may produce results, bind them to variables and let other forms +@@ -53,21 +85,23 @@ use these results. AND-LET* differs in that it checks = to make sure that + every produced result "makes sense" (that is, not an #f). The first + "failure" triggers the guard and aborts the rest of the sequence + (which presumably would not make any sense to execute anyway). +- ++

        ++

        + Examples: +-

        ++

        ++
        + (AND-LET* ((my-list (compute-list)) ((not (null? my-list))))
        +-          (do-something my-list))
        ++    (do-something my-list))
        +=20
        + (define (look-up key alist)
        +   (and-let* ((x (assq key alist))) (cdr x)))
        +=20
        + (or
        +-  (and-let* ((c (read-char))
        +-    ((not (eof-object? c))))
        +-    (string-set! some-str i c)=20=20
        +-    (set! i (+ 1 i)))
        +-  (begin (do-process-eof)))
        ++ (and-let* ((c (read-char))
        ++            ((not (eof-object? c))))
        ++     (string-set! some-str i c)
        ++   (set! i (+ 1 i)))
        ++ (begin (do-process-eof)))
        +=20
        + 			; A more realistic example
        +                         ; Parse the 'timestamp' ::=3D 'token1' 'token2'
        +@@ -88,47 +122,48 @@ Examples:
        +                    (string-ref token2 2) (string-ref token2 3))))
        +              ((positive? timestamp)))
        +            timestamp))
        +-
        +- +-

        ++

        ++

        + AND-LET* is also similar to an "anaphoric AND" LISP macro [Rob Warnock, + comp.lang.scheme, 26 Feb 1998 09:06:43 GMT, Message-ID: + 6d3bb3$3804h@fido.asd.sgi.com]. AND-LET* allows however more than one + intermediate result, each of which continues to be bound through the + rest of the form. ++

        +=20 ++

        Specification

        +=20 +-

        Specification

        +- +-

        Syntax and Informal Semantics

        ++

        Syntax and Informal Semantics

        +=20 +-
        ++
        + AND-LET* (CLAWS) BODY
        +=20
        + CLAWS ::=3D '() | (cons CLAW CLAWS)
        + CLAW  ::=3D  (VARIABLE EXPRESSION) | (EXPRESSION) |
        +            BOUND-VARIABLE
        +-
        ++
        +=20 +-
          +-
        • The CLAWS are evaluated in the strict left-to-right order +-
        • For each CLAW, the EXPRESSION part is evaluated first (or BOUND-VARIA= BLE is looked up) +-
        • If the result is #f, AND-LET* immediately returns #f +-
        • Otherwise, if the CLAW is of the form (VARIABLE EXPRESSION) ++
            ++
          • The CLAWS are evaluated in the strict left-to-right order ++
          • For each CLAW, the EXPRESSION part is evaluated first (or BOUND-= VARIABLE is looked up) ++
          • If the result is #f, AND-LET* immediately returns #f ++
          • Otherwise, if the CLAW is of the form (VARIABLE EXPRESSION) + the EXPRESSION's value is bound to a freshly made VARIABLE +-
          • The VARIABLE is available for the rest of the CLAWS , and the BODY +-
          • As usual, all VARIABLEs must be unique (like in let*) +-
          ++
        • The VARIABLE is available for the rest of the CLAWS , and the BO= DY ++
        • As usual, all VARIABLEs must be unique (like in let*) ++
        • BODY is a body as in a LET* form.
        • ++ ++
        +=20 +-

        Formal (Denotational) Semantics

        ++

        Formal (Denotational) Semantics

        +=20 +-
        ++
        + eval[ (AND-LET* (CLAW1 ...) BODY), env] =3D
        +    eval_claw[ CLAW1, env ] andalso
        +    eval[ (AND-LET* ( ...) BODY), ext_claw_env[CLAW1, env]]
        +=20
        + eval[ (AND-LET* (CLAW) ), env] =3D eval_claw[ CLAW, env ]
        +-eval[ (AND-LET* () FORM1 ...), env] =3D eval[ (BEGIN FORM1 ...), env ]
        ++eval[ (AND-LET* () FORM1 ...), env] =3D eval[ (LET* () FORM1 ...), env ]
        + eval[ (AND-LET* () ), env] =3D #t
        +=20
        + eval_claw[ BOUND-VARIABLE, env ] =3D
        +@@ -144,21 +179,15 @@ ext_claw_env[ (EXPRESSION), env ] =3D
        + ext_claw_env[ (VARIABLE EXPRESSION), env ] =3D
        +    extend-env[ env-after-eval[ EXPRESSION, env ],
        +               VARIABLE boundto eval[ EXPRESSION, env ]]
        +-
        +- +-

        Implementation

        ++
        ++

        Implementation

        +=20 +-

        The full implementation plus the validation code are available here (which is a = copy of +- +-http://pobox.com/~oleg/ftp/Scheme/vland.scm). +- +-

        This is an implementation of AND-LET* as a (Gambit) low-level macro th= at +-re-writes AND-LET* as a "tree" of AND and LET forms. A validation code is +-also presented, which verifies not only that everything works as +-expected, but also that AND-LET* finds syntax errors where expected. +- +-

        Copyright

        ++

        A full sample implementation is available at http://okmij.org/ftp/= Scheme/lib/myenv-chez.scm. The test suite is at http://okmij.org/ftp/= Scheme/tests/vland.scm. ++

        ++

        Copyright

        ++

        + Copyright (C) Oleg Kiselyov (1998). All Rights Reserved.=20 ++

        +

        + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the +@@ -182,14 +211,13 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF= OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +

        +=20 +-
        +-
        Editor: Dave M= ason
        ++
        ++
        Editor: Dave Mason
        + +-

        ++

        + +-Last modified: Wed Feb 6 17:21:57 MET 2002 ++Last modified: Sun Jan 28 13:40:28 MET 2007 + +- +- +- ++

        ++ +=20 +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-23.html b/srfi-doc/sr= fi/scribblings/srfi-std/srfi-23.html +index 8ac31ca..ae2545c 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-23.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-23.html +@@ -1,44 +1,57 @@ +- +- ++ ++ + ++ ++ + SRFI 23: Error reporting mechanism ++ ++ ++ + +=20 + +=20 +-

        Title

        ++

        SRFI 23: Error reporting mechanism

        +=20 +-SRFI 23: Error reporting mechanism ++

        by Stephan Houben

        ++

        This copy of the SRFI 23 specific= ation document ++is distributed as part of the Racket package ++srfi-doc.

        = The canonical source of this document is ++https://srfi.s= chemers.org/srfi-23/srfi-23.html.

        +=20 +-

        Author

        ++

        Status

        +=20 +-Stephan Houben ++

        This SRFI is currently in final status. Here is an explanation of each stat= us that a SRFI can hold. To provide input on this SRFI, please send email = to srfi-23 @nospamsrfi.schemers.org. To subscribe to the list, follow these instructions. You can access previous = messages via the mailing list archive.

        ++
          ++
        • Draft: 2001-03-09--2001-06-09
        • ++
        • Revised: 2001-03-22 ++
        • Revised: 2001-04-26 ++
        +=20 +-

        Status

        +=20 +-This SRFI is currently in ``final'' status. To see an explanation of +-each status that a SRFI can hold, see here.=20=20 +-You can access +-the discussion via +- +-the archive of the mailing list. +-

        +-

          +-
        • Draft: 2001/03/09-2001/06/09
        • +-
        • Revised: 2001/03/22 +-
        • Revised: 2001/04/26 +-
        +-

        +- +-

        Abstract

        ++

        Abstract

        +=20 + A mechanism is proposed to allow Scheme code to report errors and abort + execution. + The proposed mechanism is already implemented in several Scheme systems + and can be implemented, albeit imperfectly, in any R5RS conforming Scheme. +=20 +-

        Rationale

        ++

        Rationale

        +=20 +

        + R5RS Scheme requires certain operations to signal an error when they fail. +@@ -46,14 +59,14 @@ R5RS Scheme requires certain operations to signal an e= rror when they fail. + the error. + Moreover, R5RS encourages, but not requires,=20 + implementations to signal an error in many more circumstances. +- ++

        +

        + However, there is no direct way for the Scheme application programmer to = report +-an error that occurred in his or her own application.=20 ++an error that occured in his or her own application.=20 + This means that Scheme procedures created by applications or libraries are + in this respect not on equal footing with procedures provided by the + Scheme system. +- ++

        +

        + Many Scheme systems already provide a mechanism that allows application c= ode + to report an error. At least the following implementations support +@@ -63,80 +76,96 @@ Of these implementations, the following have an error = mechanism compatible + with this SRFI: Guile, MIT Scheme, PLT Scheme, RScheme, Scsh. + The implementation in SLIB has a different name than the + one proposed in this SRFI. +- ++

        +

        + To summarise, many implementations already have the error reporting + mechanism described in this SRFI and others are easily made compatible + with this SRFI. This shows that the proposed mechanism is considered usef= ul + and that it is easy to implement in most major implementations. ++

        +=20 +-

        Specification

        ++

        Specification

        +=20 +

        + The following procedure should be provided: +-

        ++

        ++

        + (error <reason> [<arg1> [<arg2> ...]= ]) ++

        +

        + The argument <reason> should be a string. + The procedure error will signal an error, + as described in R5RS, and it will report the message <reason> +-and the objects <arg1>, <arg2>, ....=20 ++and the objects <arg1>, <arg2>, ....=20 + What exactly constitutes "signalling" and "reporting" is not prescribed, = because of the large variation in Scheme systems. So it is left to the impl= ementor + to do something reasonable. To that end, a few examples of possible behav= iour + are given. ++

        +
          +
        1. + Display <reason> and <arg1>... on the screen and terminate + the Scheme program. (This might be suitable for a Scheme system + implemented as a batch compiler.) +-
        2. =20=20 ++
        3. ++
        4. + Display <reason> and <arg1>... on the screen and=20=20 + go back to the read-evaluate-print loop. (This might be suitable for + an interactive implementation). ++
        5. +
        6. + In the case of a multi-threaded system: terminate the current + thread, but do not terminate the other threads. Possibly make the + arguments to error available to other threads in some + way. See the thread-join! mechanism in SRFI-18 on + how this could be done. ++
        7. +
        8. + Package <reason> and <arg1>... up into an error object + and pass this error object to an exception handler. The default + exception handler then might do something as described in points 1 to 3. ++
        9. +
        10. + In the case of a Scheme system that runs completely unattended + and that has no way to notify a human, the only reasonable + course of action might be to do nothing at all. However, this should + be considered a last resort. Clearly, if all implementors would choose + this strategy, this SRFI would not be very useful. +-
        =20=20 ++
      • ++ ++

        + An implementation might report more information than just=20 + <reason> and <arg1>... . For instance, it might report the pr= ocedure name in which + the error occurred or even print a stack trace. + However, this will require additional support in the Scheme implementatio= n. ++

        +=20 ++

        Why error is a procedure

        +=20 +-

        Why error is a procedure

        +- ++

        + It is conceivable to allow error to be a special form, + such as a macro, rather than a procedure. This might make providing + information such as the source code location easier. This possibility + has been considered, but rejected, for two reasons. ++

        +
          +
        1. + Since error accepts a variable number of arguments, + it could occasionally be useful to use apply to call + error. However, this is not possible if error + was allowed to be a special form. ++
        2. +
        3. + Since error is currently a procedure in all Scheme + implementations mentioned above, it doesn't seem all that + worthwhile to allow it to be a special form. ++
        4. +
        +=20 +-

        Implementation

        ++

        Implementation

        +=20 ++

        + An implementation that works in almost any R5RS Scheme is the following: ++

        +
        +   (define (error reason . args)
        +       (display "Error: ")
        +@@ -148,36 +177,42 @@ An implementation that works in almost any R5RS Sche=
        me is the following:
        +       (newline)
        +       (scheme-report-environment -1))  ;; we hope that this will signal a=
        n error
        + 
        ++

        + This implementation has a flaw, + namely, in many implementations this + will actually print 2 messages. ++

        +
          +
        1. The message message, followed by objs, and +-
        2. A message about scheme-report-environment getting an i= nvalid argument.=20 +-
        =20 ++ ++
      • A message about scheme-report-environment getting an i= nvalid argument. ++
      • ++ ++

        + This might be confusing to the user. +- ++

        +

        + The SLIB pr= ocedure slib:error works like the error + procedure described in this document. + Thus, when SLIB is loaded, error can be defined as: ++

        +
        +   (define error slib:error)
        + 
        =20=20 +- +

        +-If SRFI 18 is supported= , it is allowed=20 ++If SRFI 18 is supporte= d, it is allowed=20 + (but not required) to implement error in + terms of the exception mechanism of SRFI 18. ++

        +
        +   (define (error reason . args)
        +     (raise (make-error-exception reason args)))
        + 
        ++

        + Here, make-error-exception is implementation dependent. +- +-

        Copyright

        ++

        ++

        Copyright

        +

        Copyright (C) Stephan Houben (2001). All Rights Reserved.

        +- +

        + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the +@@ -200,13 +235,11 @@ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WH= ETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +

        +- +-
        +-
        Editor: Mike Sperber ++
        ++
        Editor: Mike Sperber
        + + +-Last modified: Mon Feb 4 14:46:29 MET 2002 ++Last modified: Sun Jan 28 13:40:28 MET 2007 + + + +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-25.html b/srfi-doc/sr= fi/scribblings/srfi-std/srfi-25.html +index 4d81d03..000adb1 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-25.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-25.html +@@ -1,36 +1,50 @@ +- +- ++ ++ + ++ ++ + SRFI 25: Multi-dimensional Array Primitives ++ ++ ++ + +=20 + +=20 +-

        Title

        ++

        SRFI 25: Multi-dimensional Array Primitives

        +=20 +-SRFI 25: Multi-dimensional Array Primitives ++

        by Jussi Piitulainen

        ++

        This copy of the SRFI 25 specific= ation document ++is distributed as part of the Racket package ++srfi-doc.

        = The canonical source of this document is ++https://srfi.s= chemers.org/srfi-25/srfi-25.html.

        +=20 +-

        Author

        ++

        Status

        +=20 +-Jussi Piitulainen ++

        This SRFI is currently in final status. Here is an explanation of each stat= us that a SRFI can hold. To provide input on this SRFI, please send email = to srfi-25 @nospamsrfi.schemers.org. To subscribe to the list, follow these instructions. You can access previous = messages via the mailing list archive.

        ++
          ++
        • Draft: 2001-11-12--2002-01-11
        • ++
        • Revised: 2002-02-03
        • ++
        • Final: 2002-05-21
        • ++
        +=20 +-

        Status

        +=20 +-This SRFI is currently in ``final'' status. To see an explanation of +-each status that a SRFI can hold, see here. You can ac= cess +-the discussion via +- +-the archive of the mailing list. +-

        +-

          +-
        • Draft: 2001/11/12-2002/01/11
        • +-
        • Revised: 2002/02/03
        • +-
        • Final: 2002/05/21
        • +-
        +-

        +- +-

        Abstract

        ++

        Abstract

        +=20 +

        + A core set of procedures for creating and manipulating heterogeneous +@@ -45,7 +59,7 @@ The specification is based on an original contribution b= y Alan Bawden + in 1993. +

        +=20 +-

        Rationale

        ++

        Rationale

        +=20 +

        + The proposed arrays encourage a natural declarative programming +@@ -108,7 +122,7 @@ It is not required that vectors not be arrays. It is n= ot required that + they be, either. +

        +=20 +-

        Specification

        ++

        Specification

        +=20 +

        + Arrays are heterogeneous data structures whose elements are indexed by +@@ -141,8 +155,8 @@ alternately the lower and upper bounds for the dimensi= ons of an array. + The following ten procedures should be implemented. +

        +=20 +-

        +-(array? obj)
        =20 ++

        ++(array? obj)
        +=20 + Returns #t if obj is an array, otherwise + returns #f. +@@ -150,14 +164,14 @@ returns #f. +=20 +

        + Note: there is no reasonable way to implement this procedure +-accurately in R5RS; SRFI ++accurately in R5RS; SRFI + 9 (Defining Record Types) specifies a way, and many Scheme + implementations provide something similar. +

        +=20 +-

        +-(make-array shape)
        +-(make-array shape obj)
        ++

        ++(make-array shape)
        ++(make-array shape obj)
        +=20 + Returns a newly allocated array whose shape is given by + shape. If obj is provided, then each element is +@@ -166,8 +180,8 @@ unspecified. The array does not retain a dependence to + shape. +

        +=20 +-

        +-(shape bound ...)
        =20 ++

        ++(shape bound ...)
        +=20 + Returns a shape. The sequence bound ... must consist of an + even number of exact integers that are pairwise not decreasing. Each +@@ -190,42 +204,42 @@ corresponding upper bound, where k satisf= ies + (< k d). +

        +=20 +-

        +-(array shape obj ...)
        ++

        ++(array shape obj ...)
        +=20 + Returns a new array whose shape is given by shape and the + initial contents of the elements are obj ... in row major + order. The array does not retain a dependence to shape. +

        +=20 +-

        +-(array-rank array)
        ++

        ++(array-rank array)
        +=20 + Returns the number of dimensions of array. ++

        +
        +     (array-rank
        +        (make-array (shape 1 2 3 4)))
        + 
        +- +

        + Returns 2. +

        +=20 +-

        +-(array-start array k)
        ++

        ++(array-start array k)
        +=20 + Returns the lower bound for the index along dimension k. +

        +=20 +-

        +-(array-end array k)
        ++

        ++(array-end array k)
        +=20 + Returns the upper bound for the index along dimension k. +

        +=20 + +=20 +-

        +-(array-ref array k ...)
        +-(array-ref array index)
        ++

        ++(array-ref array k ...)
        ++(array-ref array index)
        +=20 + Returns the contents of the element of array at index + k .... The sequence k ... must be a valid index +@@ -280,30 +294,29 @@ Returns cuatro. + Returns (3 1 4). +

        +=20 +-

        +-(array-set! array k ... obj)
        +-(array-set! array index obj)
        ++

        ++(array-set! array k ... obj)
        ++(array-set! array index obj)
        +=20 + Stores obj in the element of array at index + k .... Returns an unspecified value. The sequence k + ... must be a valid index to array. In the second + form, index must be either a vector or a 0-based + 1-dimensional array containing k .... +- ++

        +
        +     (let ((a (make-array
        +                 (shape 4 5 4 5 4 5))))
        +        (array-set! a 4 4 4 'huuhkaja)
        +        (array-ref a 4 4 4))
        + 
        +- +

        + Returns huuhkaja. +

        +=20 +-

        ++

        + (share-array array shape proc) +-
        =20 ++
        +=20 + Returns a new array of shape shape that shares elements of + array through proc. The procedure +@@ -351,7 +364,7 @@ This document does not specify when arrays are e= qual?. + (Indeed, R5RS equal? will do the wrong thing.) +

        +=20 +-

        Examples

        ++

        Examples

        +=20 +

        + The reference implementation comes with a number of files that +@@ -361,36 +374,33 @@ in testing an implementation; that is their= origin). +=20 +

          +=20 +-
        1. A library arl= ib.scm that contains, among ++
        2. A library ar= lib.scm that contains, among + several other things, tabulate-array for a more + useful initialization of a new array, an + array-equal?, and a transpose that can + permute the dimensions of an array any which way. +=20 +-
        3. A test suite t= est.scm for array, +- and another test suite list.scm for ++
        4. A test suite test.scm for array, ++ and another test suite list.scm for + arlib. +=20 +-
        5. A rudimentary display procedure (play array) in play.scm, for= playing around with the system. ++
        6. A rudimentary display procedure (play array) in play.scm, for play= ing around with the system. +=20 +-
        ++ +=20 +-

        Implementation

        ++

        Implementation

        +=20 +

        + A portable reference implementation is provided. It uses a minimal +-error reporting mechanism that conforms to SRFI 23 (Error reporting ++error reporting mechanism that conforms to SRFI = 23 (Error reporting + mechanism). Type disjointness requires support from the host +-implementation, such as support for SRFI 9 (Defining Record ++implementation, such as support for SRFI 9 (D= efining Record + Types). All names not defined in this proposal are in the prefix + "array:", which serves as a module system. +

        +=20 +

        +-You can get source for the reference ++You can get source for the reference + implementation as a single file and stop reading. But there are + variations. This single file represents arrays as procedures (so the + type predicate is very approximate); it represents index mapping as +@@ -410,18 +420,18 @@ consists of the following parts, each in its own fil= e. + type disjointness, or portable as procedures, in a file + as-*.scm, and +=20 +-

      • indexing operations to match the type, in a file ++
      • indexing operations to match the type, in a file + ix-*.scm, and +=20 +-
      • an affine recogniser of one of three types, optimised ++
      • an affine recogniser of one of three types, optimised + up to some number of dimensions, in a file op-*.scm, and +=20 +-
      • the main source file array.scm. ++
      • the main source file array.scm. +=20 +- ++
      • +=20 +

        +-Affine recognisers are made by a program opt.scm ++Affine recognisers are made by a program opt.scm + but one of each type is also available here, optimized for 0, 1, 2 and + 3 dimensions. Choose one type: pick a recogniser with matching index + procedures; load as-, ix- and op- and +@@ -430,36 +440,34 @@ procedures; load as-, ix- and = op- and +=20 +

          +=20 +-
        1. In the mbda= type representation, index ++
        2. In the mbd= a type representation, index + mappings are procedures that accept an optional argument. The +- matching ac= cess procedures apply the ++ matching a= ccess procedures apply the + mapping to the arguments of array-ref and + array-set!. +=20 +-
        3. In the tter= type representation, index ++
        4. In the tter type representation, index + mappings are pairs of procedures: one takes exactly the indices, +- the other takes indices and an object. The matching access procedu= res apply the first ++ the other takes indices and an object. The matching access procedures apply the f= irst + procedure to the argumets of array-ref and the + second procedure to the arguments of array-set!. +=20 +-
        5. In ctor= representation, index mappings +- are coefficient vectors. The access ++
        6. In ct= or representation, index mappings ++ are coefficient vectors. The access + procedures compute the sum of products of coefficients and + indexes in a loop on the list. +=20 +-
        ++ +=20 +

        +-Record implementations are available for +-generic Scheme (arrays are not disjoint from procedures), for SRFI 9= (Defining Record Types) +-(not tested), and for PLT ++Record implementations are available for ++generic Scheme (arrays are not disjoint from procedures), for SRFI 9 (Def= ining Record Types) ++(not tested), and for PLT + Scheme (arrays belong to a struct type). +

        +=20 +

        +-With the three files from above, the main source ++With the three files from above, the main source + file should work in any Scheme implementation without need of + modification. +

        +@@ -471,7 +479,7 @@ code. (Sharing uses a check that is exponential in the= number of + dimensions. It is disabled above a threshold rank.) +

        +=20 +-

        Acknowledgements

        ++

        Acknowledgements

        +=20 +

        + The original concept comes from a message to the Usenet newsgroup +@@ -490,11 +498,10 @@ wording, hidden shapes, and two kinds of index objec= ts. +=20 +

        + The exact title of the proposal comes from a message titled "a proc= ess that might work" by William D. Clinger to the rrrs-authors +-mailing list in 1998. That appears to be a part of the past of the SRFI process. ++mailing list in 1998. That appears to be a part of the past of the SRFI process. +

        +=20 +-

        Copyright

        ++

        Copyright

        +

        Copyright (C) Jussi Piitulainen (2001). All Rights Reserved.

        +=20 +

        +@@ -520,12 +527,11 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF= OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +

        +=20 +-
        +-
        Editor: Mike Sperber ++
        ++
        Editor: Mike Sperber
        + + +-Last modified: Tue May 28 18:46:09 MST 2002 ++Last modified: Sun Jan 28 13:40:29 MET 2007 + + + +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-26.html b/srfi-doc/sr= fi/scribblings/srfi-std/srfi-26.html +index a6cf487..0d6d83e 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-26.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-26.html +@@ -1,39 +1,54 @@ +- +- ++ ++ + ++ ++ + SRFI 26: Notation for Specializing Parameters without Currying= ++ ++ ++ + +=20 + +=20 +-

        Title

        ++

        SRFI 26: Notation for Specializing Parameters without Currying

        +=20 +-SRFI 26: Notation for Specializing Parameters without Currying ++

        by Sebastian Egner

        ++

        This copy of the SRFI 26 specific= ation document ++is distributed as part of the Racket package ++srfi-doc.

        = The canonical source of this document is ++https://srfi.s= chemers.org/srfi-26/srfi-26.html.

        +=20 +-

        Author

        ++

        Status

        +=20 +-Sebastian Egner ++

        This SRFI is currently in final status. Here is an explanation of each stat= us that a SRFI can hold. To provide input on this SRFI, please send email = to srfi-= 26@nospamsrfi.schemers.org. To = subscribe to the list, follow these instructions. You can access previous messages= via the mailing list a= rchive.

        ++
          ++
        • Draft: 2002-02-06--2002-04-06
        • ++
        • Revised: 2002-02-15
        • ++
        • Revised: 2002-02-28
        • ++
        • Revised: 2002-06-04
        • ++
        • Revised: 2002-06-06
        • ++
        • Final: 2002-06-14
        • ++
        +=20 +-

        Status

        +- +-This SRFI is currently in ``final'' status. To see an explanation of +-each status that a SRFI can hold, see here. You can ac= cess +-the discussion via +- +-the archive of the mailing list. +- +-
          +-
        • Draft: 2002/02/06-2002/04/06
        • +-
        • Revised: 2002/02/15
        • +-
        • Revised: 2002/02/28
        • +-
        • Revised: 2002/06/04
        • +-
        • Revised: 2002/06/06
        • +-
        • Final: 2002/06/14
        • +-
        +- +-

        Abstract

        ++

        Abstract

        +=20 ++

        + When programming in functional style, + it is frequently necessary to specialize some of the + parameters of a multi-parameter procedure. +@@ -41,40 +56,41 @@ For example, from the binary operation cons + one might want to obtain the unary operation=20 + (lambda (x) (cons 1 x)). + This specialization of parameters is also known as +-"partial application", "operator section" or "projection".

        +- ++"partial application", "operator section" or "projection". ++

        ++

        + The mechanism proposed here allows to write this sort + of specialization in a simple and compact way. +-The mechanism is best explained by a few examples:

        +- +- +- +- +- +- +- +- +- +- +- +- +-
        (cut cons (+ a 1) <>)=20 +-is the same as +-(lambda (x2) (cons (+ a 1) x2)) +-
        (cut list 1 <> 3 <> 5)=20 +-is the same as +-(lambda (x2 x4) (list 1 x2 3 x4 5)) +-
        (cut list)=20 +-is the same as +-(lambda () (list)) +-
        (cut list 1 <> 3 <...>)=20 +-is the same as +-(lambda (x2 . xs) (apply list 1 x2 3 xs)) +-
        (cut <> a b)=20 +-is the same as +-(lambda (f) (f a b)) +-

        +- ++The mechanism is best explained by a few examples: ++

        ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++
        (cut cons (+ a 1) <>)is the same as(lambda (x2) (cons (+ a 1) x2))
        (cut list 1 <> 3 <> 5)is the same as(lambda (x2 x4) (list 1 x2 3 x4 5))
        (cut list)is the same as(lambda () (list))
        (cut list 1 <> 3 <...>)is the same as(lambda (x2 . xs) (apply list 1 x2 3 xs))
        (cut <> a b)is the same as(lambda (f) (f a b))
        ++

        + As you see, the macro cut specializes some of the=20 + parameters of its first argument.=20 + The parameters that are to show up as formal +@@ -83,27 +99,29 @@ pronouced as "slot". In addition, the symbol <= ;...>, + pronounced as "rest-slot", matches all residual arguments of a variable=20 + argument procedure. + As you can see from the last example above, the first argument can also +-be a slot, as one should expect in Scheme.

        +- ++be a slot, as one should expect in Scheme. ++

        ++

        + In addition to cut, there is a variant called cute + (a mnemonic for "cut with evaluated non-slots") which evalua= tes + the non-slot expressions at the time the procedure is specialized, not at= =20 + the time the specialized procedure is called. +-For example,

        +- +- +- +- +-
        (cute cons (+ a 1) <>)=20 +-is the same as +-(let ((a1 (+ a 1))) (lambda (x2) (cons a1 x2))) +-

        +- ++For example, ++

        ++ ++ ++ ++ ++ ++ ++
        (cute cons (+ a 1) <>)is the same as(let ((a1 (+ a 1))) (lambda (x2) (cons a1 x2)))
        ++

        + As you see from comparing this example with the first example above, + the cute-variant will evaluate (+ a 1) + once, while the cut-variant will evaluate it during +-every invokation of the resulting procedure.

        +- ++every invokation of the resulting procedure. ++

        ++

        + The mechanism proposed in this SRFI allows specializing any subset=20 + of the variables of a procedure. + The result can be of fixed arity or of variable arity. +@@ -111,11 +129,13 @@ The mechanism does not allow permutation, omission, = duplication + or any other processing of the arguments; + for this it is necessary to write to use a different + mechanism such as lambda. ++

        +=20 +-

        Rationale

        ++

        Rationale

        +=20 ++

        + A particularly elegant way to deal with specialization is known=20 +-as currying (Schönfinkel 1924, Curry 1958). ++as currying (Sch=C3=B6nfinkel 1924, Curry 1958). + The idea of currying is to reduce multi-argument functions to + single-argument functions by regarding an n-ary=20 + function as a unary function mapping its first argument into=20 +@@ -123,8 +143,9 @@ an (n-1)-ary function (which is curried in turn= ). + This point of view, apart from its theoretical elegance,=20 + allows an extremely compact notation for specializing the=20 + first argument of a function. +-In the first example, one could simply write (cons 1).

        +- ++In the first example, one could simply write (cons 1). ++

        ++

        + Yet, Scheme is not a curried language---the + number of arguments passed to a procedure must match + the number of its parameters at all times. +@@ -135,73 +156,91 @@ and invent some irrelevant identifiers for its + formal variables (x in the example). + For this reason, the mechanism proposed in this SRFI=20 + provides a simple and compact notation for specializing +-any subset of the parameters of a procedure.

        +- +-Note: The mechanism proposed here is not currying!

        +- ++any subset of the parameters of a procedure. ++

        ++

        ++Note: The mechanism proposed here is not currying! ++

        ++

        + The purpose of the mechanism proposed here is to make the benefits + of currying available within the programming language Scheme. + There are two primary benefits of currying in practice: + Higher-order types are substantially simplified and + there is a simple notation for specializing parameters. + The type aspect is irrelevant as Scheme has latent typing. +-The specialization aspect is largly covered with this SRFI.

        +- ++The specialization aspect is largly covered with this SRFI. ++

        ++

        + Here are a few more examples for illustration: ++

        ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++
        (map (cut * 2 <>) '(1 2 3 4))
        (map (cut vector-set! x <> 0) indices)
        (for-each (cut write <> port) exprs)
        (map (cut <> x y z) (list min max))
        (for-each (cut <>) thunks)
        ++ ++

        Specification

        +=20 +- +- +- +- +- +- +- +- +- +- +- +-
        (map (cut * 2 <>) '(1 2 3 4))=20 +-
        (map (cut vector-set! x <> 0) indices)=20 +-
        (for-each (cut write <> port) exprs)=20 +-
        (map (cut <> x y z) (list min max))=20 +-
        (for-each (cut <>) thunks)=20 +-
        +- +-

        Specification

        +- +- ++

        + The formal syntax of a specialized expression, in the style of the=20 +-Revised^= 5 Report on the Algorithmic Language Scheme:

        +- +- +- +- +- +- +- +- +- +- +- +- +- +- +-
        <cut-expression>= +---> +-(cut <slot-or-expr> <slot-or-expr>*) +- +-
        |(cut <slot-or-expr> <slot-or-expr>* &l= t;...>) +-; with "rest-slot" +-
        |(cute <slot-or-expr> <slot-or-expr>*)<= /code> +-; evaluate non-slots at specialization time +-
        |(cute <slot-or-expr> <slot-or-expr>* &= lt;...>) +-; with "rest-slot" +-
        <slot-or-expr> +---> +-<>; a "slot" +-
        | <expression>; a "non-slot expres= sion" +-

        +- ++Revised^= 5 Report on the Algorithmic Language Scheme:

        ++

        ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++
        <cut-expression>-->(cut <slot-or-expr> <slot-or-expr>*)
        |(cut <slot-or-expr> <slot-or-expr>* <...>)<= /code>; with "rest-slot"
        |(cute <slot-or-expr> <slot-or-expr>*); evaluate non-slots at specialization time
        |(cute <slot-or-expr> <slot-or-expr>* <...>)= ; with "rest-slot"
        <slot-or-expr>--><>; a "slot"
        | <expression>; a "non-slot expression"<= /td> ++
        ++

        + The macro cut transforms a <cut-expression>=20 + into a <lambda expression> with as many formal variabl= es + as there are slots in the list <slot-or-expr>*. +@@ -210,18 +249,21 @@ the first <slot-or-expr> with arg= uments from + <slot-or-expr>* in the order they appear. + In case there is a rest-slot symbol, the resulting procedure is also of=20 + variable arity, and the body calls the first <slot-or-expr> +-with all arguments provided to the actual call of the specialized procedu= re.

        +- ++with all arguments provided to the actual call of the specialized procedu= re. ++

        ++

        + The macro cute is similar to the macro cut, + except that it first binds new variables to the result of evaluating + the non-slot expressions (in an unspecific order) and then substituting=20 + the variables for the non-slot expressions. + In effect, cut evaluates non-slot expressions at the time + the resulting procedure is called, whereas cute evaluates +-the non-slot expressions at the time the procedure is constructed.

        ++the non-slot expressions at the time the procedure is constructed. ++

        +=20 +-

        Implementation

        ++

        Implementation

        +=20 ++

        + The reference implementation defines the two macros + cut and cute using macro=20 + mechanism of R5RS. +@@ -232,24 +274,26 @@ As macros in R5RS are hygienic and referentially tra= nsparent, + the macro mechanism makes sure the names of the newly + introduced formal variables are unique and do not clash. + The template (param ... slot), see=20 +-Sect. 7.1.5. of R5RS, ++Sect. 7.1.5. of R5RS, + allows to preserve the order of arguments---which would get + reversed otherwise. +- ++

        ++

        + The reference implementation has been written by +-Al Petrofsky. It can be found here.

        +- ++Al Petrofsky. It can be found here. ++

        ++

        + Finally, there is a small collection of=20 +-confidence tests. ++confidence tests<= /a>. + It checks some special cases of the mechanism defined + in this SRFI and signals an error in case something is wrong. + Passing the tests does not mean a correct implementation. ++

        +=20 ++

        Design Rationale

        +=20 +-

        Design Rationale

        +- +-

        Why not real currying/uncurrying?

        +- ++

        Why not real currying/uncurrying?

        ++

        + It is possible in Scheme to implement a macro turning a multi-argument=20 + procedure into a nesting of single-argument procedures and back. + These operations are usually called "curry" and "uncurry" in +@@ -261,11 +305,12 @@ if you apply it in the sequence "curry, specialize s= ome arguments, + and uncurry again"---which is exactly the purpose of the macro=20 + cut specified in this document. + The primary relevance of currying/uncurrying in Scheme is to +-teach concepts of combinatory logic.

        +- +-

        Why not a more general mechanism, also allowing permutation, +-omission and duplication of arguments?

        ++teach concepts of combinatory logic. ++

        +=20 ++

        Why not a more general mechanism, also allowing permutation, ++omission and duplication of arguments?

        ++

        + The reason is that I, the author of this SRFI, consider more general=20 + mechanisms too dangerous to mix them with the mechanism proposed here. + In particular, as soon as parameters are being rearranged it +@@ -273,13 +318,14 @@ is usually necessary to be aware of the meaning of t= he parameters; + unnamed variables can be quite harmful then. + The mechanism proposed here is designed to prevent this. + Please refer to the discussion threads +-"= OK, how about...," (Alan Bawden), +-"= is that useful?" (Walter C. Pelissero), and +-"= l, the ultimate curry that is not curry" (Al Petrofsky).

        +- +-

        Why are the macro called cut/cute and not=20 +-[enter your favourite here]?

        ++= "OK, how about...," (Alan Bawden), ++= "is that useful?" (Walter C. Pelissero), and ++= "l, the ultimate curry that is not curry" (Al Petrofsky). ++

        +=20 ++

        Why are the macro called cut/cute and not ++[enter your favourite here]?

        ++

        + Well, the original name proposed for this SRFI was curry + which immediately stirred some emotions as it does not what is + commonly known as currying. +@@ -306,23 +352,26 @@ concept is often called in other programming languag= es, + but I tend to remember it as the acronym for "Curry Upon This" ;-). + The names for the evaluating version of cut that + have been proposed were cut!, cutlet, +-cut*, and cute.

        +- +-

        Is it possible to implement the SRFI without macros?

        ++cut*, and cute. ++

        +=20 ++

        Is it possible to implement the SRFI without macros?

        ++

        + Not really. + As Stephan Houben has pointed out during the discussion (refer to +-"= Implementing it as a procedure") it is possible to implement the=20 ++= "Implementing it as a procedure") it is possible to implement the=20 + cute-mechanism as a procedure. + Refer also to Al Petrofsky's posting=20 +-"= Problems with "curry"'s formal specification" for details. ++= "Problems with "curry"'s formal specification" for details. + However, the procedural implementation comes with a slight performance + penalty and it is not possible the implement the cut-mechani= sm=20 + as a procedure, too. + As both are needed, we rely on macros to implement the SRFI. ++

        +=20 +-

        Why is there another symbol for the rest-slot when lambda-expressions +-use the dotted notation for variable length argument lists?

        ++

        Why is there another symbol for the rest-slot when lambda-expressions ++use the dotted notation for variable length argument lists?

        ++

        + There are two reasons. + The first one is the existence of a procedural implementation + of a related mechanism (refer to the previous paragraph). +@@ -330,10 +379,11 @@ For a procedure, however, it is not possible to have= dotted notation. + The second reason is the way the hygienic macro mechanism in R5RS + is defined to deal with dotted notation, as Felix Winkelmann has pointed = out. + Refer to the discussion threads +-"= Improper lists in macros [WAS: none]".

        ++= "Improper lists in macros [WAS: none]". ++

        +=20 +-

        Why is it impossible to specify when a non-slot is evaluated individu= ally=20 +-per non-slot?

        ++

        Why is it impossible to specify when a non-slot is evaluated individu= ally per non-slot?

        ++

        + Cut evaluates all non-slots at the time the specialized + procedure is called and cute evaluates all non-slots at + the time the procedure is being specialized. +@@ -343,32 +393,34 @@ However, I am convinced that the benefit of the grea= ter flexibility + is not worth the risk of confusion. + If a piece of code really depends on the distinction, it might be + better to make this explicit through let and=20 +-lambda.

        +- +-

        Why is (cut if <> 0 1) etc. illegal?

        ++lambda. ++

        +=20 ++

        Why is (cut if <> 0 1) etc. illegal?

        ++

        + It is specified that a <slot-or-expr> must be + either the slot symbol or an <expression> in the sense +-of R5RS,=20 +-Section 7.1.3. ++of R5RS,=20 ++Section 7.1.3. + As if is no <expression>, + the above case is illegal. + The reason why cut and cute are + restricted in this sense is the difficulty of defining + the meaning of such generalized expressions. + Please refer to the discussion archive for details. ++

        +=20 +-

        Acknowledgements

        +- ++

        Acknowledgements

        ++

        + An important part of this SRFI is based on the contribution + of other people, mostly through the discussion archive. + In particular, the semantics and the design rationale have + been greatly improved in the course of the discussion. + I would like to thank all who have contributed. ++

        +=20 +-

        Copyright

        ++

        Copyright

        +

        Copyright (C) Sebastian Egner (2002). All Rights Reserved.

        +- +

        + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the +@@ -392,12 +444,12 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF= OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +

        +=20 +-
        +-
        Editor: Mi= ke Sperber
        ++
        ++
        Editor: Mike Sperber
        +
        Author: Sebas= tian Egner
        + + +-Last modified: Wed Jun 19 10:54:36 MST 2002 ++Last modified: Sun Jan 28 13:40:30 MET 2007 + + + +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-27.html b/srfi-doc/sr= fi/scribblings/srfi-std/srfi-27.html +index 14a88ff..c568d78 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-27.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-27.html +@@ -1,55 +1,67 @@ +- +- ++ ++ + ++ ++ + SRFI 27: Sources of Random Bits ++ ++ ++ + +- + +- +-

        Title

        +- +-SRFI 27: Sources of Random Bits +- +-

        Author

        +- +-Sebastian Egner +- +-

        Status

        +- +-This SRFI is currently in ``final'' status. To see an explanation of +-each status that a SRFI can hold, see here.=20=20 +-You can access +-previous messages via +- +-the archive of the mailing list. +- +-
          +-
        • Draft: 2002/02/12-2002/04/12
        • +-
        • Revised: 2002/04/04 +-
        • Revised: 2002/04/10 +-
        • Revised: 2002/04/10 +-
        • Final: 2002/06/03 +-
        +- +-

        Abstract

        +- ++

        SRFI 27: Sources of Random Bits

        ++ ++

        by Sebastian Egner

        ++

        This copy of the SRFI 27 specific= ation document ++is distributed as part of the Racket package ++srfi-doc.

        = The canonical source of this document is ++https://srfi.s= chemers.org/srfi-27/srfi-27.html.

        ++ ++

        Status

        ++ ++

        This SRFI is currently in final status. Here is an explanation of each stat= us that a SRFI can hold. To provide input on this SRFI, please send email = to srfi-= 27@nospamsrfi.schemers.org. To = subscribe to the list, follow these instructions. You can access previous messages= via the mailing list a= rchive.

        ++
          ++
        • Draft: 2002-02-12--2002-04-12
        • ++
        • Revised: 2002-04-04 ++
        • Revised: 2002-04-10 ++
        • Revised: 2002-04-10 ++
        • Final: 2002-06-03 ++
        ++ ++

        Abstract

        ++

        + This document specifies an interface to sources of random bits, + or "random sources" for brevity. + In particular, there are three different ways to use the interface, + with varying demands on the quality of the source and the +-amout of control over the production process: +- +-

          +-
        • ++amount of control over the production process: ++

          ++
            ++
          • + The "no fuss" interface specifies that=20 +-(random-integer n) +-produces the next random integer in {0, ..., n-1} and ++(random-integer n) ++produces the next random integer in {0, ..., n-1} and + (random-real) produces the next random + real number between zero and one. + The details of how these random values are produced may not be + very relevant, as long as they appear to be sufficiently random. +-
          • ++
          • ++
          • + For simulation purposes, on the contrary, it is usually necessary + to know that the numbers are produced deterministically by a pseudo=20 + random number generator of high quality and to have explicit access=20 +@@ -57,18 +69,19 @@ to its state. + In addition, one might want to use several independent sources of + random numbers at the same time and it can be useful to have some + simple form of randomization. +-
          • ++
          • ++
          • + For security applications a serious form of true randomization + is essential, in the sense that it is difficult for an adversary to=20 + exploit or introduce imperfections into the distribution of random bits. + Moreover, the linear complexity of the stream of random bits is more=20 + important than its statistical properties. +-In these applications, an entropy source (producing truly random ++In these applications, an entropy source (producing truely random + bits at a low rate) is used to randomize a pseudo random number + generator to increase the rate of available bits. +-
          ++
        • ++
        +

        +- + Once random sources provide the infrastructure to obtain=20 + random bits, these can be used to construct other random deviates. + Most important are floating point numbers of various distributions +@@ -78,17 +91,20 @@ limited use elsewhere), we do not include them in this= SRFI. + In other words, this SRFI is not about making + all sorts of random objects---it is about obtaining random + bits in a portable, flexible, reliable, and efficient way. ++

        +=20 +-

        Rationale

        ++

        Rationale

        +=20 ++

        + This SRFI defines an interface for sources of random bits=20 + computed by a pseudo random number generator. + The interface provides range-limited integer and real numbers. + It allows accessing the state of the underlying generator. + Moreover, it is possible to obtain a large number of=20 + independent generators and to invoke a mild form of true +-randomization.

        +- ++randomization. ++

        ++

        + The design aims at sufficient flexibility to cover the + usage patterns of many applications as diverse as + discrete structures, numerical simulations, and cryptographic protocols. +@@ -96,8 +112,9 @@ At the same time, the interface aims at simplicity, + which is important for occasional use. + As there is no "one size fits all" random number generator, + the design necessarily represents some form of compromise +-between the needs of the various applications.

        +- ++between the needs of the various applications. ++

        ++

        + Although strictly speaking not part of the specification, + the emphasis of this proposal is on high quality + random numbers and on high performance. +@@ -105,51 +122,49 @@ As the state of the art in pseudo random number gene= rators + is still advancing considerably, the choice of method for + the reference implementation should essentially be=20 + considered preliminary. ++

        +=20 +-

        Specification

        +- +-
        +- +-
        +-(random-integer n) -> x +-
        ++

        Specification

        +=20 +-
        +-The next integer x in {0, ..., n-1}=20 ++
        ++
        ++(random-integer n) -> x<= /code> ++
        ++
        ++

        ++The next integer x in {0, ..., n-1}=20 + obtained from default-random-source. + Subsequent results of this procedure appear to be independent +-uniformly distributed over the range {0, ..., n-1}. +-The argument n must be a positive integer, ++uniformly distributed over the range {0, ..., n-1}. ++The argument n must be a positive integer, + otherwise an error is signalled. +-

        +- +-
        +- +-
        +- +-
        +-(random-real) -> x +-
        +- +-
        +-The next number 0 < x < 1 obtained from ++

        ++
        ++
        ++ ++
        ++
        ++(random-real) -> x ++
        ++
        ++

        ++The next number 0 < x < 1 obtained from + default-random-source. + Subsequent results of this procedure appear to be=20 + independent uniformly distributed. + The numerical type of the results and the=20 + quantization of the output range depend on the implementation; + refer to random-source-make-reals for details. +-

        +- +-
        +- +-
        ++

        ++
        ++
        +=20 +-
        ++
        ++
        + default-random-source +-
        +- +-
        ++
        ++
        ++

        + A random source from which random-integer and=20 + random-real have been derived using + random-source-make-integers and +@@ -157,18 +172,18 @@ A random source from which random-integer and + Note that an assignment to default-random-source=20 + does not change random or random-real; + it is also strongly recommended not to assign a new value. +-

        +- +- +-
        +-
        +- +-
        +-(make-random-source) -> s +-
        +- +-
        +-Creates a new random source s. ++

        ++
        ++
        ++ ++
        ++
        ++
        ++(make-random-source) -> s ++
        ++
        ++

        ++Creates a new random source s. + Implementations may accept additional, optional arguments in=20 + order to create different types of random sources. + A random source created with make-random-source +@@ -177,146 +192,148 @@ by some form of pseudo random number generator. + Each random source obtained as (make-random-source) + generates the same stream of values, unless the state is modified + with one of the procedures below. +-

        +- +-
        +- +-
        +- +-
        +-(random-source? obj) -> bool +-
        +- +-
        +-Tests if obj is a random source. ++

        ++
        ++
        ++ ++
        ++
        ++(random-source? obj) -> bool= ++
        ++
        ++

        ++Tests if obj is a random source. + Objects of type random source are distinct from all + other types of objects. +-

        +- +-
        +- +-
        +- +-
        +-(random-source-state-ref s) -> stat= e
        +-(random-source-state-set! s state= ) +-
        +- +-
        +-Get and set the current state of a random source s. The +-structure of the object state depends on the implementation; ++

        ++
        ++
        ++ ++
        ++
        ++(random-source-state-ref s) -> s= tate
        ++(random-source-state-set! s state= ) ++
        ++
        ++

        ++Get and set the current state of a random source s. The ++structure of the object state depends on the implementation; + the only portable use of it is as argument to=20 + random-source-state-set!. + It is, however, required that a state possess an external + representation. +-

        +- +-
        +- +-
        +-
        +-(random-source-randomize! s) +-
        +- +-
        ++

        ++
        ++
        ++ ++
        ++
        ++(random-source-randomize! s) ++
        ++
        ++

        + Makes an effort to set the state of the random=20 +-source s to a truly random state. ++source s to a truly random state. + The actual quality of this randomization depends on the implementation +-but it can at least be assumed that the procedure sets s to a=20 ++but it can at least be assumed that the procedure sets s to a=20 + different state for each subsequent run of the Scheme system. +-

        +-
        +- +-
        +-
        +-(random-source-pseudo-randomize! s i = j) +-
        +- +-
        +-Changes the state of the random source s into the initial +-state of the (i, j)-th independent random source, +-where i and j are non-negative integers. ++

        ++
        ++
        ++ ++
        ++
        ++(random-source-pseudo-randomize! s i = j) ++
        ++
        ++

        ++Changes the state of the random source s into the initial ++state of the (i, j)-th independent random source, ++where i and j are non-negative integers. + This procedure provides a mechanism to obtain a large number of=20 + independent random sources (usually all derived from the same backbone + generator), indexed by two integers. + In contrast to random-source-randomize!, + this procedure is entirely deterministic. +-

        +-
        +- +- +-
        ++

        ++ ++ +=20 +-
        +=20 +-
        +-(random-source-make-integers s) -> = rand +-
        ++
        +=20 +-
        +-Obtains a procedure rand to generate random integers=20 +-using the random source s. +-Rand takes a single argument n, ++
        ++
        ++(random-source-make-integers s) -> = rand ++
        ++
        ++

        ++Obtains a procedure rand to generate random integers=20 ++using the random source s. ++Rand takes a single argument n, + which must be a positive integer, and returns the next uniformly +-distributed random integer from the interval {0, ..., n-1} +-by advancing the state of the source s.

        +- ++distributed random integer from the interval {0, ..., n-1} ++by advancing the state of the source s. ++

        ++

        + If an application obtains and uses several generators for the same=20 +-random source s, a call to any of these generators advances=20 +-the state of s. Hence, the generators do not produce=20 ++random source s, a call to any of these generators advances=20 ++the state of s. Hence, the generators do not produce=20 + the same sequence of random integers each but rather share a state. + This also holds for all other types of generators derived from + a fixed random sources. + Implementations that support concurrency make sure that +-the state of a generator is properly advanced.

        +-

        +- +-
        +- +-
        +- +-
        +-(random-source-make-reals s) -> ran= d
        +-(random-source-make-reals s unit<= code>) ->
        rand
        +-
        +- +-
        +-Obtains a procedure rand to generate random real numbers +-0 < x < 1 using the random source s. +-The procedure rand is called without arguments.

        +- +-The optional parameter unit determines the type of numbers +-being produced by rand and the quantization of the output. +-Unit must be a number such that 0 < unit < 1. +-The numbers created by rand are of the same numerical +-type as unit and the potential output values are +-spaced by at most unit. One can imagine rand +-to create numbers as x*unit where x +-is a random integer in {1, ..., floor(1/unit)-1}. ++the state of a generator is properly advanced.

        ++
        ++
        ++ ++ ++
        ++
        ++(random-source-make-reals s) -> = rand
        ++(random-source-make-reals s unit<= code>) -> rand
        ++
        ++
        ++

        ++Obtains a procedure rand to generate random real numbers ++0 < x < 1 using the random source s. ++The procedure rand is called without arguments. ++

        ++

        ++The optional parameter unit determines the type of numbers ++being produced by rand and the quantization of the output. ++Unit must be a number such that 0 < unit < 1. ++The numbers created by rand are of the same numerical ++type as unit and the potential output values are ++spaced by at most unit. One can imagine rand ++to create numbers as x*unit where x ++is a random integer in {1, ..., floor(1/unit)-1}. + Note, however, that this need not be the way the values + are actually created and that the actual resolution of +-rand can be much higher than unit. +-In case unit is absent it defaults to a reasonably ++rand can be much higher than unit. ++In case unit is absent it defaults to a reasonably + small value (related to the width of the mantissa of an + efficient number format). +-

        +- +-
        ++

        ++
        ++
        +=20 +=20 +-

        Design Rationale

        ++

        Design Rationale

        +=20 +-

        Why not combine random-integer and +-random-real?

        ++

        Why not combine random-integer and random-real?

        +=20 ++

        + The two procedures are not combined into a single variable-arity=20 + procedures to save a little time and space during execution. + Although some Scheme systems can deal with variable arity as + efficiently as with fixed arity this is not always the case + and time efficiency is very important here. ++

        +=20 +-

        Why not some object-oriented interface?

        ++

        Why not some object-oriented interface?

        +=20 ++

        + There are many alternatives to the interface as specified in this SRFI.=20 + In particular, every framework for object-orientation can be used to + define a class for random sources and specify the interface for the +@@ -324,9 +341,11 @@ methods on random sources. + However, as the object-oriented frameworks differ considerably + in terms of syntax and functionality, this SRFI does not make + use of any particular framework. ++

        +=20 +-

        Why is there not just a generator with a fixed range?

        ++

        Why is there not just a generator with a fixed range?

        +=20 ++

        + A bare fixed-range generator is of very limited use. + Nearly every application has to add some functionality=20 + to make use of the random numbers. +@@ -337,22 +356,26 @@ This is exactly what is provided by + In addition, is saves the user from the pitfall of changing + the range with a simple modulo-computation + which may substantially reduce the quality of the +-numbers being produced.

        +- ++numbers being produced. ++

        ++

        + The design of the interface is based on three prototype applications: +-

          +-
        1. ++

          ++
            ++
          1. + Repeatedly choose from relatively small sets: + As the size of the set is likely to vary from call to call, +-random-integer accepts a range argument n in every ca= ll. ++random-integer accepts a range argument n in every ca= ll. + The implementation should try to avoid boxing/unboxing of values + if the ranges fit into immediate integers. +-
          2. ++
          3. ++
          4. + Generate a few large integers with a fixed number of bits: + As generating the random number itself is expensive,=20 + passing the range argument in every call does not hurt performance. + Hence, the same interface as in the first application can be used. +-
          5. ++
          6. ++
          7. + Generate real numbers: + Unlike the choose-from-set case,=20 + the range and the quantization is constant over a=20 +@@ -365,10 +388,11 @@ Therefore, + random-real does not accept any parameters but + the procedure random-source-make-reals creates + a properly configured random-real procedure. +-
          +- +-

          Why bother about floating point numbers at all?

          ++
        2. ++
        +=20 ++

        Why bother about floating point numbers at all?

        ++

        + A proper floating point implementation of a random number generator + is potentially much more efficient that an integer implementation + because it can use more powerful arithmetics hardware. +@@ -378,19 +402,21 @@ produce floating point random numbers. + A secondary reason is to save the user from the 'not as easy as + it seems' task of converting an integer generator into a real=20 + generator. ++

        +=20 +-

        Why are zero and one excluded from random-real?

        +- ++

        Why are zero and one excluded from random-real?

        ++

        + The procedure random-real does not return=20 +-x =3D 0 or x =3D 1 in order to allow=20 +-(log x) and=20 +-(log (- 1 x)) ++x =3D 0 or x =3D 1 in order to allow=20 ++(log x) and=20 ++(log (- 1 x)) + without the danger of a numerical exception. ++

        +=20 +-

        Implementation

        +- +-

        Choice of generator

        ++

        Implementation

        +=20 ++

        Choice of generator

        ++

        + The most important decision about the implementation is=20 + the choice of the random number generator. + The basic principle here is: Let quality prevail! +@@ -399,8 +425,9 @@ a cheap price to pay for some avoided catastrophes. + It may be unexpected, but I have also seen many examples + where the better generator was also the faster. + Simple linear congruential generator cannot be recommended +-as they tend to be ill-behaved in several ways.

        +- ++as they tend to be ill-behaved in several ways. ++

        ++

        + For this reason, my initial proposal was George Marsaglia's + COMBO generator, which is the combination of a 32-bit=20 + multiplicative lagged Fibonacci-generator with a 16-bit +@@ -408,16 +435,17 @@ multiply with carry generator. + The COMBO generator passes all tests of Marsaglia's + DIEHARD + testsuite for random number generators and has +-a period of order 2^60.

        +- ++a period of order 2^60. ++

        ++

        + As an improvement, Brad Lucier suggested +-s= uggested ++= suggested + Pierre L'Ecuyer's + MRG32k3a + generator which is combination of two recursive generators + of degree three, both of which fit into 54-bit arithmetics. + The MRG32k3a generator also passes DIEHARD and in addition, +-has desirable spectral properties and a period in the ++has desireable spectral properties and a period in the + order of 2^191. + As a matter of fact, multiple recursive generators (MRGs) are=20 + theoretically much better understood than special constructions +@@ -425,10 +453,12 @@ as the COMBO generator. + This is the reason why the implementations provided here + implements the MRG32k3a generator. + When implemented in floating point arithmetics with sufficient +-mantissa-width, this generator is also very fast.

        ++mantissa-width, this generator is also very fast. ++

        +=20 +-

        Choice of arithmetics

        ++

        Choice of arithmetics

        +=20 ++

        + The next important decision about the implementation is + the type of arithmetics to be used. + The choice is difficult and depends heavily on the +@@ -441,8 +471,9 @@ And if you do not have floats either, then at least + try to make sure you work with immediate integers + (instead of allocated objects). + Unfortunately, there is no portable way in Scheme to +-find out about native and emulated arithmetics.

        +- ++find out about native and emulated arithmetics. ++

        ++

        + As performance is critical to many applications,=20 + one might want to implement the actual + generator itself in native code. +@@ -450,17 +481,20 @@ For this reason, I provide three different + implementations of the backbone generator=20 + as a source of inspiration. + See the code below. ++

        +=20 +-

        Data Type for Random Sources

        ++

        Data Type for Random Sources

        +=20 ++

        + An important aspect of the specification in this SRFI + is that random sources are objects of a distinct type. + Although this is straight-forward and available in nearly + every Scheme implementation, there is no portable way=20 + to do this at present. + One way to define the record type is to use=20 +-SRFI-9.

        +- ++SRFI-9. ++

        ++

        + The reference implementations below define a record + type to contain the exported procedures. + The actual state of the generator is stored in the +@@ -468,42 +502,51 @@ binding time environment of make-random-source= . + This has the advantage that access to the state is fast + even if the record type would be slow (which need not be + the case). ++

        +=20 +-

        Entropy Source for Randomization

        ++

        Entropy Source for Randomization

        +=20 ++

        + Another problematic part of the specification with respect + to portability is random-source-randomize! as +-it needs access to a real entropy source.

        +- ++it needs access to a real entropy source. ++

        ++

        + A reasonable choice for such as source is to use the system + clock in order to obtain a value for randomization, for example + in the way John David Stone recommends (see reference below). + This is good enough for most applications with the=20 + notable exception of security related programs. + One way to obtain the time in Scheme is to use=20 +-SRFI-19.

        ++SRFI-19. ++

        +=20 +-

        Implementation of the specified interface

        ++

        Implementation of the specified interface

        +=20 ++

        + Once the portability issues are resolved,=20 + one can provide the remaining functionality as=20 +-specified in this SRFI document.

        +- ++specified in this SRFI document. ++

        ++

        + For the reference implementation, a relatively large part + of the code deals with the more advanced features of the=20 + MRG32k3a generator,=20 + in particular random-source-pseudo-randomize!. + This code is inspired by Pierre L'Ecuyer's own implementation +-of the MRG32k3a generator.

        +- ++of the MRG32k3a generator. ++

        ++

        + Another part of this generic code deals with changing + the range and quantization of the random numbers and +-with error checking to detect common mistakes and abuses.

        ++with error checking to detect common mistakes and abuses. ++

        +=20 +-

        Implementation Examples

        ++

        Implementation Examples

        +=20 +-Here are three= alternative implementations of the SRFI. +-(He= re are all files, tar-gzipped, 13300 bytes.) ++

        ++Here are thre= e alternative implementations of the SRFI. ++(Here are a= ll files, tar-gzipped, 53K bytes.) + Keep in mind that a SRFI is a "request for implementation", + which means these implementations are merely examples + to illustrate the specification and inspire people to implement=20 +@@ -513,35 +556,35 @@ on a Pentium3, 800 Mhz, Linux; x int/s, y<= /i> real/s + means (random-integer 2) can be computed about x + times a second and (random-real) about y times a seco= nd. + The implementations are ++

        +=20 +-
          +- +-
        1. for Scheme 48 0.57, using 54-bit integer only. ++
            ++
          1. for Scheme 48 0.57, using 54-bit integer only. + This implementation aims at portability, not at performance + (30000 ints/s, 3000/s reals/s). +- +-
          2. for Scheme 48 0.57 with the core generator being implemented=20 ++
          3. ++
          4. for Scheme 48 0.57 with the core generator being implemented + in C using (double)-arithmetics. + The generator is made available in Scheme 48 via the + C/Scheme=20 + interface. + The performance of this generator is good + (160000 ints/s, 180000 reals/s). +- +-
          5. for Gambit 3.0, using flonum and=20 ++
          6. ++
          7. for Gambit 3.0, using flonum and + 54-bit integer. + This code is inspired by a program by Brad Lucier as=20 +-p= osted ++= posted + to the discussion archive of this SRFI. + The performance of this generator is good when compiled + (5000 ints/s, 25000/s reals/s when interpreted, + 200000 ints/s, 400000/s reals/s when compiled; + see acknowledgements). +- +-
          +- ++
        2. ++
        ++

        + In addition to the implementations there is a small +-collection of c= onfidence tests ++collection of confidence tests + for the interface specified. + The tests merely check a few assertions expressed by the specification. + It is not the intention to provide a complete test of the interface here. +@@ -550,12 +593,13 @@ generator itself. + However, there is a function to write random bits from + the generators to a file in a way readable by the DIEHARD=20 + testsuite. This makes it easier for implementors to find out +-about their favorite generators and check their implementation.

        +- ++about their favorite generators and check their implementation. ++

        +=20 +=20 +-

        Recommended Usage Patterns

        ++

        Recommended Usage Patterns

        +=20 ++

        + Unless the functionality defined in this SRFI is sufficient, + an application has to implement more procedures to construct + other random deviates. +@@ -565,24 +609,27 @@ examples of increasing difficulty + with respect to the interface. + Note that the code below is not part of the specification, + it is merely meant to illustrate the spirit ++

        +=20 +-

        Generating Random Permutations

        ++

        Generating Random Permutations

        +=20 ++

        + The following code defines procedures to generate random=20 +-permutations of the set {0, ..., n-1}. ++permutations of the set {0, ..., n-1}. + Such a permutation is represented by a vector=20 +-of length n for the images of the points.

        +- ++of length n for the images of the points. ++

        ++

        + Observe that the implementation first defines the procedure=20 + random-source-make-permutations to +-turn a random source s into a procedure to generate +-permutations of given degree n. ++turn a random source s into a procedure to generate ++permutations of given degree n. + In a second step, this is applied to the default source + to define a ready-to-use procedure for permutations: +-(random-permutation n) +-constructs a random permutation of degree n. +- +-

        ++(random-permutation n)
        ++constructs a random permutation of degree n.
        ++

        ++
        + (define (random-source-make-permutations s)
        +   (let ((rand (random-source-make-integers s)))
        +     (lambda (n)
        +@@ -601,19 +648,21 @@ constructs a random permutation of degree n.
        +=20
        + (define random-permutation
        +   (random-source-make-permutations default-random-source))
        +-
        +- ++
        ++

        + For the algorithm refer to Knuth's "The Art of Computer Programming", + Vol. II, 2nd ed., Algorithm P of Section 3.4.2. ++

        +=20 +-

        Generating Exponentially-Distributed Random Numbers

        ++

        Generating Exponentially-Distributed Random Numbers

        +=20 ++

        + The following code defines procedures to generate exponentially + Exp(mu)-distributed random numbers. + The technical difficulty of the interface addressed here is + how to pass optional arguments to random-source-make-reals. +- +-

        ++

        ++
        + (define (random-source-make-exponentials s . unit)
        +   (let ((rand (apply random-source-make-reals s unit)))
        +     (lambda (mu)
        +@@ -621,17 +670,20 @@ how to pass optional arguments to random-sourc=
        e-make-reals.
        +=20
        + (define random-exponential
        +   (random-source-make-exponentials default-random-source))
        +-
        +- ++
        ++

        + The algorithm is folklore. Refer to Knuth's "The Art of Computer=20 + Programming", Vol. II, 2nd ed., Section 3.4.1.D. ++

        +=20 +-

        Generating Normally-Distributed Random Numbers

        ++

        Generating Normally-Distributed Random Numbers

        +=20 ++

        + The following code defines procedures to generate=20 + normal N(mu, sigma)-distributed real numbers using=20 +-the polar method.

        +- ++the polar method. ++

        ++

        + The technical difficulty of the interface addressed here + is that the polar method generates two results per computation. + We return one of the result and store the second one to be=20 +@@ -639,8 +691,8 @@ returned by the next call to the procedure. + Note that this implies that random-source-state-set! + (and the other procedures modifying the state) does not necessarily + affect the output of random-normal immediately! +- +-

        ++

        ++
        + (define (random-source-make-normals s . unit)
        +   (let ((rand (apply random-source-make-reals s unit))
        + 	(next #f))
        +@@ -653,7 +705,7 @@ affect the output of random-normal immedi=
        ately!
        + 	    (let* ((v1 (- (* 2 (rand)) 1))
        + 		   (v2 (- (* 2 (rand)) 1))
        + 		   (s (+ (* v1 v1) (* v2 v2))))
        +-	      (if (>=3D s 1)
        ++	      (if (>=3D s 1)
        + 		  (loop)
        + 		  (let ((scale (sqrt (/ (* -2 (log s)) s))))
        + 		    (set! next (* scale v2))
        +@@ -661,38 +713,40 @@ affect the output of random-normal imme=
        diately!
        +=20
        + (define random-normal
        +   (random-source-make-normals default-random-source))
        +-
        +- ++
        ++

        + For the algorithm refer to Knuth's "The Art of Computer Programming", + Vol. II, 2nd ed., Algorithm P of Section 3.4.1.C. ++

        +=20 +-

        Acknowledgements

        +- ++

        Acknowledgements

        ++

        + I would like to thank all people who have participated in the discussion, + in particular Brad Lucier and Pierre l'Ecuyer. + Their contributions have greatly improved the design of this SRFI. + Moreover, Brad has optimized the Gambit implementation quite substantiall= y. ++

        +=20 +-

        References

        ++

        References

        +=20 +-
          ++
            +=20 +-
          1. ++
          2. + G. Marsaglia:=20 + Diehard -- Testsuite for Random Number Generators.=20 + stat.fsu.edu/~ge= o/diehard.html + (Also contains some generators that do pass Diehard.) +-
          3. ++ +=20 +-
          4. ++
          5. + D. E. Knuth: + The Art of Computer Programming; + Volume II Seminumerical Algorithms. + 2nd ed. Addison-Wesley, 1981. + (The famous chapter on random number generators.) +-
          6. ++ +=20 +-
          7. ++
          8. + P. L'Ecuyer: + "Software for Uniform Random Number Generation: + Distinguishing the Good and the Bad", +@@ -700,93 +754,92 @@ Moreover, Brad has optimized the Gambit implementati= on quite substantially. + IEEE Press, Dec. 2001, 95--105. + www.iro.umontreal.ca/~lecuyer/myftp/papers/wsc01rng.pdf + (Profound discussion of random number generators.) +-
          9. ++ +=20 +-
          10. ++
          11. + P. L'Ecuyer: + "Good Parameter Sets for Combined Multiple Recursive + Random Number Generators",=20 + Shorter version in Operations Research, 47, 1 (1999), 159--164. + www.iro.umontreal.ca/~lecuyer/myftp/papers/combmrg2.ps + (Actual numbers for good generators.) +-
          12. ++ +=20 +-
          13. ++
          14. + P. L'Ecuyer: + "Software for Uniform Random Number Generation: + Distinguishing the Good and the Bad", + Proceedings of the 2001 Winter Simulation Conference,=20 + IEEE Press, Dec. 2001, 95--105. +-
          15. ++ +=20 +-
          16. ++
          17. + MIT Scheme v7.6: + random flo:random-unit *random-state* make-random-state=20 + random-state? + http://www.swiss.ai.mit.edu/projects/scheme/documen= tation/scheme_5.html#SEC53 + (A mechanism to run a fixed unspecified generator.) +-
          18. ++ +=20 +-
          19. ++
          20. + A. Jaffer:=20 + SLIB 2d2 with (require 'random): +- random *random-state* copy-random-state seed->random-state ++ random *random-state* copy-random-state seed->random-st= ate + make-random-state random:uniform random:exp random:normal-vector! + random-hollow-sphere! random:solid-sphere! +- = http://www.swiss.ai.mit.edu/~jaffer/slib_4.html#SEC92 +- (Based on the MIT Scheme mechanism.) +-
          21. ++ = http://swiss.csail.mit.edu/~jaffer/slib_5.html#SEC108 ++ (Uses RC-4.) ++ +=20 +-
          22. ++
          23. + R. Kelsey, J. Rees: + Scheme 48 v0.57 'random.scm':=20 + make-random make-random-vector + (Internal procedures of Scheme48; a fixed 28-bit generator.) +-
          24. ++ +=20 +-
          25. ++
          26. + M. Flatt:=20 + PLT MzScheme Version 200alpha1: + random random-seed current-pseudo-random-generator=20 + make-pseudo-random-generator pseudo-random-generator? +- http://download.plt-scheme.org/doc/200al= pha1/html/mzscheme/mzscheme-Z-H-3.html#%_idx_144 ++ http://download.plt-scheme.org/doc/200= alpha1/html/mzscheme/mzscheme-Z-H-3.html#%_idx_144 + (A mechanism to run a generator and to exchange the generator.) +-
          27. ++ +=20 +-
          28. ++
          29. + H. Abelson, G. J. Sussmann, J. Sussman: + Structure and Interpretation of Computer Programs. +- http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-20.h= tml#%_idx_2934 ++ http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-20= .html#%_idx_2934 + (The rand-example shows a textbook way to define a=20 + random number generator.) +-
          30. ++ +=20 +-
          31. ++
          32. + John David Stone: + A portable random-number generator. + http://www.math.grin.edu/~stone/events/scheme-workshop/random.= html + (An implementation of a linear congruental generator in Scheme.) +-
          33. ++ +=20 +-
          34. ++
          35. + Network Working Group: + RFC1750: Randomness Recommendations for Security. + h= ttp://www.cis.ohio-state.edu/htbin/rfc/rfc1750.html + (A serious discussion of serious randomness for serious security.) +-
          36. ++ +=20 +-
          37. +- http://www.random.org= /essay.html
            ++
          38. ++ http://www.random.org= /essay.html
            + http://www= .taygeta.com/random/randrefs.html + (Resources on random number generators and randomness.) +-
          39. ++ +=20 +-
          ++
        +=20 +=20 +-

        Copyright

        ++

        Copyright

        +

        Copyright (C) Sebastian Egner (2002). All Rights Reserved.

        +- +

        + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the +@@ -810,12 +863,12 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF= OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +

        +=20 +-
        +-
        Editor: Mi= ke Sperber
        ++
        ++
        Editor: Mike Sperber
        +
        Author: Sebas= tian Egner
        + + +-Last modified: Fri Sep 5 16:11:17 MST 2003 ++Last modified: Wed Jul 21 08:44:49 MST 2010 + + + +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-28.html b/srfi-doc/sr= fi/scribblings/srfi-std/srfi-28.html +index 8aae23b..c2a0de5 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-28.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-28.html +@@ -1,41 +1,58 @@ +- +- ++ ++ + +- ++ ++ ++ + SRFI 28: Basic Format Strings +- +- ++ ++ ++ ++ ++ + +=20 + +=20 +-

        Title

        ++

        SRFI 28: Basic Format Strings

        +=20 +- SRFI 28: Basic Format Strings=20 ++

        by Scott G. Miller

        ++

        This copy of the SRFI 28 specific= ation document ++is distributed as part of the Racket package ++srfi-doc.

        = The canonical source of this document is ++https://srfi.s= chemers.org/srfi-28/srfi-28.html.

        +=20 +-

        Author

        ++

        Status

        +=20 +- Scott G. Miller=20 ++

        This SRFI is currently in final status. Here is an explanation of each= status that a SRFI can hold. To provide input on this SRFI, please send e= mail to = srfi-28@nospamsrfi.schemers.org.= To subscribe to the list, follow these instructions. You can access previous mes= sages via the mailing list archive.

        ++
          ++
        • Draft: 2002-03-23--2002-05-23
        • ++
        • Final: 2002-06-25 ++
        +=20 +-

        Status

        +- +- This SRFI is currently in ``final'' status. To see an explanation of = each status that a SRFI can hold, see here. +- +- You can access the discussion on this SRFI via the archive of the mailin= g list. +- +-
          +-
        • Draft: 2002/03/23-2002/05/23
        • +-
        • Final: 2002/06/25 +-
        +- +-

        Abstract

        ++

        Abstract

        +=20 + This document specifies Format Strings, a method of + interpreting a Scheme string which contains a number of escape + sequences that are replaced with other string data according to + the semantics of each sequence.=20 +=20 +-

        Rationale

        ++

        Rationale

        +=20 + Many Scheme systems provide access to a function called + format. This function takes as arguments a format string, +@@ -47,9 +64,9 @@ + allow portable code to be written using the function without + much (if any) effort on the part of Scheme implementors.=20 +=20 +-

        Specification

        ++

        Specification

        +=20 +- format format-string [o= bj ...] -> ++ format format-string [obj ...] -= > + string=20 +=20 +
        +@@ -84,7 +101,7 @@ + value.

        +
        +=20 +-

        Examples

        ++

        Examples

        +
        + (format "Hello, ~a" "World!")
        + ; =3D> "Hello, World!"
        +@@ -93,10 +110,10 @@
        + ; =3D> "Error, list is too short: (one \"two\" 3))"
        + 
        +=20 +-

        Implementation

        ++

        Implementation

        +=20 + The implementation below requires SRFI-6 (Basic string ports) +- and SRFI-23 (Error reporting mechanism).
        ++ and SRFI-23 (Error reporting mechanism).
        +=20=20=20=20=20=20 +
        + (define format
        +@@ -134,7 +151,7 @@
        +=20=20=20=20=20
        + 
        +=20 +-

        Copyright

        ++

        Copyright

        +=20 +

        Copyright (C) Scott G. Miller (2002). All Rights Reserved.

        +=20 +@@ -161,10 +178,10 @@ + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +

        +-
        ++
        +=20 +
        +- Editor: ++ Editor: + Francisco Solsona +
        +=20 +@@ -178,4 +195,3 @@ + + + +- +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-29.html b/srfi-doc/sr= fi/scribblings/srfi-std/srfi-29.html +index e493c05..bc144b0 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-29.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-29.html +@@ -1,36 +1,46 @@ +- ++ + + +- +- ++ ++ + SRFI 29: Localization +- +- +- ++ ++ ++ + + +-

        3D29: Localization

        ++

        SRFI 29: Localization

        +=20 +

        by Scott G. Miller

        ++

        This copy of the SRFI 29 specific= ation document ++is distributed as part of the Racket package ++srfi-doc.

        = The canonical source of this document is ++https://srfi.s= chemers.org/srfi-29/srfi-29.html.

        +=20 +

        Status

        +=20 +

        This SRFI is currently in final status. Here is + an + explanation of each status that a SRFI can hold. To provide +- input on this SRFI, please send email to srfi-29@nospamsrfi.schemers.org. +- To subscribe to the list, follow these ++ input on this SRFI, please send email to srfi-29@nospa= msrfi.schemers.org. ++ To subscribe to the list, follow these + instructions. You can access previous messages via the +- mailing list archive.

        ++ mailing list archiv= e.

        +=20 +
          +
        • Draft: 2002-03-26--2002-06-19
        • +@@ -124,9 +134,9 @@ + no-argument procedures:

          +=20 +

          current-language +- -> symbol
          ++ -> symbol
          + current-language symbol -> +- undefined

          ++ undefined

          +=20 +
          + When given no arguments, returns the current ISO 639-1 language +@@ -137,9 +147,9 @@ +
          +=20 +

          current-country +- -> symbol
          ++ -> symbol
          + current-country symbol -> +- undefined

          ++ undefined

          +=20 +
          + returns the current ISO 3166-1 country code as a symbol. +@@ -149,11 +159,10 @@ + is not possible).    +
          +=20 +-

          current-locale-details +- -> list of symbols
          ++

          current-locale-details= ++ -> list of symbols
          + current-locale-details list-of-symbols -> +- undefined

          ++ undefined

          +=20 +
          + Returns a list of additional locale details as a list of +@@ -211,7 +220,7 @@ +=20 +

          declare-bundle! + bundle-specifier association-list -> +- undefined

          ++ undefined

          +=20 +
          + Declares a new bundle named by the given bundle-specifier. +@@ -219,10 +228,10 @@ + association list.  The list contains associations between + Scheme symbols and the message templates (Scheme strings) they + name.  If a bundle already exists with the given name, it +- is overwritten with the newly declared bundle.
          ++ is overwritten with the newly declared bundle.
          +
          + store-bundle +- bundle-specifier -> boolean
          ++ bundle-specifier -> boolean

          +=20 +
          + Attempts to store a bundle named by the given bundle specifier, +@@ -231,10 +240,10 @@ + an unspecified mechanism that may be persistent across Scheme + system restarts.  If successful, a non-false value is + returned.  If unsuccessful, #f is +- returned.
          ++ returned.
          +
          + load-bundle! +- bundle-specifier -> boolean
          ++ bundle-specifier -> boolean
          +=20 +
          + Attempts to retrieve a bundle from an unspecified mechanism +@@ -243,7 +252,7 @@ + non-false value, and the bundle is immediately available to the + Scheme system. If the bundle could not be found or loaded + successfully, the function returns #f, and the +- Scheme system's bundle registry remains unaffected.
          ++ Scheme system's bundle registry remains unaffected.
          +
          +=20 +

          A compliant Scheme system may choose not to provide any +@@ -259,14 +268,14 @@ +=20 +

          localized-template + package-name message-template-name +- -> string or #f

          ++ -> string or #f

          +=20 +
          + Retrieves a localized message template for the given package + name and the given message template name (both symbols). +  If no such message could be found, false (#f) is +- returned.
          +-
          ++ returned.
          ++
          +
          +=20 +

          After retrieving a template, the calling program can use +@@ -324,7 +333,7 @@ + of those functions in the reference implementation are not + capable of that distinction. Their implementation is provided + only so that the following code can run in any R4RS scheme +- system.  

          ++ system.  

          +=20 +

          In addition, the below implementation of a compliant + format requires SRFI-6 (Basic String Ports) and +@@ -500,11 +509,10 @@ + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE.

          +=20 +-
          ++
          +=20 +
          +- Editor: David ++ Editor: David + Rush +
          +=20 +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-30.html b/srfi-doc/sr= fi/scribblings/srfi-std/srfi-30.html +index b6c2fdc..ee5fafa 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-30.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-30.html +@@ -1,63 +1,69 @@ +- +- ++ ++ + ++ ++ + SRFI 30: Nested Multi-line Comments ++ ++ ++ + +=20 + +=20 +-

          Title

          ++

          SRFI 30: Nested Multi-line Comments

          +=20 +-SRFI 30: Nested Multi-line Comments ++

          by Martin Gasbichler

          ++

          This copy of the SRFI 30 specific= ation document ++is distributed as part of the Racket package ++srfi-doc.

          = The canonical source of this document is ++https://srfi.s= chemers.org/srfi-30/srfi-30.html.

          ++=20=20=20=20 ++

          Status

          +=20 +-

          Author

          ++

          This SRFI is currently in final status. Here is an explanation of each stat= us that a SRFI can hold. To provide input on this SRFI, please send email = to srfi-= 30@nospamsrfi.schemers.org. To = subscribe to the list, follow these instructions. You can access previous messages= via the mailing list a= rchive.

          +=20 +-Martin Gasbichler +-=20=20=20=20 +-

          Status

          +- +-This SRFI is currently in ``final'' status. To see an explanation of +-each status that a SRFI can hold, see here. It will +-remain in draft until 2002-04-06, or as amended. to provide input on +-this SRFI, please +- +-mail to srfi-30@srfi.schemers.org. +-See +-instructions here to subscribe to the list. You can access +-previous messages via +- +-the archive of the mailing list. +-You can access +-post-finalization messages via +- +-the archive of the mailing list. +- +-
            +-
          • Draft: 2002/04/12-2002/06/10
          • +-
          • Revised: 2002/06/05
          • +-
          • Final: 2002/08/07
          • +-
          +- +-

          Related SRFIs

          ++
            ++
          • Draft: 2002-04-12--2002-06-10
          • ++
          • Revised: 2002-06-05
          • ++
          • Final: 2002-08-07
          • ++
          ++ ++

          Related SRFIs

          +=20=20=20=20=20 +-

          SRFI 22 defines ++

          SRFI 22 defines + a multi line comment that may only appear at the beginning of a + file.

          +=20 +-

          SRFI 10 +- proposes the notation ++

          SRFI 10 ++ proposes the notation

          +=20 +-
           "#" <discriminator> <other-char>*
          for further +- SRFIs that introduce values which may be read and written.

          ++
           "#" <discriminator> <other-char>*
          ++

          for further SRFIs that introduce values which may be read and ++ written.

          +=20 +-

          Abstract

          ++

          Abstract

          +=20 +

          This SRFI extends R5RS by possibly nested, multi-line + comments. Multi-line comments start with #| and end + with |#.

          +=20=20=20=20=20 +-

          Rationale

          ++

          Rationale

          +=20=20=20=20=20 +

          Multi-line comments are common to many programming languages. They + provide a convenient mean for adding blocks of text inside a program = and +@@ -70,13 +76,11 @@ the archive of the mailing list. + with R5RS. Nested comments are an important feature for + incrementally commenting out code.

          +=20=20=20=20=20 +-

          Specification

          ++

          Specification

          +=20 +-

          This SRFI extends the specification of comments -- R5RS ++

          This SRFI extends the specification of comments -- R5RS + section 2.2 -- as follows:

          +=20 +- +

          The sequence #| indicates the start of a + multi-line comment. The multi-line comment continues until + |# appears. If the closing |# is +@@ -88,8 +92,7 @@ the archive of the mailing list. +=20=20=20=20=20 +

          This SRFI furthermore extends the production for + <comment> in the specification of lexical +- structure -- R5RS ++ structure -- R5RS + section 7.1.1 -- to: +

          +
          +@@ -101,11 +104,10 @@ the archive of the mailing list.
          +     
          +=20 +=20 +-

          <delimiter> and #

          =20 ++

          <delimiter> and #

          +=20 +

          The SRFI does not extend the specification of +- <delimiter> from R5RS ++ <delimiter> from R5RS + section 7.1.1. It is therefore required to separate tokens + which require implicit termination (identifiers, numbers, + characters, and dot) from multi-line comments by a +@@ -116,7 +118,7 @@ the archive of the mailing list. + incompatible with existing implementations which allow + # as legal character within identifiers.

          +=20 +-

          Implementation

          ++

          Implementation

          +=20=20=20=20=20 +

          The following procedure skip-comment deletes a + leading multi-line comment from the current input port. Its +@@ -143,7 +145,7 @@ the archive of the mailing list. + ((#\#) (lp 'read-sharp nested-level)) + (else (lp 'start nested-level)))) + ((read-bar) (case (next-char) +- ((#\#) (if (> nested-level 1) ++ ((#\#) (if (> nested-level 1) + (lp 'start (- nested-level 1)))) + (else (lp 'start nested-level)))) + ((read-sharp) (case (next-char) +@@ -151,18 +153,16 @@ the archive of the mailing list. + (else (lp 'start nested-level))))))) +

    +=20 +-

    A SRFI 22 script= to remove nested multi-line comments is ++

    A SRFI 22 scrip= t to remove nested multi-line comments is + available at=20 +=20=20=20=20=20=20=20 +- http://srfi.schemers.org/srfi-30/remove-srfi30-comments-script.scm. ++ https://srfi.schemers.org/srfi-30/remove-srfi30-comments-scrip= t.scm. +=20=20=20=20=20=20=20 + The script will read a Scheme program containing nested + multi-line comments from standard input and emit the same + programs with the comments removed to standard output. The + script mimics the Scheme 48 reader and uses the +- error procedure from SRFI 23.

    ++ error procedure from SRFI 23<= /a>.

    +=20 +

    A number of Scheme implemenations already support this SRFI: + Chez Scheme, Chicken, Gambit-C, Kawa, MIT Scheme, MzScheme and +@@ -171,7 +171,7 @@ the archive of the mailing list. + implementations, Scheme 48 and Guile do not support this SRFI + yet.

    +=20 +-

    Copyright

    ++

    Copyright

    +

    Copyright (C) Martin Gasbichler (2002). All Rights Reserved.

    +=20 +

    +@@ -199,12 +199,11 @@ the archive of the mailing list. +

    +=20 +=20=20=20=20=20=20=20 +-
    +-
    Editor: Mike Sperber ++
    ++
    Editor: Mike Sperber
    + + +-Last modified: Sun Sep 1 17:14:55 MST 2002 ++Last modified: Sun Jan 28 13:40:31 MET 2007 + + + +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-31.html b/srfi-doc/sr= fi/scribblings/srfi-std/srfi-31.html +index faf6eb9..dd8dc91 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-31.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-31.html +@@ -1,306 +1,319 @@ +- +- ++ ++ + +- ++ ++ + SRFI 31: A special form `rec' for recursive evaluation ++ ++ ++ + +=20 + +=20 +-

    Title

    ++

    SRFI 31: A special form rec for recursive evaluation

    +=20 +-SRFI 31: A special form rec for recursive evaluation ++

    by Mirko Luedde

    ++

    This copy of the SRFI 31 specific= ation document ++is distributed as part of the Racket package ++srfi-doc.

    = The canonical source of this document is ++https://srfi.s= chemers.org/srfi-31/srfi-31.html.

    +=20 +-

    Author

    =20 ++

    Status

    +=20 +-Mirko Luedde <Mirko.Luedde@SAP= .com> ++

    This SRFI is currently in final status. Here is an explanation of each stat= us that a SRFI can hold. To provide input on this SRFI, please send email = to srfi-= 31@nospamsrfi.schemers.org. To = subscribe to the list, follow these instructions. You can access previous messages= via the mailing list a= rchive.

    ++
      ++
    • Draft: 2002-05-24--2002-08-24
    • ++
    • Revised: 2002-08-12
    • ++
    • Final: 2002-12-02
    • ++
    +=20 +-

    Status

    +-=20 +-This SRFI is currently in ``final'' status. To see an explanation of +-each status that a SRFI can hold, see here. +- +-You can access the discussion via the +-archive of the mailing list. +- +-
      +-
    • Draft: 2002/05/24-2002/08/24
    • +-
    • Revised: 2002/08/12
    • +-
    • Final: 2002/12/02
    • +-
    +- +-

    Abstract

    =20 ++

    Abstract

    +=20 + We propose the implementation of a special form +-called rec. This form is a generalization and +-combination of the forms rec and +-named-lambda of [Clinger1985]. It allows the simple and ++called rec. This form is a generalization and ++combination of the forms rec and ++named-lambda of [Clinger1985]= . It allows the simple and + non-imperative construction of self-referential expressions. As an + important special case, it extends the A. Church form +-lambda such that it allows the direct definition of ++lambda such that it allows the direct definition of + recursive procedures without using further special forms like +-let or letrec, without using advanced ++let or letrec, without using advanced + constructions like the H. B. Curry combinator and, unlike +-define, without introducing variable bindings into the ++define, without introducing variable bindings into the + external environment. +=20 +-

    Rationale

    =20 ++

    Rationale

    +=20 +-

    General

    Among the prominent features of the Scheme +-programming language as defined in [KCR1998] ++

    General

    Among the prominent features of the Scheme ++programming language as defined in [KCR1998] + are the following. +=20 +-
      ++
        +=20 +-
      1. It has simple syntax.
      2. ++
      3. It has simple syntax.
      4. +=20=20 +-
      5. It encourages recursive definitions, e.g. by ensuring memory +- efficient tail recursion.
      6. ++
      7. It encourages recursive definitions, e.g. by ensuring memory ++ efficient tail recursion.
      8. +=20 +-
      9. It supports non-imperative programming.
      10. ++
      11. It supports non-imperative programming.
      12. +=20 +-
      ++
    +=20 + Nevertheless Scheme does not provide a syntax for recursive + evaluations with the properties of +=20 +-
      ++
        +=20 +-
      1. being as simple, intuitive and close to the mathematical standard +-notation as possible,
      2. ++
      3. being as simple, intuitive and close to the mathematical standard ++notation as possible,
      4. +=20 +-
      5. allowing general recursion,
      6. ++
      7. allowing general recursion,
      8. +=20 +-
      9. being non-imperative.
      10. ++
      11. being non-imperative.
      12. +=20 +-
      ++
    +=20 +-

    Example

    =20 +- +-

    Problem 1

    =20 ++

    Example

    +=20 ++

    Problem 1

    ++

    + Let us look at the factorial function. In mathematical notation this + function is expressed as +- +-

    =20
    +-  (F : N |--> 1,            if N =3D 0;=20
    ++

    ++
    =20
    ++  (F : N |--> 1,            if N =3D 0;=20
    +               N * F(N - 1), otherwise).
    +-
    +- ++
    ++

    + This expression is a term and not a definition or proposition. +- +-

    We investigate some approaches to express the factorial function in +-Scheme. +- +-

      +- +-
    • ++

      ++

      ++We investigate some approaches to express the factorial function in Schem= e. ++

      ++
        ++
      • ++

        + The simplest way perhaps is as +- +-

        ++

        ++
        + (define (F N)=20
        +   (if (zero? N) 1=20
        +     (* N (F (- N 1)))))
        +-
        +- ++
        ++

        + But this expression is not a term. It binds the factorial function to + the variable F. The expression itself may not occur in a +-syntactical context where a name of the factorial is required.

      • +- +-
      • ++syntactical context where a name of the factorial is required. ++

        ++
      • ++
      • ++

        + We list several ways to express the factorial as a function term. +- +-

          +- +-
        1. +-
          ++

          ++
            ++
          1. ++
            + (let ()=20
            +   (define (F N)
            +     (if (zero? N) 1=20
            +         (* N (F (- N 1)))))
            +     F)
            +-
            +-
          2. +- +-
          3. +-
            ++
            ++
          4. ++
          5. ++
            + (lambda (N)=20
            +   (let F ( (N N) )=20
            +        (if (zero? N) 1=20
            + 	 (* N (F (- N 1))))))
            +-
            +-
          6. ++
          ++
        2. +=20 +-
        3. +-
          ++
        4. ++
          + (letrec ( (F (lambda (N)=20
          + 	       (if (zero? N) 1=20
          + 		 (* N (F (- N 1)))))) )	F)
          +-
          +-
        5. ++
          ++
        6. +=20 +-
        7. +-
          ++
        8. ++
          + ((lambda (F)=20
          +    (F F))
          +  (lambda (G)=20
          +    (lambda (N)=20
          +      (if (zero? N) 1=20
          +        (* N ((G G) (- N 1)))))))
          +-
          +-
        9. +- +-
        ++
    ++ +=20 ++ ++

    + All these expressions define the factorial anonymously, not binding it + to a variable. However, all these expressions are more verbose than it + seems necessary and they are less intuitive than it seems +-desirable. +- +- ++desirable. ++

    ++ +=20 +-

    Solution 1

    =20 ++ +=20 +-A solution to our problem was already provided in
    [Clinger1985] by the form +-named-lambda. An even earlier solution with a slightly ++

    Solution 1

    ++

    ++A solution to our problem was already provided in [Clinger1985] by the form ++named-lambda. An even earlier solution with a slightly + different syntax was implemented in Kent Dybvig's Chez Scheme system. +- ++

    + Using this special form, we can denote the factorial simply by +- +-

    ++

    ++
    + (named-lambda (F N)=20
    +               (if (zero? N) 1=20
    +                 (* N (F (- N 1)))))
    +-
    +- ++
    ++

    + This expression is a function term that denotes the factorial in the + appropriate brevity. +=20 +-

    However, the form named-lambda has been dropped from ++

    However, the form named-lambda has been dropped from + later versions of the Scheme Report. Also it is missing in + state-of-the-art implementations such as Chez Scheme (6.0a) and MIT + Scheme (7.7.0). (The latter actually knows a form +-named-lambda with different semantics). ++named-lambda with different semantics). ++

    +=20 +-

    Problem 2

    =20 ++

    Problem 2

    +=20 + The constant stream of ones can be defined via +=20 +-
    (define S (cons 1 (delay S)))
    ++
    (define S (cons 1 (delay S)))
    +=20 + As in the case of the factorial, we are able to define the recursive + object at the price of spending an externally bound name. Remedying +-this with let or letrec leads to similar ++this with let or letrec leads to similar + objections as above. +=20 +-

    Solution 2

    =20 +- ++

    Solution 2

    ++

    + This particular case of the self-referential problem was solved by the +-rec form in [Clinger1985]. +- ++rec form in [Clinger1985]. ++

    + This form allows writing +- +-

    (rec S (cons 1 (delay S)))
    +- ++

    ++
    (rec S (cons 1 (delay S)))
    ++

    + This expression is non-imperative and does not introduce an external + variable binding. +=20 +-

    Also this form has been dropped from later versions of the Scheme ++

    Also this form has been dropped from later versions of the Scheme + Report. Moreover, from our point of view this form alone is not + capable of solving Problem 1. The respective definition would look + like +- +-

    ++

    ++
    + (rec F=20
    +      (lambda (N)=20
    +        (if (zero? N) 1=20
    + 	 (* N (F (- N 1))))))
    +-
    +- ++
    ++

    + This again does not seem quite as simple and intuitive as the + mathematical notation. ++

    +=20 +-

    Proposal

    =20 ++

    Proposal

    +=20 +-We therefore propose to implement the rec special form in ++We therefore propose to implement the rec special form in + a generalized way that combines the advantages of the +-named-lambda and rec forms. ++named-lambda and rec forms. +=20 + The factorial function could be written +-
    ++
    + (rec (F N)=20
    +      (if (zero? N) 1=20
    +        (* N (F (- N 1)))))
    +-
    ++
    +=20 +-

    Specification

    ++

    Specification

    +=20 +-

    Syntax

    =20 ++

    Syntax

    +=20 +-The following production rules are to be added to those of [KCR1998] (we reuse names of non-terminals). ++The following production rules are to be added to those of [KCR1998] (we reuse names of non-terminals). +=20 +-
      ++
        +=20 +-
      1. <derived expression> --> <rec expression>=
      2. ++
      3. <derived expression> --> <rec expression>=
      4. +=20 +-
      5. <rec expression> --> (rec <variable> +-<expression>)
      6. ++
      7. <rec expression> --> (rec <variable> ++<expression>)
      8. +=20 +-
      9. <rec expression> --> (rec (<variable>+) +-<body>)
      10. ++
      11. <rec expression> --> (rec (<variable>+) ++<body>)
      12. +=20 +-
      ++
    +=20 +-

    Semantics

    =20 ++

    Semantics

    +=20 +-Scheme versions such as [KCR1998] providing +-define-syntax, syntax-rules, +-letrec and lambda might implement +-rec as follows. ++Scheme versions such as [KCR1998] providing ++define-syntax, syntax-rules, ++letrec and lambda might implement ++rec as follows. +=20 +-
    ++
    + (define-syntax rec
    +   (syntax-rules ()
    +     ((rec (NAME . VARIABLES) . BODY)
    +      (letrec ( (NAME (lambda VARIABLES . BODY)) ) NAME))
    +     ((rec NAME EXPRESSION)
    +      (letrec ( (NAME EXPRESSION) ) NAME))))
    +-
    ++
    +=20 +-

    Test

    ++

    Test

    +=20 +-The following session shows in which way rec allows a ++The following session shows in which way rec allows a + tail-recursive implementation of the factorial function. +=20 +-
    +-> (define F (rec (F N)
    ++
    ++> (define F (rec (F N)
    + 		((rec (G K L)
    + 		   (if (zero? K) L
    + 		     (G (- K 1) (* K L)))) N 1)))
    +-> F
    ++> F
    + #<procedure>
    +-> (F 0)
    ++> (F 0)
    + 1
    +-> (F 10)
    ++> (F 10)
    + 3628800
    +-
    ++
    +=20 +-

    Acknowledgements

    =20 ++

    Acknowledgements

    +=20 + The author thanks Al Petrofsky for the final solution and Hal Abelson, + Chris Hanson and others for their input. The work of the maintainers + of the SRFI forum is highly appreciated. +=20 +-

    Bibliography

    ++

    Bibliography

    +=20 +- +=20 +-

    Copyright

    ++

    Copyright

    +=20 +

    Copyright (C) Dr. Mirko Luedde (2002). All Rights Reserved.

    +=20 +@@ -350,11 +362,11 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF= OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +

    +=20 +-
    ++
    +=20 +-
    Author: Mirko Luedde=
    ++
    Author: Mirko Luedde
    +=20 +-
    Editor: Franci= sco Solsona
    ++
    Editor: Francisco Solsona
    +=20 + +=20 +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-34.html b/srfi-doc/sr= fi/scribblings/srfi-std/srfi-34.html +index aa46757..144337e 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-34.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-34.html +@@ -1,82 +1,131 @@ +- +- ++ ++ + +-SRFI 34: Exception Handling for Programs ++ ++ ++ SRFI 34: Exception Handling for Programs ++ ++ ++ + +=20 + +-

    Title

    ++

    SRFI 34: Exception Handling for Programs

    +=20 +-SRFI 34: Exception Handling for Programs ++

    by Richard Kelsey and Michael Sperber

    ++

    This copy of the SRFI 34 specific= ation document ++is distributed as part of the Racket package ++srfi-doc.

    = The canonical source of this document is ++https://srfi.s= chemers.org/srfi-34/srfi-34.html.

    +=20 +-

    Authors

    ++

    Status

    +=20 +-Richard Kelsey and Michael Sperber ++

    This SRFI is currently in final status. Here is an explanation of each stat= us that a SRFI can hold. To provide input on this SRFI, please send email = to srfi-= 34@nospamsrfi.schemers.org. To = subscribe to the list, follow these instructions. You can access previous messages= via the mailing list a= rchive.

    +=20 +-

    Status

    +- +-This SRFI is currently in ``final'' status. To see an explanation of +-each status that a SRFI can hold, see here. It will +-remain in draft until 2002-10-20, or as amended. to provide input on +-this SRFI, please mail to=20 +- +-srfi-34@srfi.schemers.org. +-See +-instructions here to subscribe to the list. You can access +-the discussion via +- +-the archive of the mailing list. +-You can access +-post-finalization messages via +- +-the archive of the mailing list. +- +-
      +-
    • Draft: 2002/07/24-2002/10/20
    • +-
    • Revised: 2002/09/20
    • +-
    • Final: 2002/12/1
    • +-
    • Fixed reference implementation: 2003/03/10
    • +-
    ++
      ++
    • Draft: 2002-07-24--2002-10-20
    • ++
    • Revised: 2002-09-20
    • ++
    • Final: 2002-12-01
    • ++
    • Revised to fix errata: ++
        ++
      • 2003-03-10
      • ++
      • 2018-01-13 (missing test in guard-aux implementation)=
      • ++
      ++
    • ++
    +=20 +-

    Abstract

    +-This SRFI defines exception-handling and exception-raising constructs for= Scheme, including
    • a with-exception-handler +- procedure and a guard +- form for installing exception-handling procedures,
    • +-
    • a raise +- procedure for invoking the current exception handler.
    • ++

      Abstract

      ++

      ++ This SRFI defines exception-handling and exception-raising constructs f= or Scheme, including ++

      ++
        ++
      • a with-exception-handler ++ procedure and a guard ++ form for installing exception-handling procedures, ++
      • ++
      • a raise ++ procedure for invoking the current exception handler. ++
      • +
      +-

      This SRFI is based on (withdrawn) SRFI 12: Exception Handling +-by William Clinger, R. Kent Dybvig, Matthew Flatt, and Marc Feeley.

      +-

      Rationale

      +-

      The goals of the exception mechanism specified in this SRFI are to hel= p programmers share code which relies on exception handling, and to be easi= ly added to existing Scheme systems.

      +-

      This SRFI is primarily useful in conjunction with one or more companio= n SRFIs:

      +-
      • a SRFI specifying exception-describing objects (conditions). An e= xample is SRFI 35 +- (Conditions).
      • +-
      • a SRFI specifying a set of standard condition types to be raised by t= he primitives provided by the Scheme implementation, and requiring that cer= tain Scheme primitives indeed raise exceptions within the framework describ= ed. An example is SRFI 36 +- (I/O Conditions).
      • +-
      • a SRFI specifying how computations may be resumed after an exception = is raised.
      • ++

        ++ This SRFI is based on (withdrawn) ++ SRFI 12: Exception Handl= ing ++ by William Clinger, R. Kent Dybvig, Matthew Flatt, and Marc Feeley. ++

        ++

        Rationale

        ++

        ++ The goals of the exception mechanism specified in this SRFI are to ++ help programmers share code which relies on exception handling, and ++ to be easily added to existing Scheme systems. ++

        ++

        ++ This SRFI is primarily useful in conjunction with one or more companion= SRFIs: ++

        ++
          ++
        • ++ a SRFI specifying exception-describing objects (conditions). An ++ example is SRFI 35 ++ (Conditions). ++
        • ++
        • ++ a SRFI specifying a set of standard condition types to be raised ++ by the primitives provided by the Scheme implementation, and ++ requiring that certain Scheme primitives indeed raise exceptions ++ within the framework described. An example ++ is SRFI 36 (I/O ++ Conditions). ++
        • ++
        • ++ a SRFI specifying how computations may be resumed after an exception = is raised. ++
        • +
        +-

        Specification

        ++

        Specification

        +

        Exception handlers are one-argument procedures that determine the acti= on the program takes when an exceptional situation is signalled. The system= implicitly maintains a current exception handler.

        +

        The program raises an exception by invoking the current exception hand= ler, passing to it an object encapsulating information about the exception.= Any procedure accepting one argument may serve as an exception handler and= any object may be used to represent an exception.

        +

        The system maintains the current exception handler as part of the = dynamic environment of the program, akin to the current input or output= port, or the context for dynamic-wind. The dynamic environmen= t can be thought of as that part of a continuation that does not specify th= e destination of any returned values. It includes the current input and ou= tput ports, the dynamic-wind + context, and this SRFI's current exception handler. See the reference i= mplementation for portable definitions of current-dynamic-environment= + and with-dynamic-environment.

        +

        The initial current exception handler of the program is implementation= -dependent. However, it should interrupt the program in some way visible to= the user, either by aborting it, invoking a debugger, or some similar acti= on.

        +-

        Establishing Exception Handlers

        +-
        (with-exception-handler = handler +- thunk)
        +-

        Returns the result(s) of invoking thunk. Handler +- must be a procedure that accepts one argument. It is installed as the cu= rrent exception handler for the dynamic extent (as determined by dyna= mic-wind) of the invocation of thunk.

        ++

        Establishing Exception Handlers

        ++
        ++
        (with-exception-handler handler ++thunk)
        ++
        ++

        ++ Returns the result(s) of ++ invoking thunk. Handler must be a procedure ++ that accepts one argument. It is installed as the current ++ exception handler for the dynamic extent (as determined ++ by dynamic-wind) of the invocation ++ of thunk. ++

        +
        +
        +-
        (guard ( ++ ++
        ++
        (guard ( + <var> <clause1 + > <clause2 + > ...) +- <body>) (syntax)
        +-

        Syntax: ++<body>) (syntax) ++

        ++
        ++

        Syntax: + Each <clause> should have the same form as a cond + clause

        +

        Semantics: +@@ -91,17 +140,28 @@ by William Clinger, R. Kent Dybvig, Matthew Flatt, an= d Marc Feeley.

        + expression.

        +
        +
        +-

        Raising Exceptions

        +-
        (raise obj)
        +-

        Invokes the current exception handler on obj. The handl= er is called in the dynamic environment of the call to raise, = except that the current exception handler is that in place for the call to = with-exception-handler +- that installed the handler being called. The handler's continuation is = otherwise unspecified.

        ++ ++

        Raising Exceptions

        ++
        ++
        (raise obj) ++
        ++
        ++

        ++ Invokes the current exception handler on obj. The handler ++ is called in the dynamic environment of the call ++ to raise, except that the current exception handler is ++ that in place for the call to with-exception-handler ++ that installed the handler being called. The handler's continuation ++ is otherwise unspecified. ++

        +
        +
        +-

        Examples

        ++ ++

        Examples

        +
        (call-with-current-continuation
        +  (lambda (k)
        +    (with-exception-handler (lambda (x)
        +-                             (display "condition: ")
        ++                             (display "condition: ")
        +                              (write x)
        +                              (newline)
        +                              (k 'exception))
        +@@ -113,7 +173,7 @@ PRINTS: condition: an-error
        + (call-with-current-continuation
        +  (lambda (k)
        +    (with-exception-handler (lambda (x)
        +-                             (display "something went wrong")
        ++                             (display "something went wrong")
        +                              (newline)
        +                              'dont-care)
        +      (lambda ()
        +@@ -123,7 +183,7 @@ then behaves in an unspecified way
        +=20
        + (guard (condition
        +          (else
        +-          (display "condition: ")
        ++          (display "condition: ")
        +           (write condition)
        +           (newline)
        +           'exception))
        +@@ -133,7 +193,7 @@ PRINTS: condition: an-error
        +=20
        + (guard (condition
        +          (else
        +-          (display "something went wrong")
        ++          (display "something went wrong")
        +           (newline)
        +           'dont-care))
        +  (+ 1 (raise 'an-error)))
        +@@ -143,7 +203,7 @@ PRINTS: something went wrong
        + (call-with-current-continuation
        +  (lambda (k)
        +    (with-exception-handler (lambda (x)
        +-                             (display "reraised ") (write x) (n=
        ewline)
        ++                             (display "reraised ") (write x) (newline)
        +                              (k 'zero))
        +      (lambda ()
        +        (guard (condition
        +@@ -155,7 +215,7 @@ PRINTS: something went wrong
        + (call-with-current-continuation
        +  (lambda (k)
        +    (with-exception-handler (lambda (x)
        +-                             (display "reraised ") (write x) (n=
        ewline)
        ++                             (display "reraised ") (write x) (newline)
        +                              (k 'zero))
        +      (lambda ()
        +        (guard (condition
        +@@ -167,7 +227,7 @@ PRINTS: something went wrong
        + (call-with-current-continuation
        +  (lambda (k)
        +    (with-exception-handler (lambda (x)
        +-                             (display "reraised ") (write x) (n=
        ewline)
        ++                             (display "reraised ") (write x) (newline)
        +                              (k 'zero))
        +      (lambda ()
        +        (guard (condition
        +@@ -188,13 +248,14 @@ PRINTS: reraised 0
        +          ((assq 'b condition)))
        +   (raise (list (cons 'b 23))))
        + =3D> (b . 23)
        +-

        Reference Implementation

        +-

        The reference implementation makes use of SRFI 9 +- ("Defining Record Types"), and SRFI 23 +- ("Error reporting mechanism").

        ++
    ++

    Reference Implementation

    ++

    The reference implementation makes use of SRFI= 9 ++ ("Defining Record Types"), and SRFI 23 ++ ("Error reporting mechanism").

    +
    (define *current-exception-handlers*
    +   (list (lambda (condition)
    +-          (error "unhandled exception" condition))))
    ++          (error "unhandled exception" condition))))
    +=20
    + (define (with-exception-handler handler thunk)
    +   (with-exception-handlers (cons handler *current-exception-handlers*)
    +@@ -214,7 +275,7 @@ PRINTS: reraised 0
    +     (with-exception-handlers (cdr handlers)
    +       (lambda ()
    +         ((car handlers) obj)
    +-        (error "handler returned"
    ++        (error "handler returned"
    +                (car handlers)
    +                obj)))))
    +=20
    +@@ -255,7 +316,7 @@ PRINTS: reraised 0
    +            (result temp)
    +            (guard-aux reraise clause1 clause2 ...))))
    +     ((guard-aux reraise (test))
    +-     test)
    ++     (or test reraise))
    +     ((guard-aux reraise (test) clause1 clause2 ...)
    +      (let ((temp test))
    +        (if temp
    +@@ -269,10 +330,11 @@ PRINTS: reraised 0
    +      (if test
    +          (begin result1 result2 ...)
    +          (guard-aux reraise clause1 clause2 ...)))))
    +-

    References

    +-
    • SRFI 12: Exception = Handling ++ ++

      References

      ++ +=20 +-

      Copyright

      ++

      Copyright

      +=20 +

      Copyright (C) Richard Kelsey, Michael Sperber (2002). All Rights + Reserved.

      +@@ -321,6 +383,6 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF O= R IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +

      +=20 +-
      +-
      Editor: Fr= ancisco Solsona
      ++
      ++
      Editor: Francisco Solsona
      + +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-35.html b/srfi-doc/sr= fi/scribblings/srfi-std/srfi-35.html +index de261a8..a369fca 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-35.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-35.html +@@ -1,71 +1,73 @@ +- +-SRFI 35: Conditions +-

      Title

      +- +-Conditions +- +-

      Authors

      +- +-Richard Kelsey and Michael Sperber +- +-

      Status

      +- +-This SRFI is currently in ``final'' status. To see an explanation of +-each status that a SRFI can hold, see here. It will +-remain in draft until 2002-10-20, or as amended. to provide input on +-this SRFI, please mail to=20 +- +-srfi minus 35 at srfi dot schemers dot org. +-See +-instructions here to subscribe to the list. You can access +-the discussion via +- +-the archive of the mailing list. +-You can access +-post-finalization messages via +- +-the archive of the mailing list. ++ ++ ++ ++ ++ ++ SRFI 35: Conditions ++ ++ ++ ++ ++ ++ ++

      SRFI 35: Conditions

      ++ ++

      by Richard Kelsey and Michael Sperber

      ++

      This copy of the SRFI 35 specific= ation document ++is distributed as part of the Racket package ++srfi-doc.

      = The canonical source of this document is ++https://srfi.s= chemers.org/srfi-35/srfi-35.html.

      ++ ++

      Status

      ++ ++

      This SRFI is currently in final status. Here is an explanation of each stat= us that a SRFI can hold. To provide input on this SRFI, please send email = to srfi-= 35@nospamsrfi.schemers.org. To = subscribe to the list, follow these instructions. You can access previous messages= via the mailing list a= rchive.

      +=20 +
        +-
      • Draft: 2002/07/24-2002/10/20
      • +-
      • Revised: 2002/09/20
      • +-
      • Final: 2002/12/1
      • ++
      • Draft: 2002-07-24--2002-10-20
      • ++
      • Revised: 2002-09-20
      • ++
      • Final: 2002-12-01
      • +
      +=20 +-

      Abstract

      +-

      The SRFI defines constructs for creating and inspecting condition +-types and values. A condition value encapsulates information about an +-exceptional situation, or exception. This SRFI also defines a few basic +-condition types.

      +-

      Rationale

      +-

      Conditions are values that communicate information about exceptional +-situations between parts of a program. Code that detects an exception +-may be in a different part of the program than the code that handles +-it. In fact, the former may have been written independently from the +-latter. Consequently, to facilitate effective handling of exceptions, +-conditions must communicate as much information as possible as +-accurately as possible, and still allow effective handling by code that +-did not precisely anticipate the nature of the exception that occurred. +-

      This SRFI provides two mechanisms to enable this kind of communicatio= n

      • subtyping among condition types allows handling code to determ= ine the general +- nature of an exception even though it does not anticipate its exact<= /em> +- nature,
      • +-
      • compound conditions allow an exceptional situation to be described in= multiple ways.
      • ++

        Abstract

        ++

        The SRFI defines constructs for creating and inspecting condition types and values. A condition value encapsulates information about an e= xceptional situation, or exception. This SRFI also defines a few basic cond= ition types.

        ++

        Rationale

        ++

        Conditions are values that communicate information about exceptional s= ituations between parts of a program. Code that detects an exception may be= in a different part of the program than the code that handles it. In fact,= the former may have been written independently from the latter. Consequen= tly, to facilitate effective handling of exceptions, conditions must commun= icate as much information as possible as accurately as possible, and still = allow effective handling by code that did not precisely anticipate the natu= re of the exception that occurred.

        ++

        This SRFI provides two mechanisms to enable this kind of communicatio= n

        ++
          ++
        • ++ subtyping among condition types allows handling code to determine ++ the general nature of an exception even though it does ++ not anticipate its exact nature, ++
        • ++
        • ++ compound conditions allow an exceptional situation to be described ++ in multiple ways. ++
        • +
        +-

        +-

        Specification

        +-

        Conditions are records with named fields. Each condition belongs to on= e or more condition types. +-Each condition type specifies a set of field names. A condition +-belonging to a condition type includes a value for each of the type's +-field names. These values can be extracted from the condition by using +-the appropriate field name.

        ++ ++

        Specification

        ++

        Conditions are records with named fields. Each condition belongs to on= e or more condition types. Each condition type specifies a set of fi= eld names. A condition belonging to a condition type includes a value for e= ach of the type's field names. These values can be extracted from the condi= tion by using the appropriate field name.

        +

        There is a tree of condition types with the distinguished &c= ondition + as its root. All other condition types have a parent condition type.

        +-

        A condition belonging to several condition types with a common +-supertype may have distinct values for the supertype's fields for each +-type. The type used to access a field determines which of the values is +-returned. The program can extract each of these field values separately.<= /p> +-

        Procedures

        +-
        (make-condition-type id ++

        A condition belonging to several condition types with a common superty= pe may have distinct values for the supertype's fields for each type. The t= ype used to access a field determines which of the values is returned. The = program can extract each of these field values separately.

        ++

        Procedures

        ++
        ++
        (make-condition-type id + parent + field-names)
        +

        Make-condition-type +@@ -145,27 +147,28 @@ returns a condition of condition type condition= -type + is a compound condition, extract-condition + extracts the field values from the subcondition belonging to condi= tion-type + that appeared first in the call to make-compound-condition +- that created the condition. The returned condition may be newly created;= it is possible for

        (let* ((&c (make-condition-type 'c &con=
        dition '()))
        ++ that created the the condition. The returned condition may be newly crea=
        ted; it is possible for
        ++

        ++
        (let* ((&c (make-condition-type 'c &condition '()))
        +        (c0 (make-condition &c))
        +        (c1 (make-compound-condition c0)))
        +   (eq? c0 (extract-condition c1 &c)))
        +-
        to return false.

        ++
        ++

        to return false.

        +
        +
        +-

        Macros

        +-
        (define-condition-type <condition-type> <su= pertype> <predicate> <field-spec> ...)
        ++ ++

        Macros

        ++
        ++
        (define-condition-type <condition-type> <supert= ype> <predicate> <field-spec> ...)
        +

        This defines a new condition type. <Condition-type>, <sup= ertypes>, and <predicate> must all be identifiers. Define-co= ndition-type +-defines an identifier <condition-type> to some value describing +-the condition type. <supertype> must be the name of a previously +-defined condition type.

        +-

        Define-condition-type also defines <predicate> to +-a predicate that identifies conditions associated with that type, or +-with any of its subtypes.

        ++ defines an identifier <condition-type> to some value describing th= e condition type. <supertype> must be the name of a previously define= d condition type.

        ++

        Define-condition-type ++ also defines <predicate> to a predicate that identifies conditions= associated with that type, or with any of its subtypes.

        +

        Each <field-spec> must be of the form ( + <field> <accessor>) + where both <field> and <accessor> must be identifiers. Define-condition-type +-defines each <accessor> to a procedure which extracts the value +-of the named field from a condition associated with this condition type.<= /p> ++ defines each <accessor> to a procedure which extracts the value of= the named field from a condition associated with this condition type.

        +
        +
        (condition <type-field-binding> ...)<= /dt> +

        This creates a condition value. Each <type-field-binding> mu= st be of the form ( +@@ -173,9 +176,7 @@ of the named field from a condition associated with th= is condition type.

        + Each <field-binding> must be of the form ( + <field> <exp>) + where <field> is a field identifier from the definition of <con= dition-type>.

        +-

        The <exp> are evaluated in some unspecified order; their +-values can later be extracted from the condition object via the +-accessors of the associated condition types or their supertypes.

        ++

        The <exp> are evaluated in some unspecified order; their values = can later be extracted from the condition object via the accessors of the a= ssociated condition types or their supertypes.

        +

        The condition returned by condition + is created by a call of form

        +
        (make-compound-condition
        +@@ -184,47 +185,47 @@ accessors of the associated condition types or their=
         supertypes.

        +

        with the condition types retaining their order from theconditio= n + form. The field names and values are duplicated as necessary as described= below.

        +

        Each <type-field-binding> must contain field bindings for al= l +-fields of <condition-type> without duplicates. There is an +-exception to this rule: if a field binding is missing, and the field +-belongs to a supertype shared with one of the other +-<type-field-binding> subforms, then the value defaults to that of +-the first such binding in the condition ++ fields of <condition-type> without duplicates. There is an except= ion to this rule: if a field binding is missing, and the field belongs to a= supertype shared with one of the other <type-field-binding> subforms= , then the value defaults to that of the first such binding in the co= ndition + form.

        +
        +
        +-

        Standard Conditions

        +-
        &condition ++ ++

        Standard Conditions

        ++
        ++
        &condition +
        +

        This is the root of the entire condition type hierarchy. It has a = no fields.

        +
        +
        &message +
        +-

        This condition type could be defined by

        (define-condition-=
        type &message &condition
        ++

        This condition type could be defined by

        ++
        (define-condition-type &message &condition
        +   message-condition?
        +   (message condition-message))
        +-

        ++
        +

        It carries a message further describing the nature of the condition to= humans.

        +
        +
        &serious +
        +-

        This condition type could be defined by

        (define-condition-=
        type &serious &condition
        ++

        This condition type could be defined by

        ++
        (define-condition-type &serious &condition
        +   serious-condition?)
        +-

        +-

        This type describes conditions serious enough that they cannot +-safely be ignored. This condition type is primarily intended as a +-supertype of other condition types.

        +-
        &error ++
        ++

        This type describes conditions serious enough that they cannot safely= be ignored. This condition type is primarily intended as a supertype of o= ther condition types.

        ++
        ++
        &error +
        +-

        This condition type could be defined by

        (define-condition-=
        type &error &serious
        ++

        This condition type could be defined by ++

        ++
        (define-condition-type &error &serious
        +   error?)
        +-

        +-

        This condition describes errors, typically caused by something that +-has gone wrong in the interaction of the program with the external +-world or the user.

        ++
        ++

        This condition describes errors, typically caused by something that ha= s gone wrong in the interaction of the program with the external world or t= he user.

        +
        +- +
        +-

        Examples

        ++ ++ ++

        Examples

        +
        (define-condition-type &c &condition
        +   c?
        +   (x c-x))
        +@@ -284,10 +285,11 @@ world or the user.

        + (c-x v5) =3D> "V2" + (c1-a v5) =3D> "a3" + (c2-b v5) =3D> "b2" +-

        Reference Implementation

        +-

        The reference implementation makes use of SRFI 1 +- ("List Library"), SRFI 9 +- ("Defining Record Types"), and SRFI 23 ++ ++

        Reference Implementation

        ++

        The reference implementation makes use of SRFI= 1 ++ ("List Library"), SRFI 9 ++ ("Defining Record Types"), and SRFI 23 + ("Error reporting mechanism").

        +
        (define-record-type :condition-type
        +   (really-make-condition-type name supertype fields all-fields)
        +@@ -463,15 +465,16 @@ world or the user.

        +=20 + (define-condition-type &error &serious + error?) +-

        References

        +-
        • SRFI 12: Exception = Handling ++ ++

          References

          ++ +=20 +-

          Copyright

          ++

          Copyright

          +=20 +

          Copyright (C) Richard Kelsey, Michael Sperber (2002). All Rights + Reserved.

          +@@ -509,7 +512,6 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF O= R IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +

          +=20 +-
          ++
          +
          Editor: Francisco Solsona
          +- + +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-38.html b/srfi-doc/sr= fi/scribblings/srfi-std/srfi-38.html +index 378fbd2..535754c 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-38.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-38.html +@@ -1,61 +1,74 @@ +- +- ++ ++ + ++ ++ + SRFI 38: External Representation for Data With Shared Structur= e ++ ++ ++ + +=20 + +=20 +-

          Title

          ++

          SRFI 38: External Representation for Data With Shared Structure

          +=20 +-External Representation for Data With Shared Structure ++

          by Ray Dillinger

          ++

          This copy of the SRFI 38 specific= ation document ++is distributed as part of the Racket package ++srfi-doc.

          = The canonical source of this document is ++https://srfi.s= chemers.org/srfi-38/srfi-38.html.

          +=20 +-

          Author

          ++

          Status

          +=20 +-Ray Dillinger ++

          This SRFI is currently in final status. Here is an explanation of each stat= us that a SRFI can hold. To provide input on this SRFI, please send email = to srfi-= 38@nospamsrfi.schemers.org. To = subscribe to the list, follow these instructions. You can access previous messages= via the mailing list a= rchive.

          ++
            ++
          • Draft: 2002-12-20--2003-04-02
          • ++
          • Final: 2003-04-02
          • ++
          +=20 +-

          Status

          +- +-This SRFI is currently in ``final'' status. To see an explanation of +-each status that a SRFI can hold, see here. +-You can access +-the discussion via +- +-the archive of the mailing list. +- +-
            +-
          • Draft: 2002/12/20-2003/04/02
          • +-
          • Final: 2003/04/02
          • +-
          +- +-

          Abstract

          +-

          ++

          Abstract

          ++

          + This SRFI proposes (write-with-shared-structure) and=20 + (read-with-shared-structure), procedures for writing + and reading external representations of data containing shared + structure. These procedures implement a proposed standard + external notation for data containing shared structure. +-

          +-

          ++

          ++

          + This SRFI permits but does not require replacing the standard + (write) and (read) functions. These functions + may be implemented without the overhead in time and space required + to detect and specify shared structure. +-

          +-

          ++

          ++

          + An implementation conforms to this SRFI if it provides procedures + named (write-with-shared-structure) and + (read-with-shared-structure), which produce and read + the same notation as produced by the reference implementation. + It may also provide (read/ss) and (write/ss), + equivalent functions with shorter names. +-

          ++

          +=20 +=20 +-

          Rationale

          ++

          Rationale

          +=20 +-

          ++

          +=20 + R5RS scheme and IEEE scheme provide the procedure (write), + which prints machine-readable representations of lists and other +@@ -65,8 +78,8 @@ case of self-referential objects the behavior of (wr= ite) + itself is undefined; it is permitted to go into an infinite loop or + invoke the dreaded curse of the nasal demons. +=20 +-

          +-

          ++

          ++

          +=20 + For example, it is possible to have a list within which two or more + members are the same string (in the sense of (eq?)), but when +@@ -75,17 +88,18 @@ representation to recover the (eq?) relations= hip. When the + list is read back in, there will be two or more copies of the string + which are (eqv?) but not (eq?). +=20 +-

          +-

          ++

          ++

          + As an example of the second problem, The results of evaluating +-

          ++

          ++
          + (begin (define a (cons 'val1 'val2))
          +        (set-cdr! a a)
          +        (write a))
          +-
          ++
          +=20 +-are undefined; in R5RS parlance, calling write on such a structure +-"is an error", but not one that is necessarily ++

          are undefined; in R5RS parlance, calling write on such a structure ++"is an error", but not one that is necessarily + signalled. The routine is permitted to print a nonstandard notation + such as the one proposed in this standard or a different one, fail + silently, signal an error, go into an infinite loop, or make demons +@@ -95,33 +109,34 @@ problem by providing a method of writing data which i= s guaranteed to + be well-behaved and predictable even on data containing shared + structures. +=20 +-

          ++

          +=20 +-

          ++

          +=20 + The extended functionality described below in the implementation of + (write-with-shared-structure)is already present in the + (write) function of several major scheme implementations + (PLT, SISC, Chez, Bigloo, MIT scheme, and possibly others). +=20 +-

          ++

          +=20 +-

          Specification

          +-

          ++

          Specification

          +=20 +

          Formal Grammar of the New External Representation

          ++

          + This SRFI creates an alternative external representation for data + written and read under (write/ss) and (read/ss). + It is identical to the grammar for external representation for data + written and read under (write) and (read) given in + section 7 of R5RS, except that the single production +-

          ++

          ++
          +=20
          + <datum> --> <simple datum> | <compound datum>=20
          +=20
          +-
          +-Is replaced by the following five productions. +-
          ++
          ++

          Is replaced by the following five productions.

          ++
          +=20
          + <datum> --> <defining datum> | <nondefining datum> |=
           <defined datum>
          +=20
          +@@ -132,26 +147,25 @@ Is replaced by the following five productions.
          + <nondefining datum> --> <simple datum> | <compound datu=
          m>=20
          +=20
          + <indexnum> --> <digit 10>+
          +-
          +-

          ++
          +=20 +

          New Procedures

          +-

          +-

          +=20
          +-[[library procedure]] (write-with=
          -shared-structure obj)
          ++
          ++
          ++[[library procedure]] (write-with-shared-structure obj)
          + [[library procedure]] (write-with-shared-structure obj port)
          + [[library procedure]] (write-with-shared-structure obj port optarg)
          +=20
          +-
          +- ++
          ++

          + Writes a written representation of obj to the given port. Strings that + appear in the written representation are enclosed in doublequotes, and + within those strings backslash and doublequote characters are escaped + by backslashes. Character objects are written using the #\ + notation.=20 +=20 +-

          ++

          +=20 + Objects which denote locations rather than values (cons cells, + vectors, and non-zero-length strings in R5RS scheme; also mutable +@@ -164,15 +178,15 @@ If objects which denote locations occur only once in= the structure, + then (write-with-shared-structure) must produce the same + external representation for those objects as (write). +=20 +-

          ++

          +=20 +-

          ++

          +=20 + Write-with-shared-structure must terminate in finite time when writing + finite data. Write-with-shared-structure must produce a finite + representation when writing finite data. +=20 +-

          ++

          +=20 + Write-with-shared-structure returns an unspecified value. The port + argument may be omitted, in which case it defaults to the value +@@ -184,30 +198,29 @@ still write a representation that can be read by + use optarg to specify formatting conventions, numeric radixes, or + return values. The reference implementation ignores optarg. +=20 +-

          +-

          ++

          ++

          +=20 +-For example, the code +-

          ++For example, the code

          ++
          +=20
          + (begin (define a (cons 'val1 'val2))
          +        (set-cdr! a a)
          +        (write-with-shared-structure a))
          +=20
          +-
          ++
          +=20 +-should produce the output #1=3D(val1 . #1#) . This shows a cons ++

          should produce the output #1=3D(val1 . #1#) . This shows a = cons + cell whose cdr contains itself. ++

          +=20 +-

          +- +-

          ++
          +=20
          +-[[library procedure]] (read-with-s=
          hared-structure)
          ++[[library procedure]] (read-with-shared-structure)
          + [[library procedure]] (read-with-shared-structure  port)
          +=20
          +-
          +- ++
          ++

          + (read-with-shared-structure) converts the external + representations of Scheme objects produced by + (write-with-shared-structure) into scheme objects. That is, +@@ -217,7 +230,7 @@ external representation grammar defined above. + from the given input port, updating port to point to the first + character past the end of the external representation of the object. +=20 +-

          ++

          +=20 + If an end-of-file is encountered in the input before any characters + are found that can begin an object, then an end-of-file object is +@@ -228,20 +241,20 @@ the beginning of an object's external representation= , but the external + representation is incomplete and therefore not parsable, an error is + signalled. +=20 +-

          ++

          +=20 + The port argument may be omitted, in which case it defaults to the + value returned by (current-input-port). It is an error to + read from a closed port. +=20 +-

          ++

          +=20 +=20 +=20 +=20 +-

          Implementation

          ++

          Implementation

          +=20 +-

          ++

          +=20 + The reference implementation of (write-with-shared-structure) + is based on an implementation provided by Al Petrofsky. If there are +@@ -251,17 +264,17 @@ for an optional port argument. The reference implem= entation of + provided by Al Petrofsky. Both are used here with his generous + permission. +=20 +-

          ++

          +=20 +-

          ++

          +=20 + Note that portability forces the reference implementation of + (write-with-shared-structure) to be O(N^2) but that if an + implementor tracks objects through additional fields hidden from R5RS + scheme, a more efficient implementation can be provided. +=20 +-

          +-

          ++

          ++

          +=20 + If all the locations in your scheme are mutable and you don't do any + locking or multithreading, you can write an O(n) version that +@@ -273,10 +286,10 @@ does not give the programmer access to mutability in= formation nor to + comparison of constant data's addresses, but both of these are trivial + operations if you have access to the system's internals. +=20 +-

          ++

          +=20 +=20 +-
          ++
          + ;;; A printer that shows all sharing of substructures.  Uses the Common
          + ;;; Lisp print-circle notation: #n# refers to a previous substructure
          + ;;; labeled with #n=3D.   Takes O(n^2) time.
          +@@ -354,7 +367,7 @@ operations if you have access to the system's internal=
          s.
          +     (define (scan obj alist)
          +       (cond ((not (interesting? obj)) alist)
          + 	    ((assq obj alist)
          +-             =3D> (lambda (p) (if (cdr p) alist (acons obj #t alist))))
          ++             =3D> (lambda (p) (if (cdr p) alist (acons obj #t alist))))
          + 	    (else
          + 	     (let ((alist (acons obj #f alist)))
          + 	       (cond ((pair? obj) (scan (car obj) (scan (cdr obj) alist)))
          +@@ -406,7 +419,7 @@ operations if you have access to the system's internal=
          s.
          + 	(if (eof-object? c)
          + 	    (error "EOF inside a string")
          + 	    (case c
          +-	      ((#\") (list->string (reverse chars)))
          ++	      ((#\") (list->string (reverse chars)))
          + 	      ((#\\) (read-it (cons (read-char*) chars)))
          + 	      (else (read-it (cons c chars))))))))
          +=20
          +@@ -415,7 +428,7 @@ operations if you have access to the system's internal=
          s.
          +     (let iter ((chars '()))
          +       (let ((c (peek-char*)))
          + 	(if (or (eof-object? c) (not (pred c)))
          +-	    (list->string (reverse chars))
          ++	    (list->string (reverse chars))
          + 	    (iter (cons (read-char*) chars))))))
          +=20
          +   ;; reads a character after the #\ has been read.
          +@@ -433,11 +446,11 @@ operations if you have access to the system's intern=
          als.
          +   (define (read-number first-char)
          +     (let ((str (string-append (string first-char)
          + 			      (read-some-chars not-delimiter?))))
          +-      (or (string->number str)
          ++      (or (string->number str)
          + 	  (error "Malformed number: " str))))
          +=20
          +   (define char-standard-case
          +-    (if (char=3D? #\a (string-ref (symbol->string 'a) 0))
          ++    (if (char=3D? #\a (string-ref (symbol->string 'a) 0))
          + 	char-downcase
          + 	char-upcase))
          +=20
          +@@ -449,10 +462,10 @@ operations if you have access to the system's intern=
          als.
          + 	(string-set! new i (char-standard-case (string-ref str i))))))
          +=20
          +   (define (read-identifier)
          +-    (string->symbol (string-standard-case (read-some-chars not-delimiter?=
          ))))
          ++    (string->symbol (string-standard-case (read-some-chars not-delimit=
          er?))))
          +=20
          +   (define (read-part-spec)
          +-    (let ((n (string->number (read-some-chars char-numeric?))))
          ++    (let ((n (string->number (read-some-chars char-numeric?))))
          +       (let ((c (read-char*)))
          + 	(case c
          + 	  ((#\=3D) (cons 'decl n))
          +@@ -525,8 +538,8 @@ operations if you have access to the system's internal=
          s.
          + 	(if (char? (car first-token))
          + 	    (case (car first-token)
          + 	      ((#\() (read-list-tail))
          +-	      ((#\#) (list->vector (read-list-tail)))
          +-	      ((#\. #\)) (error (string-append "Unexpected \"" first-token "\"")=
          ))
          ++	      ((#\#) (list->vector (read-list-tail)))
          ++	      ((#\. #\)) (error (string-append "Unexpected \"" (string (car firs=
          t-token)) "\"")))
          + 	      (else
          + 	       (list (caadr (assv (car first-token)
          + 				  '((#\' 'x) (#\, ,x) (#\` `x) (#\@ ,@x))))
          +@@ -542,7 +555,7 @@ operations if you have access to the system's internal=
          s.
          + 			((use)
          + 			 ;; To use a part, it must have been
          + 			 ;; declared before this chain started.
          +-			 (cond ((assv n starting-alist) =3D> cdr)
          ++			 (cond ((assv n starting-alist) =3D> cdr)
          + 			       (else (error "Use of undeclared part " n))))
          + 			((decl)
          + 			 (if (assv n parts-alist)
          +@@ -596,10 +609,10 @@ operations if you have access to the system's intern=
          als.
          + 		       (fill-in-parts elt))))))))
          +     obj))
          +=20
          +-
          ++
          +=20 +=20 +-

          Copyright

          ++

          Copyright

          +

          Copyright (C) Ray Dillinger 2003. All Rights Reserved.

          +=20 +

          +@@ -625,13 +638,11 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF= OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +

          +=20 +-
          +-
          Editor: David Rush ++
          ++
          Editor: David Rush
          + + +-Last modified: Wed Apr 2 19:58:58 BST 2003 ++Last modified: Wed Jan 19 08:52:24 MET 2011 + + + +- +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-39.html b/srfi-doc/sr= fi/scribblings/srfi-std/srfi-39.html +index efd33ed..792b2aa 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-39.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-39.html +@@ -1,69 +1,82 @@ +- +- ++ ++ + ++ ++ + SRFI 39: Parameter objects ++ ++ ++ + +=20 + +=20 +-

          Title

          ++

          SRFI 39: Parameter objects

          +=20 +-SRFI 39: Parameter objects ++

          by Marc Feeley

          ++

          This copy of the SRFI 39 specific= ation document ++is distributed as part of the Racket package ++srfi-doc.

          = The canonical source of this document is ++https://srfi.s= chemers.org/srfi-39/srfi-39.html.

          +=20 +-

          Author

          ++

          Status

          +=20 +-Marc Feeley ++

          This SRFI is currently in final status. Here is an explanation of each stat= us that a SRFI can hold. To provide input on this SRFI, please send email = to srfi-= 39@nospamsrfi.schemers.org. To = subscribe to the list, follow these instructions. You can access previous messages= via the mailing list a= rchive.

          ++
            ++
          • Draft: 2002-12-21--2003-02-18
          • ++
          • Revised: 2003-05-15
          • ++
          • Final: 2003-06-30
          • ++
          +=20 +-

          Status

          +=20 +-This SRFI is currently in ``final'' status. To see an explanation of +-each status that a SRFI can hold, see here.=20=20 +-You can access +-previous messages via +- +-the archive of the mailing list. ++

          Abstract

          +=20 +-
            +-
          • Draft: 2002/12/21-2003/02/18
          • +-
          • Revised: 2003/5/15
          • +-
          • Final: 2003/6/30
          • +-
          +- +- +-

          Abstract

          +- +-

          +-This SRFI defines parameter objects, the procedure +-make-parameter to +-create parameter objects and the parameterize special ++

          ++This SRFI defines parameter objects, the procedure ++make-parameter to ++create parameter objects and the parameterize special + form to dynamically bind parameter objects. In the dynamic + environment, each parameter object is bound to a cell containing the + value of the parameter. When a procedure is called the called + procedure inherits the dynamic environment from the caller. The +-parameterize special form allows the binding of a ++parameterize special form allows the binding of a + parameter object to be changed for the dynamic extent of its body. +-

          ++

          +=20 +-

          Rationale

          ++

          Rationale

          +=20 +-

          +-The dynamic environment is the structure which allows ++

          ++The dynamic environment is the structure which allows + the system to find the value returned by the R5RS procedures +-current-input-port and current-output-port. +-The R5RS procedures with-input-from-file and +-with-output-to-file extend the dynamic environment to ++current-input-port and current-output-port. ++The R5RS procedures with-input-from-file and ++with-output-to-file extend the dynamic environment to + produce a new dynamic environment which is in effect for the dynamic + extent of the call to the thunk passed as their last argument. These + procedures are essentially special purpose dynamic binding operations +-on hidden dynamic variables (one for current-input-port +-and one for current-output-port). The purpose of this ++on hidden dynamic variables (one for current-input-port ++and one for current-output-port). The purpose of this + SRFI is to generalize this dynamic binding mechanism (which exists in + all R5RS compliant systems) to allow the user to introduce new dynamic + variables and dynamically bind them. +-

          ++

          +=20 +-

          ++

          + General dynamic binding mechanisms exist in several implementations of + Scheme under various names, including "fluid" variables and parameter + objects. The parameter objects specified in this SRFI are compatible +@@ -72,9 +85,9 @@ currently support parameter objects (in the sense that i= t is possible + to implement this SRFI so that old code works the same as before). We + believe Chez-Scheme was the first implementation of Scheme to have + used parameter objects. +-

          ++

          +=20 +-

          ++

          + In the presence of threads, the dynamic binding mechanism does not + behave the same way in all implementations of Scheme supporting + dynamic binding. The issue is the relationship between the dynamic +@@ -92,105 +105,105 @@ environment share the same cells (i.e. an assignmen= t of a value to a + dynamic variable is visible in the other thread). Note that in the + absence of assignment to dynamic variables the MzScheme and Gambit-C + approaches are equivalent. +-

          ++

          +=20 +-

          ++

          + Given that there are semantic differences in the presence of threads + and that there are valid reasons for choosing each semantics, this + SRFI does not specify the semantics of parameter objects in the + presence of threads. It is left to the implementation and other SRFIs + which extend this SRFI to specify the interaction between parameter + objects and threads. +-

          ++

          +=20 +-

          Specification

          ++

          Specification

          +=20 +-

          +-The dynamic environment is composed of two parts: the local +-dynamic environment and the global dynamic environment. ++

          ++The dynamic environment is composed of two parts: the local ++dynamic environment and the global dynamic environment. + The global dynamic environment is used to lookup parameter objects + that can't be found in the local dynamic environment. When parameter + objects are created, their initial binding is put in the global + dynamic environment (by mutation). The local dynamic environment is +-only extended by the parameterize form. +-

          +- +-

          +-Parameter objects are created with the +-make-parameter procedure which takes one or two +-arguments. The second argument is a one argument conversion +-procedure. If only one argument is passed to +-make-parameter the identity function is used as a ++only extended by the parameterize form. ++

          ++ ++

          ++Parameter objects are created with the ++make-parameter procedure which takes one or two ++arguments. The second argument is a one argument conversion ++procedure. If only one argument is passed to ++make-parameter the identity function is used as a + conversion procedure. The global dynamic environment is updated to + associate the parameter object to a new cell. The initial content of + the cell is the result of applying the conversion procedure to the +-first argument of make-parameter. +-

          ++first argument of make-parameter. ++

          +=20 +-

          +-A parameter object is a procedure which accepts zero or one ++

          ++A parameter object is a procedure which accepts zero or one + argument. The cell bound to a particular parameter object in the + dynamic environment is accessed by calling the parameter object. When + no argument is passed, the content of the cell is returned. When one + argument is passed the content of the cell is updated with the result + of applying the parameter object's conversion procedure to the + argument. +-

          ++

          +=20 +-

          +-The parameterize special form, when given a parameter ++

          ++The parameterize special form, when given a parameter + object and a value, binds for the dynamic extent of its body the + parameter object to a new cell. The initial content of the cell is + the result of applying the parameter object's conversion procedure to +-the value. The parameterize special form behaves +-analogously to let when binding more than one parameter ++the value. The parameterize special form behaves ++analogously to let when binding more than one parameter + object (that is the order of evaluation is unspecified and the new +-bindings are only visible in the body of the parameterize ++bindings are only visible in the body of the parameterize + special form). +-

          ++

          +=20 +-

          ++

          + Note that the conversion procedure can be used for guaranteeing the + type of the parameter object's binding and/or to perform some + conversion of the value. +-

          ++

          +=20 +-

          ++

          + Because it is possible to implement the R5RS procedures +-current-input-port and current-output-port ++current-input-port and current-output-port + as parameter objects and this offers added functionnality, it is + required by this SRFI that they be implemented as parameter objects +-created with make-parameter. +-

          ++created with make-parameter. ++

          +=20 +-

          Procedures and syntax

          ++

          Procedures and syntax

          +=20 +-
          ++
          +=20 +-
          +-(make-parameter init [converter]=
          )                     ;procedure
          +-
          ++
          ++(make-parameter init [converter])                     ;proc=
          edure
          ++
          +=20 +-

          ++

          + Returns a new parameter object which is bound in the global dynamic + environment to a cell containing the value returned by the call +-(converter init). If the conversion +-procedure converter is not specified the identity function is ++(converter init). If the conversion ++procedure converter is not specified the identity function is + used instead. +-

          ++

          +=20 +-

          ++

          + The parameter object is a procedure which accepts zero or one + argument. When it is called with no argument, the content of the cell + bound to this parameter object in the current dynamic environment is + returned. When it is called with one argument, the content of the + cell bound to this parameter object in the current dynamic environment +-is set to the result of the call (converter +-arg), where arg is the argument passed to the ++is set to the result of the call (converter ++arg), where arg is the argument passed to the + parameter object, and an unspecified value is returned. +-

          ++

          +=20 +-
          ++
          +     (define radix
          +       (make-parameter 10))
          +=20
          +@@ -202,9 +215,9 @@ parameter object, and an unspecified value is returned.
          +               x
          +               (error "only booleans are accepted by write-shared")))))
          +=20
          +-    (radix)           =3D=3D>  10
          ++    (radix)           =3D=3D>  10
          +     (radix 2)
          +-    (radix)           =3D=3D>  2
          ++    (radix)           =3D=3D>  2
          +     (write-shared 0)  gives an error
          +=20
          +     (define prompt
          +@@ -215,58 +228,61 @@ parameter object, and an unspecified value is return=
          ed.
          +               x
          +               (with-output-to-string (lambda () (write x)))))))
          +=20
          +-    (prompt)       =3D=3D>  "123"
          +-    (prompt ">")
          +-    (prompt)       =3D=3D>  ">"
          +-
          +- +-

          +-

          +-(parameterize ((expr1 expr2) ...) =
          <body>)             ;syntax
          +-
          ++ (prompt) =3D=3D> "123" ++ (prompt ">") ++ (prompt) =3D=3D> ">" ++
          ++
          ++
          ++(parameterize ((expr1 expr2) ...) <body>)     =
                  ;syntax
          ++
          ++
          ++
          +=20 +-

          +- The expressions expr1 and expr2 are evaluated in an +- unspecified order. The value of the expr1 expressions must +- be parameter objects. For each expr1 expression and in an ++

          ++ The expressions expr1 and expr2 are evaluated in an ++ unspecified order. The value of the expr1 expressions must ++ be parameter objects. For each expr1 expression and in an + unspecified order, the local dynamic environment is extended with +- a binding of the parameter object expr1 to a new cell whose +- content is the result of the call (converter +- val), where val is the value of expr2 +- and converter is the conversion procedure of the parameter ++ a binding of the parameter object expr1 to a new cell whose ++ content is the result of the call (converter ++ val), where val is the value of expr2 ++ and converter is the conversion procedure of the parameter + object. The resulting dynamic environment is then used for the +- evaluation of <body> (which refers to the R5RS grammar ++ evaluation of <body> (which refers to the R5RS grammar + nonterminal of that name). The result(s) of the +- parameterize form are the result(s) of the +- <body>. +-

          ++ parameterize form are the result(s) of the ++ <body>. ++

          +=20 +-
          +-    (radix)                                              =3D=3D>  2
          +-    (parameterize ((radix 16)) (radix))                  =3D=3D>  16
          +-    (radix)                                              =3D=3D>  2
          ++
          ++    (radix)                                              =3D=3D>  2
          ++    (parameterize ((radix 16)) (radix))                  =3D=3D>  16
          ++    (radix)                                              =3D=3D>  2
          +=20
          +-    (define (f n) (number->string n (radix)))
          ++    (define (f n) (number->string n (radix)))
          +=20
          +-    (f 10)                                               =3D=3D>  "1010"
          +-    (parameterize ((radix 8)) (f 10))                    =3D=3D>  "12"
          +-    (parameterize ((radix 8) (prompt (f 10))) (prompt))  =3D=3D>  "1010"
          +-
          ++ (f 10) =3D=3D> "101= 0" ++ (parameterize ((radix 8)) (f 10)) =3D=3D> "12" ++ (parameterize ((radix 8) (prompt (f 10))) (prompt)) =3D=3D> "101= 0" ++
          ++
          ++
          +=20 +-

          Implementation

          ++

          Implementation

          +=20 +-

          ++

          + The following implementation uses association lists to represent local + dynamic environments. The global dynamic environment binding is + stored in the parameter object itself. Since we are assuming that + there is a single thread, the current local dynamic environment can be +-bound to a global variable, dynamic-env-local. Mutations +-of this variable are wrapped in a dynamic-wind so that ++bound to a global variable, dynamic-env-local. Mutations ++of this variable are wrapped in a dynamic-wind so that + the local dynamic environment returns to its previous value when +-control exits the body of the parameterize. +-

          ++control exits the body of the parameterize. ++

          +=20 +-
          ++
          +     (define make-parameter
          +       (lambda (init . conv)
          +         (let ((converter
          +@@ -320,9 +336,9 @@ control exits the body of the parameterize.
          +=20
          +     (define dynamic-env-local-set!
          +       (lambda (new-env) (set! dynamic-env-local new-env)))
          +-
          ++
          +=20 +-

          Copyright

          ++

          Copyright

          +

          Copyright (C) Marc Feeley 2002. All Rights Reserved.

          +=20 +

          +@@ -349,7 +365,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE = SOFTWARE. +

          +=20 +=20 +-
          +-
          Editor: Mi= ke Sperber
          ++
          ++
          Editor: Mike Sperber
          + + +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-4.html b/srfi-doc/srf= i/scribblings/srfi-std/srfi-4.html +index f48174f..d11a35a 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-4.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-4.html +@@ -1,34 +1,51 @@ +- +- ++ ++ + ++ ++ + SRFI 4: Homogeneous numeric vector datatypes ++ ++ ++ + +=20 + +=20 +-

          Title

          ++

          SRFI 4: Homogeneous numeric vector datatypes

          +=20 +-SRFI-4: Homogeneous numeric vector datatypes ++

          by Marc Feeley

          ++

          This copy of the SRFI 4 specifica= tion document ++is distributed as part of the Racket package ++srfi-doc.

          = The canonical source of this document is ++https://srfi.sch= emers.org/srfi-4/srfi-4.html.

          +=20 +-

          Author

          ++

          Status

          +=20 +-Marc Feeley +- +-

          Status

          +-This SRFI is currently in ``final'' status. To see an explanation of +-each status that a SRFI can hold, see here. +-You can access previous messages via the a= rchive of the mailing list. +-

            +-
          • Received: 1998/1/11 +-
          • Draft: 1999/1/19-1999/03/19 +-
          • Revised: 1999/04/26 +-
          • Final: 1999/5/22 +-
          +- +-

          Abstract

          ++

          This SRFI is currently in final status. Here is an explanation of each stat= us that a SRFI can hold. To provide input on this SRFI, please send email = to srfi-4= @nospamsrfi.schemers.org. To su= bscribe to the list, follow these instructions. You can access previous messages v= ia the mailing list arch= ive.

          ++
            ++
          • Received: 1998-01-11
          • ++
          • Draft: 1999-01-19--1999-03-19
          • ++
          • Revised: 1999-04-26
          • ++
          • Final: 1999-05-22
          • ++
          +=20 ++

          Abstract

          ++

          + This SRFI describes a set of datatypes for vectors whose elements are + of the same numeric type (signed or unsigned exact integer or inexact + real of a given precision). These datatypes support operations +@@ -37,9 +54,9 @@ An external representation is specified which must be su= pported by the + read and write procedures and by the program + parser (i.e. programs can contain references to literal homogeneous + vectors). +- +-

          Rationale

          +- ++

          ++

          Rationale

          ++

          + Like lists, Scheme vectors are a heterogeneous datatype which impose + no restriction on the type of the elements. This generality is not + needed for applications where all the elements are of the same type. +@@ -51,76 +68,74 @@ Moreover, homogeneous vectors are convenient for inter= facing with + low-level libraries (e.g. binary block I/O) and to interface with + foreign languages which support homogeneous vectors. Finally, the use + of homogeneous vectors allows certain errors to be caught earlier. +- +-

          +- ++

          ++

          + This SRFI specifies a set of homogeneous vector datatypes which cover + the most practical case, that is where the type of the elements is + numeric (exact integer or inexact real) and the precision and + representation is efficiently implemented on the hardware of most + current computer architectures (8, 16, 32 and 64 bit integers, either + signed or unsigned, and 32 and 64 bit floating point numbers). ++

          +=20 +-

          Specification

          +- ++

          Specification

          ++

          + There are 8 datatypes of exact integer homogeneous vectors (which will + be called integer vectors): ++

          ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++
          datatype type of elements<= /strong> ++
          s8vector signed exact integer in the r= ange -(2^7) to (2^7)-1 ++
          u8vector unsigned exact integer in the= range 0 to (2^8)-1 ++
          s16vectorsigned exact integer in the r= ange -(2^15) to (2^15)-1 ++
          u16vectorunsigned exact integer in the= range 0 to (2^16)-1 ++
          s32vectorsigned exact integer in the r= ange -(2^31) to (2^31)-1 ++
          u32vectorunsigned exact integer in the= range 0 to (2^32)-1 ++
          s64vectorsigned exact integer in the r= ange -(2^63) to (2^63)-1 ++
          u64vectorunsigned exact integer in the= range 0 to (2^64)-1 ++
          +=20 +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +-
          datatype type of elements +-
          s8vector signed exact i= nteger in the range -(2^7) to (2^7)-1 +-
          u8vector unsigned exact= integer in the range 0 to (2^8)-1 +-
          s16vectorsigned exact = integer in the range -(2^15) to (2^15)-1 +-
          u16vectorunsigned exac= t integer in the range 0 to (2^16)-1 +-
          s32vectorsigned exact = integer in the range -(2^31) to (2^31)-1 +-
          u32vectorunsigned exac= t integer in the range 0 to (2^32)-1 +-
          s64vectorsigned exact = integer in the range -(2^63) to (2^63)-1 +-
          u64vectorunsigned exac= t integer in the range 0 to (2^64)-1 +-
          +- +-

          +- ++

          + There are 2 datatypes of inexact real homogeneous vectors (which will + be called float vectors): ++

          +=20 +- +- +- +- +- +- +- +-
          datatype type of elements +-
          f32vector inexact real +-
          f64vector inexact real +-
          +- +-

          ++ ++ ++ ++ ++ ++ ++ ++
          datatype type of elements<= /strong> ++
          f32vector inexact real ++
          f64vector inexact real ++
          +=20 ++

          + The only difference between the two float vector types is that + f64vectors preserve at least as much precision as + f32vectors (see the implementation section for details). +- +-

          +- ++

          ++

          + A Scheme system that conforms to this SRFI does not have to support + all of these homogeneous vector datatypes. However, a Scheme system + must support f32vectors and f64vectors if it +@@ -138,17 +153,15 @@ the Scheme system supports by calling the + string->number procedure (e.g. + (string->number "0.0") returns #f if the + Scheme system does not support inexact reals). +- +-

          +- ++

          ++

          + Each homogeneous vector datatype has an external representation which + is supported by the read and write + procedures and by the program parser. Each datatype also has a set of + associated predefined procedures analogous to those available for + Scheme's heterogeneous vectors. +- +-

          +- ++

          ++

          + For each value of TAG in { + s8, u8, + s16, u16, +@@ -156,30 +169,27 @@ For each value of TAG in { + s64, u64, + f32, f64 + }, if the datatype TAGvector is supported, then ++

          +=20 +-

          +- +-
            +- +-
          1. the external representation of instances of the datatype ++
              ++
            1. ++

              ++ the external representation of instances of the datatype + TAGvector is #TAG( ...elements... ). +- +-

              +- ++

              ++

              + For example, #u8(0 #e1e2 #xff) is an + u8vector of length 3 containing 0, 100 and 255; + #f64(-1.5) is an f64vector of length 1 + containing -1.5. +- +-

              +- ++

              ++

              + Note that the syntax for float vectors conflicts with Standard Scheme + which parses #f32() as 3 objects: #f, + 32 and (). For this reason, conformance to + this SRFI implies this minor nonconformance to Standard Scheme. +- +-

              +- ++

              ++

              + This external representation is also available in program source code. + For example, (set! x '#u8(1 2 3)) will set x + to the object #u8(1 2 3). Literal homogeneous vectors +@@ -189,22 +199,23 @@ vectors can appear in quasiquotations but must not c= ontain + (i.e. `(,x #u8(1 2)) is legal but `#u8(1 ,x + 2) is not). This restriction is to accommodate the many Scheme + systems that use the read procedure to parse programs. +- +-

              +- +-
            2. the following predefined procedures are available: +- +-
                +-
              1. (TAGvector? obj) +-
              2. (make-TAGvector n [ TAGvalue ]) +-
              3. (TAGvector TAGvalue...) +-
              4. (TAGvector-length TAGvect) +-
              5. (TAGvector-ref TAGvect i) +-
              6. (TAGvector-set! TAGvect i TAGvalue) +-
              7. (TAGvector->list TAGvect) +-
              8. (list->TAGvector TAGlist) +-
              +- ++

              ++
            3. ++
            4. ++

              ++ the following predefined procedures are available: ++

              ++
                ++
              1. (TAGvector? obj)
              2. ++
              3. (make-TAGvector n [ TAGvalue ])
              4. ++
              5. (TAGvector TAGvalue...)
              6. ++
              7. (TAGvector-length TAGvect)
              8. ++
              9. (TAGvector-ref TAGvect i)
              10. ++
              11. (TAGvector-set! TAGvect i TAGvalue)
              12. ++
              13. (TAGvector->list TAGvect)
              14. ++
              15. (list->TAGvector TAGlist)
              16. ++
              ++

              + where obj is any Scheme object, n is a + nonnegative exact integer, i is a nonnegative exact + integer less than the length of the vector, TAGvect is an +@@ -213,41 +224,40 @@ is a number of the type acceptable for elements of t= he + TAGvector datatype, and TAGlist is a proper + list of numbers of the type acceptable for elements of the + TAGvector datatype. +- +-

              +- ++

              ++

              + It is an error if TAGvalue is not the same type as the + elements of the TAGvector datatype (for example if an + exact integer is passed to f64vector). If the fill + value is not specified, the content of the vector is unspecified + but individual elements of the vector are guaranteed to be in the + range of values permitted for that type of vector. ++

              ++
            5. ++
            +=20 +-
          +- +-

          Implementation

          +- ++

          Implementation

          ++

          + The homogeneous vector datatypes described here suggest a concrete + implementation as a sequence of 8, 16, 32 or 64 bit elements, using + two's complement representation for the signed exact integers, and + single and double precision IEEE-754 floating point representation for + the inexact reals. Although this is a practical implementation on +-many modern byte addressed machines, a different implementation is ++many modern byte-addressed machines, a different implementation is + possible for machines which don't support these concrete numeric types + (the CRAY-T90 for example does not have a 32 bit floating point + representation and the 64 bit floating point representation does not + conform to IEEE-754, so both the f32vector and + f64vector datatypes could be represented the same way + with 64 bit floating point numbers). +- +-

          +- ++

          ++

          + A portable implementation of the homogeneous vector predefined + procedures can be based on Scheme's heterogeneous vectors. + Here is for example an implementation of s8vectors + which is exempt of error checking: +- +-

          ++

          ++
          + (define s8vector? #f)
          + (define make-s8vector #f)
          + (define s8vector #f)
          +@@ -318,10 +328,8 @@ which is exempt of error checking:
          +       (and (orig-vector? obj)
          +            (orig-not (and (orig-> (orig-vector-length obj) 0)
          +                           (orig-eq? (orig-vector-ref obj 0) tag)))))))
          +-
          +- +-

          +- ++
          ++

          + The Scheme system's read and write + procedures and the program parser also need to be extended to handle + the homogeneous vector external representations. The implementation +@@ -333,9 +341,12 @@ is the case, parse a symbol and check if it is = t, + f, s8, f32, and so on, and in + the case of a homogeneous vector prefix, check if the next character + is an opening parenthesis). ++

          +=20 +-

          Copyright

          ++

          Copyright

          ++

          + Copyright (C) Marc Feeley (1999). All Rights Reserved.=20 ++

          +

          + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the +@@ -360,8 +371,8 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE = SOFTWARE. +

          +=20 +=20 +-
          +-
          Editor: ++
          ++
          Editor: + Shriram Krishnamurthi
          +=20 + +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-40.html b/srfi-doc/sr= fi/scribblings/srfi-std/srfi-40.html +index 7340781..0d0300c 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-40.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-40.html +@@ -1,46 +1,67 @@ +- +- ++ ++ + ++ ++ + SRFI 40: A Library of Streams ++ ++ ++ + +=20 + +=20 +-

          Title

          ++

          SRFI 40: A Library of Streams

          +=20 +-SRFI 40: A Library of Streams ++

          by Philip L. Bewig

          ++

          This copy of the SRFI 40 specific= ation document ++is distributed as part of the Racket package ++srfi-doc.

          = The canonical source of this document is ++https://srfi.s= chemers.org/srfi-40/srfi-40.html.

          +=20 +-

          Author

          ++

          Status

          +=20 +-Philip L. Bewig ++

          This SRFI is currently in withdrawn status. Here is an explanation of each= status that a SRFI can hold. To provide input on this SRFI, please send e= mail to = srfi-40@nospamsrfi.schemers.org.= To subscribe to the list, follow these instructions. You can access previous mes= sages via the mailing list archive.

          ++ +=20 +-

          Status

          +=20 +-

          +-This SRFI is currently in ``final'' status. To see an explanation of eac= h status that a SRFI can hold, see here. +-To comments +-this SRFI, please mail to=20 +- +-srfi-40@srfi.schemers.org. +-See +-instructions here to subscribe to the list. You can access +-the discussion via +- +-the archive of the mailing list. +-You can access +-post-finalization messages via +- +-the archive of the mailing list. +-

          +- +-
        • Received: 2003/02/03 +-
        • Draft: 2003/02/03-2003/04/03 +-
        • Revised: 2003/08/02 +-
        • Revised: 2003/12/23 +-
        • Final: 2004/08/22 +-
        +- +-

        Abstract

        ++

        Abstract

        +=20 +

        + Along with higher-order functions, one of the hallmarks of functional +@@ -69,7 +90,7 @@ convenient processing of streams and shows several examp= les of their + use.=20=20 +

        +=20 +-

        Rationale

        ++

        Rationale

        +=20 +

        + Two of the defining characteristics of functional programming +@@ -90,17 +111,16 @@ programming with streams. +=20 +

        + Scheme has a long tradition of computing with streams. The great +-computer science textbook Structure and Int= erpretation ++computer science textbook Structure and Interpretation + of Computer Programs, uses streams extensively. +-The example given ++The example given + in R5RS makes use of streams to integrate systems of differential + equations using the method of Runge-Kutta. MIT Scheme, the original +-implementation of Scheme, provides streams natively. Scheme and the Art of Programmin= g,=20 ++implementation of Scheme, provides streams natively. Scheme and the Art of Programming,=20 + discusses streams. + Some Scheme-like languages also have traditions of using streams: +-Winston and Horn, in their classic Lisp tex= tbook, discuss streams, and +-so does Larry Paulson in his text on ++Winston and Horn, in their classic Lisp textbook, d= iscuss streams, and ++so does Larry Paulson in his text on + ML. Streams are an important and useful data structure. +

        +=20 +@@ -128,8 +148,7 @@ operational difference between the two types of stream= s. +

        +=20 +

        +-Philip Wadler, Walid Taha, and David MacQueen, in their paper "How to add laziness to a strict = language ++Philip Wadler, Walid Taha, and David MacQueen, in their paper "How to add laziness to a strict language + without even being odd", describe how they added streams to the + SML/NJ compiler. They discuss two kinds of streams: odd streams, as + in SICP et al, and even streams, as in Haskell; the names odd and even +@@ -180,7 +199,7 @@ Here are the first two figures from their paper, rewri= tten in Scheme: + (cutoff1 (- n 1)=20=20=20=20=20=20=20=20=20=20=20=20=20 + (cdr1 strm))))))=20=20=20=20 + +- ++ +

        ;;; FIGURE 2 -- EVEN
        +=20
        + (define nil2 (delay '()))
        +@@ -259,7 +278,7 @@ and even streams.  We expect the two constructors nil and
        + nil and cons return a strict list, but the
        + even nil and cons return promises.
        + Nil?, car and cdr change to
        +-accommodate the underlying representation differences.
        ++accomodate the underlying representation differences.
        + Cutoff is identical in the two versions, because it
        + doesn't return a stream.
        + 

        +@@ -587,7 +606,7 @@ stream-define are both library procedures, not fundame= ntal to the use + of streams, and are thus excluded from this SRFI. +

        +=20 +-

        Specification

        ++

        Specification

        +=20 +

        A stream-pair is a data structure consisting of two fields call= ed + the stream-car and stream-cdr. Stream-pairs are created +@@ -629,23 +648,25 @@ to detect and report errors. +

        +=20 +
        +-
        +-stream-null (constant)
        ++
        ++stream-null (constant)
        +
        ++

        + Stream-null is the distinguished nil stream, a single + Scheme object distinguishable from all other objects. If the last + stream-pair in a stream contains stream-null in its cdr field, the + stream is finite and has a computable length. However, there is no + need for streams to terminate. +- ++

        +
        +-    stream-null                                 =3D> (stream)
        ++    stream-null                                 =3D> (stream)
        + 
        +
        +=20 +-
        +-(stream-cons object stream) (syntax)
        ++
        ++(stream-cons object stream) (syntax)
        +
        ++

        + Stream-cons is the primitive constructor of streams, + returning a stream with the given object in its car field and the + given stream in its cdr field. The stream returned by +@@ -654,7 +675,7 @@ given stream in its cdr field. The stream returned by + of any type, and there is no requirement that successive elements of a + stream be of the same type, although it is common for them to be. It + is an error if the second argument of stream-cons is not a s= tream. +- ++

        +
            (stream-cons 'a stream-null)                =3D> (stream 'a)
        +     (stream-cons 'a (stream 'b 'c 'd))          =3D> (stream 'a 'b 'c =
        'd)
        +     (stream-cons "a" (stream 'b 'c))            =3D> (stream "a" 'b 'c)
        +@@ -663,73 +684,78 @@ is an error if the second argument of stream-c=
        ons is not a stream.
        + 
        +
        +=20 +-
        +-(stream? object) (function)
        ++
        ++(stream? object) (function)
        +
        ++

        + Stream? returns #t if the object is a stream, a= nd otherwise returns #f. A stream + object may be either the null stream or a stream pair created by st= ream-cons. +- ++

        +
            (stream? stream-null)                       =3D> #t
        +     (stream? (stream-cons 'a stream-null))      =3D> #t
        +     (stream? 3)                                 =3D> #f
        + 
        +
        +=20 +-
        +-(stream-null? object) (f= unction)
        ++
        ++(stream-null? object) (function)
        +
        ++

        + Stream-null? returns #t if the object is the di= stinguished nil stream, and +-otherwise returns #f#f. ++

        +
            (stream-null? stream-null)                  =3D> #t
        +     (stream-null? (stream-cons 'a stream-null)) =3D> #f
        +     (stream-null? 3)                            =3D> #f
        + 
        +
        +=20 +-
        +-(stream-pair? object) (f= unction)
        ++
        ++(stream-pair? object) (function)
        +
        ++

        + Stream-pair? returns #t if the object is a stre= am pair created by stream-cons, and + otherwise returns #f. +- ++

        +
            (stream-pair? stream-null)                  =3D> #f
        +     (stream-pair? (stream-cons 'a stream-null)) =3D> #t
        +     (stream-pair? 3)                            =3D> #f
        + 
        +
        +=20 +-
        +-(stream-car stream) (funct= ion)
        ++
        ++(stream-car stream) (function)
        +
        ++

        + Stream-car returns the object in the stream-car field of + a stream-pair. It is an error to attempt to evaluate the stream-car + of stream-null. +- ++

        +
            (stream-car (stream 'a 'b 'c))              =3D> a
        +     (stream-car stream-null)                    =3D> error
        +     (stream-car 3)                              =3D> error
        + 
        +
        +=20 +-
        +-(stream-cdr stream) (funct= ion)
        ++
        ++(stream-cdr stream) (function)
        +
        ++

        + Stream-cdr returns the stream in the stream-cdr field of + a stream-pair. It is an error to attempt to evaluate the stream-cdr + of stream-null. +- +- ++

        +
            (stream-cdr (stream 'a 'b 'c))              =3D> (stream 'b '=
        c)
        +     (stream-cdr stream-null)                    =3D> error
        +     (stream-cdr 3)                              =3D> error
        +-
        ++
        + 
        +
        +=20 +-
        +-(stream-delay expression) (syntax)
        ++
        ++(stream-delay expression) (syntax)
        +
        ++

        + Stream-delay is the essential mechanism for operating on str= eams, taking an + expression and returning a delayed form of the expression that can be ask= ed at + some future point to evaluate the expression and return the resulting val= ue. The +@@ -737,7 +763,7 @@ action of stream-delay is analogous to the action of d= elay, but it is specific t + the stream data type, returning a stream instead of a promise; no corresp= onding + stream-force is required, because each of the stream functio= ns performs the force + implicitly. +- ++

        +
            (define from0
        +       (let loop ((x 0))
        +         (stream-delay
        +@@ -746,26 +772,28 @@ implicitly.
        + 
        +
        +=20 +-
        (stream object ...) (libra= ry function) ++
        (stream object ...) (library functi= on)
        +
        ++

        + Stream returns a newly allocated finite stream of its argume= nts, in order. +- ++

        +
            (stream 'a (+ 3 4) 'c)                      =3D> (stream 'a 7=
         'c)
        +     (stream)                                    =3D> stream-null
        + 
        +
        +=20 +
        +-(stream-unfoldn generator seed= n) ++(stream-unfoldn generator seed = n) + (function)
        +
        ++

        + Stream-unfoldn returns n streams whose contents are p= roduced by successive calls + to generator, which takes the current seed as an arguments and returns n + 1 + values: +- ++

        +

        +-(proc seed) -> seed result0 ... = resultN +- ++(proc seed) -> seed result0 .= .. resultN ++

        +

        + where resultI indicates how to produce the next element of the Ith= result stream: +

        +@@ -806,8 +834,8 @@ multiple calls to generator. +
        + +=20 +-
        +-(stream-map function stream ..= .) (library ++
        ++(stream-map function stream ...) (library + function)
        +
        + Stream-map creates a newly allocated stream built by +@@ -826,8 +854,8 @@ streams are infinite. The stream elements are evaluat= ed in order. + +
        +=20 +-
        +-(stream-for-each procedure st= ream ...) ++
        ++(stream-for-each procedure stream ...) + (library function)
        +
        + Stream-for-each applies procedure elementwise to the element= s of the streams, +@@ -839,8 +867,8 @@ stream-for-each is unspecified. The stream elements a= re visited in order. + +
        +=20 +-
        +-(stream-filter predicate? strea= m) (library function)
        ++
        ++(stream-filter predicate? stream) (library fun= ction)
        +
        + Stream-filter applies predicate? to each element + of stream and creates a newly allocated stream consisting of those +@@ -855,18 +883,16 @@ same order as they were in the input stream, and are= tested by +
        +
        +=20 +-

        Implementation

        ++

        Implementation

        +=20 +

        A reference implementation of streams is shown below. It strongly + prefers simplicity and clarity to efficiency, and though a reasonable + attempt is made to be safe-for-space, no promises are made. The reference +-implementation relies on the mechanism for defining record types of SRFI-9, and the functions +-any and every from SRFI-1. The ++implementation relies on the mechanism for defining record types of SRFI-9, and the functions ++any and every from SRFI= -1. The + stream-error function aborts by calling error as +-defined in SRFI 23. +- ++defined in SRFI 23. ++

        +
        ;;; PROMISES A LA SRFI-45:
        +=20
        + ;;; A separate implementation is necessary to
        +@@ -1038,15 +1064,17 @@ defined in SRFI 23.
        +         ((not (stream? strm)) (stream-error "attempt to apply stream-filt=
        er to non-stream"))
        +         (else (stream-unfoldn
        +                 (lambda (s)
        +-                  (values
        +-                    (stream-cdr s)
        +-                    (cond ((stream-null? s) '())
        +-                          ((pred? (stream-car s)) (list (stream-car s)))
        +-                          (else #f))))
        ++		  (cond
        ++		   ((stream-null? s)
        ++		    (values stream-null '()))
        ++		   ((pred? (stream-car s))
        ++		    (values (stream-cdr s) (list (stream-car s))))
        ++		   (else
        ++		    (values (stream-cdr s) #f))))
        +                 strm
        +                 1))))
        +=20 +-

        References

        ++

        References

        +=20 +
          +
        • +@@ -1078,8 +1106,8 @@ Workshop on ML, pp. 24-30. + + Patrick H. Winston, Berthold K. Horn: Lisp, 3rd edition, + Addison Wesley, 1989. +-
        +-

        Copyright

        ++
      ++

      Copyright

      +

      Copyright (C) 2003 by Philip L. Bewig of Saint Louis, Missouri, United= States of + America. All rights reserved.

      +=20 +@@ -1106,11 +1134,11 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT = OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +

      +=20 +-
      +-
      Editor: Mi= ke Sperber
      ++
      ++
      Editor: Mike Sperber
      + + +-Last modified: Sat Sep 11 12:40:31 MST 2004 ++Last modified: Fri Jan 25 11:19:45 CET 2008 + + + +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-41/srfi-41.html b/srf= i-doc/srfi/scribblings/srfi-std/srfi-41/srfi-41.html +index a937761..6604d2f 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-41/srfi-41.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-41/srfi-41.html +@@ -1,42 +1,55 @@ +- +-SRFI 41: Streams +- +-

      Title

      +- +-Streams +- +- +-

      Author

      +- +-Philip L. Bewig +- +-

      Status

      +- +-This SRFI is currently in ``final'' status. To see an explanation of each +-status that a SRFI can hold, see +-here. +-To comment on this SRFI, please +-mailto:srfi minus 41 at srfi dot schemers dot org. +-See instruc= tions +-here to subscribe to the list. You can access +-the discussion via +- +-the archive of the mailing list. +-You can access +-post-finalization messages via +- +-the archive of the mailing list. ++ ++ ++ ++ ++ ++ SRFI 41: Streams ++ ++ ++ + +=20 + +=20 +-

      Title

      +- +-SRFI 42: Eager Comprehensions +- +-

      Author

      +- +-Sebastian Egner +- +-

      Status

      +- +-

      This SRFI is currently in ``final'' status. To see an explanation of +-each status that a SRFI can hold, see here. +-To comments +-this SRFI, please mail to=20 +- +-srfi-42@srfi.schemers.org. +-See +-instructions here to subscribe to the list. You can access +-the discussion via +- +-the archive of the mailing list. +-You can access +-post-finalization messages via +- +-the archive of the mailing list. +-

      +-
        =20 +-
      • Received: 2003/02/20=20 +-
      • Draft: 2003/02/20-2003/04/20 +-
      • Revised: 2003/07/07 +-
      • Final: 2003/07/07 +-
      +- +-

      Abstract

      +- +-This SRFI defines a modular and portable mechanism for=20 ++

      SRFI 42: Eager Comprehensions

      ++ ++

      by Sebastian Egner

      ++

      This copy of the SRFI 42 specific= ation document ++is distributed as part of the Racket package ++srfi-doc.

      = The canonical source of this document is ++https://srfi.s= chemers.org/srfi-42/srfi-42.html.

      ++ ++

      Status

      ++ ++

      This SRFI is currently in final status. Here is an explanation of each stat= us that a SRFI can hold. To provide input on this SRFI, please send email = to srfi-= 42@nospamsrfi.schemers.org. To = subscribe to the list, follow these instructions. You can access previous messages= via the mailing list a= rchive.

      ++
        ++
      • Received: 2003-02-20 ++
      • Draft: 2003-02-20--2003-04-20 ++
      • Revised: 2003-07-07 ++
      • Final: 2003-07-07 ++
      ++ ++

      Abstract

      ++

      ++This SRFI defines a modular and portable mechanism for + eager comprehensions extending the algorithmic language Scheme + [R5RS]. + An eager comprehension is a convenient notation +@@ -50,108 +54,108 @@ for one or more nested or parallel loops generating + a sequence of values, and accumulating this sequence into a result. + In its most simple form, a comprehension according to this SRFI + looks like this: +- +-

      (lis=
      t-ec (: i 5) (* i i)) =3D> (0 1 4 9 16).
      +- +-Here, i is a local variable that is sequentially=20 +-bound to the values 0, 1, ..., 4, and the squares of these=20 ++

      ++
      (list-ec =
      (: i 5) (* i i)) =3D> (0 1 4 9 16).
      ++

      ++Here, i is a local variable that is sequentially ++bound to the values 0, 1, ..., 4, and the squares of these + numbers are collected in a list. + The following example illustrates most conventions of this SRFI + with respect to nesting and syntax: +- +-

      (lis=
      t-ec (: n 1 4) (: i n) (list n i)=
      ) =3D> ((1 0) (2 0) (2 1) (3 0) (3 1) (3 2)).
      +- ++

      ++
      (list-ec (: n 1 4) (: i n) (list n i)) =3D> ((1 0) (2 0=
      ) (2 1) (3 0) (3 1) (3 2)).
      ++

      + In the example, the variable n is first bound to 1 +-then to 2 and finally to 3, and for each binding of n=20 +-the variable i is bound to the values=20 ++then to 2 and finally to 3, and for each binding of n ++the variable i is bound to the values + 0, 1, ..., n-1 in turn. + The expression (list n i) constructs a two-element list for + each bindings, and the comprehension list-ec collects +-all these results in a list.

      +- ++all these results in a list. ++

      ++

      + The mechanism defined in this SRFI has the following properties: ++

      ++
        +=20 +-
          +- +-
        • +-The set of comprehensions defined for this SRFI is inspired by=20 ++
        • ++The set of comprehensions defined for this SRFI is inspired by + those procedures and macros of [R5RS, 6.] + leading to natural comprehensions such as + list-ec, + append-ec, + sum-ec, + min-ec, +-every?-ec, ++every?-ec, + do-ec, and others. +-Some other natural comprehensions (e.g. gcd-ec) have=20 +-not been included into this SRFI due to their low significance=20 ++Some other natural comprehensions (e.g. gcd-ec) have ++not been included into this SRFI due to their low significance + for most applications. +-On the other hand, a few comprehensions=20 ++On the other hand, a few comprehensions + (fold-ec, + fold3-ec) +-not inspired by [R5RS] have been=20 ++not inspired by [R5RS] have been + included due to their broad applicability. +-
        • ++ +=20 +-
        • +-There are typed generators=20 +-(:list, :str= ing, ...) ++
        • ++There are typed generators ++(:list, = :string, ...) + expecting certain types of objects for their arguments. + These generators usually produce code as efficient as + hand coded do-loops. +-
        • ++ +=20 +-
        • +-There is also the special generator :=20 +-(read 'run through')=20 ++
        • ++There is also the special generator : ++(read 'run through') + dispatching on the value of its argument list at runtime. + In the examples above, one or two integers were used to define a range. + The convenience of omitting the type comes at a certain + performance penalty, both per iteration and during startup of the loop. +-
        • +- +-
        • +-Generators can be nested depth-first (as in the example above),=20 +-run in parallel (with an optional index variable=20 +-or more generally with :parallel), +-and can be stopped early before (:while<= /a>) +-or after (:until) ++
        • ++ ++
        • ++Generators can be nested depth-first (as in the example above), ++run in parallel (with an optional index variable ++or more generally with :parallel), ++and can be stopped early before (:while) ++or after (:until) + producing the current value. +-
        • ++ +=20 +-
        • +-The sequence of values can be filtered=20 ++
        • ++The sequence of values can be filtered + (if, not, + and, or), + intermediate commands can be evaluated between + generators (begin), and +-intermediate variables can be introduced (:let). +-
        • +-
        • ++intermediate variables can be introduced (:let<= /code>). ++
        • ++
        • + The mechanism is fully modular. +-This means that no existing macro or procedure needs=20 ++This means that no existing macro or procedure needs + to be modified when adding + application-specific comprehensions, +-application-specific typed generators, +-or application-specific dispatching generators. +-
        • +- +-
        • +-Syntactically, this SRFI uses the=20 +-[outer .. inner | expr] convention, +-meaning that the most right generator (inner) spins fastest ++application-specific typed generators, ++or application-specific dispatching generators. ++
        • ++ ++
        • ++Syntactically, this SRFI uses the ++[outer .. inner | expr] convention, ++meaning that the most right generator (inner) spins fastest + and is followed by the result expression over which the +-comprehension ranges (expr). ++comprehension ranges (expr). + Refer to the Section "Design Rationale". + Moreover, the syntax is strictly prefix and the naming +-convention my-comprehension-ec,=20 ++convention my-comprehension-ec, + :my-generator is used systematically. +-
        • ++ +=20 +-
        +- +-

        ++

      +=20 ++

      + The remainder of this document is organized as follows. + In section Rationale a brief + introduction is given what the motivation is for this SRFI. +@@ -170,28 +174,29 @@ Finally, the section Reference + Implementation gives source code for a reference + implementation together with a collection of runnable + examples and a few examples on extensions. ++

      +=20 +- +-

      Rationale

      +- ++

      Rationale

      ++

      + The purpose of this SRFI is to provide a compact notation +-for many common cases of loops, in particular those=20 ++for many common cases of loops, in particular those + constructing values for further computation. + The origin of this SRFI is my frustration that + there is no simple for the list of integers +-from 0 to n-1. ++from 0 to n-1. + With this SRFI it is (list-ec (: i n) i). +-Refer to the collection of examples for the=20 ++Refer to the collection of examples for the + reference implementation + what it can be used for, and what it should not be used for. +-To give a practically useful example,=20 ++To give a practically useful example, + the following procedure computes the sorted + list of all prime numbers below a certain bound + (you may want to run it yourself to get an idea of + its efficiency): ++

      +=20 +
      
      +-(define (eratosthenes n)          ; primes in {2..n-1} for n >=3D 1
      ++(define (eratosthenes n)          ; primes in {2..n-1} for n >=3D 1
      +   (let ((p? (make-string n #\1)))
      +     (do-ec (:range k 2 n)
      +            (if (char=3D? (string-ref p? k) #\1))
      +@@ -199,24 +204,25 @@ its efficiency):
      +            (string-set! p? i #\0) )
      +     (list-ec (:range k 2 n) (if (char=3D? (string-ref p? k) #\1)) k) ))
      +=20 +- +-Apart from make simple things simple,=20 ++

      ++Apart from make simple things simple, + there is no other paradigm involved for this SRFI. + In particular, it is not the ambition to implement the +-powerful lazy list comprehensions of other functional ++powerful lazy list comprehensions of other functional + programming languages in Scheme. + If you are looking for that you may want to refer to + [SRFI 40]. + (The usual definition of the stream of all primes does +-in fact also use Eratosthenes' sieve method.=20 +-It is instructive to compare.)

      +- +-The main focus of the design of this SRFI is portability under=20 ++in fact also use Eratosthenes' sieve method. ++It is instructive to compare.) ++

      ++

      ++The main focus of the design of this SRFI is portability under + [R5RS] and modularity for extension. + Portability is achieved by limiting the features included. + Modularity for generators is achieved by a special +-implementation technique using Continuation +-Passing Style for macros (which I learned from ++implementation technique using Continuation ++Passing Style for macros (which I learned from + Richard Kelsey's implementation of "Macros for writing loops", + [MWL]) and by limiting the + expressive power of generators. +@@ -224,193 +230,199 @@ Modularity for comprehensions requires no addition= al effort. + As modularity was a major design goal, I hope many people will + find it easy to define their own comprehensions and generators. + As a starting point for doing so, I have included several +-suggestions for extensions.

      +- ++suggestions for extensions. ++

      ++

      + For a detailed motivation of the design decisions, +-please refer to the Section "Design Rationale".

      ++please refer to the Section "Design Rationale". ++

      +=20 +-

      Specification

      ++

      Specification

      +=20 +-A comprehensions is a hygienic referentially transparent macro=20 ++

      ++A comprehension is a hygienic, referentially transparent macro + in the sense of [R5RS, 4.3.]. +-The macros extend the <expression>-syntax=20 ++The macros extend the <expression>-syntax + defined in [R5RS, 7.1.3.]. +-The main syntactic pattern used for defining a comprehension is=20 ++The main syntactic pattern used for defining a comprehension is + <qualifier>, representing a generator or a filter. +-It is defined in Section "Qualifiers".

      +- ++It is defined in Section "Qualifiers".

      ++

      ++

      + The most important instances of <qualifier> are genera= tors. + These are defined in Section "Generators". + Generators come in three flavors, +-as typed generators=20 +-(:list,=20 +-:range etc.), +-as the dispatching generator :=20 ++as typed generators ++(:list, ++:range etc.), ++as the dispatching generator : + (pronounced as 'run through'), +-and as combined and modified generators=20 +-(:parallel,=20 +-:while,=20 +-:until). +-Most generators in this SRFI also support an optional=20 ++and as combined and modified generators ++(:parallel, ++:while, ++:until). ++Most generators in this SRFI also support an optional + index variable counting the +-values being generated.

      +- +-Finally, it is explained how to add a new=20 ++values being generated. ++

      ++

      ++Finally, it is explained how to add a new + application-specific comprehension, +-how to add a new application-specific typed generator, ++how to add a new application-specific typed generator= , + and how to add a new +-application-specific dispatching generator. ++application-specific dispatching generator. + As this concerns code unknown at the time this is being written, + the explanation should not be taken as +-a specification in the literal sense.=20 ++a specification in the literal sense. + It rather suggests a convention to follow in order to + ensure new comprehensions and generators blend seamlessly with +-the ones defined in this SRFI.

      ++the ones defined in this SRFI. ++

      +=20 +=20 +-

      Comprehensions

      ++

      Comprehensions

      +=20 +-
      +-
      ++
      ++
      + (do-ec <qualifier>* <command>) +-
      ++
      +=20 +-
      +-Evaluates the <command> exactly once=20 ++
      ++Evaluates the <command> exactly once + for each binding in the sequence defined by the qualifiers. + If there are no qualifiers <command> + is evaluated exactly once. + The expression is evaluated for its side-effects only. + The result of the comprehension is unspecified. +-
      +-
      ++ ++ +=20 +-
      +-
      ++
      ++
      + (list-ec <qualifier>* <expression>) +-
      ++
      +=20 +-
      ++
      + The list of values obtained by evaluating +-<expression> once for each binding in the sequence=20 ++<expression> once for each binding in the sequence + defined by the qualifiers. + If there are no qualifiers the result is the list with +-the value of <expression>.=20 +-
      +-
      ++the value of <expression>. ++ ++ +=20 +-
      +-
      ++
      ++
      + (append-ec <qualifier>* <expression>) +-
      ++
      +=20 +-
      ++
      + The list obtained by appending all values of <expression>, +-which must all be lists.
      ++which must all be lists.
      + Think of it as + (apply append (list-ec <qualifier>* <expressi= on>)). +-
      +-
      ++ ++ +=20 +-
      +-
      ++
      ++
      + (string-ec <qualifier>* <expression>) +-
      ++
      +=20 +-
      +-The string of all values of <expression>.
      ++
      ++The string of all values of <expression>.
      + Think of it as +-(list->string (list-ec <qualifier>* <expressi= on>)). +-
      +-
      ++(list->string (list-ec <qualifier>* <expre= ssion>)). ++ ++ +=20 +-
      +-
      ++
      ++
      + (string-append-ec <qualifier>* <expression>= ;) +-
      ++
      +=20 +-
      ++
      + The string obtained by appending all values of <expression>, +-which must all be strings.
      ++which must all be strings.
      + Think of it as + (apply string-append (list-ec <qualifier>* <e= xpression>)). +-
      +-
      ++ ++ +=20 +-
      +-
      ++
      ++
      + (vector-ec <qualifier>* <expression>) +-
      ++
      +=20 +-
      +-The vector of all values of <expression>.
      ++
      ++The vector of all values of <expression>.
      + Think of it as +-(list->vector (list-ec <qualifier>* <expressi= on>)). +-
      +-
      ++(list->vector (list-ec <qualifier>* <expre= ssion>)). ++ ++ +=20 +-
      +-
      ++
      ++
      + (vector-of-length-ec <k> <qualifier>* <= expression>) +-
      ++
      +=20 +-
      ++
      + The vector of all values of <expression>, + of which there must be exactly <k>. + This comprehension behaves like vector-ec + but can be implemented more efficiently. +-
      +-
      ++ ++ +=20 +-
      +-
      ++
      ++
      + (sum-ec <qualifier>* <expression>) +-
      ++
      +=20 +-
      +-The sum of all values of <expression>.
      ++
      ++The sum of all values of <expression>.
      + Think of it as + (apply + (list-ec <qualifier>* <expression>= ;)). +-
      +-
      ++ ++ +=20 +-
      +-
      ++
      ++
      + (product-ec <qualifier>* <expression>) +-
      ++
      +=20 +-
      +-The product of all values of <expression>.
      ++
      ++The product of all values of <expression>.
      + Think of it as + (apply * (list-ec <qualifier>* <expression>= ;)). +-
      +-
      ++ ++ +=20 +-
      +-
      +-(min-ec <qualifier>* <expression>)<= BR> ++
      ++
      ++(min-ec <qualifier>* <expression>)<= br /> + (max-ec <qualifier>* <expression>) +-
      ++
      +=20 +-
      ++
      ++

      + The minimum and maximum of all values of <expression>. + The sequence of values must be non-empty. +-Think of these as
      +-(apply min (list-ec <qualifier>* <expression&= gt;))
      +-(apply max (list-ec <qualifier>* <expression&= gt;)).

      +- ++Think of these as
      ++(apply min (list-ec <qualifier>* <expression&= gt;))
      ++(apply max (list-ec <qualifier>* <expression&= gt;)). ++

      ++

      + If you want to return a default value in case the sequence is empty +-you may want to consider
      ++you may want to consider
      + (fold3-ec 'infinity <qualifier>* <expression&= gt; min min). +-

      +-
      +- +-
      +-
      ++

      ++ ++
      + (any?-ec <qualifier>* <test>) +-
      ++ +=20 +-
      ++
      + Tests whether any value of <test> in the sequence + of bindings specified by the qualifiers is non-#f. + If this is the case, #t is returned, otherwise #f. +@@ -418,106 +430,113 @@ If there are no bindings in the sequence specified= by the qualifiers + at all then the result is #f. + The enumeration of values stops after the first non-#f + encountered. +-
      +-
      ++ ++ +=20 +-
      +-
      ++
      ++
      + (every?-ec <qualifier>* <test>) +-
      ++
      +=20 +-
      +-Tests whether all values of <test> are non-#f.=20 ++
      ++Tests whether all values of <test> are non-#f. + If this is the case, #t is returned, otherwise #f. + If the sequence is empty the result is #t. + Enumeration stops after the first #f. +-
      +-
      ++ ++ +=20 +-
      +-
      +-(first-ec <default> <qualifier>* <expression&= gt;)
      ++
      ++
      ++(first-ec <default> <qualifier>* <expression&= gt;)
      + (last-ec  <default> <qualifier>
      * <expres= sion>) +-
      ++
      +=20 +-
      +-The first or last value of <expression>=20 ++
      ++The first or last value of <expression> + in the sequence of bindings specified by the qualifiers. + Before enumeration, the result is initialized + with the value of <default>; + so this will be the result if the sequence is empty. +-Enumeration is terminated in first-ec=20 ++Enumeration is terminated in first-ec + when the first value has been computed. +-
      +-
      ++ ++ +=20 +-
      +-
      +-(fold-ec  <x0> <qualifier>* <expression= > <f2>)
      ++
      ++
      ++(fold-ec  <x0> <qualifier>* <expression= > <f2>)
      + (fold3-ec <x0> <qualifier>
      * <expression> &= lt;f1> <f2>) +-
      ++
      +=20 +-
      +-Reduces the sequence x[0], x[1], ..., x[n-1] ++
      ++

      ++Reduces the sequence x[0], x[1], ..., x[n-1] + of values obtained by evaluating <expression> once + for each binding as specified by <qualifier>*. +-The arguments <x0>, <f2>,=20 ++The arguments <x0>, <f2>, + and <f1>, all syntactically equivalent to +-<expression>, specify the reduction process.

      +- ++<expression>, specify the reduction process. ++

      ++

      + The reduction process for fold-ec is defined as follows. +-A reduction variable x is initialized to the value=20 ++A reduction variable x is initialized to the value + of <x0>, +-and for each k in {0, ..., n-1} the command=20 +-(set! x (<f2> x[k] x)) +-is evaluated.=20 +-Finally, x is returned as the value of the comprehension.

      +- ++and for each k in {0, ..., n-1} the command ++(set! x (<f2> x[k] x)) ++is evaluated. ++Finally, x is returned as the value of the comprehension. ++

      ++

      + The reduction process for fold3-ec is different. +-If and only if n =3D 0, i.e. the sequence is empty, then=20 +-<x0> is evaluated and returned as the value=20 ++If and only if n =3D 0, i.e. the sequence is empty, then ++<x0> is evaluated and returned as the value + of the comprehension. + Otherwise, a reduction variable x is initialized +-to the value of (<f1> x[0]), +-and for each k in {1, ..., n-1} the command=20 +-(set! x (<f2> x[k] x)) +-is evaluated.=20 +-Finally, x is returned as the value of the comprehension.

      +- ++to the value of (<f1> x[0]), ++and for each k in {1, ..., n-1} the command ++(set! x (<f2> x[k] x)) ++is evaluated. ++Finally, x is returned as the value of the comprehension. ++

      ++

      + As the order of the arguments suggests, + <x0> is evaluated outside the scope of the + qualifiers, whereas the reduction expressions involving +-<f1> and <f2> are ++<f1> and <f2> are + inside the scope of the qualifiers (so they may depend on + any variable introduced by the qualifiers). + Note that <f2> is evaluated repeatedly, +-with any side-effect or overhead this might have.

      +- +-The main purpose of these comprehensions is=20 ++with any side-effect or overhead this might have. ++

      ++

      ++The main purpose of these comprehensions is + implementing other comprehensions as special cases. + They are generalizations of the procedures + fold and reduce in the sense of +-[SRFI 1].=20 +-(Concerning naming and argument order, please refer to=20 ++[SRFI 1]. ++(Concerning naming and argument order, please refer to + the discussion archive of SRFI 1, in particular + the posting [Folds].) + Note that fold3-ec is defined such that +-<x0> is only evaluated in case the=20 ++<x0> is only evaluated in case the + sequence is empty. +-This allows raising an error for the empty sequence,=20 ++This allows raising an error for the empty sequence, + as in the example definition of min-ec below. +-

      +-
      ++

      ++ ++ +=20 +-
      +-
      ++
      ++
      + <application-specific comprehension> +-
      ++
      +=20 +-
      +-An important aspect of this SRFI is a modular mechanism=20 ++
      ++

      ++An important aspect of this SRFI is a modular mechanism + to define application-specific comprehensions. +-To create a new comprehension a hygienic macro=20 ++To create a new comprehension a hygienic macro + of this name is defined. + The macro transforms the new comprehension patterns + into instances of do-ec, which is the= most +@@ -528,7 +547,7 @@ For example, the following code defines + min-ec + in terms of fold-ec + and fold3-ec: +- ++

      +
      
      + (define-syntax list-ec
      +   (syntax-rules ()
      +@@ -539,23 +558,22 @@ and fold3-ec:
      +   (syntax-rules ()
      +     ((min-ec etc1 etc ...)
      +      (fold3-ec (min) etc1 etc ... min min) )))
      +- ++

      + Note that the pattern etc1 etc ... matches + the syntax <qualifier>* <expression> +-without separate access to <qualifier>*=20 ++without separate access to <qualifier>* + and <expression>. + In order to define a comprehension that does need explicit +-access to the <expression>-part,=20 ++access to the <expression>-part, + the following method is used. +-First, all qualifiers are collected into a=20 ++First, all qualifiers are collected into a + nested-qualifier, and then the + 'exactly one qualifier'-case is implemented. + For illustration, the following code defines +-fold3-ec in terms of=20 ++fold3-ec in terms of + do-ec: +- +- +-

      
      ++

      ++
      + (define-syntax fold3-ec
      +   (syntax-rules (nested)
      +     ((fold3-ec x0 (nested q1 ...) q etc1 etc2 etc3 etc ...)
      +@@ -573,421 +591,441 @@ For illustration, the following code defines
      +                     (begin (set! result (f1 value))
      +                            (set! empty #f) )
      +                     (set! result (f2 value result)) )))
      +-       (if empty x0 result) ))))
      +- ++ (if empty x0 result) ))))
      ++

      + Finally, observe that the newly defined fold3-ec + comprehension inherits all types of qualifiers supported by + do-ec, including all application-specific generators; + no further definitions are necessary. +-

      +-
      ++

      ++ ++ +=20 +=20 +-

      Qualifiers

      ++

      Qualifiers

      +=20 ++

      + This section defines the syntax <qualifier>. + The nesting of qualifiers is from left (outer) to right (inner). + In other words, the rightmost generator spins fastest. + The nesting also defines the scope of the variables introduced +-by the generators.=20 ++by the generators. + This implies that inner generators may depend on the variables + of outer generators. +-The sequence of enumeration of values is strictly depth first. +-These conventions are illustrated by the=20 +-first example.

      +- +-The syntax <qualifier> consists of the following alter= natives:

      ++The sequence of enumeration of values is strictly depth first. ++These conventions are illustrated by the ++first example. ++

      ++

      ++The syntax <qualifier> consists of the following alter= natives: ++

      +=20 +=20 +-
      +-
      ++
      ++
      + <generator> +-
      ++
      +=20 +-
      ++
      + Enumerates a sequence of bindings of one or more variables. + The scope of the variables starts at the generator and extends + over all subsequent qualifiers and expressions in the comprehension. +-The <generator>-syntax is defined in=20 ++The <generator>-syntax is defined in + Section "Generators". +-
      +-
      ++ ++ +=20 +-
      +-
      ++
      ++
      + (if <test>) +-
      ++
      +=20 +-
      ++
      + Filters the sequence of bindings by testing if + <test> evaluates to non-#f. + Only for those bindings for which this is the case, + the subsequent qualifiers of the comprehension are evaluated. +-
      +-
      ++ ++ +=20 +-
      +-
      +-(not <test>)
      +-(and <test>
      *)
      ++
      ++
      ++(not <test>)
      ++(and <test>
      *)
      + (or  <test>
      *) +-
      ++
      +=20 +-
      ++
      + Abbreviated notations for filters of the form + (if (not <test>)), + (if (and <test>*)), and + (if (or <test>*)). + These represent frequent cases of filters. +-
      +-
      ++ ++ +=20 +-
      +-
      ++
      ++
      + (begin <sequence>) +-
      ++
      +=20 +-
      ++
      + Evaluate <sequence>, consisting of + <command>* <expression>, +-once for each binding of the variables defined by the=20 ++once for each binding of the variables defined by the + previous qualifiers in the comprehension. + Using this qualifier, side effects can be inserted + into the body of a comprehension. +-
      +-
      ++ ++ +=20 +-
      +-
      ++
      ++
      + (nested <qualifier>*) +-
      ++
      +=20 +-
      ++
      + A syntactic construct to group qualifiers. +-The meaning of a qualifier according to the=20 +-nested-syntax is the same as=20 ++The meaning of a qualifier according to the ++nested-syntax is the same as + inserting <qualifier>* + into the enclosing comprehension. + This construct can be used to reduce comprehensions with several + qualifiers into a form with exactly one qualifier. +-
      +-
      ++ ++ +=20 +=20 +-

      Generators

      +- ++

      Generators

      ++

      + This section defines the syntax <generator>. +-Each generator defines a sequence of bindings through=20 ++Each generator defines a sequence of bindings through + which one or more variables are run. +-The scope of the variables begins after the closing=20 ++The scope of the variables begins after the closing + parenthesis of the generator expression and extends +-to the end of the comprehension it is part of.

      +- +-The variables defined by the generators=20 +-are specified using the syntax

      +- ++to the end of the comprehension it is part of. ++

      ++

      ++The variables defined by the generators ++are specified using the syntax ++

      +
      + <vars> --> <variable1> [ (index <var=
      iable2>) ],
      +=20 ++

      + where <variable1> runs through the values in +-the sequence defined by the generator, and the optional=20 +-<variable2> is an exact integer-valued=20 ++the sequence defined by the generator, and the optional ++<variable2> is an exact integer-valued + index variable counting the values (starting from 0). + The names of the variables must be distinct. +-The following example illustrates the index variable:

      +- ++The following example illustrates the index variable: ++

      +
      
      +-(list-ec (: x (index i) "abc") (list x i)) =3D> ((#\a 0) (#\b 1) (#\c 2))=
      
      ++(list-ec (: x (index i) "abc") (list x i)) =3D> ((#\a 0) (#\b 1) (#\c = 2))
      +=20 ++

      + Unless defined otherwise, all generators make sure that the + expressions provided for their syntactic arguments are + evaluated exactly once, before enumeration begins. + Moreover, it may be assumed that the generators do not + copy the code provided for their arguments, because that + could lead to exponential growth in code size. +-Finally, it is possible to assign a value to the variables=20 +-defined by a generator, but the effect of this assignment=20 +-is unspecified.

      +- +-The syntax <generator> consists of the following alter= natives:

      ++Finally, it is possible to assign a value to the variables ++defined by a generator, but the effect of this assignment ++is unspecified. ++

      ++

      ++The syntax <generator> consists of the following alter= natives: ++

      +=20 +-
      +-
      ++
      ++
      + (: <vars> <arg1> <arg>*) +-
      ++
      +=20 +-
      ++
      ++

      + First the expressions <arg1> <arg>* +-are evaluated into a[1] a[2] ... a[n] ++are evaluated into a[1] a[2] ... a[n] + and then a global dispatch procedure is used to dispatch on + the number and types of the arguments and run the resulting + generator. +- +- +-Initially (after loading the SRFI),=20 +-the following cases are recognized:

      +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +-
      :list +-if +-for all i in {1..n}: +-(list? a[i]). +-
      :string +-if +-for all i in {1..n}: +-(string? a[i]). +-
      :vector +-if +-for all i in {1..n}: +-(vector? a[i]). +-
      :range +-if +-n in {1..3} and=20 +-for all i in {1..n}: +-(integer? a[i]) and +-(exact? a[i]). +-
      :real-range +-if +-n in {1..3} and=20 +-for all i in {1..n}: +-(real? a[i]). +-
      :char-range +-if +-n =3D 2 and +-for all i in {1, 2}: +-(char? a[i]). +-
      :port +-if +-n in {1,2} and +-(input-port? a[1]) and +-(procedure? a[2]). +-

      +- ++

      ++

      ++Initially (after loading the SRFI), ++the following cases are recognized: ++

      ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++
      :list ++if ++for all i in {1..n}: ++(list? a[i]). ++
      :string ++if ++for all i in {1..n}: ++(string? a[i]). ++
      :vector ++if ++for all i in {1..n}: ++(vector? a[i]). ++
      :range ++if ++n in {1..3} and ++for all i in {1..n}: ++(integer? a[i]) and ++(exact? a[i]). ++
      :real-range ++if ++n in {1..3} and ++for all i in {1..n}: ++(real? a[i]). ++
      :char-range ++if ++n =3D 2 and ++for all i in {1, 2}: ++(char? a[i]). ++
      :port ++if ++n in {1,2} and ++(input-port? a[1]) and ++(procedure? a[2]). ++
      ++

      + +-The current dispatcher can be retrieved as=20 +-(:-dispatch-ref), a new dispatcher d=20 ++The current dispatcher can be retrieved as ++(:-dispatch-ref), a new dispatcher d + can be installed by +-(:-dispatch-set! d) ++(:-dispatch-set! d) + yielding an unspecified result, + and a copy of the initial dispatcher can be obtained as + (make-initial-:-dispatch). +-Please refer to the section below ++Please refer to the section below + for recommendation how to add cases to the dispatcher. +-

      +-
      ++

      ++ +=20 +-
      +-
      +-(:list   <vars> <arg1> <arg>*)=
      +-(:string <vars> <arg1> <arg>
      *)
      ++
      ++(:list   <vars> <arg1> <arg>*)=
      ++(:string <vars> <arg1> <arg>
      *)
      + (:vector <vars> <arg1> <arg>
      *) +-
      ++ +=20 +-
      ++
      + Run through one or more lists, strings, or vectors. +-First all expressions in <arg1> <arg>*=20 ++First all expressions in <arg1> <arg>* + are evaluated and then all elements of the resulting values + are enumerated from left to right. + One can think of it as first appending all arguments and + then enumerating the combined object. +-As a clarifying example, consider
      +-(list-ec (:string c (index i) "a" "b") (cons c i)) =3D> ++As a clarifying example, consider
      ++(list-ec (:string c (index i) "a" "b") (cons c i)) =3D> + ((#\a . 0) (#\b . 1)). +-
      +-
      ++ ++ +=20 +-
      +-
      ++
      ++
      + (:integers <vars>) +-
      ++
      +=20 +-
      ++
      + Runs through the sequence 0, 1, 2, ... of non-negative integers. +-This is most useful in combination with=20 +-:parallel, +-:while, and=20 +-:until or with ++This is most useful in combination with ++:parallel, ++:while, and ++:until or with + a non-local exit in the body of the comprehension. +-
      +-
      ++ ++ +=20 +-
      +-
      +-(:range <vars>         <= stop>)
      +-(:range <vars> <start> <stop>)
      ++
      ++
      ++(:range <vars>         <= stop>)
      ++(:range <vars> <start> <stop>)
      + (:range <vars> <start> <stop> <step>)
      +-
      +- +-
      +-Runs through a range of exact rational numbers.

      ++

      +=20 ++
      ++

      ++Runs through a range of exact rational numbers. ++

      ++

      + The form (:range <vars> <stop>) + evaluates the expression <stop>, +-which must result in an exact integer n,=20 +-and runs through the finite sequence 0, 1, 2, ..., n-1. +-If n is zero or negative the sequence is empty.

      ++which must result in an exact integer n, ++and runs through the finite sequence 0, 1, 2, ..., n-1. ++If n is zero or negative the sequence is empty.

      +=20 + The form (:range <vars> <start> <stop>) +-evaluates the expressions <start> and=20 ++evaluates the expressions <start> and + <stop>, +-which must result in exact integers a and b,=20 +-and runs through the finite sequence=20 +-a, a+1, a+2, ..., b-1. +-If b is less or equal a then the sequence is empty.

      +- ++which must result in exact integers a and b, ++and runs through the finite sequence ++a, a+1, a+2, ..., b-1. ++If b is less or equal a then the sequence is empty. ++

      ++

      + The form (:range <vars> <start> <stop> <step&g= t;) +-first evaluates the expressions <start>,=20 ++first evaluates the expressions <start>, + <stop>, and <step>, +-which must result in exact integers a, b, and s +-such that s is unequal to zero. ++which must result in exact integers a, b, and s ++such that s is unequal to zero. + Then the sequence +-a, a + s, a + 2 s, ..., a + (n-1) s +-is enumerated where n =3D ceil((b-a)/s). +-In other words, the sequence starts at a, increments by s, +-and stops when the next value would reach or cross b. +-If n is zero or negative the sequence is empty. +-

      +-
      +- +-
      +-
      +-(:real-range <vars>         = ;<stop>)
      +-(:real-range <vars> <start> <stop>)
      ++a, a + s, a + 2 s, ..., a + (n
      -1) s ++is enumerated where n =3D ceil((b-a)/s). ++In other words, the sequence starts at a, increments by s, ++and stops when the next value would reach or cross b. ++If n is zero or negative the sequence is empty. ++

      ++ ++
      ++ ++
      ++
      ++(:real-range <vars>         = ;<stop>)
      ++(:real-range <vars> <start> <stop>)
      + (:real-range <vars> <start> <stop> <step>)
      +-
      ++ +=20 +-
      ++
      ++

      + Runs through a range of real numbers using an explicit index variable. + This form of range enumeration avoids accumulation of rounding errors +-and is the one to use if any of the numbers defining the range is=20 +-inexact, not an integer, or a bignum of large magnitude.

      +- ++and is the one to use if any of the numbers defining the range is ++inexact, not an integer, or a bignum of large magnitude. ++

      ++

      + Providing default value 0 for <start> and + 1 for <step>, the generator first + evaluates <start>, <stop>, + and <step>, which must result in reals +-a, b, and s such that=20 +-n =3D (b-a)/s is also representable ++a, b, and s such that ++n =3D (b-a)/s is also representable + as a real. + Then the sequence 0, 1, 2, ... is enumerated while the +-current value i is less than n, and the ++current value i is less than n, and the + variable in <vars> is bound to the +-value a + i s. +-If any of the values a, b, or s is ++value a + i s. ++If any of the values a, b, or s is + non-exact then all values in the sequence are non-exact. +-

      +-
      ++

      ++ ++ ++ +=20 +-
      +-
      ++
      ++
      + (:char-range <vars> <min> <max>) +-
      ++
      +=20 +-
      ++
      + Runs through a range of characters. + First <min> and <max> are +-evaluated, which must result in two characters a and b. +-Then the sequence of characters=20 +-a, a+1, a+2, ..., b ++evaluated, which must result in two characters a and b. ++Then the sequence of characters ++a, a+1, a+2, ..., b + is enumerated in the order defined by char<=3D? + in the sense of [R5RS, 6.3.4.]. +-If b is smaller than a then the sequence is empty. +-(Note that b is included in the sequence.) +-
      +-
      +- +-
      +-
      +-(:port <vars> <port>)
      ++If b is smaller than a then the sequence is empty. ++(Note that b is included in the sequence.) ++ ++
      ++ ++
      ++
      ++(:port <vars> <port>)
      + (:port <vars> <port> <read-proc>) +-
      ++ +=20 +-
      ++
      + Reads from the port until the eof-object is read. +-Providing the default read for=20 ++Providing the default read for + <read-proc>, the generator first +-evaluates <port> and=20 ++evaluates <port> and + <read-proc>, which must result +-in an input port p and a procedure r. ++in an input port p and a procedure r. + Then the variable is run through the sequence obtained +-by (r p) ++by (r p) + while the result does not satisfy eof-object?. +-
      +-
      ++ ++ +=20 +-
      +-
      ++
      ++
      + (:dispatched <vars> <dispatch> <arg1> <arg>= *) +-
      ++
      +=20 +-
      ++
      ++

      + Runs the variables through a sequence defined by <dispatch> + and <arg1> <arg>*. + The purpose of :dispatched is implementing + dispatched generators, in particular the predefined dispatching +-generator :.

      +- ++generator :. ++

      ++

      + The working of :dispatched is as follows. + First <dispatch> and + <arg1> <arg>* are evaluated, +-resulting in a procedure d (the 'dispatcher') and=20 +-the values a[1] a[2] ... a[n]. +-Then=20 +-(d (list a[1] a[2] ... = a[n] ))=20 +-is evaluated, resulting in a value g. +-If g is not a procedure then the dispatcher ++resulting in a procedure d (the 'dispatcher') and ++the values a[1] a[2] ... a[n]. ++Then ++(d (list a[1] a[2] ... = a[n] )) ++is evaluated, resulting in a value g. ++If g is not a procedure then the dispatcher + did not recognize the argument list and an error is raised. +-Otherwise the 'generator procedure' g is used=20 ++Otherwise the 'generator procedure' g is used + to run <vars> through a sequence of values. +-The sequence defined by g is obtained by repeated=20 +-evaluation of (g empty) +-until the result is empty. +-In other words, g indicates the end of the sequence by +-returning its only argument, for which the caller has provided=20 +-an object distinct from anything g can produce. ++The sequence defined by g is obtained by repeated ++evaluation of (g empty) ++until the result is empty. ++In other words, g indicates the end of the sequence by ++returning its only argument, for which the caller has provided ++an object distinct from anything g can produce. + (Generator procedures are state based, they are no such noble things +-as streams in the sense of SRFI 40.)

      +- +- ++as streams in the sense of SRFI 40.) ++

      ++

      + The definition of dispatchers is greatly simplified by the + macro :generator-proc that constructs a generator + procedure from a typed generator. + Let (g var arg1 arg ...) be an instance of + the <generator> syntax, for example an +-application-specific typed generator, ++application-specific typed generator, + with a single variable var and no index variable. + Then +- ++

      +
      +-(:generator-proc (g arg1 arg ...)) =3D> g,
      +- +-where the generator procedure g runs through the list +-(list-ec (g var arg1 arg ...) var).

      ++(:generator-proc (g arg1 arg ...)) =3D> g,

      ++

      ++where the generator procedure g runs through the list ++(list-ec (g var arg1 arg ...) var). ++

      +=20 +- +-Adding an application-specific dispatching generator. ++

      ++Adding an application-specific dispatching generator. + In order to define a new dispatching generator (say :my) + first a dispatching procedure (say :my-dispatch) is defined. + The dispatcher will be called with a single (!) argument +@@ -998,9 +1036,9 @@ when it is called with the empty list. + Otherwise (if there is at least one value to dispatch on), + the dispatcher must either return a generator procedure + or #f (=3D no interest). +-As an example, the following skeleton code defines a dispatcher=20 +-similar to the initial dispatcher of :: +- ++As an example, the following skeleton code defines a dispatcher ++similar to the initial dispatcher of :: ++

      +
      + (define (:my-dispatch args)
      +   (case (length args)
      +@@ -1011,28 +1049,28 @@ similar to the initial dispatcher of ::
      +              (:generator-proc (:list a1)) )
      +             ((string? a1)
      +              (:generator-proc (:string a1)) )
      +-            ...more unary cases...
      ++            ...more unary cases...
      +             (else
      +              #f ))))
      +     ((2) (let ((a1 (car args)) (a2 (cadr args)))
      +            (cond
      +             ((and (list? a1) (list? a2))
      +              (:generator-proc (:list a1 a2)) )
      +-            ...more binary cases...
      ++            ...more binary cases...
      +             (else
      +              #f ))))
      +-    ...more arity cases...
      ++    ...more arity cases...
      +     (else
      +      (cond
      +       ((every?-ec (:list a args) (list? a))
      +        (:generator-proc (:list (apply append args))) )
      +-      ...more large variable arity cases...
      ++      ...more large variable arity cases...
      +       (else
      +        #f )))))
      +- +-Once the dispatcher has been defined, the following macro=20 ++

      ++Once the dispatcher has been defined, the following macro + implements the new dispatching generator: +- ++

      +
      + (define-syntax :my
      +   (syntax-rules (index)
      +@@ -1040,83 +1078,85 @@ implements the new dispatching generator:
      +      (:dispatched cc var (index i) :my-dispatch arg1 arg ...) )
      +     ((:my cc var arg1 arg ...)
      +      (:dispatched cc var :my-dispatch arg1 arg ...) )))
      +- ++

      + This method of extension yields complete control of the dispatching proce= ss. + Other modules can only add cases to :my +-if they have access to :my-dispatch.

      +- +- +-Extending the predefined dispatched generator. ++if they have access to :my-dispatch. ++

      ++

      ++Extending the predefined dispatched generator. + An alternative to adding a new dispatched generators is extending +-the predefined generator :. +-Technically, extending : means ++the predefined generator :. ++Technically, extending : means + installing a new global dispatching procedure using +-:-dispatch-set! ++:-dispatch-set! + as described above. +- +- ++

      ++

      + In most cases, however, the already installed dispatcher should +-be extended by new cases.=20 ++be extended by new cases. + The following procedure is a utility for doing so: +- +-

      (dispatch-union d1 d2) =3D> d,
      =20 +- +-where the new dispatcher d recognizes the union of the +-cases recognized by the dispatchers d1 and d2. ++

      ++
      (dispatch-union d1 d2) =3D> d,
      ++

      ++where the new dispatcher d recognizes the union of the ++cases recognized by the dispatchers d1 and d2. + The new dispatcher always tries both component dispatchers + and raises an error in case of conflict. +-The identification returned by (d) ++The identification returned by (d) + is the concatenation of the component identifications +-(d1) and=20 +-(d2), enclosed in lists ++(d1) and ++(d2), enclosed in lists + if necessary. + For illustration, consider the following code: +- ++

      +
      + (define (example-dispatch args)
      +   (cond
      +    ((null? args)
      +     'example )
      +    ((and (=3D (length args) 1) (symbol? (car args)) )
      +-    (:generator-proc (:string (symbol->string (car args)))) )
      ++    (:generator-proc (:string (symbol->string (car args)))) )
      +    (else
      +     #f )))
      +=20
      + (:-dispatch-set! (dispatch-union (:-dispatch-ref) example-dispatch))
      +- ++

      + After evaluation of this code, the following example will work: +- +-

      (list-ec (: c 'abc) c) =3D> (#\a #\b #\c)
      +- +-Adding cases to : is particularly useful= =20 ++

      ++
      (list-ec (: c 'abc) c) =3D> (#\a #\b #\c)
      ++

      ++Adding cases to : is particularly useful + for frequent cases of interactive input. + Be warned, however, that the advantage of global extension also carries + the danger of conflicts, unexpected side-effects, and slow dispatching. +- +- ++

      ++ ++ ++ +=20 +-
      +-
      +-(:do (<lb>*) <ne1?> (<ls>*))<= br> ++
      ++
      ++(:do (<lb>*) <ne1?> (<ls>*))<= br /> + (:do (let (<ob>*) <oc>*) (<lb>= ;*) <ne1?> (let (<ib>*) <ic>*) <ne2?> (<ls>*)) +-
      ++
      +=20 +-
      ++
      + Defines a generator in terms of a named-let, + optionally decorated with inner and outer lets. + This generator is for defining other generators. + (In fact, the reference implementation transforms any other + generator into an instance of fully decorated :do.) +-The generator is a compromise between expressive power=20 ++The generator is a compromise between expressive power + (more flexible loops) and fixed structure (necessary + for merging and modifying generators). +-In the fully decorated form, the syntactic variables=20 ++In the fully decorated form, the syntactic variables + <ob> (outer binding), + <oc> (outer command), + <lb> (loop binding), + <ne1?> (not-end1?), + <ib> (inner binding), +-<ic> (inner command),=20 ++<ic> (inner command), + <ne2?> (not-end2?), and + <ls> (loop step) + define the following loop skeleton: +@@ -1124,11 +1164,11 @@ define the following loop skeleton: +
      + (let (<ob>*)
      +   <oc>*
      +-  (let loop (<lb>*)=20
      ++  (let loop (<lb>*)
      +     (if <ne1?>
      +         (let (<ib>*)
      +           <ic>*
      +-          payload
      ++          payload
      +           (if <ne2?>
      +               (loop <ls>*) ))))),
      +=20 +@@ -1139,120 +1179,129 @@ i.e. they do not begin with a <definiti= on>. + The latter requirement allows the code generator to + produce more efficient code for special cases by + removing empty let-expressions altogether. +-
      +-
      ++ ++ +=20 +-
      +-
      ++
      ++
      + (:let <vars> <expression>) +-
      ++
      +=20 +-
      +-Runs through the sequence consisting of the value of=20 ++
      ++Runs through the sequence consisting of the value of + <expression>, only. + This is the same as + (:list <vars> (list <expression>)). + If an index variable is specified, its value is 0. +-The :let-generator can be used to introduce=20 ++The :let-generator can be used to introduce + an intermediate variable depending on outer generators. +-
      +-
      ++ ++ +=20 +-
      +-
      ++
      ++
      + (:parallel <generator>*) +-
      ++
      +=20 +-
      ++
      + Runs several generators in parallel. + This means that the next binding in the sequence is obtained + by advancing each generator in <generator>* + by one step. + The parallel generator terminates when any of its component + generators terminates. +-The generators share a common scope for the variables=20 ++The generators share a common scope for the variables + they introduce. +-This implies that the names of the variables introduced=20 ++This implies that the names of the variables introduced + by the various generators must be distinct. +-
      +-
      ++ ++ +=20 +-
      +-
      ++
      ++
      + (:while <generator> <expression>) +-
      ++
      +=20 +-
      ++
      ++

      + Runs <generator> while <expression> + evaluates to non-#f. + The guarding expression is included in the scope +-of the variables introduced by the generator.

      +- ++of the variables introduced by the generator. ++

      ++

      + Note the distinction between the filter if and + the modified generator expressed by :while. +-

      +-
      ++

      ++ ++ ++ +=20 +-
      +-
      ++
      ++
      + (:until <generator> <expression>) +-
      ++
      +=20 +-
      +-Runs <generator> until after=20 ++
      ++

      ++Runs <generator> until after + <expression> has evaluated to non-#f. + The guarding expression is included in the scope +-of the variables introduced by the generator.

      +- +-Note the distinction between :while, stopping at +-a certain condition, and :until, stopping after ++of the variables introduced by the generator. ++

      ++

      ++Note the distinction between :while, stopping at ++a certain condition, and :until, stopping after + a certain condition has occurred. The latter implies that the binding + that has triggered termination has been processed by the comprehension. +-

      +-
      ++

      ++ ++ +=20 +-
      +-
      ++
      ++
      + <application-specific typed generator> +-
      ++
      +=20 +-
      ++
      ++

      + An important aspect of this SRFI is a modular mechanism to + define new typed generators. + To define a new typed generator a hygienic referentially + transparent macro of the same name is defined to transform +-the generator pattern into an instance of the=20 +-:do-generator. ++the generator pattern into an instance of the ++:do-generator. + The extension is fully modular, meaning that no other + macro has to be modified to add the new generator. + This is achieved by defining the new macro in +-Continuation Passing Style, as in [MWL].

      +- ++Continuation Passing Style, as in [MWL]. ++

      ++

      + Technically, this works as follows. +-Assume the generator syntax (:mygen <var> <arg>)= =20 ++Assume the generator syntax (:mygen <var> <arg>) + is to be implemented, for example running the variable <var><= /code> + through the list (reverse <arg>). +-The following definition implements :mygen=20 +-in terms of :list=20 +-using the additional syntactic variable cc=20 +-(read current continuation): +- ++The following definition implements :mygen ++in terms of :list ++using the additional syntactic variable cc ++(read current continuation): ++

      +
      + (define-syntax :mygen
      +   (syntax-rules ()
      +     ((:mygen cc var arg)
      +      (:list cc var (reverse arg)) )))
      +- +-After this definition, any comprehension will accept=20 ++

      ++After this definition, any comprehension will accept + the :mygen-generator and produce the + proper code for it. +-This works as follows.=20 ++This works as follows. + When a comprehension sees something of the form + (g arg ...) in the position of a + <qualifier> then it will +-transform the entire comprehension into=20 ++transform the entire comprehension into + (g (continue ...) arg ...). +-This effectively 'transfers control' to the=20 ++This effectively 'transfers control' to the + macro g, for example :mygen. + The macro g has full control of + the transformation, but eventually it should +@@ -1263,145 +1312,152 @@ by the :list-macro. + The macro :do finally transforms + into (continue ... (:do etc ...)). + As continue has been chosen by the +-macro implementing the comprehension,=20 ++macro implementing the comprehension, + it can regain control and proceed +-with other qualifiers.

      +- +-In order to ensure consistency of new generators=20 ++with other qualifiers. ++

      ++

      ++In order to ensure consistency of new generators + with the ones defined in this SRFI, a few conventions + are in order. +-Firstly, the generator patterns begin with one or more=20 ++Firstly, the generator patterns begin with one or more + variables followed by arguments defining the sequence. +-Secondly, each generator except :do=20 ++Secondly, each generator except :do + can handle an optional index variable. + This is most easily implemented using +-:parallel +-together with :integers. ++:parallel ++together with :integers. + In case the payload generator needs an index anyhow +-(e.g. :vector) ++(e.g. :vector) + it is more efficient to add an index-variable if + none is given and to implement the indexed case. + Finally, make sure that no syntactic variable of the + generator pattern ever gets duplicated in the code + (to avoid exponential code size in nested application), +-and introduce sufficient intermediate variables to=20 ++and introduce sufficient intermediate variables to + make sure expressions are evaluated at the correct time. +-

      +-
      +- +-

      +-Suggestions for application-specific extensions

      ++

      ++ ++ +=20 +-

      Arrays in the sense of [SRFI25]

      ++

      ++Suggestions for application-specific extensions

      +=20 ++

      Arrays in the sense of [SRFI25]

      ++

      + In order to create an array from a sequence of elements, + a comprehension with the following syntax would be useful: +- ++

      +
      (array-ec <shape> <qualifier>* <expression>).
      +- ++

      + The comprehension constructs a new array of the given shape +-by filling it row-major with the sequence of elements as specified=20 ++by filling it row-major with the sequence of elements as specified + by the qualifiers. +- ++

      ++

      + On the generator side, it would be most useful to have a + generator of the form +- ++

      +
      (:array <vars> <arg>),
      +- ++

      + running through the elements of the array in row-major. +-For the optional index variable, the extension=20 ++For the optional index variable, the extension + (index <k1> <k>*) + could be defined where <k1> <k>* + are variable names indexing the various dimensions. ++

      +=20 +- +-

      Random Numbers in the sense of [SRFI27]

      +- ++

      Random Numbers in the sense of [SRFI27]

      ++

      + In order to create a vector or list of random numbers, + it would be convenient to have generators of the following form: +- ++

      +
      + (:random-integer [ <range> [ <number> ] ] )
      + (:random-real    [ <number> ] )
      +- +-where <range> (default 2) indicates the range of=20 ++

      ++where <range> (default 2) indicates the range of + the integers and <number> (default infinity) + specifies how many elements are to be generated. + Derived from these basic generators, one could define several + other generators for other distributions (e.g. Gaussian). ++

      +=20 +- +-

      Bitstrings in the sense of [SRFI33]

      +- ++

      Bitstrings in the sense of [SRFI33]

      ++

      + As eager comprehensions are efficient, they can be useful + for operations involving strings of bits. + It could be useful to have the following comprehension: +- ++

      +
      (bitwise-ec <qualifier>* <expression>),
      +- ++

      + which constructs an integer from bits obtained as values + of <expression> in the ordering defined + by [SRFI33]. +-In other words, if the sequence of values is=20 +-x[0], x[1], ..., x[n-1] then +-the result is x[0] + x[1] 2 + ... + x[n-1] 2^= (n-1). ++In other words, if the sequence of values is ++x[0], x[1], ..., x[n-1] then ++the result is x[0] + x[1] 2 + ... + x[n-1] 2^= (n-1). + On the generator side, a generator of the form +- ++

      +
      (:bitwise <vars> <arg1> <arg>*)
      +- ++

      + runs through the sequence of bits obtained by appending the + binary digits of the integers <arg1> <arg>*. ++

      ++

      Streams in the sense of [SRFI 40]

      +=20 +-

      Streams in the sense of [SRFI 40]

      +- +-It is possible to 'lazify' the eager comprehension=20 ++

      ++It is possible to 'lazify' the eager comprehension + list-ec, + constructing a stream in the sense of [SRFI 40]. + Clearly, such a comprehension (stream-ec) + is not eager at all since it only runs the loops when results are request= ed. + It is also possible to define a :stream-generator with +-the same API as :list but running +-through streams instead of lists.

      +- +-For what it is worth,=20 +-the file srfi4= 0-ec.scm implements ++the same API as :list but running ++through streams instead of lists. ++

      ++

      ++For what it is worth, ++the file srfi= 40-ec.scm implements + :stream and stream-ec and gives an example. +-The implementation makes substantial use of=20 ++The implementation makes substantial use of + call-with-current-continuation to run the loop + only when necessary. + In some implementations of Scheme this may involve + considerable overhead. ++

      +=20 +-

      Reading Text Files

      +- ++

      Reading Text Files

      ++

      + Eager comprehensions can also be used to process files. + However, bear in mind that an eager comprehension wants + to read and process the entire file right away. + Nevertheless, these generators would be useful for + reading through the lines of a file or through the + characters of a file: +- ++

      +
      + (:lines-of-file <vars> <file>)
      + (:chars-of-file <vars> [ (line <variable1>) ] [ (column <v=
      ariable2>) ] <file>)
      +- ++

      + Here <file> is either an input port + or a string interpreted as a filename. + In a similar fashion, generators reading from sockets defined + by URLs or other communication facilities could be defined. ++

      +=20 +-

      The Scheme shell Scsh

      +- ++

      The Scheme shell Scsh

      ++

      + In the Scheme-shell Scsh it could be useful to have certain +-comprehensions and generators.=20 ++comprehensions and generators. + Candidates for comprehensions are + begin-ec, + |-ec, + ||-ec, and +-&&-ec. ++&&-ec. + Concerning generators, it might be useful to have +-:directory running through the=20 +-records of a directory, and maybe a=20 ++:directory running through the ++records of a directory, and maybe a + sophisticated :file-match-generator + could enumerate file record in a directory structure. + Optional variables of the generators could give +@@ -1409,18 +1465,18 @@ convenient access frequent components of the file = records + (e.g. the filename). + Another candidate is :env to run through + the environment associations. +-It is left to other authors and other SRFIs to=20 ++It is left to other authors and other SRFIs to + define a useful set of comprehensions and generators + for Scsh. ++

      +=20 ++

      Design Rationale

      +=20 +-

      Design Rationale

      +- +-

      What is the difference between eager and lazy comprehensions?

      +- +-A lazy comprehension, for example stream-of in the=20 ++

      What is the difference between eager and lazy comprehensions?

      ++

      ++A lazy comprehension, for example stream-of in the + sense of [SRFI 40], constructs an object +-representing a sequence of values.=20 ++representing a sequence of values. + Only at the time these values are needed that they + are actually produced. + An eager comprehension, on the other hand, is an instruction to +@@ -1429,167 +1485,187 @@ for example as in do-ec= . + In other words, it is nothing more sophisticated than a loop, + potentially with a more convenient notation. + This also explains why stream-of is the most +-fundamental lazy comprehension, and all others can ++fundamental lazy comprehension, and all others can + be formulated in terms of it, whereas the most fundamental +-eager comprehension is do-ec. +- +- +-

      Why the [outer .. inner | expr]=20 +-order of qualifiers?

      ++eager comprehension is do-ec. ++

      +=20 ++

      Why the [outer .. inner | expr] ++order of qualifiers?

      ++

      + In principle, there are six possible orders in which the + qualifiers and the expression of a comprehension can be written. + We denote the different conventions with a pattern in which +-expr denotes the expression over which the comprehension +-ranges, inner denotes the generator spinning fastest, and +-outer denotes the generator spinning slowest. +-For example, [Haskell] and=20 ++expr denotes the expression over which the comprehension ++ranges, inner denotes the generator spinning fastest, and ++outer denotes the generator spinning slowest. ++For example, [Haskell] and + [Python] use +-[expr | outer .. inner]. ++[expr | outer .. inner]. + (Probably with sufficient persistence, instances for any + of the conventions can be found on the Internet.) +-In addition, there is the common mathematical notation=20 +-'{f(x) | x in X}'.

      +- ++In addition, there is the common mathematical notation ++'{f(x) | x in X}'. ++

      ++

      + It is important to understand that the notational convention + does not only determine the order of enumeration but also the + scope of the variables introduced by the generators. +-The scope of inner includes expr, and the +-scope of outer should include inner to allow ++The scope of inner includes expr, and the ++scope of outer should include inner to allow + inner generates depending on outer generators. + Eventually, the choice for a particular syntactic convention is + largely a matter of personal preferences. + However, there are a few considerations that went into the +-choice made for this SRFI:

      +- +-1. The mathematical notation is universally known and widely used. +-However, the mathematical notation denotes a set comprehension ++choice made for this SRFI: ++

      ++
        ++
      1. ++

        ++The mathematical notation is universally known and widely used. ++However, the mathematical notation denotes a set comprehension + in which the order of the qualifiers is either irrelevant or must + be deduced from the context. +-For the purpose of eager comprehensions as a programming language=20 ++For the purpose of eager comprehensions as a programming language + construct, the order does matter and a simple convention is a plus. + For these reasons, the mathematical notation as such is undesirable, + but its widespread use is in favor of +-[expr | inner .. outer] and +-[expr | outer .. inner].

        +- +-2. It is desirable to have the scope of the variables increase ++[expr | inner .. outer] and ++[expr | outer .. inner]. ++

        ++
      2. ++
      3. ++

        ++It is desirable to have the scope of the variables increase + into one direction, as in +-[expr | inner .. outer] and +-[outer .. inner | expr], and ++[expr | inner .. outer] and ++[outer .. inner | expr], and + not change direction, as in +-[expr | outer .. inner] +-where expr is in the scope of inner +-but outer is not. ++[expr | outer .. inner] ++where expr is in the scope of inner ++but outer is not. + This is even more important if the syntax in Scheme +-does not explicitly contain the '|'-separator.

        +- +-3. More complicated comprehensions with several nested generators ++does not explicitly contain the '|'-separator. ++

        ++
      4. ++
      5. ++

        ++More complicated comprehensions with several nested generators + eventually look like nested loops and Scheme always +-introduces them outer .. inner as in=20 ++introduces them outer .. inner as in + do and named-let. +-This is in favor of=20 +-[expr | outer .. inner] and +-[outer .. inner | expr]. ++This is in favor of ++[expr | outer .. inner] and ++[outer .. inner | expr]. + Shorter comprehension may look more naturally the +-other way around.

        +- +-Regarding these contradicting preferences, I regard=20 +-linearity in scoping (2.) most important, followed by=20 ++other way around. ++

        ++
      6. ++
      ++

      ++Regarding these contradicting preferences, I regard ++linearity in scoping (2.) most important, followed by + readability for more complicated comprehensions (3.). +-This leads to [outer .. inner | expr]. ++This leads to [outer .. inner | expr]. + An example in Scheme-syntax is + (list-ec (: x 10) (: y x) (f x y)), + which looks acceptable to me even without similarity + to the mathematical notation. + As a downside, the convention clashes with other the + convention used in other languages (e.g. Haskell and Python). ++

      +=20 +- +-

      You forgot [choose your favorite here]-ec!

      +- ++

      You forgot [choose your favorite here]-ec!

      ++

      + I tried to construct a reasonably useful set of tools + according to what [R5RS] specifies. + Nevertheless, is the choice what to include and what to +-leave out eventually a matter of personal preference.

      +- ++leave out eventually a matter of personal preference.

      ++

      ++

      + When 'packing the toolbox' I went for travelling light; + this SRFI does not include everything imaginable + or even everything useful. +-I oriented myself at the standard procedures=20 ++I oriented myself at the standard procedures + of [R5RS], + with a few omissions and additions. +-A notable omission are gcd-ec and=20 ++A notable omission are gcd-ec and + lcm-ec because they are one-liners, + and more severely, of questionable value in practice. + A notable addition are + fold-ec and + fold3-ec, + providing a mechanism to define lots of useful one-liners. +-The other notable addition is=20 ++The other notable addition is + first-ec, which + is the fundamental 'early stopping' comprehension. +-It is used to define=20 +-any?-ec and +-every?-ec +-which are among the most frequent comprehensions.

      +- ++It is used to define ++any?-ec and ++every?-ec ++which are among the most frequent comprehensions. ++

      ++

      + Concerning the generators, the same principle has been used. +-Additions include :range +-and friends because they are universally needed, and=20 +-:dispatched which is +-primarily intended for implementing :. +- +- +-

      Why is the order of enumeration specified? ++Additions include :range ++and friends because they are universally needed, and ++:dispatched which is ++primarily intended for implementing :. ++

      +=20 ++

      Why is the order of enumeration specified?

      ++

      + For the purpose of this SRFI, every generator runs through +-its sequence of bindings in a well specified order, and nested=20 +-generators run through the Cartesian product in the order=20 ++its sequence of bindings in a well specified order, and nested ++generators run through the Cartesian product in the order + of nested loops. +-The purpose of this definition is making the sequence as=20 ++The purpose of this definition is making the sequence as + easily predictable as possible. +- +-On the other hand, many mechanisms for lazy comprehensions ++

      ++

      ++On the other hand, many mechanisms for lazy comprehensions + do not specify the order in which the elements are enumerated. +-When it comes to infinite streams, this has the great advantage=20 +-that a comprehension may interleave an inner and an outer=20 ++When it comes to infinite streams, this has the great advantage ++that a comprehension may interleave an inner and an outer + enumeration, a method also known as 'dove-tailing' or 'diagonalizing'. +-Interleaving ensures that any value of the resulting stream is=20 +-produced after a finite amount of time, even if one or more=20 ++Interleaving ensures that any value of the resulting stream is ++produced after a finite amount of time, even if one or more + inner streams are infinite. ++

      +=20 +-

      Why both typed and dispatching generators?

      +- ++

      Why both typed and dispatching generators?

      ++

      + The reason for typed generators is runtime efficiency. + In fact, the code produced by :range and others + will run as fast as a hand-coded do-loop. + The primary purpose of the dispatching generator is convenience. + It comes at the price of reduced runtime performance, + both for loop iteration and startup. ++

      +=20 +-

      Why the something-ec and :type naming?

      +- +-The purpose of the :type convention is to keep=20 ++

      Why the something-ec and :type naming?

      ++

      ++The purpose of the :type convention is to keep + many common comprehensions down to one-liners. + In my opinion, the fundamental nature of eager comprehensions + justifies a single character naming convention. +-The something-ec convention is primarily intended to +-stay away from the widely used something-of. ++The something-ec convention is primarily intended to ++stay away from the widely used something-of. + It reduces confusion and conflict with related mechanisms. ++

      +=20 +-

      Why combine variable binding and sequence definition?

      +- ++

      Why combine variable binding and sequence definition?

      ++

      + The generators of this SRFI do two different things with + a single syntactic construct: They define a sequence of values + to enumerate and they specify a variable (within a certain + scope) to run through that sequence. +-An alternative is to separate the two, for example as it=20 +-has been done in=20 +-SRFI 40.

      +- ++An alternative is to separate the two, for example as it ++has been done in ++SRFI 40. ++

      ++

      + The reason for combining sequence definition and enumeration +-for the purpose of this SRFI is threefold.=20 ++for the purpose of this SRFI is threefold. + Firstly, sequences of values are not explicitly represented as + objects in the typed generators; the generators merely + manipulate an internal state. +@@ -1598,115 +1674,125 @@ common comprehensions and reduces syntax to the = naked minimum. + Thirdly, this SRFI aims at the highest possible performance for + typed generators, which is achieved if the state being manipulated + is represented by the loop variable itself. ++

      +=20 +-

      Why is (: <vars>) illegal?

      +- +-It is reasonable and easy to define (: <vars&= gt;)=20 +-as (:integers <vars>),=20 ++

      Why is (: <vars>) illegal?

      ++

      ++It is reasonable and easy to define (: <var= s>) ++as (:integers <vars>), + enumerating the non-negative integers. + However, it turned out that a frequent mistake in using the + eager comprehensions is to forget either the variable + or an argument for the enumeration. +-As this would lead to an infinite loop (not always=20 ++As this would lead to an infinite loop (not always + equally pleasant in interactive sessions), it is not allowed. ++

      +=20 +-

      Why is there no :sequential?

      +- +-Just like :parallel=20 ++

      Why is there no :sequential?

      ++

      ++Just like :parallel + enumerates generators in + parallel, a :sequential generator could +-enumerate a concatenation of several generator, starting=20 ++enumerate a concatenation of several generator, starting + the next one when the previous has finished. + The reason for not having such a qualifier is + that the generators should use all the same variable name + and there is no hygienic and referentially transparent + way of enforcing this (or even knowing the variable). ++

      +=20 +-

      Why is there no general let-qualifier?

      +- +-It is easy to add let, let*,=20 ++

      Why is there no general let-qualifier?

      ++

      ++It is easy to add let, let*, + and letrec as cases to <qualifier>. +-This would allow more sophisticated local variables=20 +-and expressions than possible with=20 +-(:let <vars> <expression>)= and ++This would allow more sophisticated local variables ++and expressions than possible with ++(:let <vars> <expression>) and + (begin <sequence>*). + In particular, a local <definition> + in the sense of [R5RS, 7.1.5.] would +-be possible.

      +- +-There are two reasons for not including let=20 ++be possible. ++

      ++

      ++There are two reasons for not including let + and friends as qualifiers. + The first reason concerns readability. +-A qualifier of the form=20 ++A qualifier of the form + (let (<binding spec>*) <body>) +-only makes sense if the scope of the new variables ends at the=20 +-end of the comprehension, and not already ++only makes sense if the scope of the new variables ends at the ++end of the comprehension, and not already + after <body>. +-The similarity with ordinary let-expressions=20 ++The similarity with ordinary let-expressions + would be very confusing. + The second reason concerns the design rationale. + If sophisticated let-qualifiers involving +-recursion or local definitions are needed, it is likely=20 ++recursion or local definitions are needed, it is likely + that eager comprehensions are being overused. + In that case it might be better to define a procedure + for the task. + So including an invitation to overuse the mechanism would +-be a serious violation of the=20 +-Keep It Simple and Stupid principle. +- +-

      Why is there no :nested generator?

      ++be a serious violation of the ++Keep It Simple and Stupid principle. ++

      +=20 ++

      Why is there no :nested generator?

      ++

      + The specification above defines nested +-as a qualifier but :parallel=20 ++as a qualifier but :parallel + as a generator. + In particular, this makes it impossible to make parallel +-generators from nested ones.

      +- ++generators from nested ones. ++

      ++

      + This design simply reflects an implementability limitation. + All component generators of :parallel are +-transformed into :do-generators +-and these can be merged into a parallel generator.=20 ++transformed into :do-generators ++and these can be merged into a parallel generator. + However, nested generators cannot be merged easily without +-losing the type of the generator,=20 ++losing the type of the generator, + which would seriously hurt modularity and performance. ++

      +=20 +-

      Is any?-ec eager?

      +- +-Yes, it is still eager because it immediately starts to=20 +-run through the sequence.

      +- +-In fact, the reference implementation makes sure=20 ++

      Is any?-ec eager?

      ++

      ++Yes, it is still eager because it immediately starts to ++run through the sequence. ++

      ++

      ++In fact, the reference implementation makes sure + first-ec, +-any?-ec, and +-every?-ec +-execute efficiently so they can be used conveniently=20 +-as in=20 ++any?-ec, and ++every?-ec ++execute efficiently so they can be used conveniently ++as in + (every?-ec (:list x my-list) (pred? x)). ++

      +=20 +-

      Why this whole :dispatched business?

      +- +-It is specified above that the dispatching generator, +-called :, is just a special case +-of :dispatched using=20 ++

      Why this whole :dispatched business?

      ++

      ++It is specified above that the dispatching generator, ++called :, is just a special case ++of :dispatched using + a global dispatching procedure. + Alternatively, a simple fixed global mechanism to extend +-: could have been used. ++: could have been used. + This is much simpler but does not support the definition +-of new dispatched generators.

      +- +-The purpose of :dispatched ++of new dispatched generators. ++

      ++

      ++The purpose of :dispatched + and its utilities +-(:generator-proc and ++(:generator-proc and + dispatch-union) + is the following. +-Assume : is to be used inside a ++Assume : is to be used inside a + module but it is essential that no other module can spoil it, + e.g. by installing a very slow dispatcher. + The recommended way to proceed in this case is to define a +-local copy of the original dispatching generator=20 +-:, ++local copy of the original dispatching generator ++:, + for example with the following code +- ++

      +
      + (define :my-dispatch
      +   (make-initial-:-dispatch) )
      +@@ -1717,33 +1803,36 @@ for example with the following code
      +      (:dispatched cc var (index i) :my-dispatch arg1 arg ...) )
      +     ((:my cc var arg1 arg ...)
      +      (:dispatched cc var :my-dispatch arg1 arg ...) ))),
      +- ++

      + and to use the new generator :my instead of +-:.

      +- ++:. ++

      ++

      + An alternative for the dispatching mechanism as defined in + this SRFI is the use of parameter objects in the sense of +-[SRFI 39].=20 ++[SRFI 39]. + The dispatching generator would then access a dynamically + scoped variable to find the dispatcher, allowing full + control over dispatching. + However, this approach does not solve the dilemma that it is +-sometimes useful that : is global ++sometimes useful that : is global + and sometimes undesired. + The approach specified for this SRFI addresses this dilemma +-by offering options.

      +- ++by offering options. ++

      ++

      + Another alternative for dealing with the dispatching + problem is adding an optional argument to the syntax of +-: through which the dispatcher ++: through which the dispatcher + can be passed explicitly. +-However, as : has variable ++However, as : has variable + arity and the identifier for the variable cannot be +-distinguished from any value for a dispatcher,=20 ++distinguished from any value for a dispatcher, + this is syntactically problematic. ++

      +=20 +-

      Why is there no local mechanism for adding to :<= /code>?

      +- ++

      Why is there no local mechanism for adding to = :?

      ++

      + According to [R5RS, 7.1.6.] macros can only + be defined at the level of the <program> syntax. + This implies that the scope of typed generators cannot easily be +@@ -1751,17 +1840,19 @@ limited to local scopes. + As typed and dispatched generators go together, + there is also no strong need for a limited scope + of dispatched generators either. +-Furthermore, locally extendable dispatchers are another major=20 ++Furthermore, locally extendable dispatchers are another major + headache to those trying to understand other people's code. ++

      +=20 +-

      Why are dispatchers unary?

      +- +-As defined in :dispatched, ++

      Why are dispatchers unary?

      ++

      ++As defined in :dispatched, + a dispatching procedure is called with a single argument being +-the list of values to dispatch on.=20 ++the list of values to dispatch on. + An alternative is to apply the dispatcher to the +-list of values to dispatch on, which would be more natural in Scheme.

      +- ++list of values to dispatch on, which would be more natural in Scheme. ++

      ++

      + The reason for not using apply is a minor + improvement in efficiency. + Every time apply is used on a procedure of variable +@@ -1769,55 +1860,61 @@ arity, an object containing the argument list is a= llocated on + the heap. + As a dispatcher may call many other dispatchers, this will adds + to the overhead of dispatching, which is relevant in inner loops. ++

      +=20 +-

      Why are there two fold comprehensions?

      +- +-The reason for having two fold comprehensions=20 ++

      Why are there two fold comprehensions?

      ++

      ++The reason for having two fold comprehensions + (fold-ec and +-fold3-ec) is efficiency.

      +- +-Clearly, the more general construction is=20 +-fold3-ec=20 ++fold3-ec) is efficiency. ++

      ++

      ++Clearly, the more general construction is ++fold3-ec + as it allows individual treatment of the empty + sequence case and the singleton sequence case. + However, this comes at the price of more book-keeping +-as can be seen from the=20 ++as can be seen from the + implementation example. + As the overhead is located within inner loops, + it makes sense to define another fold comprehension + for the case where the added flexibility is not needed. +-This is fold-ec.

      +- ++This is fold-ec. ++

      ++

      + The names fold-ec and fold3-ec + have been chosen for the comprehensions in order to stay + clear any other 'fold' that may be around. ++

      +=20 +-

      Why is :char-range not defined by integer->char?

      +- +-The definition of :char-range ++

      Why is :char-range not defined by integer->char= ?

      ++

      ++The definition of :char-range + specifies a sequence of adjacent characters ordered by char<=3D?= . +-The reason for not using char->integer and=20 +-integer->char is the fact that ++The reason for not using char->integer and ++integer->char is the fact that + [R5RS, 6.3.4.] leaves it to the implementation + whether the integers representing characters are consecutive or not. + In effect, this underspecification is inherited by :char-range. ++

      +=20 +- +-

      Related Work and Acknowledgements

      +- ++

      Related Work and Acknowledgements

      ++

      + Several other proposals related to the mechanism specified here exists. +-The following mechanisms are made for and in Scheme (or at least a=20 +-specific dialect thereof):

      +- ++The following mechanisms are made for and in Scheme (or at least a ++specific dialect thereof): ++

      ++

      + First of all, the report [R5RS] of Scheme itself +-defines two constructs for writing loops: do and=20 ++defines two constructs for writing loops: do and + named-let. +-Both constructs express a single loop (not nested),=20 ++Both constructs express a single loop (not nested), + possibly with several variables running in parallel, +-based on explicit manipulation of the state variables.=20 ++based on explicit manipulation of the state variables. + For example (do ((x 0 (+ x 1))) ((=3D x 10)) (display x)) +-explicitly mentions how to obtain the next binding of x.

      +- ++explicitly mentions how to obtain the next binding of x. ++

      ++

      + Richard Kelsey's "Macros for writing loops", [MWL] + are an extension to Scheme48 to simplify the formulation of loops. + The basic idea is to stick with a do-like syntax for +@@ -1826,9 +1923,9 @@ a state variable explicitly. + For example, (list* x '(1 2 3)) expresses an enumeration + of the variable x through the list (1 2 3) + without explicit state manipulation. +-The iteration constructs of [MWL], named=20 ++The iteration constructs of [MWL], named + iterate and reduce, +-express a single (not nested) loop (iterate) or=20 ++express a single (not nested) loop (iterate) or + comprehension (reduce) with any number of + parallel enumerations. + A most important feature of the [MWL]-concept +@@ -1837,10 +1934,11 @@ In effect, the addition of a new sequence type doe= s not + require a modification of the existing macros. + This is achieved by carefully limiting the expressive + power of the loop constructs and by using the macros +-in Continuation Passing Style to call other macros. +-The [MWL]-concept, and its implementation,=20 +-were most influential for this SRFI.

      +- ++in Continuation Passing Style to call other macros. ++The [MWL]-concept, and its implementation, ++were most influential for this SRFI. ++

      ++

      + Another related mechanism is the library of streams recently + submitted by Phil L. Bewig as [SRFI 40]. + The library contains a data type to represent even +@@ -1856,35 +1954,36 @@ Nevertheless, modularity is high since it is easy = to define + a procedure producing a stream object and this can be + used for enumeration. + The order of enumeration is left unspecified to allow +-interleaving of generators (also refer to=20 ++interleaving of generators (also refer to + above.) + Before Phil submitted his SRFIs, we had a short + discussion in which we clarified the semantic and syntactic + differences of our approaches. +-It turned out that the mechanisms are sufficiently=20 ++It turned out that the mechanisms are sufficiently + different not to unify them. + The most important difference is the design rationale: + Phil created his library to support the stream-paradigm +-in Scheme, inspired by the work done for Haskell and=20 ++in Scheme, inspired by the work done for Haskell and + other lazy languages, and intrigued by the beauty + of programming with infinite streams. +-My work only aims at a convenient way of expressing=20 ++My work only aims at a convenient way of expressing + frequent patterns of loops in a compact way. + For what it is worth, section SRFI40-ec + contains a suggestion for extending the eager comprehension +-mechanism for SRFI40-streams.

      +- ++mechanism for SRFI40-streams. ++

      ++

      + Phil's work on streams and lazy comprehensions in Scheme + triggered Eli Barzilay to implement a library of eager + comprehensions for PLT-Scheme, [Eli]. + The mechanism implemented by Eli is in essence very + similar to the one proposed in this SRFI, and the two + efforts have been independent until recently. +-Syntactically, Eli uses infix operators for generators,=20 +-whereas this SRFI is purely prefix, and Eli uses the=20 +-[expr | outer .. inner] convention ++Syntactically, Eli uses infix operators for generators, ++whereas this SRFI is purely prefix, and Eli uses the ++[expr | outer .. inner] convention + for nesting, whereas this SRFI uses the +-[outer .. inner | expr] ++[outer .. inner | expr] + convention. + Semantically, Eli's mechanism defines more flexible + loops than this SRFI. +@@ -1892,208 +1991,214 @@ Comprehensions are regarded as generalized colle= ction + processes like fold and reduce. + The mechanism in this SRFI is more restricted with respect + to control flow (there is no general while) +-and more extensive with respect to generators and=20 ++and more extensive with respect to generators and + comprehensions. +-Despite the strong conceptual similarity, the design=20 ++Despite the strong conceptual similarity, the design + rationales are different. + This SRFI focuses on portability and modular extension, +-whatever that may cost in terms of expressive power.

      +- +-Finally, I would like to thank Mike Sperber for his=20 ++whatever that may cost in terms of expressive power. ++

      ++

      ++Finally, I would like to thank Mike Sperber for his + encouragement to proceed with the SRFI and for several + discussions of the matter. + In particular, the dispatching mechanism evolved + rapidly during discussions with Mike. ++

      +=20 +- +-

      Implementation

      +- +-The reference implementation focuses on portability,=20 ++

      Implementation

      ++

      ++The reference implementation focuses on portability, + performance, readability and simplicity, roughly in this order. +-It is written in [R5RS]-Scheme=20 ++It is written in [R5RS]-Scheme + (including macros) extended by [SRFI 23] + (error). + The reference implementation was developed + under Scheme48 (0.57), + PLT (202, 204), and +-SCM (5d7).

      +- +-The file ec.scm i= s the source of ++SCM (5d7). ++

      ++

      ++The file ec.scm = is the source of + the reference implementation. + It also contains comments concerning potential problems. +-Implementors might find the file design.scm +-helpful.=20 +-It contains alternative implementations of certain comprehensions=20 ++Implementors might find the file design.scm ++helpful. ++It contains alternative implementations of certain comprehensions + and generators in order to simplify tuning the implementation +-of this SRFI for different Scheme systems.

      +- +-The file exampl= es.scm contains a ++of this SRFI for different Scheme systems. ++

      ++

      ++The file examp= les.scm contains a + collection of examples, and some code checking their results. + The purpose of most examples is detecting implementation errors, + but the section 'Less artificial examples' contains a few +-real-world examples.

      +- +-The file timing.s= cm contains some ++real-world examples. ++

      ++

      ++The file timing.= scm contains some + code to measure an idea of performance of the comprehensions. + A hand-coded do-loop, the typed generator +-(:range n),=20 +-and the dispatching generator=20 +-(: n) ++(:range n), ++and the dispatching generator ++(: n) + are compared. + For each loop we compare the time needed + per iteration and the time needed to construct the loop (the startup dela= y). +-As a rule of thumb, :range is as fast (or slightly faster)=20 +-as a hand-coded do-loop per iteration and needs about a=20 ++As a rule of thumb, :range is as fast (or slightly faster) ++as a hand-coded do-loop per iteration and needs about a + third more time for startup (due to type checking of the argument). + The dispatching generator needs about twice the time per iteration + (due to calling the generator procedure) and needs about five times +-as long for startup (due to dispatching).

      +- +-The file exten= sion.scm contains +-examples for adding new generators and comprehensions.

      ++as long for startup (due to dispatching). ++

      ++

      ++The file exte= nsion.scm contains ++examples for adding new generators and comprehensions. ++

      +=20 +-

      References

      ++

      References

      +=20 +- ++
      +=20 +- +- ++ ++ +=20 +- +- ++ +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +=20 +- +- ++ ++h= ttp://srfi.schemers.org/srfi-1/mail-archive/msg00021.html ++ +=20 +- +- ++ ++ +=20 +- +- ++ ++ +=20 +- +- ++ ++ +=20 +- +- ++ ++ +=20 +- +- ++ ++ +=20 +- +- ++ ++ +=20 +- +- ++ ++ +=20 +- +- ++ ++ +=20 +=20 +-
      [R5RS] +-Richard Kelsey, William Clinger, and Jonathan Rees (eds.): ++
      [R5RS] ++Richard Kelsey, William Clinger, and Jonathan Rees (eds.): + Revised(5) Report on the Algorithmic Language Scheme of + 20 February 1998. + Higher-Order and Symbolic Computation, Vol. 11, No. 1, September 1998. + + http://schemers.org/Documents/Standards/R5RS/. +-
      [MWL] +-Richard Kelsey, Jonathan Rees:=20 ++
      [MWL] ++Richard Kelsey, Jonathan Rees: + The Incomplete Scheme48 Reference Manual for Release 0.57 (July 15, 2001). + Section "Macros for writing loops". + http://s48.org/0= .57/manual/s48manual_49.html +-
      [SRFI 1] +-Olin Shivers: List Library. +-http://srfi.schemers.org/srf= i-1/ +-
      [SRFI 23] +-Stephan Houben: Error reporting mechanism +-http://srfi.schemers.org/sr= fi-23/ +-
      [SRFI 25] +-Jussi Piitulainen: Multi-dimensional Array Primitives. +-http://srfi.schemers.org/sr= fi-25/ +-
      [SRFI 27] +-Sebastian Egner: Sources of Random Bits. +-http://srfi.schemers.org/sr= fi-27/ +-
      [SRFI 33] +-Olin Shivers: Integer Bitwise-operation Library. +-http://srfi.schemers.org/sr= fi-33/ +-
      [SRFI 39] +-Marc Feeley: Parameter objects. +-http://srfi.schemers.org/sr= fi-39/ +-
      [SRFI 40] +-Philip L. Bewig: A Library of Streams. +-http://srfi.schemers.org/sr= fi-40/ +-
      [Eli] +-Eli Barzilay: Documentation for "misc.ss". 2002. ++
      [SRFI 1] ++Olin Shivers: List Library. ++http://srfi.schemers.org/srfi-1/ ++
      [SRFI 23] ++Stephan Houben: Error reporting mechanism ++http://srfi.schemers.org/srfi-23/ ++
      [SRFI 25] ++Jussi Piitulainen: Multi-dimensional Array Primitives. ++http://srfi.schemers.org/srfi-25/ ++
      [SRFI 27] ++Sebastian Egner: Sources of Random Bits. ++http://srfi.schemers.org/srfi-27/ ++
      [SRFI 33] ++Olin Shivers: Integer Bitwise-operation Library. ++http://srfi.schemers.org/s= rfi-33/ ++
      [SRFI 39] ++Marc Feeley: Parameter objects. ++http://srfi.schemers.org/srfi-39/ ++
      [SRFI 40] ++Philip L. Bewig: A Library of Streams. ++http://srfi.schemers.org/srfi-40/ ++
      [Eli] ++Eli Barzilay: Documentation for "misc.ss". 2002. + h= ttp://www.cs.cornell.edu/eli/Swindle/misc-doc.html#collect +-
      [Folds] +-John David Stone: Folds and reductions. ++
      [Folds] ++John David Stone: Folds and reductions. + Posting in relation to [SRFI 1] on 8-Jan-1999. +-ht= tp://srfi.schemers.org/srfi-1/mail-archive/msg00021.html +-
      [Haskell] +-Simon L. Peyton Jones, John Hughes: The Haskell 98 Report 1 February = 1999. ++
      [Haskell] ++Simon L. Peyton Jones, John Hughes: The Haskell 98 Report 1 Febr= uary 1999. + Section 3.11 "List Comprehensions". + http:/= /www.haskell.org/onlinereport/exps.html#sect3.11 +-
      [Python] +-Guido van Rossum, Fred L. Drake Jr. (eds.): ++
      [Python] ++Guido van Rossum, Fred L. Drake Jr. (eds.): + Python Reference Manual. + Section 5.2.4 "List displays". + Release 2.2, December 21, 2001. + http://python.org/do= c/2.2/ref/lists.html +-
      [SICP] +-Harold Abelson, Gerald J. Sussman, Julie Sussman: ++
      [SICP] ++Harold Abelson, Gerald J. Sussman, Julie Sussman: + Structure and Interpretation of Computer Programs. + MIT Press, 1985. + http://mitpress.mit.edu/sicp/ +-
      [IFPL] +-Philip Wadler: List Comprehensions (Chapter 7). In: ++
      [IFPL] ++Philip Wadler: List Comprehensions (Chapter 7). In: + Simon L. Peyton Jones: The Implementation of Functional Programming Langu= ages. + Prentice Hall, 1987. +-
      [Scheme48] +-Richard Kelsey, Jonathan Rees: Scheme48 Release 0.57 (July 15, 2001). ++
      [Scheme48] ++Richard Kelsey, Jonathan Rees: Scheme48 Release 0.57 (July 15, 2= 001). + http://s48.org/ +-
      [SCM] +-Aubrey Jaffer: SCM Scheme Implementation. Version 5d7 (November 27, 2= 002). ++
      [SCM] ++Aubrey Jaffer: SCM Scheme Implementation. Version 5d7 (November = 27, 2002). + http://www.swiss= .ai.mit.edu/~jaffer/SCM.html +-
      [PLT] +-PLT People: PLT Scheme, DrScheme Version 203. ++
      [PLT] ++PLT People: PLT Scheme, DrScheme Version 203. + http://www.plt-scheme.org/ +-
      [Scsh] +-Olin Shivers, Brian D. Carlstrom, Martin Gasbichler, Mike Sperber: ++
      [Scsh] ++Olin Shivers, Brian D. Carlstrom, Martin Gasbichler, Mike Sperbe= r: + Scsh Reference Manual. + For scsh release 0.6.3. + http://scsh.net/ +-
      ++ +=20 +=20 +=20 +-

      Copyright

      ++

      Copyright

      +

      Copyright (C) Sebastian Egner (2003). All Rights Reserved.

      +=20 +

      +@@ -2120,12 +2225,12 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN = THE SOFTWARE. +

      +=20 +=20 +-
      ++
      +
      Author: Sebas= tian Egner
      +-
      Editor: Fr= ancisco Solsona
      ++
      Editor: Francisco Solsona
      + + +-Last modified: Tue Apr 5 10:43:00 CEST 2005 ++Last modified: Sun Jan 28 13:40:34 MET 2007 + +=20 + +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-43.html b/srfi-doc/sr= fi/scribblings/srfi-std/srfi-43.html +index 7ca1cd3..8c12b5a 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-43.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-43.html +@@ -1,34 +1,30 @@ +- +- ++ ++ + ++ ++ + +-SRFI 43: Vector Library +- ++ SRFI 43: Vector Library ++ ++ ++ + +-
      +-

      Title

      +-A Scheme API for test suites +-
      +- +-

      Author

      +-

      Per Bothner +-<per@bothner.com>

      ++ ++ ++ ++ ++

      SRFI 64: A Scheme API for test suites

      +=20 +-

      Status

      +- +-This SRFI is currently in ``final'' status. To see an explanation of each +-status that a SRFI can hold, see +-here. +-It will remain in draft status until 2005/03/17, or as amended. To +-provide input on this SRFI, please +-mailto:srfi minus 64 at srfi dot schemers dot org. +-See instruc= tions +-here to subscribe to the list. You can access previous messages via +-t= he +-archive of the mailing list. +-

      +-

        +-
      • Received: 2005/01/07
      • +-
      • Draft: 2005/01/28 - 2005/03/28
      • +-
      • Revised: 2005/10/18=20=20 +-
      • Revised: 2006/02/24=20=20 +-
      • Final: 2006/06/18
      • ++

        by Per Bothner
        ++<per@bothner.com>

        ++

        This copy of the SRFI 64 specific= ation document ++is distributed as part of the Racket package ++srfi-doc.

        = The canonical source of this document is ++https://srfi.s= chemers.org/srfi-64/srfi-64.html.

        ++ ++

        Status

        ++ ++

        This SRFI is currently in final status. Here is an explanation of each stat= us that a SRFI can hold. To provide input on this SRFI, please send email = to srfi-64 @nospamsrfi.schemers.org. To subscribe to the list, follow these instructions. You can access previous = messages via the mailing list archive.

        ++
          ++
        • Received: 2005-01-07
        • ++
        • Draft: 2005-01-28--2005-03-28
        • ++
        • Revised: 2005-10-18=20=20 ++
        • Revised: 2006-02-24=20=20 ++
        • Final: 2006-06-18
        • ++
        • Revised to fix errata: 2016-08-11
        • +
        +-

        +=20 +=20 +-

        Abstract

        ++ ++

        Abstract

        +

        + This defines an API for writing test suites, to make it easy + to portably test Scheme APIs, libraries, applications, and implementation= s. +@@ -52,7 +61,7 @@ in the context of a test-runner. This specif= ications + also supports writing new test-runners, to allow customization + of reporting and processing the result of running test suites.

        +=20 +-

        Rationale

        ++

        Rationale

        +=20 +

        The Scheme community needs a standard for writing test suites. + Every SRFI or other library should come with a test suite. +@@ -91,18 +100,19 @@ as functions or macros or built-ins. The reason for = specifying them as + syntax is to allow specific tests to be skipped without evaluating sub-ex= pressions, or for implementations + to add features such as printing line numbers or catching exceptions.

        +=20 +-

        Specification

        ++

        Specification

        +=20 +

        While this is a moderately complex specification, + you should be able to write simple test suites after just reading the + first few sections below. More advanced functionality, such + as writing a custom test-runner, is at the end of the specification.

        +=20 +-

        Writing basic test suites

        ++

        Writing basic test suites

        +

        Let's start with a simple example. + This is a complete self-contained test-suite.

        +=20 +-
        ;; Initialize and give a name to a simple testsuite.
        ++
        ++;; Initialize and give a name to a simple testsuite.
        + (test-begin "vec-test")
        + (define v (make-vector 5 99))
        + ;; Require that an expression evaluate to true.
        +@@ -132,12 +142,13 @@ tests to be executed using an implementation-specifi=
        ed default test runner,
        + and test-end will cause a summary to be displayed
        + in an implementation-specified manner.

        +=20 +-

        Simple test-cases

        ++

        Simple test-cases

        +

        + Primitive test cases test that a given condition is true. + They may have a name. + The core test case form is test-assert:

        +-
        (test-assert [test-name] expression)
        ++
        ++(test-assert [test-name] expression)
        + 
        +

        + This evaluates the expression. +@@ -156,39 +167,46 @@ if there is no current test runner.

        +

        + The following forms may be more convenient than + using test-assert directly:

        +-
        (test-eqv [test-name] expected tes=
        t-expr)
        ++
        ++(test-eqv [test-name] expected test-exp=
        r)
        + 
        +

        + This is equivalent to:

        +-
        (test-assert [test-name] (eqv? expected t=
        est-expr))
        ++
        ++(test-assert [test-name] (eqv? expected test-e=
        xpr))
        + 
        +

        + Similarly test-equal and test-eq + are shorthand for test-assert combined with + equal? or eq?, respectively:

        +-
        (test-equal [test-name] expected t=
        est-expr)
        ++
        ++(test-equal [test-name] expected test-e=
        xpr)
        + (test-eq [test-name] expected test-expr=
        )
        +

        + Here is a simple example:

        +-
        (define (mean x y) (/ (+ x y) 2.0))
        ++
        ++(define (mean x y) (/ (+ x y) 2.0))
        + (test-eqv 4 (mean 3 5))
        + 
        +

        For testing approximate equality of inexact reals + we can use test-approximate:

        +-
        (test-approximate [test-name] expected test-expr error)
        ++
        ++(test-approximate [test-name] expected test-expr error)
        + 
        +

        + This is equivalent to (except that each argument is only evaluated once):=

        +-
        (test-assert [test-name]
        ++
        ++(test-assert [test-name]
        +   (and (>=3D test-expr (- expected error))
        +        (<=3D test-expr (+ expected error))))
        + 
        +=20 +-

        Tests for catching errors

        ++

        Tests for catching errors

        +

        + We need a way to specify that evaluation should fail. + This verifies that errors are detected when required.

        +-
        (test-error [[test-name] error-type] test-expr)
        ++
        ++(test-error [[test-name] error-type] te=
        st-expr)
        + 
        +

        + Evaluating test-expr is expected to signal an error. +@@ -197,33 +215,36 @@ The kind of error is indicated by error-type.

        + If the error-type is left out, or it is + #t, it means "some kind of unspecified error should be signa= led". + For example:

        +-
        (test-error #t (vector-ref '#(1 2) 9))
        ++
        ++(test-error #t (vector-ref '#(1 2) 9))
        + 
        +

        + This specification leaves it implementation-defined (or for a future + specification) what form test-error may take, + though all implementations must allow #t. + Some implementations may support +-SRFI-35's condi= tions, ++SRFI-35's conditions, + but these are only standardized for=20 +-SRFI-36's I/O c= onditions, which are seldom useful in test suites. ++SRFI-36's I/O = conditions, which are seldom useful in test suites. + An implementation may also allow implementation-specific + exception types. + For example Java-based implementations may allow + the names of Java exception classes:

        +-
        ;; Kawa-specific example
        ++
        ++;; Kawa-specific example
        + (test-error <java.lang.IndexOutOfBoundsException> (vector-ref '#(1 =
        2) 9))
        + 
        +

        + An implementation that cannot catch exceptions should skip + test-error forms.

        +=20 +-

        Testing syntax

        ++

        Testing syntax

        +

        + Testing syntax is tricky, especially if we want to + check that invalid syntax is causes an error. + The following utility function can help:

        +-
        (test-read-eval-string string)
        ++
        ++(test-read-eval-string string)
        + 
        +

        + This function parses string (using read) +@@ -231,16 +252,17 @@ and evaluates the result. + The result of evaluation is returned from test-read-eval-string. + An error is signalled if there are unread characters after the + read is done. +-For example:
        +-(test-read-eval-string "(+ 3 4)") evaluates to = 7.
        +-(test-read-eval-string "(+ 3 4") signals an error.
        ++For example:
        ++(test-read-eval-string "(+ 3 4)") evaluates to = 7.
        ++(test-read-eval-string "(+ 3 4") signals an error. + (test-read-eval-string "(+ 3 4) ") signals an error, + because there is extra junk (i.e. a space) after the + list is read. +

        +

        + The test-read-eval-string used in tests:

        +-
        (test-equal 7 (test-read-eval-string "(+ 3 4)"))
        ++
        ++(test-equal 7 (test-read-eval-string "(+ 3 4)"))
        + (test-error (test-read-eval-string "(+ 3"))
        + (test-equal #\newline (test-read-eval-string "#\\newline"))
        + (test-error (test-read-eval-string "#\\newlin"))
        +@@ -251,7 +273,7 @@ The test-read-eval-string used in tests:<=
        /p>
        + (test-equal '(x z) (test-read-string "(list 'x #;'y 'z)"))
        + 
        +=20 +-

        Test groups and paths

        ++

        Test groups and paths

        +

        A test group is a named sequence of forms containing testca= ses, + expressions, and definitions. + Entering a group sets the test group name; leaving a +@@ -265,7 +287,8 @@ Scheme values, nor are they syntactic forms.

        + A test group may contain nested inner test groups. + The test group path is a list of the currently-active + (entered) test group names, oldest (outermost) first.

        +-
        (test-begin suite-name [count])
        ++
        ++(test-begin suite-name [count])
        + 
        +

        A test-begin enters a new test group. + The suite-name becomes the current test group name, +@@ -286,7 +309,8 @@ get executed because of some unexpected error.

        +

        + Additionally, if there is no currently executing test runner, + one is installed in an implementation-defined manner.

        +-
        (test-end [suite-name])
        ++
        ++(test-end [suite-name])
        + 
        +

        + A test-end leaves the current test group. +@@ -301,11 +325,13 @@ installed a new test-runner, then the test-end= + will de-install it, after reporting the accumulated test + results in an implementation-defined manner.

        +=20 +-
        (test-group suite-name decl-or-expr ...)
        ++
        ++(test-group suite-name decl-or-expr ...)
        + 
        +

        + Equivalent to:

        +-
        (if (not (test-to-skip% suite-name))
        ++
        ++(if (not (test-to-skip% suite-name))
        +   (dynamic-wind
        +     (lambda () (test-begin suite-name))
        +     (lambda () decl-or-expr ...)
        +@@ -316,8 +342,9 @@ within the named test group.  However, the entire grou=
        p is skipped
        + if it matched an active test-skip (see later).
        + Also, the test-end is executed in case of an exception.

        +=20 +-

        Handling set-up and cleanup

        +-
        (test-group-with-cleanup suite-name
        ++

        Handling set-up and cleanup

        ++
        ++(test-group-with-cleanup suite-name
        +   decl-or-expr ...
        +   cleanup-form)
        + 
        +@@ -329,14 +356,16 @@ The latter should be executed even if + one of a decl-or-expr forms raises an exception + (assuming the implementation has a way to catch exceptions).

        +

        For example:

        +-
        (test-group-with-cleanup "test-file"
        +-  (define f (open-output-file "log"))
        +-  (do-a-bunch-of-tests f)
        +-  (close-output-port f))
        ++
        ++(let ((f (open-output-file "log")))
        ++  (test-group-with-cleanup "test-file"
        ++    (do-a-bunch-of-tests f)
        ++    (close-output-port f)))
        + 
        +- ++

        Erratum note: Earlier versions had a non-working example. ++

        + +=20 +-

        Conditonal test-suites and other advanced features

        ++

        Conditonal test-suites and other advanced features

        +

        + The following describes features for controlling which tests to execute, + or specifing that some tests are expected to fail.

        +=20 +-

        Test specifiers

        ++

        Test specifiers

        +

        Sometimes we want to only run certain tests, or we know that + certain tests are expected to fail. + A test specifier is one-argument function that takes a test-ru= nner +@@ -374,16 +403,17 @@ which is coerced to a specifier procedure, as descri= bed below for + count and name.

        +

        + A simple example is:

        +-
        (if some-condition
        ++
        ++(if some-condition
        +   (test-skip 2)) ;; skip next 2 tests
        + 
        +

        +-(test-match-name name)
        ++(test-match-name name)
        + The resulting specifier matches if the current test name (as + returned by test-runner-test-name) is equals? to + name.

        +

        +-(test-match-nth n [count])
        ++(test-match-nth n [count])
        + This evaluates to a stateful predicate: A counter keeps track of + how many times it has been called. + The predicate matches the n'th time it is called +@@ -391,29 +421,30 @@ The predicate matches the n'th time it is= called + the next (- count 1) times, + where count defaults to 1.

        +

        +-(test-match-any specifier ...)
        ++(test-match-any specifier ...)
        + The resulting specifier matches if any specifier + matches. + Each specifier is applied, in order, + so side-effects from a later specifier happen + even if an earlier specifier is true.

        +

        +-(test-match-all specifier ...)
        ++(test-match-all specifier ...)
        + The resulting specifier matches if each specifier + matches. + Each specifier is applied, in order, + so side-effects from a later specifier happen + even if an earlier specifier is false.

        +

        +-count (i.e. an integer)
        ++count (i.e. an integer)
        + Convenience short-hand for: (test-match-nth 1 count).

        +

        +-name (i.e. a string)
        ++name (i.e. a string)
        + Convenience short-hand for (test-match-name name)= .

        +=20 +-

        Skipping selected tests

        ++

        Skipping selected tests

        +

        In some cases you may want to skip a test.

        +-
        (test-skip specifier)
        ++
        ++(test-skip specifier)
        + 
        +

        Evaluating test-skip adds the + resulting specifier +@@ -425,40 +456,44 @@ If any specifier matches, then the test is skipped.<= /p> + For convenience, if the specifier is a string that + is syntactic sugar for (test-match-name specifier). + For example:

        +-
        (test-skip "test-b")
        ++
        ++(test-skip "test-b")
        + (test-assert "test-a")   ;; executed
        + (test-assert "test-b")   ;; skipped
        + 
        +

        + Any skip specifiers introduced by a test-skip + are removed by a following non-nested test-end.

        +-
        (test-begin "group1")
        ++
        ++(test-begin "group1")
        + (test-skip "test-a")
        + (test-assert "test-a")   ;; skipped
        + (test-end "group1")      ;; Undoes the prior test-skip
        + (test-assert "test-a")   ;; executed
        + 
        +=20 +-

        Expected failures

        ++

        Expected failures

        +

        + Sometimes you know a test case will fail, but you don't have time + to or can't fix it. Maybe a certain feature only works on certain platf= orms. + However, you want the test-case to be there + to remind you to fix it. You want to note that=20 + such tests are expected to fail.

        +-
        (test-expect-fail specifier)
        ++
        ++(test-expect-fail specifier)
        + 
        +

        + Matching tests (where matching is defined as in test-skip) + are expected to fail. This only affects test reporting, + not test execution. For example:

        +-
        (test-expect-fail 2)
        ++
        ++(test-expect-fail 2)
        + (test-eqv ...) ;; expected to fail
        + (test-eqv ...) ;; expected to fail
        + (test-eqv ...) ;; expected to pass
        + 
        +=20 +-

        Test-runner

        ++

        Test-runner

        +

        + A test-runner is an object that runs a test-suite, + and manages the state. The test group path, and the sets skip and +@@ -466,39 +501,39 @@ expected-fail specifiers are part of the test-runner. + A test-runner will also typically accumulate statistics about executed te= sts, +

        +

        +-(test-runner? value)
        ++(test-runner? value)
        + True iff value is a test-runner object.

        +

        +-(test-runner-current)
        +-(test-runner-current runner)
        ++(test-runner-current)
        ++(test-runner-current runner)
        + Get or set the current test-runner. + If an implementation supports parameter objects +-(as in SRFI-39<= /a>), ++(as in SRFI-39), + then test-runner-current can be a parameter object. + Alternatively, test-runner-current may be implemented + as a macro or function=20 + that uses a fluid or thread-local variable, or a plain global variable. +

        +-(test-runner-get)
        +-Same as (test-runner-current), buth trows an exception ++(test-runner-get)
        ++Same as (test-runner-current), buth throws an exception + if there is no current test-runner.

        +

        +-(test-runner-simple)
        ++(test-runner-simple)
        + Creates a new simple test-runner, that prints errors and a summary + on the standard output port.

        +

        +-(test-runner-null)
        ++(test-runner-null)
        + Creates a new test-runner, that does nothing with the test results. + This is mainly meant for extending when writing a custom runner.

        +

        + Implementations may provide other test-runners, perhaps + a (test-runner-gui).

        +-

        (test-runner-create)
        ++

        (test-runner-create)
        + Create a new test-runner. Equivalent to + ((test-runner-factory)).

        +

        +-(test-runner-factory)
        +-(test-runner-factory factory)
        ++(test-runner-factory)
        ++(test-runner-factory factory)
        + Get or set the current test-runner factory. + A factory is a zero-argument function that creates a new test-runner. + The default value is test-runner-simple, +@@ -506,9 +541,9 @@ but implementations may provide a way to override the = default. + As with test-runner-current, this may be a parameter object, + or use a per-thread, fluid, or global variable.

        +=20 +-

        Running specific tests with a specified runner

        ++

        Running specific tests with a specified runner

        +

        +-(test-apply [runner] specifier ... procedure)
        ++(test-apply [runner] specifier ... procedure)
        + Calls procedure with no arguments using the specified + runner as the current test-runner. + If runner is omitted, +@@ -521,16 +556,16 @@ if it matches any of the specifiers in the + test-apply and does not match any + active test-skip specifiers.

        +

        +-(test-with-runner runner decl-or-expr = ...)
        ++(test-with-runner runner decl-or-expr = ...)
        + Executes each decl-or-expr in order in a context + where the current test-runner is runner.

        +=20 +-

        Test results

        ++

        Test results

        +

        Running a test sets various status properties in the current test-runn= er. + This can be examined by a custom test-runner, + or (more rarely) in a test-suite.

        +=20 +-

        Result kind

        ++

        Result kind

        +

        Running a test may yield one of the following + status symbols:

        +
        +@@ -541,7 +576,7 @@ status symbols:

        +
        'skip
        The test was skipped.
        +
        +

        +-(test-result-kind [runner])
        ++(test-result-kind [runner])
        + Return one of the above result codes from the most recent tests. + Returns #f if no tests have been run yet. + If we've started on a new test, but don't have a result yet, +@@ -549,13 +584,13 @@ then the result kind is 'xfail is the t= est is expected to fail, + 'skip is the test is supposed to be skipped, + or #f otherwise.

        +

        +-(test-passed? [runner])
        ++(test-passed? [runner])
        + True if the value of (test-result-kind [runner]) + is one of 'pass or 'xpass. + This is a convenient shorthand that might be useful + in a test suite to only run certain tests if the previous test passed.

        +=20 +-

        Test result properties

        ++

        Test result properties

        +

        + A test runner also maintains a set of more detailed result properties<= /q> + associated with the current or most recent test. (I.e. the properties of= the +@@ -564,44 +599,44 @@ Each property has a name (a symbol) and a value (any= value). + Some properties are standard or set by the implementation; + implementations can add more.

        +

        +-(test-result-ref runner 'pname [d= efault])
        ++(test-result-ref runner 'pname [d= efault])
        + Returns the property value associated with the pname property = name. + If there is no value associated with 'pname + return default, + or #f if default isn't specified.

        +

        +-(test-result-set! runner 'pname v= alue)
        ++(test-result-set! runner 'pname v= alue)
        + Sets the property value associated with the pname + property name to value. + Usually implementation code should call this function, but it may be + useful for a custom test-runner to add extra properties.

        +

        +-(test-result-remove runner 'pname)
        ++(test-result-remove runner 'pname)
        + Remove the property with the name 'pname.

        +

        +-(test-result-clear runner)
        ++(test-result-clear runner)
        + Remove all result properties. + The implementation automatically calls test-result-clear + at the start of a test-assert and similar procedures.

        +

        +-(test-result-alist runner)
        ++(test-result-alist runner)
        + Returns an association list of the current result properties. + It is unspecified if the result shares state with the test-runner. + The result should not be modified, on the other hand the result + may be implicitly modified by future test-result-set! or + test-result-remove calls. +-However, A test-result-clear does not modify the returned ++However, a test-result-clear does not modify the returned + alist. Thus you can archive result objects from previous runs.

        +=20 +-

        Standard result properties

        ++

        Standard result properties

        +

        + The set of available result properties is implementation-specific. + However, it is suggested that the following might be provided:

        +
        +
        'result-kind
        +
        The result kind, as defined previously. +-This is the only mandatory result property.
        +-(test-result-kind runner) is equivalent to:
        ++This is the only mandatory result property.
        ++(test-result-kind runner) is equivalent to:
        + (test-result-ref runner 'result-kind) +
        +
        'source-file
        +@@ -622,12 +657,12 @@ specified in a test-error, if it meanin= gful and known. + The actual error value is implementation-defined. +
        +=20 +-

        Writing a new test-runner

        ++

        Writing a new test-runner

        +

        This section specifies how to write a test-runner. + It can be ignored if you just want to write test-cases.

        +=20 +=20 +-

        Call-back functions

        ++

        Call-back functions

        +

        + These call-back functions are methods (in the object-oriented sens= e) + of a test-runner. A method test-runner-on-event +@@ -635,66 +670,66 @@ is called by the implementation when event happens.

        +

        + To define (set) the callback function for event use the follow= ing expression. + (This is normally done when initializing a test-runner.) +-
        ++
        + (test-runner-on-event! runner event-func= tion)

        +

        + An event-function takes a test-runner argument, and possibly o= ther arguments, depending on the event.

        +

        +-To extract (get) the callback function for event do this:
        ++To extract (get) the callback function for event do this:
        + (test-runner-on-event runner)

        +

        + To extract call the callback function for event use the follow= ing expression. +-(This is normally done by the implementation core.)
        ++(This is normally done by the implementation core.)
        + ((test-runner-on-event runner) runner other-args ...)

        +

        + The following call-back hooks are available.

        +

        +-(test-runner-on-test-begin runner)
        +-(test-runner-on-test-begin! runner on-test-b= egin-function)
        +-(on-test-begin-function runner)
        ++(test-runner-on-test-begin runner)
        ++(test-runner-on-test-begin! runner on-test-b= egin-function)
        ++(on-test-begin-function runner)
        + The on-test-begin-function is called at the start of an + individual testcase, before the test expression (and expected value) are + evaluated. +

        +

        +-(test-runner-on-test-end runner)
        +-(test-runner-on-test-end! runner on-test-end= -function)
        +-(on-test-end-function runner)
        ++(test-runner-on-test-end runner)
        ++(test-runner-on-test-end! runner on-test-end= -function)
        ++(on-test-end-function runner)
        + The on-test-end-function is called at the end of an + individual testcase, when the result of the test is available.

        +

        +-(test-runner-on-group-begin runner)
        +-(test-runner-on-group-begin! runner on-group= -begin-function)
        +-(on-group-begin-function runner suite-na= me count)
        ++(test-runner-on-group-begin runner)
        ++(test-runner-on-group-begin! runner on-group= -begin-function)
        ++(on-group-begin-function runner suite-na= me count)
        + The on-group-begin-function is called by a test-begin, + including at the start of a test-group. + The suite-name is a Scheme string, + and count is an integer or #f.

        +

        +-(test-runner-on-group-end runner)
        +-(test-runner-on-group-end! runner on-group-e= nd-function)
        +-(on-group-end-function runner)
        ++(test-runner-on-group-end runner)
        ++(test-runner-on-group-end! runner on-group-e= nd-function)
        ++(on-group-end-function runner)
        + The on-group-end-function is called by a test-end, + including at the end of a test-group.

        +

        +-(test-runner-on-bad-count runner)
        +-(test-runner-on-bad-count! runner on-bad-cou= nt-function)
        +-(on-bad-count-function runner actual-cou= nt expected-count)
        ++(test-runner-on-bad-count runner)
        ++(test-runner-on-bad-count! runner on-bad-cou= nt-function)
        ++(on-bad-count-function runner actual-cou= nt expected-count)
        + Called from test-end (before the on-group-end-function<= /var> + is called) if an expected-count was specified by the matching + test-begin and the expected-count does not match + the actual-count of tests actually executed or skipped.

        +

        +-(test-runner-on-base-end-name runner)
        +-(test-runner-on-bad-end-name! runner on-bad-= end-name-function)
        +-(on-bad-end-name-function runner begin-n= ame end-name)
        ++(test-runner-on-bad-end-name runner)
        ++(test-runner-on-bad-end-name! runner on-bad-= end-name-function)
        ++(on-bad-end-name-function runner begin-n= ame end-name)
        + Called from test-end (before the on-group-end-function<= /var> + is called) if a suite-name was specified, and it did not that = the + name in the matching test-begin.

        +

        +-(test-runner-on-final runner)
        +-(test-runner-on-final! runner on-final-funct= ion)
        +-(on-final-function runner)
        ++(test-runner-on-final runner)
        ++(test-runner-on-final! runner on-final-funct= ion)
        ++(on-final-function runner)
        + The on-final-function takes one parameter (a test-runner) + and typically displays a summary (count) of the tests. + The on-final-function is called after called the +@@ -705,73 +740,74 @@ to the standard output port the number of tests of t= he various kinds. +

        +

        + The default test-runner returned by test-runner-simple +-uses the following call-back functions:
        +-(test-on-test-begin-simple runner)
        +-(test-on-test-end-simple runner)
        +-(test-on-group-begin-simple runner suite-nam= e count)
        +-(test-on-group-end-simple runner)
        +-(test-on-bad-count-simple runner actual-coun= t expected-count)
        +-(test-on-bad-end-name-simple runner begin-na= me end-name)
        +-You can call those if you want to write a your own test-runner.

        ++uses the following call-back functions:
        ++(test-on-test-begin-simple runner)
        ++(test-on-test-end-simple runner)
        ++(test-on-group-begin-simple runner suite-nam= e count)
        ++(test-on-group-end-simple runner)
        ++(test-on-bad-count-simple runner actual-coun= t expected-count)
        ++(test-on-bad-end-name-simple runner begin-na= me end-name)
        ++You can call those if you want to write your own test-runner.

        +=20 +-

        Test-runner components

        ++

        Test-runner components

        +

        + The following functions are for accessing the other components of a test-= runner. + They would normally only be used to write a new test-runner or + a match-predicate.

        +

        +-(test-runner-pass-count runner)
        ++(test-runner-pass-count runner)
        + Returns the number of tests that passed, and were expected to pass.

        +

        +-(test-runner-fail-count runner)
        ++(test-runner-fail-count runner)
        + Returns the number of tests that failed, but were expected to pass.

        +

        +-(test-runner-xpass-count runner)
        ++(test-runner-xpass-count runner)
        + Returns the number of tests that passed, but were expected to fail.

        +

        +-(test-runner-xfail-count runner)
        ++(test-runner-xfail-count runner)
        + Returns the number of tests that failed, and were expected to pass.

        +

        +-(test-runner-skip-count runner)
        ++(test-runner-skip-count runner)
        + Returns the number of tests or test groups that were skipped.

        +

        +-(test-runner-test-name runner)
        ++(test-runner-test-name runner)
        + Returns the name of the current test or test group, as a string. + During execution of test-begin this is the name of the + test group; during the execution of an actual test, this is the name + of the test-case. + If no name was specified, the name is the empty string.

        +

        +-(test-runner-group-path runner)
        ++(test-runner-group-path runner)
        + A list of names of groups we're nested in, with the outermost group first= .

        +

        +-(test-runner-group-stack runner)
        ++(test-runner-group-stack runner)
        + A list of names of groups we're nested in, with the outermost group last. + (This is more efficient than test-runner-group-path, + since it doesn't require any copying.)

        +

        +-(test-runner-aux-value runner)
        +-(test-runner-aux-value! runner on-test= )
        ++(test-runner-aux-value runner)
        ++(test-runner-aux-value! runner on-test= )
        + Get or set the aux-value field of a test-runner. + This field is not used by this API or the test-runner-simple + test-runner, but may be used by custom test-runners to store extra state.=

        +

        +-(test-runner-reset runner)
        ++(test-runner-reset runner)
        + Resets the state of the runner to its initial state. +

        +=20 +-

        Example

        ++

        Example

        +

        This is an example of a simple custom test-runner. + Loading this program before running a test-suite will install + it as the default test runner.

        +-
        (define (my-simple-runner filename)
        ++
        ++(define (my-simple-runner filename)
        +   (let ((runner (test-runner-null))
        + 	(port (open-output-file filename))
        +         (num-passed 0)
        +         (num-failed 0))
        +-    (test-runner-on-test! runner
        +-      (lambda (runner result)
        +-        (case (cdr (assq 'result-kind result))
        ++    (test-runner-on-test-end! runner
        ++      (lambda (runner)
        ++        (case (test-result-kind runner)
        +           ((pass xpass) (set! num-passed (+ num-passed 1)))
        +           ((fail xfail) (set! num-failed (+ num-failed 1)))
        +           (else #t))))
        +@@ -786,31 +822,31 @@ it as the default test runner.

        + (lambda () (my-simple-runner "/tmp/my-test.log"))) +
        +=20 +-

        Implementation

        ++

        Implementation

        +

        + The test implementation uses cond-expand +-(SRFI-0) ++(SRFI-0) + to select different code depending on certain SRFI names (srfi-9, + srfi-34, srfi-35, srfi-39), + or implementations (kawa). + It should otherwise be portable to any R5RS implementation.

        +=20 +-

        testing.scm

        ++

        testing.scm<= /a>

        +=20 +-

        Examples

        +-

        Here is = srfi-25-test.scm, ++

        Examples

        ++

        Here is srfi-25-test.scm, + based converted from Jussi Piitulainen's +-test.scm +-for SRFI-25= .

        ++test.scm ++for SRFI-25.

        +=20 +-

        Test suite

        ++

        Test suite

        +

        + Of course we need a test suite for the testing framework itself. +-This suite srfi-64-test.scm ++This suite srfi-64-test.scm + was contributed by Donovan Kolbly + <donovan@rscheme.org><= /code>.

        +=20 +-

        Copyright

        ++

        Copyright

        +

        + Copyright (C) Per Bothner (2005, 2006)

        +

        +@@ -832,14 +868,14 @@ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR CO= PYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

        +-
        ++
        +
        Author: Per Bothner +
        Editor: Francisco Solsona
        +

        + + +-Last modified: Sun Jan 28 13:40:18 MET 2007 ++Last modified: Thu Mar 31 19:49:52 MST 2011 + +

        +-=20=20 +- ++ ++ +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-66.html b/srfi-doc/sr= fi/scribblings/srfi-std/srfi-66.html +index 7d8fcb3..c3936b9 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-66.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-66.html +@@ -1,40 +1,243 @@ +- +- +- ++ ++ + +-SRFI 66: Octet Vectors ++ ++ ++ SRFI 66: Octet Vectors ++ ++ ++ + +=20 + +-

        Title

        +- +-Octet Vectors +- +-

        Authors

        +- +-Michael Sperber +- +-

        Status

        +- +-This SRFI is currently in ``final'' status. To see an explanation of each +-status that a SRFI can hold, see +-here. +-To +-provide input on this SRFI, please +-mailto:srfi-66@srfi.schemers= .org. +-See instruc= tions +-here to subscribe to the list. You can access previous messages via +-t= he +-archive of the mailing list. +-

        +-

        +- +-

        Abstract

        This SRFI defines a set of procedures for creating, a= ccessing, and manipulating uniform vectors of octets.

        Rationale

        =

        A number of applications deal with sequences of octets (often called byt= es), most prominently interfaces to C and I/O. Vectors are typically too s= pace-costly and too slow to work well in these circumstance. This justifie= s having a separate type for octet vectors.

        This SRFI is related to <= a href=3D"http://srfi.schemers.org/srfi-4/">SRFI 4 (Homogeneous numeric= vector datatypes), which also provides vectors of octets, and uses names = consistent with it. However, the extension described here does not require = any extensions to the syntax of the underlying Scheme system, and provides = a slightly richer set of primtives.

        Scheme systems implementing both = SRFI 4 and this SRFI should use the same type for u8vector and= octet vectors as specified here.

        Specification

        Octet vectors= are objects of a new type. This type may or may not be disjoint from the = type of regular vectors. Its elements must be octets, that is, exact integ= ers in the range [0,255].

        As with vectors, the length of a octet vect= or is the number of elements it contains. This number is fixed. A valid i= ndex into a octet vector is an exact, non-negative integer. The first ele= ment of a octet vector has index 0, the last element has an index one less= than the length of the vector.

        (u8vector? ob= j)

        Returns #t if obj = is a vector, otherwise returns #f. Analogous to vector?= .

        (make-u8vector k fill)

        Returns a newly allocated octet vector of = k elements. Each element is initialized to fill. Fi= ll must be an octet. Analogous to make-vector.

        =
        (u8vector octet ...)

        Re= turns a newly allocated octet vector whose elements contain the given argu= ments, which must all be octets. Analogous to vector.

        (u8vector->list u8vector)
        =
        (list->u8vector octets)

        u8vector->listreturns a newly allocated list of the ele= ments of u8vector in the same order.Analogous to vector-&g= t;list.

        List->u8vector returns a newl= y allocated octet vector whose elements are the elements of list octet= s, which must all be octets. Analogous to list->vector.

        (u8vector-length u8vector)

        Returns the number of elements in u8vector as an = exact integer. Analogous to vector-length.

        = (u8vector-ref u8vector k)

        k must be a valid index of u8vector. u8vec= tor-ref returns the contents of element k of u8vecto= r. Analogous to vector-ref.

        (u8vector= -set! u8vector k octet)

        k must be a valid index of u8vector. u8vector-set! stores octet in element k of= u8vector. The number of return values and the return values a= re unspecified. However, the number of return values is such that it is a= ccepted by a continuation created by begin. Analogous to vector-set!.

        (u8vector=3D? u8vector-= 1 u8vector-2)

        Returns #t if u8vector-1 and u8vector-2 are equal---that is, i= f they have the same length and equal elements at all valid indices.

        (u8vector-compare u8vector-1 u8vector-2<= /var>)

        Compares u8vector-1 and u8ve= ctor-2 and returns a value consistent with the vector ordering specif= ied in SRFI 67, i.e. -1 i= f u8vector-1 is smaller than u8vector-2, 0 if they ar= e equal, and 1 if u8vector-1 is greater than u8vector-2. Shorter vectors are always smaller than longer ones, and vectors of eq= ual length are compared lexicographically.

        (u8vector-copy= ! source source-start target t= arget-start n)

        Copies data from oc= tet vector source to octet vector target. Sourc= e-start, target-start, and n must be non-negati= ve exact integers that satisfy

        0 <=3D source-start <= =3D source-start + n <=3D (u8vector-length <= var>source)

        0 <=3D target-start <=3D target-start + n <=3D (u8vector-length ta= rget)

        This copies the octets from source at i= ndices [source-start, source-start + n) to= consecutive indices in target starting at target-index.

        This must work even if the memory regions for the source and the = target overlap, i.e., the octets at the target location after the copy must= be equal to the octets at the source location before the copy.

        The n= umber of return values and the return values are unspecified. However, th= e number of return values is such that it is accepted by a continuation cr= eated by begin. Analogous to vector-ref.

        (u8vector-copy u8vector)
        =

        Returns a newly allocated copy of octet vector u8vector.

        <= /dd>

        Reference Implementation

        This reference implementation = makes use of SRFI 9 (Defin= ing Record Types) and SRFI 23= (Error reporting mechanism) .

        (define-record-type :u8vector
        ++

        SRFI 66: Octet Vectors

        ++ ++

        by Michael Sperber

        ++

        This copy of the SRFI 66 specific= ation document ++is distributed as part of the Racket package ++srfi-doc.

        = The canonical source of this document is ++https://srfi.s= chemers.org/srfi-66/srfi-66.html.

        ++ ++

        Status

        ++ ++

        ++ This SRFI is currently in final status. Here ++ is an explanati= on ++ of each status that a SRFI can hold. To provide input on this SRFI, pl= ease ++ send email ++ to s= rfi-66@nospamsrfi.schemers.org. ++ To subscribe to the list, ++ follow t= hese ++ instructions. You can access previous messages via the mailing ++ list archive. ++

          ++
        • ++ Received: 2005-03-11 ++
        • ++
        • ++ Revised: 2005-04-18 ++
        • ++
        • ++ Revised: 2005-06-06 ++
        • ++
        • ++ Final: 2005-12-15 ++
        • ++
        • ++ Revised to fix errata: ++
            ++
          • ++ 2017-07-17 (Added missing arguments to u8vector-ref.) ++
          • ++
          ++
        • ++
        ++ ++

        Abstract

        ++

        ++ This SRFI defines a set of procedures for creating, accessing, and ++ manipulating uniform vectors of octets. ++

        ++

        Rationale

        ++

        ++ A number of applications deal with sequences of octets (often called by= tes), ++ most prominently interfaces to C and I/O. Vectors are typically too ++ space-costly and too slow to work well in these circumstance. This ++ justifies having a separate type for octet vectors. ++

        ++

        ++ This SRFI is related to SRFI ++ 4 (Homogeneous numeric vector datatypes), which also provides vecto= rs of ++ octets, and uses names consistent with it. However, the extension descr= ibed ++ here does not require any extensions to the syntax of the underlying Sc= heme ++ system, and provides a slightly richer set of primtives. ++

        ++

        ++ Scheme systems implementing both SRFI 4 and this SRFI should use the sa= me ++ type for u8vector and octet vectors as specified here. ++

        ++

        Specification

        ++

        ++ Octet vectors are objects of a new type. This type may or may not be ++ disjoint from the type of regular vectors. Its elements must be octets, ++ that is, exact integers in the range [0,255]. ++

        ++

        ++ As with vectors, the length of a octet vector is the number of elements= it ++ contains. This number is fixed. A valid index into a octet vector is = an ++ exact, non-negative integer. The first element of a octet vector has i= ndex ++ 0, the last element has an index one less than the length of the vector. ++

        ++
        ++
        (u8vector? obj)
        ++
        ++

        ++ Returns #t if obj is an octect vector, otherw= ise ++ returns #f. Analogous to vector?. ++

        ++
        ++
        (make-u8vector k fill)
        ++
        ++

        ++ Returns a newly allocated octet vector of k elements. Each ++ element is initialized to fill. Fill must be an ++ octet. Analogous to make-vector. ++

        ++
        ++
        (u8vector octet ...)
        ++
        ++

        ++ Returns a newly allocated octet vector whose elements contain the giv= en ++ arguments, which must all be octets. Analogous to vector. ++

        ++
        ++
        (u8vector->list u8vector)
        ++
        (list->u8vector octets)
        ++
        ++

        ++ u8vector->listreturns a newly allocated list of the ++ elements of u8vector in the same order.Analogous ++ to vector->list. ++

        ++
        ++
        ++

        ++ List->u8vector returns a newly allocated octet vector ++ whose elements are the elements of list octets, which must= all ++ be octets. Analogous to list->vector. ++

        ++
        ++
        (u8vector-length u8vector)
        ++
        ++

        ++ Returns the number of elements in u8vector as an exact int= eger. ++ Analogous to vector-length. ++

        ++
        ++
        (u8vector-ref u8vector k)
        ++
        ++

        ++ k must be a valid index ++ of u8vector. u8vector-ref returns the conten= ts of ++ element k of u8vector. Analogous ++ to vector-ref. ++

        ++
        ++
        (u8vector-set! u8vector k oct= et)
        ++
        ++

        ++ k must be a valid index ++ of u8vector. u8vector-set! ++ stores octet in element k of u8vector. ++ The number of return values and the return values are unspecified. ++ However, the number of return values is such that it is accepted by a ++ continuation created by begin. Analogous ++ to vector-set!. ++

        ++
        ++
        (u8vector=3D? u8vector-1 u8vector-2)
        ++
        ++

        ++ Returns #t if u8vector-1 and u8vector-2 ++ are equal---that is, if they have the same length and equal elements = at ++ all valid indices. ++

        ++
        ++
        (u8vector-compare u8vector-1 u8vector-2<= /var>)
        ++
        ++

        ++ Compares u8vector-1 and u8vector-2 and returns a ++ value consistent with the vector ordering specified ++ in SRFI 67, i.e. -1 ++ if u8vector-1 is smaller than u8vector-2, 0 if = they ++ are equal, and 1 if u8vector-1 is greater ++ than u8vector-2. Shorter vectors are always smaller than l= onger ++ ones, and vectors of equal length are compared lexicographically. ++

        ++
        ++
        (u8vector-copy! source source-start target target-start n)
        ++
        ++

        ++ Copies data from octet vector source to octet ++ vector target. Source-start, target-start= , ++ and n must be non-negative exact integers that satisfy ++

        ++

        ++ 0 <=3D source-start <=3D source-start ++ + n <=3D (u8vector-length source) ++

        ++

        ++ 0 <=3D target-start <=3D target-start ++ + n <=3D (u8vector-length target) ++

        ++

        ++ This copies the octets from source at indices ++ [source-start, source-start + n) to ++ consecutive indices in target starting ++ at target-index. ++

        ++

        ++ This must work even if the memory regions for the source and the targ= et ++ overlap, i.e., the octets at the target location after the copy must = be ++ equal to the octets at the source location before the copy. ++

        ++

        ++ The number of return values and the return values are unspecified. ++ However, the number of return values is such that it is accepted by a ++ continuation created by begin. Analogous ++ to vector-ref. ++

        ++
        ++
        (u8vector-copy u8vector)
        ++
        ++

        ++ Returns a newly allocated copy of octet vector u8vector. ++

        ++
        ++
        ++

        Reference Implementation

        ++

        ++ This reference implementation makes use ++ of SRFI 9 (Defining Record ++ Types) and SRFI 23 (Error ++ reporting mechanism) . ++

        ++
        (define-record-type :u8vector
        +   (really-make-u8vector elements)
        +   u8vector?
        +   (elements u8vector-elements))
        +@@ -44,7 +247,7 @@ archive of the mailing list.
        + 		(exact? thing)
        + 		(>=3D thing 0)
        + 		(<=3D thing 255)))
        +-      (error "not a octet" thing)))
        ++      (error "not a octet" thing)))
        +=20
        + (define (make-u8vector k fill)
        +   (ensure-octet fill)
        +@@ -94,8 +297,8 @@ archive of the mailing list.
        +     (and (=3D size (u8vector-length u8vector-2))
        + 	 (let loop ((i 0))
        + 	   (or (>=3D i size)
        +-	       (and (=3D (u8vector-ref u8vector-1)
        +-		       (u8vector-ref u8vector-2))
        ++	       (and (=3D (u8vector-ref u8vector-1 i)
        ++		       (u8vector-ref u8vector-2 i))
        + 		    (loop (+ 1 i))))))))
        +=20
        + (define (u8vector-compare u8vector-1 u8vector-2)
        +@@ -113,27 +316,45 @@ archive of the mailing list.
        +                (cond ((< elt-1 elt-2) -1)
        +                      ((> elt-1 elt-2)  1)
        +                      (else (loop (+ i 1)))))))))))
        +-

        References

        • SRFI 4 (Homogeneous numeric vector datatypes)
        • The "By= te Vectors" section of The Incomplete Scheme 48 Reference Manual available from this page.

        Copyright

        +-Copyright (C) Michael Sperber (2005). All Rights Reserved.=20 ++
        ++

        References

        ++
          ++
        • ++ SRFI 4 (Homogeneous ++ numeric vector datatypes) ++
        • ++
        • ++ The "Byte Vectors" section of The Incomplete Scheme 48 ++ Reference Manual available from t= his ++ page. ++
        • ++
        ++

        Copyright

        ++

        ++ Copyright (C) Michael Sperber (2005). All Rights Reserved. ++

        +

        +-Permission is hereby granted, free of charge, to any person obtaining a +-copy of this software and associated documentation files (the "Software"), +-to deal in the Software without restriction, including without limitation +-the rights to use, copy, modify, merge, publish, distribute, sublicense, +-and/or sell copies of the Software, and to permit persons to whom the +-Software is furnished to do so, subject to the following conditions: ++ Permission is hereby granted, free of charge, to any person obtaining a= copy ++ of this software and associated documentation files (the "Software"), to ++ deal in the Software without restriction, including without limitation = the ++ rights to use, copy, modify, merge, publish, distribute, sublicense, an= d/or ++ sell copies of the Software, and to permit persons to whom the Software= is ++ furnished to do so, subject to the following conditions: ++

        +

        +-The above copyright notice and this permission notice shall be included in +-all copies or substantial portions of the Software. ++ The above copyright notice and this permission notice shall be included= in ++ all copies or substantial portions of the Software. ++

        +

        +-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +-THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +-FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +-DEALINGS IN THE SOFTWARE. +- +-


        +-
        Editor: Da= vid Van Horn
        +- ++ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS= OR ++ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL= THE ++ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEA= LINGS ++ IN THE SOFTWARE. ++

        ++
        ++
        Editor: David Van Horn
        ++ ++ +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-69.html b/srfi-doc/sr= fi/scribblings/srfi-std/srfi-69.html +index 6e4c3bb..3f99b11 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-69.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-69.html +@@ -1,69 +1,81 @@ +- +- ++ ++ + +- SRFI 69: Basic hash tables +- +- +- +- ++ ++ ++ SRFI 69: Basic hash tables ++ ++ ++ ++ ++ ++ + + +=20 +-

        Title

        ++

        SRFI 69: Basic hash tables

        +=20 +-SRFI 69: Basic hash tables ++

        by Panu Kalliokoski

        ++

        This copy of the SRFI 69 specific= ation document ++is distributed as part of the Racket package ++srfi-doc.

        = The canonical source of this document is ++https://srfi.s= chemers.org/srfi-69/srfi-69.html.

        +=20 +-

        Author

        ++

        Status

        +=20 +-Panu Kalliokoski +- +-

        Status

        +- +-This SRFI is currently in ``final'' status. To see an explanation of each +-status that a SRFI can hold, see +-here. +-It will remain in draft status until 2005/09/09, or as amended. To +-provide input on this SRFI, please +-mailto:srfi-69@srfi.schemers= .org. +-See instruc= tions +-here to subscribe to the list. You can access previous messages via +-t= he +-archive of the mailing list. +-

        ++

        This SRFI is currently in final status. Here is an explanation of each stat= us that a SRFI can hold. To provide input on this SRFI, please send email = to srfi-69 @nospamsrfi.schemers.org. To subscribe to the list, follow these instructions. You can access previous = messages via the mailing list archive.

        + +=20 +-

        Abstract

        ++

        Abstract

        +=20 +

        This SRFI defines basic hash tables. Hash tables are widely recognised + as a fundamental data structure for a wide variety of applications. A + hash table is a data structure that: +- ++

        +
        1. provides a mapping from some set of keys to some set of values + associated to those keys +-
        2. has no intrinsic order for the (key, value) associations it contains +-
        3. supports in-place modification as the primary means of setting the ++
        4. has no intrinsic order for the (key, value) associations it cont= ains ++
        5. supports in-place modification as the primary means of setting t= he + contents of a hash table +-
        6. provides key lookup and destructive update in amortised constant ++
        7. provides key lookup and destructive update in amortised constant + time, provided that a good hash function is used. +=20 +-

        This SRFI aims to accomplish these goals: +- ++ ++

        This SRFI aims to accomplish these goals: ++

        +
        1. to provide a consistent, generic and widely applicable API for ha= sh + tables +-
        2. to improve code portability by providing a standard hash table ++
        3. to improve code portability by providing a standard hash table + facility with guaranteed behaviour +-
        4. to help the programmer by defining utility routines that account for ++
        5. to help the programmer by defining utility routines that account= for + the most common situations of using hash tables. +=20 +-

        Issues

        ++ ++ ++

        Issues

        +=20 +

        There is no single best way to make hash tables. The tables presented + in this SRFI aim at being both conceptually simple and usable for a wide +@@ -77,7 +89,7 @@ the global environment, and specifically, to provide sup= port for + between implementation-specific environment data types and the hash + table API presented here; however, these issues are left open. +=20 +-

        This SRFI does not conform to the interface of maps presented in SRFI ++

        This SRFI does not conform to the interface of maps presented in S= RFI + 44. Following SRFI 44 would seriously cripple the interface of hash + tables. The naming of the operations for maps in SRFI 44 goes against + common use and is unnatural. However, this SRFI has been written so +@@ -85,15 +97,16 @@ that it does not prevent a SRFI-44 API to has= h tables. An + implementation supporting both SRFI 44 and this SRFI is encouraged to + provide a SRFI 44 interface to hash tables in addition to the one + presented here. ++

        +=20 +-

        Rationale

        ++

        Rationale

        +=20 +

        Hash tables are widely recognised as a fundamental data structure for + many kinds of computational tasks. Thus far, there is no existing + standard for Scheme hash tables; however, almost every non-minimal + Scheme implementation provides some kind of hash table functionality. +=20 +-

        Alas, although somewhat similar, these hash table APIs have many ++

        Alas, although somewhat similar, these hash table APIs have many + differences: some trivial, like the naming of certain functions; some + complex, like revealing different aspects of the internal implementation + to the user; some coarse, like requiring keys to be of some specific +@@ -102,86 +115,89 @@ hash table in advance to get optimal performance. A= s a result, the + existing hash table facilities cannot be used to write portable + programs. +=20 +-

        The primary aim of this SRFI is to establish a standard API for hash ++

        The primary aim of this SRFI is to establish a standard API for ha= sh + tables so that portable programs can be written that make efficient use + of common hash table functionality. The SRFI resolves discrepancies + that exist between the various hash table API's with respect to naming + and semantics of hash table operations. A lot of effort has been put +-into making the API consistent, simple and generic. The SRFI also ++into making the the API consistent, simple and generic. The SRFI also + defines some of the most common utility routines that would otherwise + need to be written and rewritten for various applications. +=20 +-

        Incorporating this SRFI as a standard feature in Scheme implementations ++

        Incorporating this SRFI as a standard feature in Scheme implementa= tions + makes it possible to write efficient and portable programs that use hash + tables. ++

        +=20 +-

        Specification

        ++

        Specification

        +=20 +

        Names defined in this SRFI: +- ++

        +
        Type constructors and predicate
        +-
        make-hash-table, hash-table?, alist->hash-tab= le ++
        make-hash-table, hash-table?, alist->hash-table +=20 +
        Reflective queries
        +-
        hash-table-equivalence-function, <= a href=3D"srfi-69.html#hsht2">hash-table-hash-function ++
        hash-table-equivalence-function, hash-table-hash-function +=20 +
        Dealing with single elements
        +-
        hash-table-ref, hash-table-ref/default, has= h-table-set!, +-hash-table-delete!, hash-table-exists?, +-hash-table-update!, hash-table-update!/default ++
        hash-table-ref, hash-table-= ref/default, hash-table-set!, ++hash-table-delete!, hash-table-= exists?, ++hash-table-update!, hash-table-= update!/default +=20 +
        Dealing with the whole contents
        +-
        hash-table-size, hash-table-keys, hash-t= able-values, +-hash-table-walk, hash-table-fold, hash-table= ->alist, +-hash-table-copy, hash-table-merge! ++
        hash-table-size, hash-tab= le-keys, hash-table-values, ++hash-table-walk, hash-table-f= old, hash-table->alist, ++hash-table-copy, hash-table-m= erge! +=20 +
        Hashing
        +-
        hash, string-hash, string-ci-hash, hash-by-identity ++
        hash, string-hash, string-ci-hash, hash-by-identity +=20 +-

        An implementation that does not provide hash-table-ref, ++ ++

        An implementation that does not provide hash-table-ref, + hash-table-set!, hash-table-delete!, hash-table-upd= ate!, + hash-table-exists?, and hash-table-size in amortised co= nstant + time (when a good hash function is used), or fails to provide good hash + function definitions for hash, string-hash, string-= ci-hash, + and hash-by-identity, does not conform to this SRFI. +=20 +-

        Hash table implementations are allowed to rely on the fact that the ha= sh ++

        Hash table implementations are allowed to rely on the fact that th= e hash + value of a key in hash table does not change. In most cases, modifying + a key in-place after it has been inserted into the hash table will + violate this constraint and thus leads to unspecified behaviour. ++

        +=20 +-

        Type constructors and predicate

        +- +-

        Procedure: make-hash-table [ equal? [ <= var>hash [ args … ]]] +-→ hash-table ++

        Type constructors and predicate

        +=20 ++

        Procedure: make-hash-table [ equal? [ <= var>hash [ args =E2=80=A6 ]]] ++=E2=86=92 hash-table ++

        +

        Create a new hash table with no associations. equal? is a + predicate that should accept two keys and return a boolean telling + whether they denote the same key value; it defaults to equal?. +- ++

        +

        hash is a hash function, and defaults to an appropriate has= h function +-for the given equal? predicate (see section Hashing). However, ++for the given equal? predicate (see section = Hashing). However, + an acceptable default is not guaranteed to be given for any equivalence + predicate coarser than equal?, except for string-ci=3D?= .[1] The function hash must be acceptable for equal?, so if + you use coarser equivalence than equal? other than string-ci= =3D?, + you must always provide the function hash yourself. +-
        [1] An ++
        [1] An + equivalence predicate c1 is coarser than a equivalence predica= te c2 + iff there exist values x and y such that (and (= c1 x y) (not (c2 x +-y))).
        +- ++y)))
        . ++

        +

        Implementations are allowed to use the rest args for + implementation-specific extensions. Be warned, though, that using these + extensions will make your program less portable. +- +-

        Procedure: hash-table? objboolean +- ++

        ++

        Procedure: hash-table? obj =E2=86=92 <= var>boolean ++

        +

        A predicate to test whether a given object obj is a hash ta= ble. The + hash table type should be disjoint from all other types, if possible. +- +-

        Procedure: alist->hash-table alist [= equal? [ hash=20 +-[ args … ]]] → hash-table +- ++

        ++

        Procedure: alist->hash-table alist [= equal? [ hash ++[ args =E2=80=A6 ]]] =E2=86=92 hash-table ++

        +

        Takes an association list alist and creates a hash t= able + hash-table which maps the car of every element in alist to the + cdr of corresponding elements in alist. equal?<= /var>, hash, and +@@ -191,24 +207,26 @@ precedence over later ones. (Note: the choice of us= ing cdr (instead + of cadr) for values tries to strike balance between the two + approaches: using cadr would render this procedure unusable for + cdr alists, but not vice versa.) +- +-

        The rest args are passed to ma= ke-hash-table and can thus be used for ++

        ++

        The rest args are passed to make-hash-tabl= e and can thus be used for + implementation-specific extensions. ++

        +=20 +-

        Reflective queries

        ++

        Reflective queries

        +=20 +

        Procedure: hash-table-equivalence-function = hash-table +- ++

        +

        Returns the equivalence predicate used for keys of hash-table. +- ++

        +

        Procedure: hash-table-hash-function hash-ta= ble +- ++

        +

        Returns the hash function used for keys of hash-table. ++

        +=20 +-

        Dealing with single elements

        +- +-

        Procedure: hash-table-ref hash-table = key [ thunk ] → value ++

        Dealing with single elements

        +=20 ++

        Procedure: hash-table-ref hash-table = key [ thunk ] =E2=86=92 value ++

        +

        This procedure returns the value associated to key in hash-table. + If no value is associated to key and thunk is given, it is called + with no arguments and its value is returned; if thunk is not g= iven, an +@@ -217,28 +235,28 @@ Given a good hash function, this operation should ha= ve an (amortised) + complexity of O(1) with respect to the number of associations in + hash-table. (Note: this rules out implementation by associati= on lists + or fixed-length hash tables.) +- +-

        Procedure: hash-table-ref/default hash-tabl= e key default → ++

        ++

        Procedure: hash-table-ref/default hash-tabl= e key default =E2=86=92 + value +- ++

        +

        Evaluates to the same value as (hash-table-ref hash-table key (lam= bda + () default)).=20=20 + Given a good hash function, this operation should have an (amortised) + complexity of O(1) with respect to the number of associations in + hash-table. (Note: this rules out implementation by associati= on lists + or fixed-length hash tables.) +- +-

        Procedure: hash-table-set! hash-table= key value → undefined +- ++

        ++

        Procedure: hash-table-set! hash-table= key value =E2=86=92 undefined ++

        +

        This procedure sets the value associated to key = in hash-table. + The previous association (if any) is removed.=20=20 + Given a good hash function, this operation should have an (amortised) + complexity of O(1) with respect to the number of associations in + hash-table. (Note: this rules out implementation by associati= on lists + or fixed-length hash tables.) +- +-

        Procedure: hash-table-delete! hash-table key → undefined +- ++

        ++

        Procedure: hash-table-delete! hash-table key =E2=86=92 undefined ++

        +

        This procedure removes any association to key in hash-= table. It is + not an error if no association for that key exists; in this case, + nothing is done.=20=20 +@@ -246,69 +264,70 @@ Given a good hash function, this operation should ha= ve an (amortised) + complexity of O(1) with respect to the number of associations in + hash-table. (Note: this rules out implementation by associati= on lists + or fixed-length hash tables.) +- +-

        Procedure: hash-table-exists? hash-table keyboolean +- ++

        ++

        Procedure: hash-table-exists? hash-table key =E2=86=92 boolean ++

        +

        This predicate tells whether there is any association to key in + hash-table.=20=20 + Given a good hash function, this operation should have an (amortised) + complexity of O(1) with respect to the number of associations in + hash-table. (Note: this rules out implementation by associati= on lists + or fixed-length hash tables.) +- ++

        +

        Procedure: hash-table-update! hash-table key function +-[ thunk ] → undefined +- ++[ thunk ] =E2=86=92 undefined ++

        +

        Semantically equivalent to, but may be implemented more efficiently + than, the following code: ++

        +
        + (hash-table-set! hash-table key
        +                  (function (hash-table-ref hash-table key thunk)))
        + 
        +- +

        Procedure: hash-table-update!/default +-hash-table key function default<= /var> → undefined +- ++hash-table key function default<= /var> =E2=86=92 undefined ++

        +

        Behaves as if it evaluates to (hash-table-update! hash-table key + function (lambda () default)). ++

        +=20 +-

        Dealing with the whole contents

        +- +-

        Procedure: hash-table-size hash-table → integer ++

        Dealing with the whole contents

        +=20 ++

        Procedure: hash-table-size hash-table =E2=86=92 integer ++

        +

        Returns the number of associations in hash-table. This ope= ration + must have a complexity of O(1) with respect to the number of + associations in hash-table. +- +-

        Procedure: hash-table-keys hash-table → list +- ++

        ++

        Procedure: hash-table-keys hash-table =E2=86=92 list ++

        +

        Returns a list of keys in hash-table. The order of the key= s is + unspecified. +- +-

        Procedure: hash-table-values hash-table → list +- ++

        ++

        Procedure: hash-table-values hash-table =E2=86=92 list ++

        +

        Returns a list of values in hash-table. The order of the v= alues is + unspecified, and is not guaranteed to match the order of keys in the +-result of hash-table-keys. +- +-

        Procedure: hash-table-walk hash-table proc → unspecified +- ++result of hash-table-keys. ++

        ++

        Procedure: hash-table-walk hash-table proc =E2=86=92 unspecified ++

        +

        proc should be a function taking two arguments, a key<= /var> and a value. + This procedure calls proc for each association in hash-ta= ble, giving + the key of the association as key and the value of the associa= tion as + value. The results of proc are discarded. The ord= er in which + proc is called for the different associations is unspecified. +- ++

        +

        (Note: in some implementations, there is a procedure called + hash-table-map which does the same as this procedure. However, = in + other implementations, hash-table-map does something else. In no + implementation that I know of, hash-table-map does a real functo= rial + map that lifts an ordinary function to the domain of hash tables. + Because of these reasons, hash-table-map is left outside this SR= FI.) +- ++

        +

        Procedure: hash-table-fold hash-table f init-value +-→ final-value +- ++=E2=86=92 final-value ++

        +

        This procedure calls f for every association in hash-t= able with + three arguments: the key of the association key, the value of = the + association value, and an accumulated value, val. val is +@@ -317,42 +336,44 @@ invocations of f, the return value of the= previous invocation of final-value returned by hash-table-fold is = the return + value of the last invocation of f. The order in which f<= /var> is called + for different associations is unspecified. +- +-

        Procedure: hash-table->alist hash-table= alist +- ++

        ++

        Procedure: hash-table->alist hash-table= =E2=86=92 alist ++

        +

        Returns an association list such that the car of each element= in + alist is a key in hash-table and the corresponding = cdr of each + element in alist is the value associated to the key in ha= sh-table. + The order of the elements is unspecified. +- ++

        +

        The following should always produce a hash table with the same mappings + as a hash table h: ++

        +
        + (alist->hash-table (hash-table->alist h)
        +                         (hash-table-equivalence-function h)
        +                         (hash-table-hash-function h))
        + 
        +=20 +-

        Procedure: hash-table-copy hash-table → hash-table +- ++

        Procedure: hash-table-copy hash-table =E2=86=92 hash-table ++

        +

        Returns a new hash table with the same equivalence predicate, hash + function and mappings as in hash-table. +- +-

        Procedure: hash-table-merge! hash-table1 hash-table2 → ++

        ++

        Procedure: hash-table-merge! hash-table1 hash-table2 =E2=86=92 + hash-table +- ++

        +

        Adds all mappings in hash-table2 into hash-table1 and returns the + resulting hash table. This function may modify hash-table1 + destructively. ++

        +=20 +-

        Hashing

        ++

        Hashing

        +=20 +

        Hashing means the act of taking some value and producing a number from + the value. A hash function is a function that does this. Every + equivalence predicate e has a set of acceptable has= h functions for +-that predicate; a hash function hash is acceptable iff (e = obj1 +-obj2)(=3D (hash obj1) (hash obj2)). +- ++that predicate; a hash funtion hash is acceptable iff (e o= bj1 ++obj2) =E2=86=92 (=3D (hash obj1) (hash obj2)). ++

        +

        A hash function h is good for a equivalence pred= icate e if it + distributes the result numbers (hash values) for non-equal obj= ects (by + e) as uniformly as possible over the numeric range of hash val= ues, +@@ -360,44 +381,45 @@ especially in the case when some (non-equal) objects= resemble each other + by e.g. having common subsequences. This definition is vague but should + be enough to assert that e.g. a constant function is not a good = hash + function. +- +-

        When the definition of make-hash-table above talks about an ++

        ++

        When the definition of make-hash-table above talk= s about an + appropriate hashing function for e, it means a hashing = function that + gives decent performance (for the hashing operation) while being both + acceptable and good for e. This definition, too, is intention= ally + vague. +- +-

        Procedure: hash object [ bound ] → integer +- ++

        ++

        Procedure: hash object [ bound ] =E2=86=92 integer ++

        +

        Produces a hash value for object in the range ( 0, bou= nd (. If + bound is not given, the implementation is free to choose any b= ound, + given that the default bound is greater than the size of any imaginable + hash table in a normal application. (This is so that the implementation + may choose some very big value in fixnum range for the default bound.) + This hash function is acceptable for equal?. +- +-

        Procedure: string-hash string [ = bound ] → integer +- +-

        The same as hash, except that the arg= ument string must be a string. +- +-

        Procedure: string-ci-hash string [ = bound ] → integer +- +-

        The same as string-hash, except tha= t the case of characters in ++

        ++

        Procedure: string-hash string [ = bound ] =E2=86=92 integer ++

        ++

        The same as hash, except that the argument s= tring must be a string. ++

        ++

        Procedure: string-ci-hash string [ = bound ] =E2=86=92 integer ++

        ++

        The same as string-hash, except that the case o= f characters in + string does not affect the hash value produced. +- +-

        Procedure: hash-by-identity object [ <= var>bound ] → integer +- +-

        The same as hash, except that this fu= nction is only guaranteed to be ++

        ++

        Procedure: hash-by-identity object [ <= var>bound ] =E2=86=92 integer ++

        ++

        The same as hash, except that this function is on= ly guaranteed to be + acceptable for eq?. The reason for providing this function is t= hat + it might be implemented significantly more efficiently than hash. + Implementations are encouraged to provide this function as a builtin. ++

        +=20 +-

        Implementation

        ++

        Implementation

        +=20 +

        This implementation relies on SRFI-9 for distinctness of the hash table + type, and on SRFI-23 for error reporting. Otherwise, the implementation + is pure R5RS. +- ++

        +
        +=20
        + (define *default-bound* (- (expt 2 29) 3))
        +@@ -657,10 +679,10 @@ is pure R5RS.
        +=20
        + 
        +=20 +-

        Copyright

        +- +-

        Copyright © Panu Kalliokoski (2005). All Rights Reserved. ++

        Copyright

        +=20 ++

        Copyright =C2=A9 Panu Kalliokoski (2005). All Rights Reserved. ++

        +

        Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the + Software), to deal in the Software without restriction, including +@@ -668,20 +690,20 @@ without limitation the rights to use, copy, modify, = merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: +- ++

        +

        The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. +- ++

        +

        THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, E= XPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +-SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.=20 +-


        +-
        Editor: Da= vid Van Horn
        ++SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ++

        ++
        ++
        Editor: David Van Horn
        + Last modified: Wed Sep 14 09:54:51 EDT 2005 +- + + +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-7.html b/srfi-doc/srf= i/scribblings/srfi-std/srfi-7.html +index 17cbb0b..056522a 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-7.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-7.html +@@ -1,32 +1,51 @@ +- +- ++ ++ + ++ ++ + SRFI 7: Feature-based program configuration language ++ ++ ++ + + +=20 +-

        Title

        ++

        SRFI 7: Feature-based program configuration language

        +=20 +-SRFI-7: Feature-based program configuration language ++

        by Richard Kelsey

        ++

        This copy of the SRFI 7 specifica= tion document ++is distributed as part of the Racket package ++srfi-doc.

        = The canonical source of this document is ++https://srfi.sch= emers.org/srfi-7/srfi-7.html.

        +=20 +-

        Author

        ++

        Status

        +=20 +-Richard Kelsey ++

        This SRFI is currently in final status. Here is an explanation of each stat= us that a SRFI can hold. To provide input on this SRFI, please send email = to srfi-7= @nospamsrfi.schemers.org. To su= bscribe to the list, follow these instructions. You can access previous messages v= ia the mailing list arch= ive.

        ++
          ++
        • Received: 1999-05-12 ++
        • Draft: 1999-05-26--1999-07-26 ++
        • Final: 1999-08-19 ++
        +=20 +-

        Status

        +- +-This SRFI is currently in ``final'' status. To see an explanation of eac= h status that a SRFI can hold, see here. +-You can access the discussion via the archive of the mailing list. +-

          +-
        • Received: 1999/05/12 +-
        • Draft: 1999/05/26-1999/07/26 +-
        • Final: 1999/08/19 +-
        +- +-

        Abstract

        ++

        Abstract

        +=20 +

        +-This SRFI describes a configuration language to be used for specifing ++This SRFI describes a configuration language to be used for specifying + the set of Scheme features or extensions required to run a program. + In addition to a list of required features, a program may also contain + Scheme code to be used only when a particular feature or combination of +@@ -38,7 +57,7 @@ The configuration language is entirely distinct from Sch= eme; it is + neither embedded in Scheme nor includes Scheme as a subset. +

        +=20 +-

        Rationale

        ++

        Rationale

        +=20 +

        + The use of a separate configuration language makes it easy for +@@ -48,48 +67,38 @@ macros to determine which features, and thus which mac= ros, are used + in the program. +

        +=20 +-

        See SRFI 0 for a ++

        See SRFI 0 for a + rationale for the need for some kind of configuration control. +

        +=20 +-

        Specification

        +- +- +- +- +- +- +- +- ++

        Specification

        +=20 +-

        Syntax

        ++

        Syntax

        +=20 +-

        +-

        ++
        +  <program> --> (program <program clause>+)
        +=20
        +  <program clause>
        +-   --> (requires <feature identifier>+)
        ++   --> (requires <feature identifier&g=
        t;+)
        +      | (files <filename>*)
        +-     | (code <Scheme expression, definition, or syntax definition>*)
        +-     | (feature-cond <feature-cond clause>+)
        +-     | (feature-cond <feature-cond clause>* (else <program claus=
        e>+))
        ++     | (code <Scheme expression, definition, =
        or syntax definition>*)
        ++     | (feature-cond <feature-cond cl=
        ause>+)
        ++     | (feature-cond <feature-cond clause>* (else=
         <program clause>+))
        +=20
        +  <feature-cond clause>
        +    --> (<feature requirement> <program clause>+)
        +=20
        +  <feature requirement>
        +    --> <feature identifier>
        +-     | (and <feature requirement>*)
        +-     | (or <feature requirement>*)
        +-     | (not <feature requirement>)
        ++     | (and <feature requirement>*)
        ++     | (or <feature requirement>*)
        ++     | (not <feature requirement>)
        +=20
        +  <feature identifier>
        +    --> a symbol which is the name of a SRFI
        + 
        +-

        +=20 +-

        Semantics

        ++

        Semantics

        +

        + The configuration language is distinct from Scheme. Given a set of + available features a <program> can be converted into a +@@ -109,7 +118,7 @@ compiles a program into an executable file. + given below. The ordering of the clauses in a <program> + determines the order of the forms in the resultant Scheme program. +=20 +-

        In processing the REQUIRES and ++

        In processing the REQUIRES and + FEATURE-COND clauses in a <program>, + an implementation should be consistent with some fixed set of present + and absent features. An implementation may analyze a <program&g= t; +@@ -132,14 +141,16 @@ same <program>. +

        The forms in <body> are added to the program.
        +=20 +
        (feature-cond <feature-cond clause>+)
        +-
        The meaning of a FEATURE-COND clause is that of the ++
        ++

        ++ The meaning of a FEATURE-COND clause is that of the + <program-clause>s in the first <feature-cond = clause> whose + <implementation-requirement> is satisfied by the imple= mentation. + If an ELSE clause is present it is used if and only if no pr= eceding + clause is satisfied; a FEATURE-COND with an + ELSE clause is always satisfied. +- +-

        If no clause can be satisified the <program> cannot= be evaluated in ++

        ++

        If no clause can be satisfied the <program> cannot = be evaluated in + the implementation.

        +=20 +

        +@@ -163,10 +174,11 @@ The meaning of the <implementation requirem= ent>s is as follow +=20 + (not x)satisfied if X is no= t satisfied + +- ++

        + +=20 +-

        Implementation

        ++ ++

        Implementation

        +=20 +

        Two implementations are provided here. The first is a + PROCESS-PROGRAM function that converts a +@@ -184,7 +196,6 @@ an (implementation-dependent) method for evaluating th= e forms returned by + PROCESS-PROGRAM. +

        +=20 +-

        +

        + (define (process-program program features)
        +   (call-with-current-continuation
        +@@ -271,17 +282,17 @@ an (implementation-dependent) method for evaluating =
        the forms returned by
        + 			  '()
        + 			  (cons next (label)))))))
        + 	      (read-files (cdr filenames)))))
        +-

        ++
        +=20 +

        + The second implementation is a PROGRAM macro that implements + the configuration language in terms of the COND-EXPAND +-syntax of SRFI 0. ++syntax of SRFI 0. + Note that this implementation requires that LOAD use the cur= rent + evaluation environment. +

        +=20 +-

        ++
        + (define-syntax program
        +   (syntax-rules (requires files code feature-cond)
        +     ((program)
        +@@ -302,11 +313,12 @@ evaluation environment.
        +               more ...)
        +      (begin (cond-expand (requirement (program stuff ...)) ...)
        +             (program more ...)))))
        +-

        +- +-

        Copyright

        ++
        +=20 ++

        Copyright

        ++

        + Copyright (C) Richard Kelsey (1999). All Rights Reserved. ++

        +

        + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the +@@ -330,8 +342,8 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF O= R IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +

        +=20 +-
        +-
        Editor: Mi= ke Sperber
        ++
        ++
        Editor: Mike Sperber
        +=20 + + +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-71.html b/srfi-doc/sr= fi/scribblings/srfi-std/srfi-71.html +index a22c3d6..f8a75e7 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-71.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-71.html +@@ -1,46 +1,54 @@ +- +- ++ ++ + ++ ++ + SRFI 71: Extended LET-syntax for multiple values ++ ++ ++ + +=20 + +=20 +-

        Title

        ++

        SRFI 71: Extended LET-syntax for multiple values

        +=20 +-Extended LET-syntax for multiple values ++

        by Sebastian Egner

        ++

        This copy of the SRFI 71 specific= ation document ++is distributed as part of the Racket package ++srfi-doc.

        = The canonical source of this document is ++https://srfi.s= chemers.org/srfi-71/srfi-71.html.

        +=20 +-

        Author

        ++

        Status

        +=20 +-Sebastian Egner +- +-

        +-This SRFI is currently in ``final'' status. To see an explanation of each +-status that a SRFI can hold, see +-here. +-To +-provide input on this SRFI, please +-mailto:srfi-71@srfi.schemers= .org. +-See instruc= tions +-here to subscribe to the list. You can access the discussion via +-t= he +-archive of the mailing list. +-You can access +-post-finalization messages via +- +-the archive of the mailing list. +-

        +- ++

        This SRFI is currently in final status. Here is an explanation of each stat= us that a SRFI can hold. To provide input on this SRFI, please send email = to srfi-= 71@nospamsrfi.schemers.org. To = subscribe to the list, follow these instructions. You can access previous messages= via the mailing list a= rchive.

        ++ +=20 +=20 +-

        Abstract

        ++

        Abstract

        +=20 ++

        + This SRFI is a proposal for extending let, + let*, and letrec + for receiving multiple values. +@@ -48,16 +56,19 @@ The syntactic extension is fully compatible with the e= xisting syntax. + It is the intention that single-value bindings,=20 + i.e. (let ((var expr)) ...), and + multiple-value binding can be mixed freely and conveniently. ++

        +

        + The most simple form of the new syntax is best explained by an example: +-

        +-

        (define (quo-rem x y)
        ++

        ++
        ++(define (quo-rem x y)
        +   (values (quotient x y) (remainder x y)))
        +=20
        + (define (quo x y)
        +   (let ((q r (quo-rem x y)))
        +     q))
        + 
        ++

        + The procedure quo-rem delivers two values to + its continuation. These values are received as q + and r in the let-expression of the +@@ -65,13 +76,17 @@ procedure quo. + In other words, the syntax of let is extended such + that several variables can be specified---and these variables + receive the values delivered by the expression (quo-rem x y). ++

        +

        + The syntax of let is further extended to cases in which + a rest argument receives the list of all residual values. + Again by example,=20 +-

        (let (((values y1 y2 . y3+) (foo x)))
        ++

        ++
        ++(let (((values y1 y2 . y3+) (foo x)))
        +    body)
        + 
        ++

        + In this example, values is a syntactic keyword=20 + indicating the presence of multiple values to be received, + and y1, y2, and y3+,=20 +@@ -82,6 +97,7 @@ The syntactic keyword values allows receivi= ng + all values as in (let (((values . xs) (foo x))) body). + It also allows receiving no values at all as in=20 + (let (((values) (for-each foo list))) body). ++

        +

        + A common application of binding multiple values is + decomposing data structures into their components. +@@ -90,9 +106,12 @@ The procedure uncons (defined below) + decomposes a pair x into its car and its cdr + and delivers them as two values to its continuation. + Then an extended let can receive these values: +-

        (let ((car-x cdr-x (uncons x)))
        ++

        ++
        ++(let ((car-x cdr-x (uncons x)))
        +   (foo car-x cdr-x))
        + 
        ++

        + Of course, for pairs this method is probably neither faster=20 + nor clearer than using the procedures car + and cdr. +@@ -107,16 +126,19 @@ point already as both quotient and remainder are pro= bably + computed by a common exact division algorithm. + (And often caching is used to avoid executing this + algorithm twice as often as needed.) ++

        +

        + As the last feature of this SRFI, a mechanism is specified + to store multiple values in heap-allocated data structures. +-For this purpose, values->list and values->vector ++For this purpose, values->list and values->vecto= r + construct a list (a vector, resp.) storing all values delivered=20 + by evaluating their argument expression. + Note that these operations cannot be procedures. ++

        +=20 +-

        Rationale

        ++

        Rationale

        +=20 ++

        + My original motivation for writing this SRFI is my unhappiness with + the current state of affairs in Scheme with respect to multiple values. + Multiple values are mandatory in the +@@ -124,6 +146,7 @@ Revised^5 Report on the Algorithmic + Language Scheme (R5RS), + and they are fully available in all major Scheme implementations. + Yet there is often a painful hesitation about using them. ++

        +

        + The reason for this hesitation is that multiple values are + nearly fully integrated into Scheme---but not quite. +@@ -136,6 +159,7 @@ and I understand this SRFI as a minor contribution + "placing the last corner stone". + But first a very brief history of multiple values in Scheme, + as far as relevant for this SRFI. ++

        +

        + R5RS specifies the procedures values + and call-with-values for passing any number of values +@@ -143,6 +167,7 @@ from a producer procedure to a consumer procedure. + This is the only construct in R5RS=20 + dealing with multiple values explicitly, and it is sufficient + to implement anything that can be implemented for multiple values. ++

        +

        + However, as John David Stone observed in SRFI 8, + the mechanism exposes explicitly how multiple values are=20 +@@ -155,6 +180,7 @@ by adding the special form + for receiving several values produced by the expression + in variables specified by <formals> and + using them in the body. ++

        +

        + The major limitation of receive is that it can only=20 + handle a single expression, which means programs dealing with +@@ -173,17 +199,19 @@ to the list of all values delivered by x (as in S + Or is x to deliver a single value to be + bound to v (as in let)? + Refer to the=20 +-di= scussion ++d= iscussion + archive of SRFI 11 for details. + Moreover, let-values suffers from "parenthesis complexity", + despite Scheme programmers are tolerant to braces. ++

        +

        +-Eli Barzilay's Swindle library (for MzScheme) on=20 ++Eli Barzilay's Swindle library (for MzScheme) on= =20 + the other hand redefines let to include multiple-values and internal + procedures: The syntactic keyword values indicates the + presence of multiple values, while additional parentheses (with the + syntax of <formals>) + indicate a lambda-expression as right-hand side. ++

        +

        + This SRFI follows Eli's approach, while keeping the syntax + simple (few parentheses and concepts) and adding tools for +@@ -194,6 +222,7 @@ This is achieved by extending the syntax in two differ= ent + ways (multiple left-hand sides or a syntactic keyword) + and adding operations to convert between (implicitly passed) + values and (first class) data structures. ++

        +

        + Finally, I would like to mention that Oscar Waddell et al. + describe an efficient compilation method for Scheme's=20 +@@ -203,25 +232,30 @@ to as a basis for internal define. + I expect their compilation method (and letrec*) + and this SRFI to be fully compatible with one another, + although I have not checked this claim by way of implementation. ++

        +=20 +-

        Specification

        ++

        Specification

        +=20 +-The syntax of Scheme (R5RS, Sec= tion 7.1.3.) ++

        ++The syntax of Scheme (R5RS, Section 7.1.3.) + is extended by replacing the existing production: +- +-

        <binding spec> --> (<variable> <expression>)
        ++

        ++
        ++<binding spec> --> (<variable> <expression>)
        + 
        +- ++

        + by the three new productions +- +-

        <binding spec> --> ((values <variable>*) <expressi=
        on>)
        ++

        ++
        ++<binding spec> --> ((values <variable>*) <expression>=
        ;)
        + <binding spec> --> ((values <variable>* . <variable>=
        ) <expression>)
        + <binding spec> --> (<variable>+ <expression>)
        + 
        +- ++

        + The form (<variable>+ <expression>) is just + an abbreviation for ((values <variable>+) <expression>)= , + and it includes the original <binding spec> of R5RS. ++

        +

        + The first two forms are evaluated as follows: The variables are bound and + the expression is evaluated according to the enclosing construct +@@ -229,6 +263,7 @@ the expression is evaluated according to the enclosing= construct + However, the expression may deliver any number of values to its continuat= ion,=20 + which stores these values into the variables specified,=20 + possibly allocating a rest list in case of the . <variable> form.=20 ++

        +

        + The number of values delivered by the expression must match the + number of values expected by the binding specification. +@@ -236,12 +271,16 @@ Otherwise an error is raised, as call-with-val= ues would. + This implies in particular, that each binding of a named let involves + exactly one value, because this binding can also be an argument to a + lambda-expression. ++

        +=20 +

        Standard operations

        +=20 ++

        + The following procedures, specified in terms of standard procedures, + are added to the set of standard procedures: +-

        (define (uncons pair)
        ++

        ++
        ++(define (uncons pair)
        +   (values (car pair) (cdr pair)))
        +=20
        + (define (uncons-2 list)
        +@@ -253,20 +292,22 @@ are added to the set of standard procedures:
        + (define (uncons-4 list)
        +   (values (car list) (cadr list) (caddr list) (cadddr list) (cddddr list)=
        ))
        +=20
        +-(define (uncons-cons alist)
        ++(define (uncons-cons alist)
        +   (values (caar alist) (cdar alist) (cdr alist)))
        +=20
        +-(define (unlist list)
        ++(define (unlist list)
        +   (apply values list))
        +=20
        +-(define (unvector vector)
        +-  (apply values (vector->list vector)))
        ++(define (unvector vector)
        ++  (apply values (vector->list vector)))
        + 
        ++

        + These procedures decompose the standard concrete data structures + (pair, list, vector) and deliver the components as values. + It is an error if the argument cannot be decomposed as expected. + Note that the procedures are not necessarily implemented by + the definition given above. ++

        +

        + The preferred way of decomposing a list into the first two elements + and the rest list is (let ((x1 x2 x3+ (uncons-2 x))) body), +@@ -275,33 +316,38 @@ This is not equivalent to + (let (((values x1 x2 . x3+) (unlist x))) body) + because the latter binds x3+ to a newly allocated + copy of (cddr x). ++

        +

        + Finally, the following two macros are added to the standard macros: +- +-

        (values->list   <expression>)
        +-(values->vector <expression>)
        ++

        ++
        ++(values->list   <expression>)
        ++(values->vector <expression>)
        + 
        +- ++

        + These operation receive all values (if any) delivered by their=20 + argument expression and return a newly allocated list (vector, resp.) + of these values.=20 +-Note that values->list is not the same as=20 ++Note that values->list is not the same as=20 + list (the procedure returning the list of its arguments). ++

        +=20 +-

        Design Rationale

        ++

        Design Rationale

        +=20 +

        Which alternatives designs for the syntax were considered?

        +=20 ++

        + This SRFI defines two notations for receiving several values: + Using the keyword values, + or simply listing the variables if there is at least one. + There are several alternatives for this design, + some of which were proposed during the discussion. +-(Refer in particular to msg00000, +-m= sg00001, and +-m= sg00002, +-m= sg00007.) ++(Refer in particular to msg00000, ++= msg00001, and ++= msg00002, ++= msg00007.) + The alternatives considered include: ++

        +
          +
        1. Just listing the variables (no syntactic keyword at all) as in + (let ((x1 x2 expr)) body).
        2. +@@ -316,20 +362,21 @@ rest list as in (let ((x1 x2 (rest x3+) expr))= body). +
        3. Using the <formals> syntax of + R5RS as in + (let (((x1 x2 . x3+) expr)) body). +-
        4. Mimicking <formals> but with ++
        5. Mimicking <formals> but with + one level of parentheses removed as in + (let ((x1 x2 . x3+ expr)) body).
        6. +
        7. As the previous but with additional syntax for=20 +-"no values" and "just a rest", e.g. ++"no values" and "just a rest", e.g. + (let ((! expr)) body) and + (let ((xs . expr)) body). +-
        ++ +

        + The requirements for the design are + compatibility with the existing let, + concise notation for the frequent use cases, + robustness against most common mistakes, and + full flexibility of receiving values. ++

        +

        + For the sake of compatibility, + only modifications of <binding spec> were +@@ -340,9 +387,10 @@ Concerning concise notation, by far the most convenie= nt notation + is listing the variables. + As this notation also covers the existing syntax, it was adopted + as the basis of the extension to be specified. ++

        +

        + The listing the variables notation is limited by the fact that +-the preferred marker for a rest list (".") ++the preferred marker for a rest list (".") + cannot follow an opening parenthesis as in + (let ((. xs expr)) body),=20 + nor that it can be followed by two syntactic elements as in +@@ -350,6 +398,7 @@ nor that it can be followed by two syntactic elements = as in + Lifting these restrictions would require major modifications + in unrelated parts of the Scheme syntax, which is not an + attractive option. ++

        +

        + Another problematic aspect of the listing the variables notation + is the case of no variables at all. +@@ -360,29 +409,34 @@ it seriously harms syntactic robustness: + syntactically correct and could easily be confused with one another. + For this reason, the notation of listing the variables was + restricted to one or more variables. ++

        +

        + This leaves the problem of extending the notation in order to +-cover rest arguments and the "no values"-case. ++cover rest arguments and the "no values"-case. + This can either be done ad hoc, covering the open cases, + or by adding a general notation covering all cases. + In view of readability and uniformity (useful when code gets + processed automatically) the latter approach was chosen. + This has resulted in the design specified in this SRFI. ++

        +=20 +-

        Why is values needed in the "zero values"-case= ?

        ++

        Why is values needed in the "zero values"-case?

        +=20 ++

        + The syntax specified in this SRFI allows zero variables being + bound in a binding specification using the syntax + (let (((values) (for-each foo (bar)))) body). + An alternative is allowing (<expression>) + as a binding specification. +-(Refer to the discussion archive starting at msg00001.) ++(Refer to the discussion archive starting at msg00001.) ++

        +

        + The syntax specified in this SRFI is designed for static + detection of the most frequent types (forgotten parentheses). + For example, writing=20 + (let ((values) (for-each foo (bar))) body) + is not a well-formed let-expression in this SRFI. ++

        +

        + In the alternative syntax, both=20 + (let (((for-each foo (bar)))) body) +@@ -396,29 +450,36 @@ the error will probably manifest itself at the moment + (bar) fails to deliver exactly two values. + Unless it does, in which case the error must manifest itself much=20 + further downstream from the fact that foo never got called.= =20 ++

        +

        + In order to avoid this sort of expensive typos,=20 + the syntax proposed in this SRFI is more verbose + than it needs to be. ++

        +=20 +

        Why not also include a syntax for procedures?

        +=20 ++

        + This SRFI is a proposal for extending the syntax of let + etc. in order to include multiple values. + It is also desirable to extend the syntax of let=20 + for simplifying the definition of local procedures. + (For example, as in Swindle.) + However, this SRFI does not include this feature. ++

        +

        + The reason I have chosen not restrict this SRFI to a syntax + for multiple values is simplicity. ++

        +=20 +

        Why the names unlist etc.?

        +=20 ++

        + An alternative naming convention for the decomposition +-operation unlist is list->values, ++operation unlist is list->values, + which is more symmetric with respect to its +-inverse operation values->list. ++inverse operation values->list. ++

        +

        + This symmetry ends, however, as soon as more complicated + data structures with other operations are involved. +@@ -426,21 +487,25 @@ Then it becomes apparent that the same data structur= e can + support different decomposition operations: + A double-ended queue (deque) for example supports splitting off + the head and splitting of the tail; and neither of these +-operations should be named deque->values. ++operations should be named deque->values. + The un-convention covers this in a natural way. ++

        +

        + Please also refer to the double-ended queue (deque) example +-in examples.scm to see how to ++in examples.sc= m to see how to + use decomposition procedures for dealing with data structures. ++

        +=20 +

        Which decomposition operations are included?

        +=20 ++

        + The particular set of operations specified in this SRFI=20 + for decomposing lists represents a trade-off between limiting + the number of operations and convenience. ++

        +

        + As Al Petrofsky has pointed out during the discussion +-( ++( + msg00018) it is not sufficient to have only=20 + unlist as this will copy the rest list. + For this reason specialized decomposition operations +@@ -448,15 +513,17 @@ for splitting off the first 1, ..., 4 elements are + provided, and a decomposition operation expecting the + first element to be a pair itself. + These appear to be the most common cases. ++

        +=20 +-

        Implementation

        ++

        Implementation

        +=20 ++

        + The reference implementation is written in R5RS=20 + using hygienic macros, only. + It is not possible, however, to portably detect read access to + an uninitialized variable introduced by letrec. + The definition of the actual functionality can be found=20 +-here. ++here. + The implementation defines macros srfi-let/*/rec etc. + in terms of r5rs-let/*/rec. + Implementors may use this to redefine (or even re-implement) +@@ -464,86 +531,93 @@ Implementors may use this to redefine (or even re-im= plement) + while providing implementations of r5rs-let/*/rec. + An efficient method for the latter is given in Fixing Le= trec + by O. Waddell et al. ++

        +

        + R5RS: + For trying out the functionality, a complete implementation under +-R5RS can be found he= re.=20 ++R5RS can be found here.=20 + It defines r5rs-let/*/rec in terms of lambda + and redefines let/*/rec as srfi-let/*/rec. + This may not be the most efficient implementation, because many + Scheme systems handle let etc. specially and do not + reduce it into lambda ++

        +

        + PLT 208: +-The implementation found here +-uses PLT's module system for exporting=20 ++The implementation found here ++uses PLT's module system for exporting + srfi-let/*/rec + under the name of let/*/rec, while defining + r5rs-let/*/rec as a copy of the built-in + let/*/rec. This code should be efficient. ++

        +

        + Examples using the new functionality +-can be found in examples.scm. ++can be found in examples.scm. ++

        +=20 +-

        References

        ++

        References

        +=20 + +=20 + + ++ +=20 + + ++ +=20 + + ++ +=20 + +- ++ +=20 + + ++ +=20 +
        [R5RS] +-Richard Kelsey, William Clinger, and Jonathan Rees (eds.): ++Richard Kelsey, William Clinger, and Jonathan Rees (eds.): + Revised^5 Report on the Algorithmic Language Scheme of + 20 February 1998. + Higher-Order and Symbolic Computation, Vol. 11, No. 1, September 1998. + + http://schemers.org/Documents/Standards/R5RS/. +-
        [SRFI 8] +-John David Stone: Receive: Binding to multiple values. +-http://srfi.schemers.org/srf= i-8/ +-
        John David Stone: Receive: Binding to multiple valu= es. ++http://srfi.schemers.org/srfi-8/ ++
        [SRFI 11] +-Lars T. Hansen: Syntax for receiving multiple values. +-http://srfi.schemers.org/sr= fi-11/ +-
        Lars T. Hansen: Syntax for receiving multiple values. ++http://srfi.schemers.org/srfi-11/ ++
        [Swindle] +-Eli Barzilay: Swindle, documentation for "base.ss" (Swindle Version 2= 0040908.) ++[Swindle] ++Eli Barzilay: Swindle, documentation for "base.ss" (Swindle Vers= ion 20040908.) + http:= //www.cs.cornell.edu/eli/Swindle/base-doc.html#let +-
        [Fix] +-O. Waddell, D. Sarkar, R. K. Dybvig: ++O. Waddell, D. Sarkar, R. K. Dybvig: + Fixing Letrec: A Faithful Yet Efficient Implementation of Scheme's + Recursive Binding Construct. To appear, 2005. + http://= www.cs.indiana.edu/~dyb/pubs/fixing-letrec.pdf +-
        +=20 +=20 +-

        Copyright

        ++

        Copyright

        ++

        + Copyright (c) 2005 Sebastian Egner. ++

        +

        + Permission is hereby granted, free of charge, to any person obtaining a c= opy of this software and associated documentation files (the ``Software''),= to deal in the Software without restriction, including without limitation = the rights to use, copy, modify, merge, publish, distribute, sublicense, an= d/or sell copies of the Software, and to permit persons to whom the Softwar= e is furnished to do so, subject to the following conditions: ++

        +

        + The above copyright notice and this permission notice shall be included i= n all copies or substantial portions of the Software. ++

        +

        + THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS= OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY= , FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL T= HE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER L= IABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM= , OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN= THE SOFTWARE. +- +-


        ++

        ++
        +
        Author: Sebas= tian Egner
        +-
        Editor: Mike Sperber ++
        Editor: Mike Sperber
        + + +-Last modified: Sun Sep 11 16:07:38 CEST 2005 ++Last modified: Sun Jan 28 13:40:16 MET 2007 + + + +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-74.html b/srfi-doc/sr= fi/scribblings/srfi-std/srfi-74.html +index 50be385..6058742 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-74.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-74.html +@@ -1,60 +1,449 @@ +- +- +- ++ ++ + +-SRFI 74: Octet-Addressed Binary Blocks ++ ++ ++ SRFI 74: Octet-Addressed Binary Blocks ++ ++ ++ + +=20 + +-

        Title

        +- +-Octet-Addressed Binary Blocks ++

        SRFI 74: Octet-Addressed Binary Blocks

        +=20 +-

        Authors

        ++

        by Michael Sperber

        ++

        This copy of the SRFI 74 specific= ation document ++is distributed as part of the Racket package ++srfi-doc.

        = The canonical source of this document is ++https://srfi.s= chemers.org/srfi-74/srfi-74.html.

        +=20 +-Michael Sperber ++

        Status

        +=20 +

        +-This SRFI is currently in ``final'' status. To see an explanation of each +-status that a SRFI can hold, see +-here. +-To +-provide input on this SRFI, please +-mailto:srfi-74@srfi.schemers= .org. +-See instruc= tions +-here to subscribe to the list. You can access previous messages via +-t= he +-archive of the mailing list. ++ This SRFI is currently in final status. Here ++ is an explanati= on ++ of each status that a SRFI can hold. To provide input on this SRFI, pl= ease ++ send email ++ to s= rfi-74@nospamsrfi.schemers.org. ++ To subscribe to the list, ++ follow t= hese ++ instructions. You can access previous messages via the mailing ++ list archive. ++

        ++ ++

        Abstract

        ++

        ++ This SRFI defines a set of procedures for creating, accessing, and ++ manipulating octet-addressed blocks of binary data, in ++ short, blobs. The SRFI provides access primitives for fixed-leng= th ++ integers of arbitrary size, with specified endianness, and a choice of ++ unsigned and two's complement representations. ++

        ++

        Rationale

        ++

        ++ Many applications must deal with blocks of binary data by accessing the= m in ++ various ways---extracting signed or unsigned numbers of various sizes. = Such ++ an application can use octet vectors as ++ in SRFI 66 or any of the ++ other types of homogeneous vectors ++ in SRFI 4, but these both ++ only allow retrieving the binary data of one type. ++

        ++

        ++ This is awkward in many situations, because an application might access ++ different kinds of entities from a single binary block. Even for unifo= rm ++ blocks, the disjointness of the various vector data types in SRFI 4 mea= ns ++ that, say, an I/O API needs to provide an army of procedures for each of ++ them in order to provide efficient access to binary data. ++

        ++

        ++ Therefore, this SRFI provides a single type for blocks of bina= ry ++ data with multiple ways to access that data. It deals only with intege= rs in ++ various sizes with specified endianness, because these are the most fre= quent ++ applications. Dealing with other kinds of binary data, such as ++ floating-point numbers or variable-size integers would be natural ++ extensions, but are left for a future SRFI. ++

        ++

        Specification

        ++

        General remarks

        ++

        ++ Blobs are objects of a new type. Conceptually, a blob represents a seq= uence ++ of octets. ++

        ++

        ++ Scheme systems implementing both SRFI 4 and/or SRFI 66 and this SRFI ma= y or ++ may not use the same type for u8vector and blobs. They are encouraged = to do ++ so, however. ++

        ++

        ++ As with u8vectors, the length of a blob is the number of octets it cont= ains. ++ This number is fixed. A valid index into a blob is an exact, non-negat= ive ++ integer. The first octet of a blob has index 0, the last octet has an = index ++ one less than the length of the blob. ++

        ++

        ++ Generally, the access procedures come in different flavors according to= the ++ size of the represented integer, and ++ the endianness = of the ++ representation. The procedures also distinguish signed and unsigned ++ representations. The signed representations all ++ use two's ++ complement.

        ++

        ++ For procedures that have no "natural" return value, this SRFI often use= s the ++ sentence: ++

        ++

        ++ The return values are unspecified. ++

        ++

        ++ This means that number of return values and the return values are ++ unspecified. However, the number of return values is such that it is ++ accepted by a continuation created by begin. Specifically= , on ++ Scheme implementations where continuations created by begin ++ accept an arbitrary number of arguments (this includes most ++ implementations), it is suggested that the procedure return zero return ++ values. ++

        ++

        Interface

        ++
        ++
        (endianness big) (syntax)
        ++
        (endianness little) (syntax) ++
        (endianness native) (syntax) ++
        ++

        ++ (endianness big) and (endianness little) ++ evaluate to two distinct and unique objects representing an endiannes= s. ++ The native endianness evaluates to the endianness of the ++ underlying machine architecture, and must be eq? to ++ either (endianness big) or (endianness little). ++

        ++
        ++
        (blob? obj)
        ++
        ++

        ++ Returns #t if obj is a blob, otherwise ++ returns #f. ++

        ++
        ++
        (make-blob k)
        ++
        ++

        ++ Returns a newly allocated blob of k octets, all of them 0. ++

        ++
        ++
        (blob-length blob)
        ++
        ++

        ++ Returns the number of octets in blob as an exact integer. ++

        ++
        ++
        (blob-u8-ref blob k)<= /dt> ++
        (blob-s8-ref blob k)<= /dt> ++
        ++

        ++ K must be a valid index of blob. ++

        ++

        ++ Blob-u8-ref returns the octet at index k ++ of blob. ++

        ++

        ++ Blob-s8-ref returns the exact integer corresponding to t= he ++ two's complement representation at index k ++ of blob. ++

        ++
        ++
        (blob-u8-set! blob k octet)
        ++
        (blob-s8-set! blob k byte)
        ++
        ++

        ++ K must be a valid index ++ of blob.

        Blob-u8-set! ++ stores octet in element k of blob. ++

        ++

        ++ Byte, must be an exact integer in the interval {-128, ..., ++ 127}. Blob-u8-set! stores the two's complement represent= ation ++ of byte in element k of blob. ++

        ++

        The return values are unspecified.

        ++
        ++
        (blob-uint-ref size endianness blob k)
        ++
        (blob-sint-ref size endianness blob k)
        ++
        (blob-uint-set! size endianness blob k n)
        ++
        (blob-sint-set! size endianness blob k n)
        ++
        ++

        ++ Size must be a positive exact integer. K must b= e a ++ valid index of blob; so must the indices {k, ++ ..., k + size - 1}. Endianness must = be an ++ endianness object. ++

        ++

        ++ Blob-uint-ref retrieves the exact integer corresponding = to ++ the unsigned representation of size size and specified ++ by endianness at indices {k, ..., k ++ + size - 1}. ++

        ++

        ++ Blob-sint-ref retrieves the exact integer corresponding = to ++ the two's complement representation of size size and speci= fied ++ by endianness at indices {k, ..., k ++ + size - 1}. ++

        ++

        ++ For blob-uint-set!, n must be an exact intege= r in ++ the interval [0, (256^size)-1]. Blob-uint-set! ++ stores the unsigned representation of size size and specif= ied ++ by endianness into the blob at indices {k, ++ ..., k + size - 1}. ++

        ++

        ++ For blob-uint-set!, n must be an exact intege= r in ++ the interval [-256^(size-1), ++ (256^(size-1))-1]. Blob-sint-set! stores the = two's ++ complement representation of size size and specified ++ by endianness into the blob at indices {k, ++ ..., k + size - 1}. ++

        ++
        ++
        (blob-u16-ref endianness blob k)
        ++
        (blob-s16-ref endianness blob k)
        ++
        (blob-u16-native-ref blob k)=
        ++
        (blob-s16-native-ref blob k)=
        ++
        (blob-u16-set! endianness blob k n)
        ++
        (blob-s16-set! endianness blob k n)
        ++
        (blob-u16-native-set! blob k = n)
        ++
        (blob-s16-native-set! blob k = n)
        ++
        ++

        ++ K must be a valid index of blob; so must the ++ index k+ 1. Endianness must be an endianness ++ object. ++

        ++

        ++ These retrieve and set two-octet representations of numbers at ++ indices k and k+1, according to the endianness ++ specified by endianness. The procedures with u16 ++ in their names deal with the unsigned representation, those ++ with s16 with the two's complement representation. ++

        ++

        ++ The procedures with native in their names employ the nat= ive ++ endianness, and only work at aligned indices: k must be a ++ multiple of 2. It is an error to use them at non-aligned indices. ++

        ++
        ++
        (blob-u32-ref endianness blob k)
        ++
        (blob-s32-ref endianness blob k)
        ++
        (blob-u32-native-ref blob k)=
        ++
        (blob-s32-native-ref blob k)=
        ++
        (blob-u32-set! endianness blob k n)
        ++
        (blob-s32-set! endianness blob k n)
        ++
        (blob-u32-native-set! blob k = n)
        ++
        (blob-s32-native-set! blob k = n)
        ++
        ++

        ++ K must be a valid index of blob; so must the in= dices ++ {k, ..., k+ 3}. Endianness must be an ++ endianness object. ++

        ++

        ++ These retrieve and set four-octet representations of numbers at indic= es ++ {k, ..., k+ 3}, according to the endianness ++ specified by endianness. The procedures with u32 ++ in their names deal with the unsigned representation, those ++ with s32 with the two's complement representation. ++

        ++

        ++ The procedures with native in their names employ the nat= ive ++ endianness, and only work at aligned indices: k must be a ++ multiple of 4. It is an error to use them at non-aligned indices. ++

        ++
        ++
        (blob-u64-ref endianness blob k)
        ++
        (blob-s64-ref endianness blob k)
        ++
        (blob-u64-native-ref blob k)=
        ++
        (blob-s64-native-ref blob k)=
        ++
        (blob-u64-set! endianness blob k n)
        ++
        (blob-s64-set! endianness blob k n)
        ++
        (blob-u64-native-set! blob k = n)
        ++
        (blob-s64-native-set! blob k = n)
        ++
        ++

        ++ K must be a valid index of blob; so must the in= dices ++ {k, ..., k+ 7}. Endianness must be an ++ endianness object. ++

        ++

        ++ These retrieve and set eight-octet representations of numbers at indi= ces ++ {k, ..., k+ 7}, according to the endianness ++ specified by endianness. The procedures with u64 ++ in their names deal with the unsigned representation, those ++ with s64 with the two's complement representation. ++

        ++

        ++ The procedures with native in their names employ the nat= ive ++ endianness, and only work at aligned indices: k must be a ++ multiple of 8. It is an error to use them at non-aligned indices. ++

        ++
        ++
        (blob=3D? blob-1 blob-2)
        ++
        ++

        ++ Returns #t if blob-1 and blob-2 are ++ equal---that is, if they have the same length and equal octets at all ++ valid indices. ++

        ++
        ++
        (blob-copy! source source-start target target-start n)
        ++
        ++

        ++ Copies data from blob source to ++ blob target. Source-start, target-start, ++ and n must be non-negative exact integers that satisfy ++

        ++

        ++ 0 <=3D source-start <=3D source-start ++ + n <=3D (blob-length source) ++

        ++

        ++ 0 <=3D target-start <=3D target-start ++ + n <=3D (blob-length target) ++

        ++

        ++ This copies the octets from source at indices ++ [source-start, source-start + n) to ++ consecutive indices in target starting ++ at target-index. ++

        ++

        ++ This must work even if the memory regions for the source and the targ= et ++ overlap, i.e., the octets at the target location after the copy must = be ++ equal to the octets at the source location before the copy. ++

        ++

        ++ The return values are unspecified. ++

        ++
        ++
        (blob-copy blob)
        ++
        ++

        ++ Returns a newly allocated copy of blob blob. ++

        ++
        ++
        (blob->u8-list blob)
        ++
        (u8-list->blob blob)
        ++
        ++

        ++ blob->u8-listreturns a newly allocated list of the oc= tets ++ of blob in the same ++ order. ++

        ++
        ++
        ++

        ++ U8-list->blob returns a newly allocated blob whose ++ elements are the elements of list octets, which must all be ++ octets, in the same order. Analogous to list->vector. ++

        ++
        ++
        (blob->uint-list size endianness blob)
        ++
        (blob->sint-list size endianness blob)
        ++
        (uint-list->blob size endianness list)
        ++
        (sint-list->blob size endianness list)
        ++
        ++

        ++ Size must be a positive exact integer. Endianness ++ must be an endianness object. ++

        ++

        ++ These convert between lists of integers and their consecutive ++ representations according to size and endianness in ++ blobs in the same way ++ as blob->u8-list, blob->s8-list, ++ u8-list->blob, and s8-list->blob do f= or ++ one-octet representations. ++

        ++
        ++
        +=20 ++

        Reference Implementation

        ++

        ++ This reference i= mplementation makes use ++ of SRFI 23 (Error reporting ++ mechanism), SRFI 26 ++ (Notation for Specializing Parameters without ++ Currying), SRFI 60 (Integers ++ as Bits), and SRFI 66 (Octet ++ Vectors). ++

        ++

        Examples

        ++

        ++ The test suit= e doubles as a source of examples. +

        ++

        References

        + +-

        Abstract

        This SRFI defines a set of procedures for creating, a= ccessing, and manipulating octet-addressed blocks of binary data, in short,= blobs. The SRFI provides access primitives for fixed-length integer= s of arbitrary size, with specified endianness, and a choice of unsigned an= d two's complement representations.

        Rationale

        Many applicatio= ns must deal with blocks of binary data by accessing them in various ways--= -extracting signed or unsigned numbers of various sizes. Such an applicati= on can use octet vectors as in SRFI 66 or any of the other types of homogeneous vectors in SRFI 4, but these both only allow= retrieving the binary data of one type.

        This is awkward in many situ= ations, because an application might access different kinds of entities fro= m a single binary block. Even for uniform blocks, the disjointness of the = various vector data types in SRFI 4 means that, say, an I/O API needs to pr= ovide an army of procedures for each of them in order to provide efficient = access to binary data.

        Therefore, this SRFI provides a single type for blocks of binary data with multiple ways to access that data. I= t deals only with integers in various sizes with specified endianness, beca= use these are the most frequent applications. Dealing with other kinds of = binary data, such as floating-point numbers or variable-size integers would= be natural extensions, but are left for a future SRFI.

        Specificatio= n

        General remarks

        Blobs are objects of a new type. Conceptu= ally, a blob represents a sequence of octets.

        Scheme systems implemen= ting both SRFI 4 and/or SRFI 66 and this SRFI may or may not use the same t= ype for u8vector and blobs. They are encouraged to do so, however.

        A= s with u8vectors, the length of a blob is the number of octets it contains.= This number is fixed. A valid index into a blob is an exact, non-negati= ve integer. The first octet of a blob has index 0, the last octet has an = index one less than the length of the blob.

        Generally, the access pr= ocedures come in different flavors according to the size of the represented= integer, and the endia= nness of the representation. The procedures also distinguish signed an= d unsigned representations. The signed representations all use two's complement.

        = For procedures that have no "natural" return value, this SRFI often uses th= e sentence

        The return values are unspecified.

        This mea= ns that number of return values and the return values are unspecified. Ho= wever, the number of return values is such that it is accepted by a contin= uation created by begin. Specifically, on Scheme implementati= ons where continuations created by begin accept an arbitrary n= umber of arguments (this includes most implementations), it is suggested th= at the procedure return zero return values.

        Interface

        (endianness big) (syntax)
        (endianness little) (syntax)
        (endianness native) (syntax)
        (endianness big) and (endianness little) evaluat= e to two distinct and unique objects representing an endianness. The native endianness evaluates to the endianness of the underlying ma= chine architecture, and must be eq? to either (endiannes= s big) or (endianness little).

        (blob?= obj)

        Returns #t if = obj is a blob, otherwise returns #f.

        (make-blob k)

        Returns a newly= allocated blob of k octets, all of them 0.

        (b= lob-length blob)

        Returns the numb= er of octets in blob as an exact integer.

        (blo= b-u8-ref blob k)
        (b= lob-s8-ref blob k)

        K must be a valid index of blob.

        Blob-u8-ref= returns the octet at index k of blob.

        <= code>Blob-s8-ref returns the exact integer corresponding to the two'= s complement representation at index k of blob.

        (blob-u8-set! blob k octet)
        (blob-s8-set! blob = k byte)

        K must be a val= id index of blob.

        Blob-u8-set! stores oc= tet in element k of blob.

        Byte= , must be an exact integer in the interval {-128, ..., 127}. Blob-u8-= set! stores the two's complement representation of byte = in element k of blob.

        The return values are uns= pecified.

        (blob-uint-ref size endi= anness blob k)
        (blob= -sint-ref size endianness blob k)
        (blob-uint-set! size= endianness blob k n)
        (blob-sint-set! size endianness blob k n)

        Size must be a positive exact integer. K must be a valid = index of blob; so must the indices {k, ..., k + size - 1}. Endianness must be an endianness obj= ect.

        Blob-uint-ref retrieves the exact integer correspo= nding to the unsigned representation of size size and specified = by endianness at indices {k, ..., k + size - 1}.

        Blob-sint-ref retrieves the exact inte= ger corresponding to the two's complement representation of size size<= /var> and specified by endianness at indices {k, ...,= k + size - 1}.

        For blob-uint-set!= , n must be an exact integer in the interval [0, (256^size<= /var>)-1]. Blob-uint-set! stores the unsigned representation o= f size size and specified by endianness into the blob= at indices {k, ..., k + size - 1}.

        = For blob-uint-set!, n must be an exact integer in t= he interval [-256^(size-1), (256^(size-1))-1]. = Blob-sint-set! stores the two's complement representation of size size and specified by endianness into the blob at indic= es {k, ..., k + size - 1}.

        (blob-u16-ref endianness blob k<= code>)
        (blob-s16-ref endianness blob k)
        (blob-u16-native-ref <= /code>blob k)
        (blob-s16-na= tive-ref blob k)
        (b= lob-u16-set! endianness blob k n)
        (blob-s16-set! endianness<= /var> blob k n)
        (blob-u16-native-set! blob k n)
        (blob-s16-native-set! blob = k n)

        K must be a valid = index of blob; so must the index k+ 1. Endiannes= s must be an endianness object.

        These retrieve and set two-oct= et representations of numbers at indices k and k+1, a= ccording to the endianness specified by endianness. The procedur= es with u16 in their names deal with the unsigned representati= on, those with s16 with the two's complement representation.

        The procedures with native in their names employ the nati= ve endianness, and only work at aligned indices: k must be a mul= tiple of 2. It is an error to use them at non-aligned indices.

        (blob-u32-ref endianness blob k)
        (blob-s32-ref endianness = blob k)
        (blob-u32-native-r= ef blob k)
        (blob-s3= 2-native-ref blob k)
        (blob-u32-set! endianness blob k = n)
        (blob-s32-set! endiann= ess blob k n)
        <= code>(blob-u32-native-set! blob k n= )
        (blob-s32-native-set! blob <= var>k n)

        K must be a va= lid index of blob; so must the indices {k, ..., = k+ 3}. Endianness must be an endianness object.

        The= se retrieve and set four-octet representations of numbers at indices {= k, ..., k+ 3}, according to the endianness specified by endianness. The procedures with u32 in their names de= al with the unsigned representation, those with s32 with the t= wo's complement representation.

        The procedures with native in their names employ the native endianness, and only work at aligned in= dices: k must be a multiple of 4. It is an error to use them at= non-aligned indices.

        (blob-u64-ref endiannes= s blob k)
        (blob-s64-= ref endianness blob k)=
        (blob-u64-native-ref blob k)
        (blob-s64-native-ref blob k= )
        (blob-u64-set! endianness blob k n)
        (= blob-s64-set! endianness blob k n)
        (blob-u64-native-set! blo= b k n)
        (blob-s64-nat= ive-set! blob k n)

        K must be a valid index of blob; so must the = indices {k, ..., k+ 7}. Endianness must be= an endianness object.

        These retrieve and set eight-octet representa= tions of numbers at indices {k, ..., k+ 7}, according= to the endianness specified by endianness. The procedures with = u64 in their names deal with the unsigned representation, thos= e with s64 with the two's complement representation.

        The= procedures with native in their names employ the native endia= nness, and only work at aligned indices: k must be a multiple of= 8. It is an error to use them at non-aligned indices.

        (= blob=3D? blob-1 blob-2)
        <= p>Returns #t if blob-1 and blob-2 are equa= l---that is, if they have the same length and equal octets at all valid ind= ices.

        (blob-copy! source source-st= art target target-start n)

        Copies data from blob source to blob target<= /var>. Source-start, target-start, and n = must be non-negative exact integers that satisfy

        0 <=3D sourc= e-start <=3D source-start + n <=3D = (blob-length source)

        0 <=3D target-start <=3D target-start + n <=3D (blob-leng= th target)

        This copies the octets from source<= /var> at indices [source-start, source-start + n= ) to consecutive indices in target starting at target= -index.

        This must work even if the memory regions for the sourc= e and the target overlap, i.e., the octets at the target location after the= copy must be equal to the octets at the source location before the copy.

        The return values are unspecified.

        (blob-copy blob)

        Returns a newly allocated copy of= blob blob.

        (blob->u8-list blob= )
        (u8-list->blob blob= )

        blob->u8-listreturns a newly allo= cated list of the octets of blob in the same order.

        =

        U8-list->blob returns a newly allocated blob whose eleme= nts are the elements of list octets, which must all be octets, i= n the same order. Analogous to list->vector.

        (blob->uint-list size endianness b= lob)
        (blob->sint-list size<= /var> endianness blob)
        (ui= nt-list->blob size endianness list)
        (sint-list->blob size <= var>endianness list)

        Size must be a positive exact integer. Endianness must be an endia= nness object.

        These convert between lists of integers and their conse= cutive representations according to size and endianness in blobs in the same way as blob->u8-list, blob-&g= t;s8-list, u8-list->blob, and s8-list->blo= b do for one-octet representations.

        Reference Imple= mentation

        This reference implementation mak= es use of SRFI 23 (Error = reporting mechanism), SRFI 26= (Notation for Specializing Parameters without Currying), SRFI 60 (Integers as Bits), and SRFI 66 (Octet Vectors) .

        Examples

        The test suite doubles as a so= urce of examples.

        References

        Copyright

        +-Copyright (C) Michael Sperber (2005). All Rights Reserved.=20 +-

        +-Permission is hereby granted, free of charge, to any person obtaining a +-copy of this software and associated documentation files (the "Software"), +-to deal in the Software without restriction, including without limitation +-the rights to use, copy, modify, merge, publish, distribute, sublicense, +-and/or sell copies of the Software, and to permit persons to whom the +-Software is furnished to do so, subject to the following conditions: +-

        +-The above copyright notice and this permission notice shall be included in +-all copies or substantial portions of the Software. +-

        +-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +-THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +-FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +-DEALINGS IN THE SOFTWARE. +- +-


        +-
        Editor: Da= vid Van Horn
        +- ++

        Copyright

        ++

        ++ Copyright (C) Michael Sperber (2005). All Rights Reserved. ++

        ++

        ++ Permission is hereby granted, free of charge, to any person obtaining a= copy ++ of this software and associated documentation files (the "Software"), to ++ deal in the Software without restriction, including without limitation = the ++ rights to use, copy, modify, merge, publish, distribute, sublicense, an= d/or ++ sell copies of the Software, and to permit persons to whom the Software= is ++ furnished to do so, subject to the following conditions: ++

        ++

        ++ The above copyright notice and this permission notice shall be included= in ++ all copies or substantial portions of the Software. ++

        ++

        ++ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS= OR ++ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL= THE ++ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEA= LINGS ++ IN THE SOFTWARE. ++

        ++
        ++
        Editor: David Van Horn
        ++ ++ +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-78.html b/srfi-doc/sr= fi/scribblings/srfi-std/srfi-78.html +index 4267157..270196e 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-78.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-78.html +@@ -1,102 +1,122 @@ +- +- ++ ++ + ++ ++ + SRFI 78: Lightweight testing ++ ++ ++ + +=20 + +=20 +-

        Title

        +- +-Lightweight testing +- +-

        Author

        +- +-Sebastian Egner +- +-

        Status

        +- +-This SRFI is currently in ``final'' status. To see an explanation of +-each status that a SRFI can hold, see here. +- +-To provide input on this SRFI, please mail to +-<srfi-78@srfi.schemers.org>. See instructions here to subscribe to +-the list. You can access previous messages via the archive of the mailing list. +- +- +-

          +-
        • Received: 2005/10/25
        • +-
        • Draft: 2005/11/11 - 2006/01/10
        • +-
        • Draft extended: 2006/01/17 - 2006/01/31
        • +-
        • Revised: 2006/01/18
        • +-
        • Revised: 2006/02/08
        • +-
        • Final: 2006/03/06
        • +-
        +- +-

        Abstract

        +- ++

        SRFI 78: Lightweight testing

        ++ ++

        by Sebastian Egner

        ++

        This copy of the SRFI 78 specific= ation document ++is distributed as part of the Racket package ++srfi-doc.

        = The canonical source of this document is ++https://srfi.s= chemers.org/srfi-78/srfi-78.html.

        ++ ++

        Status

        ++ ++

        This SRFI is currently in final status. Here is an explanation of each stat= us that a SRFI can hold. To provide input on this SRFI, please send email = to srfi-= 78@nospamsrfi.schemers.org. To = subscribe to the list, follow these instructions. You can access previous messages= via the mailing list a= rchive.

        ++
          ++
        • Received: 2005-10-25
        • ++
        • Draft: 2005-11-11--2006-01-10
        • ++
        • Draft extended: 2006-01-17--2006-01-31
        • ++
        • Revised: 2006-01-18
        • ++
        • Revised: 2006-02-08
        • ++
        • Final: 2006-03-06
        • ++
        • Revised to fix errata:
            ++
          • 2019-10-25 (Fix broken links.)
        • ++
        ++ ++

        Abstract

        ++

        + A simple mechanism is defined for testing Scheme programs. + As a most primitive example, the expression +- +-

           (check (+ 1 1) =3D> 3)
        +-
        +- +-evaluates the expression (+ 1 1) and compares the result ++

        ++
        ++   (check (+ 1 1) =3D> 3)
        ++
        ++

        ++evaluates the expression (+ 1 1) and compares the result + with the expected result 3 provided after the syntactic +-keyword =3D>. Then the outcome of this comparison is repo= rted ++keyword =3D>. Then the outcome of this comparison is repo= rted + in human-readable form by printing a message of the form +- +-

           (+ 1 1) =3D> 2 ; *** failed ***
        ++

        ++
        ++   (+ 1 1) =3D> 2 ; *** failed ***
        +    ; expected result: 3
        +-
        +- ++
        ++

        + Moreover, the outcome of any executed check is recorded + in a global state counting the number of correct and failed + checks and storing the first failed check. At the end of a + file, or at any other point, the user can print a summary +-using check-report. ++using check-report. ++

        +

        + In addition to the simple test above, it is also possible + to execute a parametric sequence of checks. Syntactically, + this takes the form of an eager comprehension in the sense +-of SRFI 42 [5]. For exam= ple, +- +-

           (check-ec (:range e 100)
        ++of SRFI 42 [5]. For example,
        ++

        ++
        ++   (check-ec (:range e 100)
        +              (:let x (expt 2.0 e))=20
        +-             (=3D (+ x 1) x) =3D> #f (e x))
        +-
        +- +-This statement runs the variable e through {0..99} and +-for each binding defines x as (expt 2.0 e). The= n it is=20 +-checked if (+ x 1) is equal to x, and it is exp= ected that +-this is not the case (i.e. expected value is #f). The +-trailing (e x) tells the reporting mechanism to print +-the values of both e and x in case of a failed = check. ++ (=3D (+ x 1) x) =3D> #f (e x)) ++
        ++

        ++This statement runs the variable e through {0..99} and ++for each binding defines x as (expt 2.0 e). The= n it is=20 ++checked if (+ x 1) is equal to x, and it is exp= ected that ++this is not the case (i.e. expected value is #f). The ++trailing (e x) tells the reporting mechanism to print ++the values of both e and x in case of a failed = check. + The output could look like this: +- +-

           (let ((e 53) (x 9007199254740992.0)) (=3D (+ x 1) x)) =3D> #t ; *=
        ** failed ***
        ++

        ++
        ++   (let ((e 53) (x 9007199254740992.0)) (=3D (+ x 1) x)) =3D> #t ; ***=
         failed ***
        +     ; expected result: #f
        +-
        +- +-The specification of bindings to report, (e x) in the=20 ++
        ++

        ++The specification of bindings to report, (e x) in the=20 + example, is optional but very informative. +- ++

        ++

        + Other features of this SRFI are: +-

          +-
        • A way to specify a different equality predicate (default is equ= al?).
        • +-
        • Controlling the amount of reporting being printed.
        • +-
        • Switching off the execution and reporting of checks entriely.
        • +-
        • Retrieving a boolean if all checks have been executed and passed.
        • +-
        +- +-

        Rationale

        ++

        ++
          ++
        • A way to specify a different equality predicate (default is equ= al?).
        • ++
        • Controlling the amount of reporting being printed.
        • ++
        • Switching off the execution and reporting of checks entriely.
        • ++
        • Retrieving a boolean if all checks have been executed and passed.
        • ++
        ++ ++

        Rationale

        ++

        + The mechanism defined in this SRFI should be available in + every Scheme system because it has already proven useful + for interactive development---of SRFIs.=20 ++

        +

        + Although it is extremely straight-forward, the origin of the + particular mechanism described here is the 'examples.scm' file +@@ -104,209 +124,234 @@ accompanying the reference implementation of SRFI = 42 [5]. + The same mechanism has been reimplemented for the reference + implementation of SRFI 67, and a simplified version is yet + again found in the reference implementation of SRFI 77. ++

        +

        + The mechanism in this SRFI does not replace more sophisticated + approaches to unit testing, like SRFI 64 [1] or SchemeUnit [2]. + These systems provide more control of the testing, separate + the definition of a test, its execution, and its reports, and + provide several other features. ++

        +

        + Neil Van Dyke's Testeez library [3] is very close in spirit=20 + to this SRFI. In Testeez, tests are disabled by (re-)defining a + macro. The advantage of this method is that the code for the + test cases can be removed entirely, and hence even the dependency + on the Testeez library. This SRFI on the other hand, uses a +-Scheme conditional (COND, IF) to prevent execut= ion of the ++Scheme conditional (COND, IF) to prevent execut= ion of the + testing code. This method is more dynamic but retains dead + testing code, unless a compiler and a module system are used + to apply constant folding and dead code elimination. The only + major addition in SRFI over Testeez is the comprehension for + formulating parametric tests. ++

        +

        + Design considerations for this SRFI include the following: +-

          +-
        • Reporting is human-readable and as specific as possible, ++

          ++
            ++
          • Reporting is human-readable and as specific as possible, + i.e. not just "assertion failed" but the expression with + actual and expected value, and if possibly the relevant=20 +- part of the bindings environment.
          • +-
          • An effort is made to print closed Scheme expressions, i.e.=20 ++ part of the bindings environment.
          • ++
          • An effort is made to print closed Scheme expressions, i.e.=20 + expressions that can directly be copy/pasted into a REPL +- for further analysis (e.g. the let expression in the abstract).
          • +-
          • By default the checks report both correct and failed checks. ++ for further analysis (e.g. the let expression in the abstract).
          • ++
          • By default the checks report both correct and failed checks. + However, it is possible to reduce the output---or even to=20 + switch off the execution of checks. It has turned out useful + to be able to run only some subset checks for the features + currently under development. This can be done by changing +- the reporting mode between different sections.
          • +-
          • The global state (correct/failed count) is not made available ++ the reporting mode between differnt sections.
          • ++
          • The global state (correct/failed count) is not made available + to the user program. This reduces the dependencies between +- different checks because it is not possible to use the state.
          • +-
          • Ocassionally, it is useful to check that a certain expression=20 +- does not yield an ordinary result but raises an error. However,= =20 ++ different checks because it is not possible to use the state.
          • ++
          • Ocassionally, it is useful to check that a certain expression=20 ++ does not yield an ordinary result but raises an error. However,= =20 + R5RS [4] does not specify the mechanism by which this occurs + (e.g. raising exception, breaking into a REPL, aborting the + program, etc.). For this reason, this SRFI is restricted to=20 +- the case that the checked expressions evaluate normally.
          • +-
          • Though usually I am very much in favor of strictly prefix ++ the case that the checked expressions evaluate normally.
          • ++
          • Though usually I am very much in favor of strictly prefix + syntax, for this SRFI I make an exception because the=20 +- infix "=3D>" syntax is widely used and intuitive.
          • +-
          ++ infix "=3D>" syntax is widely used and intuitive.
        • ++
        +=20 +-

        Specification

        ++

        Specification

        +=20 +-
        +-
        +-(check <expr> (=3D> <equal>) <exp= ected>)     = ;    MACRO
        ++
        ++
        ++(check <expr> (=3D> <equal>) <expected>) =        &nb= sp;MACRO
        + (check <expr> =3D> <expected>) +-
        +-
        +- evaluates <expr> and compares the value to the value +- of <expected> using the predicate <equal&g= t;, which is +- equal? when omitted. Then a report is printed according ++
        ++
        ++ evaluates <expr> and compares the value to the value ++ of <expected> using the predicate <equal&g= t;, which is ++ equal? when omitted. Then a report is printed according + to the current mode setting (see below) and the outcome +- is recorded in a global state to be used in check-report. +- The precise order of evaluation is that first <equal> +- and <expected> are evaluated (in unspecified order)= and +- then <expr> is evaluated.
        +- Example: (check (+ 1 1) =3D> 2) +-
        +-
        +- +-
        +-
        +-(check-ec <qualifier>* <ex= pr> (=3D> <equal>) <expected> (<argument>*))         MACRO=
        +-(check-ec <qualifier>
        * <expr> =3D> = <expected> (<argument>*))
        +-(check-ec <qualifier>
        * <expr> (=3D> <equal= >) <expected>)
        +-(check-ec <qualifier>
        * <expr> =3D> = <expected>) +-
        +-
        +- an eager comprehension for executing a parametric sequence of checks.<= p> +- Enumerates the sequence of bindings specified by <qualifie= r>*. +- For each binding evaluates <equal> and <ex= pected> in unspecified +- order. Then evalues <expr> and compares the value o= btained to the +- value of <expected> using the value of <eq= ual> as predicate, which +- is equal? when omitted. ++ is recorded in a global state to be used in check-report. ++ The precise order of evaluation is that first <equal> ++ and <expected> are evaluated (in unspecified order)= and ++ then <expr> is evaluated.
        ++ Example: (check (+ 1 1) =3D> 2) ++
        ++
        ++ ++
        ++
        ++(check-ec <qualifier>* <expr> (=3D> <equal= >) <expected> (<argument>*))  &nb= sp;      MACRO
        ++(check-ec <qualifier>
        * <expr> =3D> = <expected> (<argument>*))
        ++(check-ec <qualifier>
        * <expr> (=3D> <equal= >) <expected>)
        ++(check-ec <qualifier>
        * <expr> =3D> = <expected>) ++
        ++
        ++

        ++ an eager comprehension for executing a parametric sequence of checks. ++

        ++

        ++ Enumerates the sequence of bindings specified by <qualifie= r>*. ++ For each binding evaluates <equal> and <ex= pected> in unspecified ++ order. Then evalues <expr> and compares the value o= btained to the ++ value of <expected> using the value of <eq= ual> as predicate, which ++ is equal? when omitted. + The comprehension stops after the first failed check, if there + is any. Then a report is printed according to the current mode=20 + setting (see below) and the outcome is recorded in a global state=20 +- to be used in check-report. The entire check-ec counts as a single=20 +- check.

        +- In case the check fails <argument>* is used for = constructing an +- informative message with the argument values. Use <argument&g= t;* to +- list the relevant free variables of <expr> (see exa= mples) that you +- want to have printed.

        +- A <qualifier> is any qualifier of an eager compr= ehension as +- specified in SRFI 42 = [5].

        +- ++ to be used in check-report. The entire check-ec counts as a single=20 ++ check.

        ++ In case the check fails <argument>* is used for = constructing an ++ informative message with the argument values. Use <argument&g= t;* to ++ list the relevant free variables of <expr> (see exa= mples) that you ++ want to have printed.

        ++ A <qualifier> is any qualifier of an eager compr= ehension as ++ specified in SRFI 42 [5]. ++

        ++

        + Examples: +-

             (check-ec (: e 100) (positive? (expt 2 e)) =3D> #t (e)) ;=
         fails on fixnums
        ++

        ++
        ++     (check-ec (: e 100) (positive? (expt 2 e)) =3D> #t (e)) ; fails o=
        n fixnums
        +      (check-ec (: e 100) (:let x (expt 2.0 e)) (=3D (+ x 1) x) =3D> #f=
         (x)) ; fails
        +      (check-ec (: x 10) (: y 10) (: z 10)
        +                (* x (+ y z)) =3D> (+ (* x y) (* x z))
        +                (x y z)) ; passes with 10^3 cases checked
        +-   
        +-
        +-
        ++
        ++ ++ ++ +=20 +-
        +-
        +-(check-report)    &nbs= p;    PROCEDURE +-
        +-
        ++
        ++
        ++(check-report)         PRO= CEDURE ++
        ++
        ++

        + prints a summary and the first failed check, if there is any, + depending on the current mode settings. +-

        +-
        +- +-
        +-
        +-(check-set-mode! mode)   =       PROCEDURE +-
        +-
        ++

        ++
        ++
        ++ ++
        ++
        ++(check-set-mode! mode)        &= nbsp;PROCEDURE ++
        ++
        ++

        + sets the current mode to mode, which must be a symbol in +- '(off summary report-failed report), default is 're= port. ++ '(off summary report-failed report), default is 're= port. + Note that you can change the mode at any time, and that check, +- check-ec and check-report use the current va= lue. +-

        +- The mode symbols have the following meaning:
        +- off: do not execute any of the checks,
        +- summary: print only summary in (check-repor= t) and nothing else,
        +- report-failed: report failed checks when they happen, a= nd in summary,
        +- report: report every example executed.
        +-

        +-
        +- +-
        +-
        +-(check-reset!)     = ;    PROCEDURE +-
        +-
        ++ check-ec and check-report use the current va= lue. ++

        ++

        ++ The mode symbols have the following meaning:
        ++ off: do not execute any of the checks,
        ++ summary: print only summary in (check-repor= t) and nothing else,
        ++ report-failed: report failed checks when they happen, a= nd in summary,
        ++ report: report every example executed.
        ++

        ++
        ++
        ++ ++ ++
        ++
        ++(check-reset!)         PRO= CEDURE ++
        ++
        + resets the global state (counters of correct/failed examples) + to the state immediately after loading the module for the + first time, i.e. no checks have been executed. +-
        +-
        +- +-
        +-
        +-(check-passed? expected-total-count) =         PROCEDURE +-
        +-
        +- #t if there were no failed checks and expected-total-coun= t=20 +- correct checks, #f otherwise.

        ++

        ++
        ++ ++
        ++
        ++(check-passed? expected-total-count)      = ;   PROCEDURE ++
        ++
        ++

        ++ #t if there were no failed checks and expected-total-coun= t=20 ++ correct checks, #f otherwise. ++

        ++

        + Rationale: This procedure can be used in automatized + tests by terminating a test program with the statement +- (exit (if (check-passed? n) 0 1)). +-

        +-
        +- ++ (exit (if (check-passed? n) 0 1)). ++

        ++
        ++
        +=20 +-

        Implementation

        +=20 +-check.scm: ++

        Implementation

        ++

        ++check.scm: + implementation in R5RS + SRFI 23 (error) + SRFI 42 (comprehensions); +- tested under PLT 208p1 and Scheme 48 1.3.
        +- +-examples.scm: ++ tested under PLT 208p1 and Scheme 48 1.3.
        ++

        ++

        ++examples.scm: + a few examples. ++

        ++

        References

        +=20 +-

        References

        +- +-
        +=20 ++

        Copyright

        ++

        + Copyright (C) Sebastian Egner (2005-2006). All Rights Reserved. ++

        +

        + Permission is hereby granted, free of charge, to any person obtaining a c= opy of this software and associated documentation files (the "Software"), t= o deal in the Software without restriction, including without limitation th= e rights to use, copy, modify, merge, publish, distribute, sublicense, and/= or sell copies of the Software, and to permit persons to whom the Software = is furnished to do so, subject to the following conditions:=20 ++

        +

        + The above copyright notice and this permission notice shall be included i= n all copies or substantial portions of the Software.=20 ++

        +

        + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS O= R IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, = FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE= AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIA= BILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, = OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN T= HE SOFTWARE. +-

        +-


        ++

        ++
        +
        Author: srfi-= 78@sebastian-egner.net
        +-
        Editors: s= rfi-editors@srfi.schemers.org
        +- ++
        Editor: David Van Horn
        ++ + +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-8.html b/srfi-doc/srf= i/scribblings/srfi-std/srfi-8.html +index 38b7340..ed3e26e 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-8.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-8.html +@@ -1,41 +1,58 @@ +- +- ++ ++ + +-SRFI 8: RECEIVE: Binding to multiple values ++ ++ ++ SRFI 8: RECEIVE: Binding to multiple values ++ ++ ++ + +=20 + +-

        Title

        ++

        SRFI 8: receive: Binding to multiple values

        +=20 +-SRFI 8: receive: Binding to multiple values +- +-

        Author

        +- +-John David Stone +- +-

        ++

        by John David Stone
        + Department of Mathematics and Computer Science, Grinnell College, Grinnel= l, Iowa 50112, + email. +

        ++

        This copy of the SRFI 8 specifica= tion document ++is distributed as part of the Racket package ++srfi-doc.

        = The canonical source of this document is ++https://srfi.sch= emers.org/srfi-8/srfi-8.html.

        +=20 +-

        Status

        ++

        Status

        +=20 +-This SRFI is currently in ``final'' status. To see an explanation of eac= h status that a SRFI can hold, see here. +-You can access the discussion via the archive of the mailing list. +-

          +-
        • Received: 1999/05/27 +-
        • Draft: 1999/07/01-1999/08/30 +-
        • Final: 1999/08/30 +-
        ++

        This SRFI is currently in final status. Here is an explanation of each stat= us that a SRFI can hold. To provide input on this SRFI, please send email = to srfi-8= @nospamsrfi.schemers.org. To su= bscribe to the list, follow these instructions. You can access previous messages v= ia the mailing list arch= ive.

        ++
          ++
        • Received: 1999-05-27 ++
        • Draft: 1999-07-01--1999-08-30 ++
        • Final: 1999-08-30 ++
        +=20 +-

        Related SRFIs

        ++

        Related SRFIs

        +=20 +

        + The syntax proposed in this SRFI is used in the reference implementation = of + SRFI-1, ``List library.'' +

        +=20 +-

        Abstract

        ++

        Abstract

        +=20 +

        + The only mechanism that R5RS provides for binding identifiers = to +@@ -44,7 +61,7 @@ the values of a multiple-valued expression is the primit= ive + readable syntax for creating such bindings. +

        +=20 +-

        Rationale

        ++

        Rationale

        +=20 +

        + Although R5RS supports multiple-valued expressions, it provides +@@ -116,8 +133,8 @@ established from a ``body'' in which they are used mak= es it easier to + follow the code. +

        +=20 +-

        Specification

        +- ++

        Specification

        ++ +

        + (receive <formals> <expression> + <body>)     library synt= ax=20 +@@ -134,7 +151,7 @@ forms: + (<variable1> ... + <variablen>): The environment in whi= ch=20 + the receive-expression is evaluated is extended by binding +-<variable1>, ..., ++<variable1>, ..., + <variablen> to fresh locations. The + <expression> is evaluated, and its values are stored into those + locations. (It is an error if <expression> does not have exactly +@@ -154,7 +171,7 @@ stored in the location bound to <variable>. + <variablen> . <variablen + + 1>): The environment in which=20 + the receive-expression is evaluated is extended by binding +-<variable1>, ..., ++<variable1>, ..., + <variablen + 1> to fresh locations. The + <expression> is evaluated. Its first n values are stored in= to + the locations bound to <variable1> ... +@@ -172,7 +189,7 @@ the extended environment. The results of the last exp= ression in the body + are the values of the receive-expression. +

        +=20 +-

        Reference implementation

        ++

        Reference implementation

        +=20 +
        + 
        +@@ -184,7 +201,7 @@ are the values of the receive-expression.
        + 
        + 
        +=20 +-
        ++
        +=20 +

        + Copyright (C) John David Stone (1999). All Rights Reserved. +@@ -213,9 +230,9 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF O= R IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +

        +=20 +-
        ++
        +=20 +-
        Editor: Mi= ke Sperber
        ++
        Editor: Mike Sperber
        +=20 + + +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-86.html b/srfi-doc/sr= fi/scribblings/srfi-std/srfi-86.html +index 39255f2..414fc56 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-86.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-86.html +@@ -1,41 +1,51 @@ +- +-SRFI 86: MU and NU simulating VALUES & CALL-WITH-V= ALUES, and their related LET-syntax +- +-

        Title

        +- +-MU and NU simulating VALUES & CALL-WITH-VALUES, and their related LET= -syntax +- +-

        Author

        +- +-Joo ChurlSoo +- +-

        Status

        +- +-This SRFI is currently in ``final'' status. To see an explanation of each +-status that a SRFI can hold, see +-here. +-To +-provide input on this SRFI, please +-mailt= o:srfi minus 86 at srfi dot schemers dot org. +-See instructions +-here to subscribe to the list. You can access the discussion via +-t= he +-archive of the mailing list. +-You can access +-post-finalization messages via +- +-the archive of the mailing list. +-

        +-

          +-
        • Received: 2006/04/03
        • +-
        • Revised: 2006/05/08
        • +-
        • Revised: 2006/05/22
        • +-
        • Revised: 2006/06/20
        • +-
        • Final: 2006/06/20
        • +-
        • Draft: 2006/04/04 - 2006/06/01
        • ++ ++ ++ ++ ++ ++ SRFI 86: MU and NU simulating VALUES & CALL-WITH-VALUES, a= nd their related LET-syntax ++ ++ ++ ++ ++ ++ ++

          SRFI 86: MU and NU simulating VALUES & CALL-WITH-VALUES, and thei= r related LET-syntax

          ++ ++

          by Joo ChurlSoo

          ++

          This copy of the SRFI 86 specific= ation document ++is distributed as part of the Racket package ++srfi-doc.

          = The canonical source of this document is ++https://srfi.s= chemers.org/srfi-86/srfi-86.html.

          ++ ++

          Status

          ++ ++

          This SRFI is currently in final status. Here is an explanation of each stat= us that a SRFI can hold. To provide input on this SRFI, please send email = to srfi-= 86@nospamsrfi.schemers.org. To = subscribe to the list, follow these instructions. You can access previous messages= via the mailing list a= rchive.

          ++ +=20 +-

          Abstract

          ++

          Abstract

          +=20=20=20=20=20 +

          + Unlike the values/call-with-values mechanism of +@@ -66,7 +76,7 @@ multiple values. In addition, they have several new bin= ding forms for + useful functions such as escape, recursion, etc. +

          +=20 +-

          Rationale

          ++

          Rationale

          +=20 +

          + It is impossible to bind the evaluated result of values +@@ -79,7 +89,8 @@ consumer procedure of call-with-values. Th= e following are examples + show the differences. +

          +=20 +-
          (define v (values 1 2 3))		=3D> error
          ++
          ++(define v (values 1 2 3))		=3D> error
          + (define v (lambda () (values 1 2 3)))	=3D> (lambda () (values 1 2 3))
          + (define m (mu 1 2 3))			=3D> (lambda (f) (f 1 2 3))
          + (define a (apply values 1 '(2 3)))	=3D> error
          +@@ -107,21 +118,24 @@ best explained by simple examples.
          +=20
          + 

          In SRFI 11:

          +=20 +-
          (let-values ((a (values 1 2)) ((b c) (values 3 4)))
          ++
          ++(let-values ((a (values 1 2)) ((b c) (values 3 4)))
          + 	    (list a b c))
          + =3D> ((1 2) 3 4)
          + 
          +=20 +

          In SRFI 71:

          +=20 +-
          (srfi-let (((values . a) (values 1 2)) ((values b c) (values 3 4)))
          ++
          ++(srfi-let (((values . a) (values 1 2)) ((values b c) (values 3 4)))
          + 	  (list a b c))
          + =3D> ((1 2) 3 4)
          + 
          +=20 +

          In this SRFI:

          +=20 +-
          (alet (a (mu 1 2) ((b c) (mu 3 4)))
          ++
          ++(alet (a (mu 1 2) ((b c) (mu 3 4)))
          +   (list a b c))
          + =3D> ((1 2) 3 4)
          + 
          +@@ -134,7 +148,8 @@ sequence from left to right unlike let of= R5RS and +=20 +

          In SRFI 71:

          +=20 +-
          (srfi-let ((a (begin (display "1st") 1))
          ++
          ++(srfi-let ((a (begin (display "1st") 1))
          + 	   (b c (values (begin (display "2nd") 2) 3))
          + 	   (d (begin (display "3rd") 4))
          + 	   ((values e . f) (values (begin (display "4th") 5) 6)))
          +@@ -144,7 +159,8 @@ sequence from left to right unlike let of=
           R5RS and
          +=20
          + 

          In this SRFI:

          +=20 +-
          (alet ((a (begin (display "1st") 1))
          ++
          ++(alet ((a (begin (display "1st") 1))
          +        (b c (mu (begin (display "2nd") 2) 3))
          +        (d (begin (display "3rd") 4))
          +        ((e . f) (mu (begin (display "4th") 5) 6)))
          +@@ -157,7 +173,8 @@ sequence from left to right unlike let of=
           R5RS and
          +    syntactically possible, as well as a single expression that produce
          +    multiple values.

          +=20 +-
          (alet* (((a b) (mu 1 2))
          ++
          ++(alet* (((a b) (mu 1 2))
          + 	((c d e) a (+ a b c) (+ a b c d))
          + 	((f . g) (mu 5 6 7))
          + 	((h i j . k) e 9 10 h i j))
          +@@ -172,14 +189,16 @@ allowed to take multiple values bindings.

          +=20 +

          In SRFI 71:

          +=20 +-
          (srfi-let tag ((a 1) (b 2) (c 3) (d 4) (e 5))
          ++
          ++(srfi-let tag ((a 1) (b 2) (c 3) (d 4) (e 5))
          + 	  (if (< a 10) (tag 10 b c d e) (list a b c d e)))
          + =3D> (10 2 3 4 5)
          + 
          +=20 +

          In this SRFI:

          +=20 +-
          (alet* tag ((a 1) (a b b c (mu (+ a 2) 4 5 6)) ((d e e) b 5 (+ a b c=
          )))
          ++
          ++(alet* tag ((a 1) (a b b c (mu (+ a 2) 4 5 6)) ((d e e) b 5 (+ a b c)))
          +        (if (< a 10) (tag a 10 b c c d e d) (list a b c d e)))
          + =3D> (10 6 6 5 5)
          + 
          +@@ -189,7 +208,8 @@ allowed to take multiple values bindings.

          + named-alet. It is also allowed to take multiple values + bindings.

          +=20 +-
          (alet* ((a 1)
          ++
          ++(alet* ((a 1)
          + 	((b 2) (b c c (mu 3 4 5)) ((d e d (mu a b c)) . intag) . tag)
          + 	(f 6))
          +   (if (< d 10)
          +@@ -203,7 +223,8 @@ bindings.

          +=20 +
        • They have a new binding form that has an escape function.

          +=20 +-
          (alet ((exit)
          ++
          ++(alet ((exit)
          +        (a (begin (display "1st") 1))
          +        (b c (mu (begin (display "2nd") 2) (begin (display "3rd") 3))))
          +   (display (list a b c))
          +@@ -217,7 +238,8 @@ bindings.

          + integrated into the alet and alet* with a + syntactic keyword and.

          +=20 +-
          (alet ((and (a (begin (display "1st") 1))
          ++
          ++(alet ((and (a (begin (display "1st") 1))
          + 	    (b (begin (display "2nd") 2))
          + 	    (c (begin (display "false") #f))
          + 	    (d (begin (display "3nd") 3))))
          +@@ -238,7 +260,8 @@ integrated into the alet and alet*<=
          /code> with a
          +    syntactic keywords opt and cat in the
          +    similar way to let-optionals in Scsh.

          +=20 +-
          ((lambda (str . rest)
          ++
          ++((lambda (str . rest)
          +    (alet* ((len (string-length str))
          + 	   (opt rest
          + 		(start 0 (integer? start)
          +@@ -277,8 +300,9 @@ integrated into the alet and alet*<=
          /code> with a
          + 	  are integrated into the alet and
          + 	  alet* with a syntactic keyword key.
          + 	  They use any Scheme objects as keywords.
          +-
          +-

          (define rest-list '(a 10 cc 30 40 b 20))
          ++

          ++
          ++(define rest-list '(a 10 cc 30 40 b 20))
          + (alet ((key rest-list (a 1) (b 2) ((c 'cc) 3) . d)) (list a b c d))
          + =3D> (10 2 30 (40 b 20))
          +=20
          +@@ -318,7 +342,8 @@ integrated into the alet and alet*<=
          /code> with a
          + into the alet and alet* with a
          +     syntactic keyword rec.

          +=20 +-
          (alet* ((a 1)
          ++
          ++(alet* ((a 1)
          + 	(rec (a 2) (b 3) (b (lambda () c)) (c a))
          + 	(d 50))
          +   (list a (b) c d))
          +@@ -330,7 +355,8 @@ into the alet and alet* with=
           a
          + and values to handle multiple values with a syntactic
          + keyword values like SRFI 71.

          +=20 +-
          (alet ((a b (mu 1 2))
          ++
          ++(alet ((a b (mu 1 2))
          +        (values c d (values 3 4))	;This is different from SRFI 71.
          +        ((e f) (mu 5 6))
          +        ((values g h) (values 7 8))
          +@@ -347,7 +373,8 @@ keyword values like S=
          RFI 71.

          + environment in alet and as an intervening internal + environment in alet*.

          +=20 +-
          (alet ((a 1)
          ++
          ++(alet ((a 1)
          +        (() (define a 10) (define b 100))
          +        (b a))
          +   (list a b))
          +@@ -362,9 +389,10 @@ keyword values like =
          SRFI 71.

          +
        • + +=20 +-

          Specification

          ++

          Specification

          +=20 +-
          (mu <expr> ...)			=3D> (lambda (f) (f <expr> ...))
          ++
          ++(mu <expr> ...)			=3D> (lambda (f) (f <expr> ...))
          + (nu <expr> ... <exprn>)		=3D> (lambda (f) (apply f <exp=
          r> ... <exprn>))
          + 
          +=20 +@@ -381,7 +409,8 @@ argument procedure of mu is called with t= he <expr>s, + and that of nu is applied to APPLY procedure with the + <expr>s.

          +=20 +-
          (alet  (<binding spec> ...) body ...)
          ++
          ++(alet  (<binding spec> ...) body ...)
          + (alet* (<binding spec> ...) body ...)
          + 
          +=20 +@@ -406,17 +435,20 @@ and that of nu is applied to APPLY proc= edure with the +
        • (<binding spec1> <binding spec2> ... . <var>)<=
          /pre>
        • +
        • (() . <var>)
        • +
        • (and (<var1> <expr1> [<test1>]) (<var2> =
          <expr2> [<test2>]) ...)
        • +-
        • (opt <rest list>
          ++
        • ++(opt <rest list>
          +     (<var1> <default1> [<test1> [<true substitute1&g=
          t; [<false substitute1>]]])
          +     ...
          +     (<varn> <defaultn> [<testn> [<true substituten&g=
          t; [<false substituten>]]])
          +     . [<rest var>])
        • +-
        • (cat <rest list>
          ++
        • ++(cat <rest list>
          +      (<var1> <default1> [<test1> [<true substitute1&=
          gt; [<false substitute1>]]])
          +      ...
          +      (<varn> <defaultn> [<testn> [<true substituten&=
          gt; [<false substituten>]]])
          +      . [<rest var>])
        • +-
        • (key <rest list>
          ++
        • ++(key <rest list>
          +  (<var spec1> <default1> [<test1> [<true substitute1=
          > [<false substitute1>]]])
          +  ...
          +  (<var specn> <defaultn> [<testn> [<true substituten=
          > [<false substituten>]]])
          +@@ -527,7 +559,8 @@ instead of signaling an error.  If it returns a true v=
          alue and there is a
          + substitute>.
          +       
        • +=20 +-
        • (cat <rest list>
          ++
        • ++(cat <rest list>
          +      (<var1> <default1> [<test1> [<true substitute1&=
          gt; [<false substitute1>]]])
          +      ...
          +      (<varn> <defaultn> [<testn> [<true substituten&=
          gt; [<false substituten>]]])
          +@@ -549,7 +582,8 @@ and <test> returns a true value, <var> is =
          finally bound to
          + the result of evaluating <true substitute>.
          +       
        • +=20 +-
        • (key <rest list>
          ++
        • ++(key <rest list>
          +  (<var spec1> <default1> [<test1> [<true substitute1=
          > [<false substitute1>]]])
          +  ...
          +  (<var specn> <defaultn> [<testn> [<true substituten=
          > [<false substituten>]]])
          +@@ -642,7 +676,8 @@ This works as an intervening external environment in
          +       
        • + +=20 +-
          (alet  name (<binding spec> ...) body ...)
          ++
          ++(alet  name (<binding spec> ...) body ...)
          + (alet* name (<binding spec> ...) body ...)
          + 
          +=20 +@@ -651,9 +686,10 @@ These are the same as the named-let (R5R= S, 4.2.4) except + binding specification. These allow all sorts of bindings in <binding + spec>.

          +=20 +-

          Examples

          ++

          Examples

          +=20 +-
          (alet ((a (begin (display "1st") 1))
          ++
          ++(alet ((a (begin (display "1st") 1))
          +        ((b c) 2 (begin (display "2nd") 3))
          +        (() (define m #f) (define n (list 8)))
          +        ((d (begin (display "3rd") 4))
          +@@ -749,14 +785,15 @@ spec>.

          + "cdefghi" +
          +=20 +-

          Implementation

          ++

          Implementation

          +=20 +

          + The following implementation is written in R5RS hygienic macros and + requires SRFI 23 (Error reporting mechanism). +

          +=20 +-
          ;;; mu & nu
          ++
          ++;;; mu & nu
          + (define-syntax mu
          +   (syntax-rules ()
          +     ((mu argument ...)
          +@@ -1888,7 +1925,7 @@ requires SRFI 23 (Error reporting mechanism).
          +      (let ((e z)) bd ...))))
          + 
          +=20 +-

          References

          ++

          References

          +=20 +
            +
          • [R5RS] Richard Kelsey, William Clinger, and Jona= than Rees: Revised(5) +@@ -1896,20 +1933,21 @@ requires SRFI 23 (Error reporting mechanism). + Link +
          • [SRFI 2] Oleg Kiselyov: and-let*: = and and with local bindings, a guarded + let* special form. +- Link
          • ++ Link +
          • [SRFI 11] Lars T. Hansen: Syntax for receiving= multiple values. +- Link
          • ++ Link +
          • [SRFI 51] Joo ChurlSoo: Handling rest list. +- Link
          • ++ Link +
          • [SRFI 71] Sebastian Egner: Extended let<= /code>-syntax for multiple values. +- Link
          • ++ Link +
          • [Scsh] Olin Shivers, Brian Carlstrom, Martin Gas= bichler, Mike Sperber +- Link
          • ++ Link +
          +=20=09=20=20=20=20 +-

          Copyright

          +- ++

          Copyright

          ++

          + Copyright (c) 2006 Joo ChurlSoo. ++

          +

          + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), +@@ -1917,10 +1955,12 @@ to deal in the Software without restriction, inclu= ding without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: +-

          ++

          ++

          + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. +-

          ++

          ++

          + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +@@ -1928,10 +1968,8 @@ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY = CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +- +-


          ++

          ++
          +
          Editor: Mike + Sperber
          +- +- + +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-87.html b/srfi-doc/sr= fi/scribblings/srfi-std/srfi-87.html +index 73986bb..7920a28 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-87.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-87.html +@@ -1,44 +1,63 @@ +- +-SRFI 87: =3D> in case clauses ++ ++ ++ ++ ++ ++ SRFI 87: =3D> in case clauses ++ ++ ++ ++ +=20 +-

          Title

          ++ +=20 +-=3D> in case clauses ++

          SRFI 87: =3D> in case clauses

          +=20 +-

          Author

          ++

          by Chongkai Zhu

          ++

          This copy of the SRFI 87 specific= ation document ++is distributed as part of the Racket package ++srfi-doc.

          = The canonical source of this document is ++https://srfi.s= chemers.org/srfi-87/srfi-87.html.

          +=20 +-Chongkai Zhu ++

          Status

          +=20 +-

          Status

          +- +-This SRFI is currently in ``final'' status. To see an explanation of each +-status that a SRFI can hold, see +-here. +-To provide input on this SRFI, please +-mailto:srfi-87@srfi.schemers= .org. +-See instruc= tions +-here to subscribe to the list. You can access the discussion via +-t= he +-archive of the mailing list. +-You can access +-post-finalization messages via +- +-the archive of the mailing list. +-

          +-

            +-
          • Received: 2006/04/10
          • +-
          • Revised: 2006/05/08
          • +-
          • Draft: 2006/04/10 - 2006/06/08
          • +-
          • Final: 2006/10/18
          • ++

            This SRFI is currently in final status. Here is an explanation of each stat= us that a SRFI can hold. To provide input on this SRFI, please send email = to srfi-= 87@nospamsrfi.schemers.org. To = subscribe to the list, follow these instructions. You can access previous messages= via the mailing list a= rchive.

            ++ +=20 +-

            Abstract

            This SRFI proposes an extension to the case= syntax=20 ++

            Abstract

            ++

            ++This SRFI proposes an extension to the case syntax + to allow the =3D> clauses as in cond. +-

            Rationale

            case is introduced as a syntax sugar based= on=20 ++

            ++ ++

            Rationale

            ++

            ++case is introduced as a syntax sugar based on + cond, which helps to save a explicit calling to let.=20 + But without the =3D> clause, if the result e= xpression=20 + needs the value of key, the let can't be saved.= For an=20 + easy example, suppose we want the following: ++

            +
            (case (get-symbol)
            +   ((true) #t)
            +   ((false) #f)
            +@@ -49,14 +68,15 @@ write:

            + (cond ((eq? key 'true) #t) + ((eq? key 'false) #f) + (else key)))
            +-

            Specification

            ++ ++

            Specification

            +

            (Based on R5RS section 4.2.1 Conditionals)

            +
            +-
            library syntax: case <key&= gt; <clause1>=20 +- <clause2> ...=20 ++
            library syntax: case <key> <c= lause1> ++ <clause2> ... +
            Syntax: <Key> may be any expression. Each <c= lause>=20 + should have the form
            ((<datum1> ...) <expression1>=
             <expression2> ...),
            +-

            where each <datum> is an external representation of some objec= t. All=20 ++

            where each <datum> is an external representation of = some object. All=20 + the <datum>s must be distinct. The last <clause> may be an = "else=20 + clause," which has the form

            (else <expression1> <=
            expression2> ...).
            +

            Alternatively, a <clause> may be of th= e form=20 +@@ -66,7 +86,7 @@ write:

            +

            Semantics: A `case' expression is evaluated as= =20 + follows. <Key> is evaluated and its result is compared against ea= ch=20 + <datum>. If the result of evaluating <key> is equivalent (i= n the=20 +- sense of `eqv?'; see section see section 6.1 Equivalence=20 ++ sense of `eqv?'; see section see section 6.1 Equivalence=20 + predicates) to a <datum>, then the expressions in the corresp= onding=20 + <clause> are evaluated from left to right and the result(s) of th= e last=20 + expression in the <clause> is(are) returned as the result(s) of t= he=20 +@@ -79,13 +99,14 @@ write:

            + <expression> is evaluated. Its value must be a procedure that acc= epts=20 + one argument; this procedure is then called on the value of <Key>= and=20 + the value(s) returned by this procedure is(are) returned by the=20 +- `case' expression.

            ++ `case' expression.

            +

            (Based on R5RS section 3.5 Proper tail recursion)

            +-
            If a cond or case ex= pression is in a tail context, and has a clause of the=20 ++

            If a cond or case exp= ression is in a tail context, and has a clause of the=20 + form (<expression1> =3D> <expression2>) then the=20 + (implied) call to the procedure that results from the evaluation of <e= xpression2>=20 +-is in a tail context. <expression2> itself is not in a t= ail context.

            +-

            Implementation

            ++is in a tail context. <expression2> itself is not in a t= ail context.

            ++ ++

            Implementation

            +
            (define-syntax case
            +   (syntax-rules (else =3D>)
            +     ((case (key ...)
            +@@ -118,24 +139,31 @@ is in a tail context. <expression2>=
             itself is not in a tail con
            +      (if (memv key '(atoms ...))
            +          (begin result1 result2 ...)
            +          (case key clause clauses ...)))))
            +-

            Copyright

            Copyright (C) 2006 Chongkai Zhu. All Rights Reserved.=20 ++

            Copyright

            ++

            ++Copyright (C) 2006 Chongkai Zhu. All Rights Reserved. ++

            +

            Permission is hereby granted, free of charge, to any person obtaining = a copy=20 + of this software and associated documentation files (the "Software"), to = deal in=20 + the Software without restriction, including without limitation the rights= to=20 + use, copy, modify, merge, publish, distribute, sublicense, and/or sell co= pies of=20 + the Software, and to permit persons to whom the Software is furnished to = do so,=20 + subject to the following conditions:=20 +-

            The above copyright notice and this permission notice shall be inc= luded in=20 ++

            ++

            ++The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software.=20 +-

            THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EX= PRESS OR=20 ++

            ++

            ++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, = FITNESS=20 + FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHO= RS OR=20 + COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WH= ETHER=20 + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN=20 + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE= .=20 +-


            ++

            ++
            +=20 +-
            Editor: Mike=20 ++
            Editor: Mike=20 + Sperber
            Last=20 +-modified: Mon Apr 10 21:20:25 CEST 2006 +- ++modified: Mon Apr 10 21:20:25 CEST 2006 +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-9.html b/srfi-doc/srf= i/scribblings/srfi-std/srfi-9.html +index 0bf112a..4a64ddb 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-9.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-9.html +@@ -1,63 +1,90 @@ +- +- ++ ++ + ++ ++ + SRFI 9: Defining Record Types ++ ++ ++ + +=20 + +=20 +-

            Title

            ++

            SRFI 9: Defining Record Types

            +=20 +-SRFI 9: Defining Record Types ++

            by Richard Kelsey

            ++

            This copy of the SRFI 9 specifica= tion document ++is distributed as part of the Racket package ++srfi-doc.

            = The canonical source of this document is ++https://srfi.sch= emers.org/srfi-9/srfi-9.html.

            +=20 +-

            Author

            ++

            Status

            +=20 +-Richard Kelsey +- +-

            Status

            +- +-This SRFI is currently in ``final'' status. To see an explanation of eac= h status that a SRFI can hold, see here. +-You can access the discussion via the archive of the mailing list. +-

              +-
            • Received: 1999/07/01 +-
            • Revised: 1999/08/25 +-
            • Draft: 1999/07/07-1999/09/06 +-
            • Final: 1999/09/09 +-
            +- +-

            Abstract

            ++

            This SRFI is currently in final status. Here is an explanation of each stat= us that a SRFI can hold. To provide input on this SRFI, please send email = to srfi-9= @nospamsrfi.schemers.org. To su= bscribe to the list, follow these instructions. You can access previous messages v= ia the mailing list arch= ive.

            ++
              ++
            • Received: 1999-07-01
            • ++
            • Revised: 1999-08-25
            • ++
            • Draft: 1999-07-07--1999-09-06
            • ++
            • Final: 1999-09-09
            • ++
            +=20 ++

            Abstract

            ++

            + This SRFI describes syntax for creating new data types, called record typ= es. + A predicate, constructor, and field accessors and modifiers are defined f= or + each record type. Each new record type is distinct from all existing typ= es, + including other record types and Scheme's predefined types. ++

            +=20 +-

            Rationale

            +- ++

            Rationale

            ++

            + Many Scheme implementations provide means for creating new types, + usually called either records or structures. + The DEFINE-RECORD-TYPE syntax described here is a slight +- simplification of one written for Scheme 48 by Jonathan Rees. ++ simplification of one written for Scheme 48 by Jonathan Rees. + Unlike many record-defining macros or special forms, it + does not create any new identifiers. + Instead, the names of the + record type, predicate, constructor, and so on are all listed explicitly + in the source. + This has the following advantages: +-

              +-
            • It can be defined using a simple SYNTAX-RULES macro ++

              ++
                ++
              • ++ It can be defined using a simple SYNTAX-RULES macro + in Scheme implementations that provide a procedural interface + for creating record types. +-
              • It does not restrict users to a particular naming convention. +-
              • Tools like grep and GNU Emacs's tag facility will see t= he ++
              • ++
              • ++ It does not restrict users to a particular naming convention. ++
              • ++
              • ++ Tools like grep and GNU Emacs's tag facility will see the + defining occurrence of each identifier. +-
              +- +-

              Specification

              ++
            • ++
            +=20 ++

            Specification

            ++

            + The syntax of a record-type definition is: +- +-

            ++

            ++
            +  <command or definition>=20=20=20=20=20=20=20=20=20=20=20
            +    -> <record type definition>           ; addition to 8.1.6 in =
            R5RS
            +=20
            +@@ -72,70 +99,80 @@ The syntax of a record-type definition is:
            +=20
            +  <field tag> -> <identifier>
            +  <... name>  -> <identifier>
            +-
            =20 +- ++
            ++

            + DEFINE-RECORD-TYPE is generative:=20 + each use creates a new record type that is distinct from all existing typ= es, + including other record types and Scheme's predefined types. +- ++

            ++

            + Record-type definitions may only occur at top-level (there are two + possible semantics for `internal' record-type definitions, generative + and nongenerative, and no consensus as to which is better). +- +-

            ++

            ++

            + An instance of DEFINE-RECORD-TYPE is equivalent to the follo= wing + definitions: +-

              +-
            • <type name> is bound to a representation of the r= ecord ++

              ++
                ++
              • ++ <type name> is bound to a representation of the re= cord + type itself. Operations on record types, such as defining print + methods, reflection, etc. are left to other SRFIs. +- +-
              • <constructor name> is bound to a procedure that t= akes ++
              • ++
              • ++ <constructor name> is bound to a procedure that ta= kes + as many arguments as there are <field tag>s in the + (<constructor name> ...) + subform and returns a new <type name> record. + Fields whose tags are listed with <constructor name> + have the corresponding argument as their + initial value. The initial values of all other fields are unspecifie= d. +- +-
              • <predicate name> is a predicate that returns #T w= hen ++
              • ++
              • ++ <predicate name> is a predicate that returns #T wh= en + given a value returned by <constructor name> and #F + for everything else. +- +-
              • Each <accessor name> is a procedure that takes a = record ++
              • ++
              • ++ Each <accessor name> is a procedure that takes a r= ecord + of type <type name> and returns the current value = of the + corresponding field. + It is an error to pass an accessor a value which is not a record of + the appropriate type. +-=20=20=20=20 +-
              • Each <modifier name> is a procedure that takes a = record ++
              • ++
              • ++ Each <modifier name> is a procedure that takes a r= ecord + of type <type name> and a value which becomes the = new + value of the corresponding field; an unspecified value is returned. + It is an error to pass a modifier a first + argument which is not a record of the appropriate type. +-
              ++
            • ++
            +=20 +-

            ++

            + Records are disjoint from the types listed in Section 4.2 of R5RS. +- +-

            ++

            ++

            + Set!ing the value of any of these identifiers has no + effect on the behavior of any of their original values. +- +-

            ++

            ++

            + The following +-

            ++

            =20=20 ++
            +   (define-record-type :pare
            +     (kons x y)
            +     pare?
            +     (x kar set-kar!)
            +     (y kdr))
            +-
            ++
            ++

            + defines KONS to be a constructor, KAR and + KDR to be accessors, SET-KAR! to be a modifier, + and PARE? to be a predicate for :PAREs. +- +-

            ++

            ++
            +   (pare? (kons 1 2))        --> #t
            +   (pare? (cons 1 2))        --> #f
            +   (kar (kons 1 2))          --> 1
            +@@ -143,27 +180,33 @@ and PARE? to be a predicate for :=
            PAREs.
            +   (let ((k (kons 1 2)))
            +     (set-kar! k 3)
            +     (kar k))                --> 3
            +-
            +- +-

            Implementation

            ++
            +=20 ++

            Implementation

            ++

            + This code is divided into three layers. In top-down order these are: +-

              +-
            1. Syntax definitions for DEFINE-RECORD-TYPE and an auxili= ary +- macro. +-
            2. An implementation of record types with a procedural interface. ++

              ++
                ++
              1. ++Syntax definitions for DEFINE-RECORD-TYPE and an auxillary m= acro. ++
              2. ++
              3. ++An implementation of record types with a procedural interface. + Some Scheme implementations already have something close to this. +-
              4. Vector-like records implemented in R5RS. This redefines some standa= rd ++
              5. ++
              6. ++Vector-like records implemented in R5RS. This redefines some standard + Scheme procedures and therefor must be loaded before any other code, incl= uding + part 2 above. Note that these procedures can be used to break the + record-type abstraction (for example, RECORD-SET! can be used + to modify the type of a record). Access to these procedures should be + restricted. +-
              ++
            3. ++
            +=20 +-

            Syntax definitions

            ++

            Syntax definitions

            +=20 +-
            ++
            + ; Definition of DEFINE-RECORD-TYPE
            +=20
            + (define-syntax define-record-type
            +@@ -193,23 +236,23 @@ restricted.
            +      (begin
            +        (define accessor (record-accessor type 'field-tag))
            +        (define modifier (record-modifier type 'field-tag))))))
            +-
            ++
            +=20 +-

            Record types

            ++

            Record types

            +=20 +-
            ++
            + ; We define the following procedures:
            + ;=20
            +-; (make-record-type <type-name <field-names>)    -> <record-t=
            ype>
            +-; (record-constructor <record-type<field-names>) -> <construc=
            tor>
            +-; (record-predicate <record-type>)               -> <predicate&g=
            t;
            +-; (record-accessor <record-type <field-name>)    -> <accessor=
            >
            +-; (record-modifier <record-type <field-name>)    -> <modifier=
            >
            ++; (make-record-type <type-name <field-names>)    -> <recor=
            d-type>
            ++; (record-constructor <record-type<field-names>) -> <const=
            ructor>
            ++; (record-predicate <record-type>)               -> <predicat=
            e>
            ++; (record-accessor <record-type <field-name>)    -> <acces=
            sor>
            ++; (record-modifier <record-type <field-name>)    -> <modif=
            ier>
            + ;   where
            +-; (<constructor> <initial-value> ...)         -> <record&g=
            t;
            +-; (<predicate> <value>)                       -> <boolean&=
            gt;
            +-; (<accessor> <record>)                       -> <value>
            +-; (<modifier> <record> <value>)         -> <unspecif=
            ic>
            ++; (<constructor> <initial-value> ...)         -> <recor=
            d>
            ++; (<predicate> <value>)                       -> <boole=
            an>
            ++; (<accessor> <record>)                       -> <value=
            >
            ++; (<modifier> <record> <value>)         -> <unspe=
            cific>
            +=20
            + ; Record types are implemented using vector-like records.  The first
            + ; slot of each record contains the record's type, which is itself a
            +@@ -308,19 +351,19 @@ restricted.
            +                     type))
            +           (record-set! thing index value)
            +           (error "modifier applied to bad value" type tag thing)))))
            +-
            ++
            +=20 +-

            Records

            ++

            Records

            +=20 +-
            ++
            + ; This implements a record abstraction that is identical to vectors,
            + ; except that they are not vectors (VECTOR? returns false when given a
            + ; record and RECORD? returns false when given a vector).  The following
            + ; procedures are provided:
            +-;   (record? <value>)                -> <boolean>
            +-;   (make-record <size>)             -> <record>
            +-;   (record-ref <record> <index>)    -> <value>
            +-;   (record-set! <record> <index> <value>) -> <unspe=
            cific>
            ++;   (record? <value>)                -> <boolean>
            ++;   (make-record <size>)             -> <record>
            ++;   (record-ref <record> <index>)    -> <value>
            ++;   (record-set! <record> <index> <value>) -> <un=
            specific>
            + ;
            + ; These can implemented in R5RS Scheme as vectors with a distinguishing
            + ; value at index zero, providing VECTOR? is redefined to be a procedure
            +@@ -366,9 +409,9 @@ restricted.
            +=20
            + (define (record-set! record index value)
            +   (vector-set! record (+ index 1) value))
            +-
            ++
            +=20 +-

            Copyright

            ++

            Copyright

            +=20 +

            Copyright (C) Richard Kelsey (1999). All Rights Reserved.

            +=20 +@@ -395,9 +438,9 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF O= R IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +

            +=20 +-
            ++
            +=20 +-
            Editor: Mi= ke Sperber
            ++
            Editor: Mike Sperber
            +=20 + + +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-98.html b/srfi-doc/sr= fi/scribblings/srfi-std/srfi-98.html +index 8ff8dfb..f5edd0e 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-98.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-98.html +@@ -1,57 +1,63 @@ +- +- +-= +- +- +-=20=20 ++ ++ ++ ++ ++ + SRFI 98: An interface to access environment variables. +- +- +-

            Title

            +- +-An interface to access environment variables. +- +-

            Author

            +- +-Taro Minowa(Higepon) +- +-

            Status

            +- +-This SRFI is currently in ``final'' status. To see an explanation of +-each status that a SRFI can hold, see here. +- +-To provide input on this SRFI, please send email to +- +-<srfi minus 98 at srfi dot schemers dot org>. See= =20 +-instruction= s here to subscribe to +-the list. You can access the discusssion via=20 +-t= he archive of the mailing list. +-You can access +-post-finalization messages via +- +-the archive of the mailing list. +-

              +- +-
            • Received: 2008/07/06
            • +-
            • Draft: 2008/07/06 - 2008/09/06
            • +-
            • Revised: 2008/07/18
            • +-
            • Revised: 2008/07/18
            • +-
            • Revised: 2008/08/14
            • +-
            • Final: 2008/09/19
            • +-
            • R6RS library name: 2009/02/16
            • ++ ++ ++ ++ ++ ++ ++ ++

              SRFI 98: An interface to access environment variables.

              ++ ++

              by Taro Minowa (Higepon)

              ++

              This copy of the SRFI 98 specific= ation document ++is distributed as part of the Racket package ++srfi-doc.

              = The canonical source of this document is ++https://srfi.s= chemers.org/srfi-98/srfi-98.html.

              ++ ++

              Status

              ++ ++

              This SRFI is currently in final status. Here is an explanation of each stat= us that a SRFI can hold. To provide input on this SRFI, please send email = to srfi-= 98@nospamsrfi.schemers.org. To = subscribe to the list, follow these instructions. You can access previous messages= via the mailing list a= rchive.

              ++ +=20 +-

              Abstract

              ++

              Abstract

              + This SRFI specifies the procedure get-environment-variable, which gets + the value of the specified environment variable, and the procedure + get-environment-variables, which gets an association list of all + environment variables. +=20 +-

              Rationale

              ++

              Rationale

              +

              Most operating systems provide a mechanism for passing auxiliary + parameters implicitly to child processes. Usually, this mechanism is + called "the environment", and is conceptually a map from string names +-to string values. The string names are called environment ++to string values. The string names are called enviornment + variables.

              +=20 +

              Some applications rely on environment variables to modify their +@@ -60,9 +66,8 @@ protocols rely on environment variables as a form of int= erprocess + communication. For example, most implementations of the common + gateway interface (CGI) use environment variables to pass + Meta-Variables from the server to the script [1]. +-Environment variables are also required +-by SRFI 96: SLIB Prerequisites. ++Environment variables are also required by ++SRFI 96: SLIB Prerequisites. + Providing a means to access environment variables is therefore + indispensable for writing practical programs in Scheme. +

              +@@ -83,10 +88,10 @@ Meta-Variables "QUERY_STRING", "CONTENT_LENGTH" and +
          +=20 +

          [1] The Common Gateway Interface (CGI) Version= 1.1, RFC3875, http://www.ietf.org/rfc/rfc3875.

          +-

          Specification

          ++

          Specification

          +
          R6RS library name
          + The following two procedures belong to the R6RS library named (srfi :98 o= s-environment-variables). +-
          Function: get-environment-varia=
          ble name
          Returns the value of ++
          Function: get-environment-variable n=
          ame
          Returns the value of + the named environment variable as a string, or #f if the named + environment variable is not found. The name argument is expected to be + a string. +@@ -96,19 +101,21 @@ the environment variable. + If get-environment-variable can't decode the value, get-environment-varia= ble may raise an exception. +
          (get-environment-variable "PATH") =3D> "/usr/local/sbin:/usr/loca=
          l/bin:/usr/sbin:/usr/bin"
          + 
          +-
          Function: get-environment-vari=
          ables
          ++
          Function: get-environment-variables=
          
          + Returns names and values of all the environment variables as an a-list. + The same decoding considerations as for get-environment-variable apply. +
          (get-environment-variables) =3D> (("PATH" . "/usr/local/sbin:/usr=
          /local/bin:/usr/sbin:/usr/bin") ("USERNAME" . "taro"))
          + 
          +=20 +-

          Implementation

          +-

          Gauche

          +-
          (define get-environment-variable sys-getenv)
          ++

          Implementation

          ++

          Gauche

          ++
          ++(define get-environment-variable sys-getenv)
          + (define get-environment-variables sys-environ->alist)
          + 
          +-

          Scheme48

          +-
          (define (get-environment-variable name)
          ++

          Scheme48

          ++
          ++(define (get-environment-variable name)
          +   (cond
          +     ((lookup-environment-variable name) =3D> os-string->string)
          +     (else #f)))
          +@@ -117,17 +124,19 @@ The same decoding considerations as for get-environm=
          ent-variable apply.
          +         (cons (os-string->string (car p)) (os-string->string (cdr p=
          ))))
          +        (environment-alist)))
          + 
          +-

          scsh

          +-
          (define get-environment-variable getenv)
          ++

          scsh

          ++
          ++(define get-environment-variable getenv)
          + (define get-environment-variables env->alist)
          + 
          +=20 +-

          SCM

          +-
          (define get-environment-variable getenv)
          ++

          SCM

          ++
          ++(define get-environment-variable getenv)
          + (define get-environment-variables getenv)
          + 
          +=20 +-

          Issues

          ++

          Issues

          +

          get-environment-variable is expected to return a "Scheme string". + Unfortunately, many current platforms, including POSIX-like ones, do + not require environment variables to be interpretable as sequences of +@@ -143,7 +152,7 @@ implementations, and captures the semantically desirab= le behavior in + the common case that the byte sequence is interpretable as a string.

          +=20 + +-

          Appendix: Existing implementations

          ++

          Appendix: Existing implementations

          + + + +@@ -161,10 +170,10 @@ the common case that the byte sequence is interpreta= ble as a string.

          + + +
          Scheme implementationget environment variableget all the environment variables as an a-list
          Bigloo(getenv name) =3D> (or string? false) name:st= ring? 
          STklos(getenv name) =3D> (or string? false) name:st= ring?(getenv)
          SCM(getenv name) =3D> (or string? false) name:strin= g?(getenv)
          +-

          Acknowledgements

          ++

          Acknowledgements

          + Thanks to Shiro Kawai, Alexey Radul, jmuk, Kokosabu, leque and all the me= mbers of the #Lisp_Scheme IRC channel on Freenode. +-

          Copyright

          +-Copyright (C) Taro Minowa(Higepon) (2008). All Rights Reserved. ++

          Copyright

          ++Copyright (C) Taro Minowa (Higepon) (2008). All Rights Reserved. +

          + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the +@@ -185,7 +194,7 @@ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTIO= N OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +

          +-
          ++
          +
          Editor: Mike Sperber
          + + +diff --git a/srfi-doc/srfi/scribblings/srfi.scrbl b/srfi-doc/srfi/scribbli= ngs/srfi.scrbl +index 4ab1397..3b1807d 100644 +--- a/srfi-doc/srfi/scribblings/srfi.scrbl ++++ b/srfi-doc/srfi/scribblings/srfi.scrbl +@@ -1,12 +1,23 @@ + #lang scribble/doc +-@(require srfi/scribblings/util ++@(require "util.rkt" + scribble/manual + scribble/eval + scriblib/render-cond + scribble/core + scribble/html-properties + (for-syntax scheme/base) +- (for-label scheme/base ++ (for-label (except-in scheme/base ++ make-date ;; but we DO want `date` ++ date? ++ date-second ++ date-minute ++ date-hour ++ date-day ++ date-month ++ date-year ++ date-week-day ++ date-year-day) ++ srfi/19 + racket/stream)) +=20 + @; ---------------------------------------------------------------------- +@@ -27,7 +38,7 @@ which can be implemented as libraries. To import the bin= dings of SRFI + ] +=20 + This document lists the SRFIs that are supported by Racket and +-provides a link to the original SRFI specification (which is also ++provides links to the original SRFI specifications (which are also + distributed as part of Racket's documentation). +=20 + @table-of-contents[] +@@ -95,7 +106,7 @@ functions. + (concatenate #f "concatenate") + (concatenate! #f "concatenate!") + (reverse #f "reverse") +- (reverse! #f "srfi-1.html") ++ (reverse! #f "reverse!") + (append-reverse #f "append-reverse") + (append-reverse! #f "append-reverse!") + (zip #f "zip") +@@ -114,7 +125,7 @@ functions. + (unfold #f "unfold") + (unfold-right #f "unfold-right") + (map #f "map") +- (for-each #f "srfi-1.html") ++ (for-each #f "for-each") + (append-map #f "append-map") + (append-map! #f "append-map!") + (map! #f "map!") +@@ -153,7 +164,6 @@ functions. + (alist-copy #f "alist-copy") + (alist-delete #f "alist-delete") + (alist-delete! #f "alist-delete!") +- (lset #f "lset") + (lset=3D #f "lset=3D") + (lset-adjoin #f "lset-adjoin") + (lset-union #f "lset-union") +@@ -198,6 +208,11 @@ are also available from @racketmodname[scheme/foreign= ]. +=20 + @; ---------------------------------------- +=20 ++@; special case for historical license reasons ++@include-section["srfi-5-doc-free.scrbl"] ++ ++@; ---------------------------------------- ++ + @srfi[6]{Basic String Ports} +=20 + @redirect[6 '( +@@ -430,7 +445,7 @@ are also available from @racketmodname[scheme/foreign]. + @srfi[17]{Generalized set!} +=20 + @redirect[17 '( +- (set! #t "set!") ++ (set! #t "!set") + (getter-with-setter #f "getter-with-setter") + )] +=20 +@@ -439,13 +454,13 @@ are also available from @racketmodname[scheme/foreig= n]. + @srfi[19]{Time Data Types and Procedures} +=20 + @redirect[19 '( +- (time-duration #f "") ++ (time-duration #f "time-duration") + (time-monotonic #f "time-monotonic") + (time-process #f "time-process") + (time-tai #f "time-tai") + (time-thread #f "time-thread") + (time-utc #f "time-utc") +- (current-date #f "") ++ (current-date #f "current-date") + (current-julian-day #f "current-julian-day") + (current-modified-julian-day #f "current-modified-julian-day") + (current-time #f "current-time") +@@ -526,20 +541,31 @@ to the one provided by @racketmodname[racket/base] i= n most cases + (see @racket[date]). +=20 + For backwards compatibility, when an invalid date field value is +-provided to the SRFI constructor, the constructor will produce a lax +-date structure. A lax date structure is @emph{not} compatible with +-functions from @racketmodname[racket/base] or ++provided to the SRFI constructor, the constructor will produce a ++@deftech{lax date structure}. A lax date structure is @emph{not} ++compatible with functions from @racketmodname[racket/base] or + @racketmodname[racket/date]. SRFI functions such as + @racket[string->date] may return a lax date structure depending on the + format string. ++The predicate @racket[lax-date?] recognizes lax dat structures. ++ ++As an extension, Racket's implementation of @racket[string->date] ++supports @litchar{~?} as a conversion specifier: ++it parses one- and two-digit years like @litchar{~y} ++and three- and four-digit years like @litchar{~Y}. +=20 + @(define srfi-19-eval (make-base-eval)) + @(srfi-19-eval '(require srfi/19)) +=20 ++@examples[#:eval srfi-19-eval ++ (string->date "4-1-99" "~d-~m-~?") ++ (string->date "4-1-1999" "~d-~m-~?") ++] ++ + @defproc[(lax-date? [v any/c]) boolean?]{ +=20 +-Returns @racket[#t] if @racket[_v] is a lax date structure. Otherwise +-returns @racket[#f]. ++Returns @racket[#t] if @racket[_v] is a @tech{lax date structure}. ++Otherwise, returns @racket[#f]. +=20 + @examples[#:eval srfi-19-eval + (lax-date? (make-date 0 19 10 10 14 "bogus" "bogus" 0)) +@@ -688,8 +714,8 @@ This SRFI's syntax is part of Racket's default reader = and printer. +=20 + @redirect[40 '( + (stream-cons #t "stream-cons") +- (stream? #f "stream?") +- (stream-null? #f "stream-null?") ++ (stream? #f "streamp") ++ (stream-null? #f "stream-nullp") + (stream-car #f "stream-car") + (stream-cdr #f "stream-cdr") + (stream-delay #t "stream-delay") +@@ -787,7 +813,7 @@ same as from @racketmodname[racket/stream]. + (:real-range #t ":real-range") + (:char-range #t ":char-range") + (:port #t ":port") +- (:dispatched #t "") ++ (:dispatched #t ":dispatched") + (:generator-proc #t ":generator-proc") + (:do #t ":do") + (:let #t ":let") +@@ -814,7 +840,7 @@ from @racketmodname[scheme/base] and @mz-if from + (vector-append #f "vector-append") + (vector-concatenate #f "vector-concatenate") + (vector? #f "vector-p") +- (vector-empty? #f "vector-empty?") ++ (vector-empty? #f "vector-empty-p") + (vector=3D #f "vector-eq") + (vector-ref #f "vector-ref") + (vector-length #f "vector-length") +@@ -837,10 +863,10 @@ from @racketmodname[scheme/base] and @mz-if from + (vector-reverse! #f "vector-reverse-bang") + (vector-copy! #f "vector-copy-bang") + (vector-reverse-copy! #f "vector-reverse-copy-bang") +- (vector->list #f "vector->list") +- (reverse-vector->list #f "reverse-vector->list") +- (list->vector #f "list->vector") +- (reverse-list->vector #f "reverse-list->vector") ++ (vector->list #f "vector-to-list") ++ (reverse-vector->list #f "reverse-vector-to-list") ++ (list->vector #f "list-to-vector") ++ (reverse-list->vector #f "reverse-list-to-vector") + )] +=20 + @; ---------------------------------------- +diff --git a/srfi-doc/srfi/scribblings/util.rkt b/srfi-doc/srfi/scribbling= s/util.rkt +index d67c82a..786fea9 100644 +--- a/srfi-doc/srfi/scribblings/util.rkt ++++ b/srfi-doc/srfi/scribblings/util.rkt +@@ -59,3 +59,20 @@ +=20 + @(define srfi-std (style #f (list (install-resource "srfi-std")))) +=20 ++@(define srfi-license-history-url ++ ;; explains the "historical reasons" for the restrictive license on SR= FI 5 ++ "https://srfi-email.schemers.org/srfi-announce/msg/2652023/") ++@(define srfi-5-std-taglet "srfi-5-std") ++@(define srfi-5-license-taglet "srfi-5-std-license") ++ ++@(define (racket-license-link . args) ++ ;; FIXME why does this not work? ++ #; ++ (apply seclink "License" #:doc '(lib "scribblings/main/license.scrbl")= args) ++ (define (link base) ++ (apply hyperlink (string-append base "license/index.html") args)) ++ (cond-element ++ [(or latex text) ++ (link "https://docs.racket-lang.org/")] ++ [else ++ (link "../")])) +diff --git a/srfi-lib/info.rkt b/srfi-lib/info.rkt +index da0d08d..56d31b7 100644 +--- a/srfi-lib/info.rkt ++++ b/srfi-lib/info.rkt +@@ -2,6 +2,8 @@ +=20 + (define collection 'multi) +=20 ++(define version "1.1") ++ + (define deps '("scheme-lib" + "base" + "srfi-lite-lib" +diff --git a/srfi-lib/srfi/5/let.rkt b/srfi-lib/srfi/5/let.rkt +index a1a88fb..19be931 100644 +--- a/srfi-lib/srfi/5/let.rkt ++++ b/srfi-lib/srfi/5/let.rkt +@@ -7,51 +7,62 @@ + (define-syntax (s:let stx) + (define-syntax-class loopid + #:description "loop identifier" ++ #:opaque + (pattern :id)) + (define-syntax-class binding-pair + #:description "binding pair" + (pattern [name:id arg:expr])) +- (define-syntax-class rest-binding +- #:description "\"rest\" binding" +- (pattern [rest-name:id rest-arg:expr ...])) +- (define-splicing-syntax-class let-style-bindings +- #:description "let-style bindings" +- #:attributes (loop* [name 1] [arg 1] rest-name [rest-arg 1]) +- ;; in let-style bindings, rest-binding only allowed w/ +- ;; at least one binding-pair +- (pattern (~seq (~optional loop*:loopid) +- (:binding-pair ...)) +- #:with (rest-arg ...) #'() +- #:attr rest-name #f) +- (pattern (~seq (~optional loop*:loopid) +- (:binding-pair ...+ . :rest-binding)))) +- (define-splicing-syntax-class define-style-bindings +- #:description "define-style bindings" +- #:attributes (loop* [name 1] [arg 1] rest-name [rest-arg 1]) +- (pattern (~seq (loop*:loopid :binding-pair ...)) +- #:with (rest-arg ...) #'() +- #:attr rest-name #f) +- (pattern (~seq (loop*:loopid +- :binding-pair ... +- . :rest-binding)))) +- (define-splicing-syntax-class bindings ++ (define-splicing-syntax-class maybe-rest-binding + #:description #f ++ #:no-delimit-cut ++ (pattern (~describe "\"rest\" binding" ++ (~seq (~describe #:opaque "\"rest\" identifier" ++ rest-name:id) ++ ~! ++ (~describe #:opaque "\"rest\" init expressi= on" ++ rest-arg:expr) ++ ...))) ++ (pattern (~seq) ++ #:attr rest-name #f ++ #:with (rest-arg ...) #'())) ++ (define-splicing-syntax-class bindings ++ #:description "bindings" + #:attributes (loop* [name 1] [arg 1] rest-name [rest-arg 1]) +- (pattern :let-style-bindings) +- (pattern :define-style-bindings))=20 ++ (pattern ++ (~describe ++ "\"named let\"-style bindings" ++ (~seq loop*:loopid ++ ~! ++ (~describe ++ "parenthesized sequence of binding pairs with optional \"res= t\" binding" ++ (:binding-pair ... :maybe-rest-binding))))) ++ (pattern ++ (~describe ++ "\"define\"-style bindings" ++ (~seq (loop*:loopid ~! :binding-pair ... :maybe-rest-binding)))) ++ (pattern ++ (~describe ++ "\"let\"-style bindings with no loop identifier" ++ (~seq ++ (~or* (~describe #:opaque "empty sequence of binding pairs" ++ (~and () (:binding-pair ... :maybe-rest-binding))) ++ (~describe ++ "parenthesized sequence of one or more binding pairs with o= ptional \"rest\" binding" ++ (:binding-pair ...+ :maybe-rest-binding))))) ++ #:attr loop* #f)) + (syntax-parse stx +- [(_ () body:expr ...+) +- #'(let () body ...)] + [(_ :bindings +- body:expr ...+) ++ (~describe "body forms" (~seq body:expr ...+))) ++ ;; it is NOT an error for loop* to be shaddowed: ++ ;; see https://srfi-email.schemers.org/srfi-5/msg/18712014/ + #:fail-when (check-duplicate-identifier + (syntax->list #'(name ... (~? rest-name)))) + "duplicate variable name" +- #:with loop (or (attribute loop*) #'tmp-loop) +- #'(letrec ([loop (=CE=BB (~? (name ... . rest-name) +- (name ...)) +- body ...)]) ++ #:with loop (or (attribute loop*) #'anonymous-srfi-5-let) ++ #`(letrec ([loop #,(syntax-property ++ (syntax/loc stx ++ (=CE=BB (~? (name ... . rest-name) ++ (name ...)) ++ body ...)) ++ 'inferred-name (or (attribute loop*) (void)))]) + (loop arg ... rest-arg ...))])) +- +- +- +diff --git a/srfi-test/tests/srfi/5/srfi-5-test.rkt b/srfi-test/tests/srfi= /5/srfi-5-test.rkt +index 47bb660..9b3ab73 100644 +--- a/srfi-test/tests/srfi/5/srfi-5-test.rkt ++++ b/srfi-test/tests/srfi/5/srfi-5-test.rkt +@@ -27,16 +27,24 @@ + (cons x y)) + '(1 2) + "rest binding w/ 1 value") ++ (check-equal? (s:let ([x 1] y 2) ++ (cons x y)) ++ '(1 2) ++ "rest binding w/ 1 value (no dot)") + (check-equal? (s:let ([x 1] . [y 2 3]) + (cons x y)) + '(1 2 3) + "rest binding w/ multiple values") ++ (check-equal? (s:let ([x 1] y 2 3) ++ (cons x y)) ++ '(1 2 3) ++ "rest binding w/ multiple values (no dot)") + (check-exn exn:fail:syntax? + (=CE=BB () (convert-syntax-error (s:let ([x 1 2]) x))) +- "rest binding alone is an error")) ++ "malformed binding pair is an error")) +=20 + (test-case +- "let-style loop" ++ "\"named let\"-style loop" + (check-equal? (s:let loop () 1) + 1 + "loop w/ no bindings is ok") +@@ -61,6 +69,13 @@ + [else (list args)])) + '((a) (b) (c d)) + "rest binding w/ 1 initial value") ++ (check-equal? (s:let loop ([continue? 0] args 'a) ++ (case continue? ++ [(0) (cons args (loop 1 'b))] ++ [(1) (cons args (loop 2 'c 'd))] ++ [else (list args)])) ++ '((a) (b) (c d)) ++ "rest binding w/ 1 initial value (no dot)") + (check-equal? (s:let loop ([continue? 0] + . [args 'a 'a1 'a2]) + (case continue? +@@ -69,12 +84,48 @@ + [else (list args)])) + '((a a1 a2) (b) (c d)) + "rest binding w/ multiple initial values") ++ (check-equal? (s:let loop ([continue? 0] args 'a 'a1 'a2) ++ (case continue? ++ [(0) (cons args (loop 1 'b))] ++ [(1) (cons args (loop 2 'c 'd))] ++ [else (list args)])) ++ '((a a1 a2) (b) (c d)) ++ "rest binding w/ multiple initial values (no dot)") ++ (check-equal? (s:let loop (x) ++ x) ++ '() ++ "rest binding alone w/ 0 initial values") ++ (check-equal? (s:let loop (x 1) ++ x) ++ '(1) ++ "rest binding alone w/ 1 initial value") ++ (check-equal? (s:let loop (x 1 2) ++ x) ++ '(1 2) ++ "rest binding alone w/ multiple initial values") ++ (check-equal? (s:let a (b (+ 1)) ++ b) ++ '(1) ++ ;; "confusable" here means that the expression (+ 1) ++ ;; could be confused for a binding pair ++ "rest binding alone w/ confusable initial value") ++ (check-exn (=CE=BB (e) ++ (and (exn:fail:syntax? e) ++ (regexp-match? #rx"^x: unbound" (exn-message e)))) ++ (=CE=BB () ++ (convert-syntax-error ++ (s:let a (b [x 1]) 2))) ++ "rest binding alone: correct error when confused w/ define= ") ++ (check-pred procedure? ++ (s:let loop (args 1 2 3) ++ loop) ++ "rest binding alone: does bind procedure") + (check-exn exn:fail:syntax? + (=CE=BB () (convert-syntax-error (s:let loop ([x 1 2]) x))) +- "rest binding alone is an error")) ++ "malformed binding pair is an error")) +=20 + (test-case +- "define-style loop" ++ "\"define\"-style loop" + (check-equal? (s:let (loop) 1) + 1 + "loop w/ no bindings is ok") +@@ -91,6 +142,20 @@ + (list x))) + '(1 2) + "loop w/ 2 normal args") ++ (check-equal? (s:let (loop [continue? 0] . [args]) ++ (case continue? ++ [(0) (cons args (loop 1 'b))] ++ [(1) (cons args (loop 2 'c 'd))] ++ [else (list args)])) ++ '(() (b) (c d)) ++ "rest binding w/ 0 initial values") ++ (check-equal? (s:let (loop [continue? 0] args) ++ (case continue? ++ [(0) (cons args (loop 1 'b))] ++ [(1) (cons args (loop 2 'c 'd))] ++ [else (list args)])) ++ '(() (b) (c d)) ++ "rest binding w/ 0 initial values (no dot)") + (check-equal? (s:let (loop [continue? 0] + . [args 'a]) + (case continue? +@@ -99,24 +164,94 @@ + [else (list args)])) + '((a) (b) (c d)) + "rest binding w/ 1 initial value") +- (check-equal? (s:let (loop [continue? 0] +- . [args 'a 'a1 'a2]) ++ (check-equal? (s:let (loop [continue? 0] args 'a) ++ (case continue? ++ [(0) (cons args (loop 1 'b))] ++ [(1) (cons args (loop 2 'c 'd))] ++ [else (list args)])) ++ '((a) (b) (c d)) ++ "rest binding w/ 1 initial value (no dot)") ++ (check-equal? (s:let (loop [continue? 0] args 'a 'a1 'a2) + (case continue? + [(0) (cons args (loop 1 'b))] + [(1) (cons args (loop 2 'c 'd))] + [else (list args)])) + '((a a1 a2) (b) (c d)) +- "rest binding w/ multiple initial values") ++ "rest binding w/ multiple initial values (no dot)") ++ (check-equal? (s:let (loop . [args]) ++ (case args ++ [(()) (cons args (loop 'b))] ++ [((b)) (cons args (loop 'c 'd))] ++ [else (list args)])) ++ '(() (b) (c d)) ++ "rest binding alone w/ 0 initial values") ++ (check-equal? (s:let (loop args) ++ (case args ++ [(()) (cons args (loop 'b))] ++ [((b)) (cons args (loop 'c 'd))] ++ [else (list args)])) ++ '(() (b) (c d)) ++ "rest binding alone w/ 0 initial values (no dot)") + (check-equal? (s:let (loop . [args 'a]) + (case args + [((a)) (cons args (loop 'b))] + [((b)) (cons args (loop 'c 'd))] + [else (list args)])) + '((a) (b) (c d)) +- "define-style loop can have only rest arg")) +- +- (check-exn exn:fail:syntax? +- (=CE=BB () +- (convert-syntax-error +- (s:let a (b [x 1]) x))) +- "combining let- and define- style loop names is an error"))) ++ "rest binding alone w/ 1 initial value") ++ (check-equal? (s:let (loop args 'a) ++ (case args ++ [((a)) (cons args (loop 'b))] ++ [((b)) (cons args (loop 'c 'd))] ++ [else (list args)])) ++ '((a) (b) (c d)) ++ "rest binding alone w/ 1 initial value (no dot)") ++ (check-equal? (s:let (loop . [args 'a1 'a2 'a3]) ++ (case args ++ [((a1 a2 a3)) (cons args (loop 'b))] ++ [((b)) (cons args (loop 'c 'd))] ++ [else (list args)])) ++ '((a1 a2 a3) (b) (c d)) ++ "rest binding alone w/ multiple initial values") ++ (check-equal? (s:let (loop args 'a1 'a2 'a3) ++ (case args ++ [((a1 a2 a3)) (cons args (loop 'b))] ++ [((b)) (cons args (loop 'c 'd))] ++ [else (list args)])) ++ '((a1 a2 a3) (b) (c d)) ++ "rest binding alone w/ multiple initial values (no dot)= ")) ++ (test-case ++ "shaddowing" ++ ;; See: https://srfi-email.schemers.org/srfi-5/msg/18712014/ ++ (check-equal? (s:let x ((x 1)) x) ++ 1 ++ "let-style: loop id can be shaddowed") ++ (check-equal? (s:let (x (x 1)) x) ++ 1 ++ "define-style: loop id can be shaddowed") ++ (check-eq? (object-name (s:let f () f)) ++ 'f ++ "let-style object name") ++ (check-eq? (object-name (s:let (g) g)) ++ 'g ++ "define-style object name") ++ (check-exn #rx"duplicate" ++ (=CE=BB () (convert-syntax-error (s:let loop ((x 1) x) #t)= )) ++ "let-style: check duplicate ids") ++ (check-exn #rx"duplicate" ++ (=CE=BB () (convert-syntax-error (s:let (loop (x 1) x) #t)= )) ++ "define-style: check duplicate ids") ++ (check-exn #rx"duplicate" ++ (=CE=BB () (convert-syntax-error (s:let ((x 1) (x 2)) #t))) ++ "non-loop: check duplicate ids")) ++ (test-case ++ "ambiguous \"define\"-style loop: preserve compatible behavior" ++ ;; See: https://srfi-email.schemers.org/srfi-5/msg/18709896/ ++ (check-pred procedure? ++ (s:let (ambiguous (+ 1) (- 2) (list 5)) ++ ambiguous) ++ "ambiguous is not a rest binding") ++ (check-equal? (s:let (ambiguous (+ 1) (- 2) (abs -7)) ++ (list + - abs)) ++ '(1 2 -7) ++ "binds identifiers")))) +diff --git a/srfi/info.rkt b/srfi/info.rkt +index c8d82de..45152e3 100644 +--- a/srfi/info.rkt ++++ b/srfi/info.rkt +@@ -3,11 +3,9 @@ + (define collection 'multi) +=20 + (define deps '("srfi-lib" +- "srfi-doc" +- "srfi-doc-nonfree")) ++ ["srfi-doc" #:version "1.1"])) + (define implies '("srfi-lib" +- "srfi-doc" +- "srfi-doc-nonfree")) ++ "srfi-doc")) +=20 + (define pkg-desc "Legacy SRFI (Scheme) libraries") +=20 +--=20 +2.32.0 + diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index e8d016c07b..62053500cb 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -2,7 +2,7 @@ ;;; Copyright =C2=A9 2013, 2014, 2015, 2016, 2018, 2020, 2021 Ludovic Cour= t=C3=A8s ;;; Copyright =C2=A9 2017, 2018, 2019, 2020 Tobias Geerinckx-Rice ;;; Copyright =C2=A9 2020 Pierre Neidhardt -;;; Copyright =C2=A9 2021 Philip McGrath +;;; Copyright =C2=A9 2021, 2022 Philip McGrath ;;; Copyright =C2=A9 2021 jgart ;;; ;;; This file is part of GNU Guix. @@ -21,8 +21,6 @@ ;;; along with GNU Guix. If not, see . =20 (define-module (gnu packages racket) - #:use-module ((guix licenses) - #:select (asl2.0 expat lgpl3+)) #:use-module (guix packages) #:use-module (guix download) #:use-module (guix git-download) @@ -30,7 +28,10 @@ (define-module (gnu packages racket) #:use-module (guix gexp) #:use-module (guix build-system gnu) #:use-module (srfi srfi-1) + #:use-module (srfi srfi-26) #:use-module (ice-9 match) + #:use-module (ice-9 regex) + #:use-module (ice-9 exceptions) #:use-module (gnu packages) #:use-module (gnu packages autotools) #:use-module (gnu packages bash) @@ -47,200 +48,87 @@ (define-module (gnu packages racket) #:use-module (gnu packages multiprecision) #:use-module (gnu packages sqlite) #:use-module (gnu packages tls) - #:use-module (gnu packages xorg)) - -;; Commentary: -;; -;; Here's how bootstrapping minimal Racket works: -;; -;; - Racket BC [CGC] can be built with only a C compiler (except for -;; one caveat discussed below). -;; - Racket BC [3M] needs an existing Racket to run "xform", -;; which transforms its own C source code to add additional annotations -;; for the precise garbage collector. -;; - Racket CS needs (bootfiles for) Racket's fork of Chez Scheme. -;; It also needs an existing Racket to compile Racket-implemented -;; parts of the runtime system to R6RS libraries. -;; - Chez Scheme also needs bootfiles for itself, but Racket can simulate -;; enough of Chez Scheme to load Racket's fork of the Chez Scheme comp= iler -;; purely from source into Racket and apply the compiler to itself, -;; producing the needed bootfiles (albeit very slowly). -;; Any variant of Racket since version 7.1 can run the simulation. -;; -;; So, we build CGC to build 3M to build bootfiles and CS. -;; -;; One remaining bootstrapping limitation is that Racket's reader, module -;; system, and macro expander are implemented in Racket. For Racket CS, -;; they are compiled to R6RS libraries as discussed above. This note from = the -;; README file applies to all such subsystems: -;; -;; The Racket version must be practically the same as the current Rack= et -;; verson, although it can be the Racket BC implementation (instead of -;; the Racket CS implementation). -;; -;; Unlike Chez Scheme boot files, the files generated in "schemified" -;; are human-readable and -editable Scheme code. That provides a way -;; out of bootstrapping black holes, even without BC. -;; -;; However, other Racket subsystems implemented in Racket for Racket CS -;; use older C implementations for Racket BC, whereas the reader, expander, -;; and module system were completely replaced with the Racket implementati= on -;; as of Racket 7.0. -;; -;; For Racket BC, the compiled "linklet" s-expressions (primitive modules) -;; are embeded in C as a static string constant. Eventually, they are furt= her -;; compiled by the C-implemented Racket BC bytecode and JIT compilers. -;; (On platforms where Racket BC's JIT is not supported, yet another compi= ler -;; instead compiles the linklets to C code, but this is not a bootstrapping -;; issue.) -;; -;; Code: - -(define cfg-flag:sh-for-rktio - `(string-append "CPPFLAGS=3D-DGUIX_RKTIO_PATCH_BIN_SH=3D" - (assoc-ref %build-inputs "sh") - "/bin/sh")) -(define cfg-flag:enable-lt - `(string-append "--enable-lt=3D" - (assoc-ref %build-inputs "libtool") - "/bin/libtool")) -(define cfg-flag:enable-racket - `(let ((racket (assoc-ref %build-inputs "racket"))) - (string-append "--enable-racket=3D" - racket - "/bin/racket"))) - -(define unpack-nanopass+stex - ;; Copied from chez-scheme. - ;; TODO: Eventually, we should refactor Chez Scheme - ;; enough to share more directly, so that we can make - ;; Racket's version of Chez avalable as a Guix package, - ;; e.g. for architectures not supported upstream. - ;; For now, we let Racket drive the Chez build process - ;; other than this step. - `(for-each (lambda (dep) - (define src - (assoc-ref (or native-inputs inputs) dep)) - (copy-recursively src dep - #:keep-mtime? #t)) - '("nanopass" "stex"))) - + #:use-module (gnu packages xorg) + #:use-module ((guix licenses) + #:prefix license:)) =20 (define-public racket-minimal (package (name "racket-minimal") - (version "8.3") ; note: remember to also update racket! - (source - (origin - (method git-fetch) - (uri (git-reference - (url "https://github.com/racket/racket") - (commit (string-append "v" version)))) - (sha256 - "1i1jnv1wb0kanfg47hniafx2vhwjc33qqx66lq7wkf5hbmgsyws3") - (file-name (git-file-name name version)) - (patches (search-patches "racket-minimal-sh-via-rktio.patch")) - (modules '((guix build utils))) - (snippet - (with-imported-modules '((guix build utils)) - #~(begin - ;; Unbundle Chez submodules. - (with-directory-excursion "racket/src/ChezScheme" - ;; Remove bundled libraries (copied from 'chez-scheme'). - (for-each delete-file-recursively - '("stex" - "nanopass" - "lz4" - "zlib"))) - ;; Unbundle libffi. - (delete-file-recursively "racket/src/bc/foreign/libffi")))))) - (inputs - `(;; common to all racket-minimal variants: - ("openssl" ,openssl) - ("sqlite" ,sqlite) - ("sh" ,bash-minimal) - ;; only for CS - ("zlib" ,zlib) - ("zlib:static" ,zlib "static") - ("lz4" ,lz4) - ("lz4:static" ,lz4 "static"))) - (native-inputs - `(("bootfiles" ,racket-bootstrap-chez-bootfiles) - ,@(package-native-inputs racket-bootstrap-chez-bootfiles))) + (version (package-version (racket-vm-for-system))) + (source (package-source (racket-vm-for-system))) + ;; For cross-compilation, Matthew Flatt recommends reusing + ;; as much of `raco cross` as possible. So, put that off until + ;; we have a build system for Racket packages. + (inputs (list openssl sqlite (racket-vm-for-system))) (build-system gnu-build-system) (arguments - `(#:configure-flags - (list "--enable-csonly" - "--enable-libz" - "--enable-liblz4" - ,cfg-flag:enable-racket - ,cfg-flag:sh-for-rktio) - #:out-of-source? #true - ;; Tests are in packages like racket-test-core and - ;; main-distribution-test that aren't part of the main distribution. - #:tests? #f - #:modules ((ice-9 match) - (guix build gnu-build-system) - (guix build utils)) - #:phases - (modify-phases %standard-phases - (add-after 'unpack 'unpack-nanopass+stex - (lambda* (#:key inputs native-inputs #:allow-other-keys) - (with-directory-excursion "racket/src/ChezScheme" - ,unpack-nanopass+stex) - #t)) - (add-after 'unpack-nanopass+stex 'unpack-bootfiles - (lambda* (#:key inputs #:allow-other-keys) - (with-directory-excursion "racket/src/ChezScheme" - (copy-recursively - (string-append (assoc-ref inputs "bootfiles") "/boot") - "boot")) - #t)) - (add-before 'configure 'initialize-config.rktd - (lambda* (#:key inputs #:allow-other-keys) - (define (write-racket-hash alist) - ;; inside must use dotted pair notation - (display "#hash(") - (for-each (match-lambda - ((k . v) - (format #t "(~s . ~s)" k v))) - alist) - (display ")\n")) - (mkdir-p "racket/etc") - (with-output-to-file "racket/etc/config.rktd" - (lambda () - (write-racket-hash - `((lib-search-dirs - . (#f ,@(map (lambda (lib) - (string-append (assoc-ref inputs lib) - "/lib")) - '("openssl" - "sqlite")))) - (build-stamp . "") - (catalogs - . (,(string-append - "https://download.racket-lang.org/releases/" - ,version - "/catalog/") - #f)))))) - #t)) - (add-before 'configure 'change-directory - (lambda _ - (chdir "racket/src") - #t)) - (add-after 'install 'remove-pkgs-directory - ;; If the configured pkgs-dir exists, "pkgs.rktd" does not - ;; exist, and a lock file does not exist, commands like - ;; `raco pkg show` will try to create a lock file and fail - ;; due to the read-only store. - ;; Arguably this may be a bug in `pkg/private/lock`: - ;; see . - ;; As a workaround, remove the directory. - (lambda* (#:key outputs #:allow-other-keys) - ;; rmdir because we want an error if it isn't empty - (rmdir (string-append (assoc-ref outputs "out") - "/share/racket/pkgs")) - #t))))) + (list + #:configure-flags + #~`("--tethered" + "--extra-foreign-lib-search-dirs" + ,(format #f "~s" + (list #$(file-append (this-package-input "openssl") "/l= ib") + #$(file-append (this-package-input "sqlite") "/li= b")))) + #:make-flags #~`("base") + #:tests? #f ;; packaged separately + #:modules '((guix build gnu-build-system) + (guix build utils) + (ice-9 match)) + #:phases + #~(modify-phases %standard-phases + (replace 'configure + (lambda* (#:key inputs configure-flags make-flags + #:allow-other-keys) + (let* ((vm-dir (search-input-directory inputs "opt/racket-vm= ")) + (racket (string-append vm-dir "/bin/racket"))) + (apply invoke + racket + #$make-installation-layer.rkt + `(,@(cond + ((false-if-exception + (search-input-file + inputs "etc/racket/config.rktd")) + =3D> (lambda (file) + `("--parent" + ,(dirname (dirname (dirname file)))))) + (else + '())) + ,@configure-flags + ,vm-dir + ,#$output)) + (invoke racket + "--config" (string-append #$output "/etc/racket") + "-l" "raco" "setup" + "--no-user")))) + (replace 'build + (lambda* (#:key inputs #:allow-other-keys) + (mkdir-p (string-append #$output "/lib/racket/pkgs")) + (for-each (lambda (name) + (copy-recursively + (string-append "pkgs/" name) + (string-append #$output "/lib/racket/pkgs/" nam= e))) + '("base" "racket-lib")))) + (replace 'install + (lambda* (#:key inputs make-flags #:allow-other-keys) + (let ((racket + (search-input-file inputs "/opt/racket-vm/bin/racket"= ))) + (unless (null? make-flags) + (invoke racket + "-l-" + "pkg/dirs-catalog" + "--link" + "local-catalog" + (string-append #$output "/lib/racket/pkgs")) + (apply invoke + racket + "--config" (string-append #$output "/etc/racket") + "-l" "raco" + "pkg" "install" + "--installation" + "--auto" + "--catalog" "local-catalog" + make-flags)))))))) (home-page "https://racket-lang.org") (synopsis "Racket without bundled packages such as DrRacket") (description @@ -254,280 +142,77 @@ (define (write-racket-hash alist) DrRacket IDE, are not included.") ;; https://download.racket-lang.org/license.html ;; The LGPL components are only used by Racket BC. - (license (list asl2.0 expat)))) - - -(define-public racket-minimal-bc-3m - (hidden-package - (package - (inherit racket-minimal) - (name "racket-minimal-bc-3m") - (inputs - (modify-inputs (package-inputs racket-minimal) - (delete "zlib" "zlib:static" "lz4" "lz4:static") - (prepend libffi ;; <- only for BC variants - ))) - (native-inputs - `(("libtool" ,libtool) - ("racket" ,(if (%current-target-system) - racket-minimal - racket-minimal-bc-cgc)))) - (arguments - (substitute-keyword-arguments (package-arguments racket-minimal) - ((#:configure-flags _ '()) - `(list "--enable-bconly" - ,cfg-flag:enable-racket - ,cfg-flag:enable-lt - ,cfg-flag:sh-for-rktio)) - ((#:phases usual-phases) - `(modify-phases ,usual-phases - (delete 'unpack-nanopass+stex) - (delete 'unpack-bootfiles))))) - (synopsis "Minimal Racket with the BC [3M] runtime system") - (description "The Racket BC (``before Chez'' or ``bytecode'') -implementation was the default before Racket 8.0. It uses a compiler writ= ten -in C targeting architecture-independent bytecode, plus a JIT compiler on m= ost -platforms. Racket BC has a different C API and supports a slightly differ= ent -set of architectures than the current default runtime system, Racket CS (b= ased -on ``Chez Scheme''). - -This package is the normal implementation of Racket BC with a precise garb= age -collector, 3M (``Moving Memory Manager'').") - ;; https://download.racket-lang.org/license.html - ;; The LGPL components are only used by Racket BC. - (license (list lgpl3+ asl2.0 expat))))) - - -(define-public racket-minimal-bc-cgc - (package - (inherit racket-minimal-bc-3m) - (name "racket-minimal-bc-cgc") - (native-inputs - (alist-delete "racket" (package-native-inputs racket-minimal-bc-3m))) - (arguments - (substitute-keyword-arguments (package-arguments racket-minimal-bc-3m) - ((#:configure-flags _ '()) - `(list "--enable-cgcdefault" - ,cfg-flag:enable-lt - ,cfg-flag:sh-for-rktio)))) - (synopsis "Old Racket implementation used for bootstrapping") - (description "This variant of the Racket BC (``before Chez'' or -``bytecode'') implementation is not recommended for general use. It uses -CGC (a ``Conservative Garbage Collector''), which was succeeded as default= in -PLT Scheme version 370 (which translates to 3.7 in the current versioning -scheme) by the 3M variant, which in turn was succeeded in version 8.0 by t= he -Racket CS implementation. - -Racket BC [CGC] is primarily used for bootstrapping Racket BC [3M]. It may -also be used for embedding applications without the annotations needed in C -code to use the 3M garbage collector."))) - - -(define-public racket-bootstrap-chez-bootfiles - (hidden-package - (package - (inherit racket-minimal) - (name "racket-bootstrap-chez-bootfiles") - (inputs `()) - (native-inputs - `(("racket" ,(if (%current-target-system) - racket-minimal - racket-minimal-bc-3m)) - ("stex" ,(package-source stex)) - ("nanopass" ,(package-source chez-nanopass)))) - (arguments - `(#:phases - (modify-phases %standard-phases - (add-after 'unpack 'unpack-nanopass+stex - (lambda* (#:key inputs native-inputs #:allow-other-keys) - (with-directory-excursion "racket/src/ChezScheme" - ,unpack-nanopass+stex) - #t)) - (delete 'configure) - (delete 'patch-generated-file-shebangs) - (replace 'build - (lambda* (#:key inputs outputs #:allow-other-keys) - (with-directory-excursion "racket/src/ChezScheme" - (invoke (string-append (assoc-ref inputs "racket") - "/bin/racket") - "rktboot/main.rkt" - "--dest" (assoc-ref outputs "out"))) - #t)) - (delete 'check) - (delete 'install)))) - (synopsis "Chez Scheme bootfiles bootstrapped by Racket") - (description "Chez Scheme is a self-hosting compiler: building it -requires ``bootfiles'' containing the Scheme-implemented portions compiled= for -the current platform. (Chez can then cross-compile bootfiles for all other -supported platforms.) - -The Racket package @code{cs-bootstrap} (part of the main Racket Git -repository) implements enough of a Chez Scheme simulation to load the Chez -Scheme compiler purely from source into Racket and apply the compiler to -itself, thus bootstrapping Chez Scheme. Bootstrapping takes about 10 time= s as -long as using an existing Chez Scheme, but @code{cs-bootstrap} supports Ra= cket -7.1 and later, including the Racket BC variant. - -Note that the generated bootfiles are specific to Racket's fork of Chez -Scheme, and @code{cs-bootstrap} does not currently support building upstre= am -Chez Scheme.") - (license (list asl2.0))))) - - -(define %installer-mirrors - ;; Source: - ;; https://github.com/racket/racket-lang-org/blob/master/download/data.r= kt#L58 - ;; Matthew Flatt says: "note that many are commented out" - ;; INVARIANT: End with a trailing "/"! - '("https://mirror.racket-lang.org/installers/" - "https://www.cs.utah.edu/plt/installers/" - "https://plt.cs.northwestern.edu/racket-mirror/" - "https://mirror.csclub.uwaterloo.ca/racket/racket-installers/" - ;; Universit=C3=A4t T=C3=BCbingen is using a self-signed HTTPS certifi= cate: - "http://mirror.informatik.uni-tuebingen.de/mirror/racket/" - "https://racket.infogroep.be/" - )) - -(define %main-repo-main-distribution-pkgs - ;; These are the packages developed in the main Racket Git repository - ;; that are part of the main distribution. - '("at-exp-lib" - "base" - "compiler-lib" - ;; NOT "compiler-test" - "compiler" - "net-doc" - "net-lib" - ;; NOT "net-test" - "net" - ;; NOT "plt-services" - ;; NOT "racket-benchmarks" - ;; NOT "racket-build-guide" - "racket-doc" - "racket-index" - "racket-lib" - ;; NOT "racket-test-core" - ;; NOT "racket-test-extra" - ;; NOT "racket-test" - "zo-lib")) - + (license (list license:asl2.0 license:expat)))) =20 (define-public racket (package (inherit racket-minimal) (name "racket") - (version (package-version racket-minimal)) ; needed for origin uri to = work - (source - (origin - (method url-fetch) - (uri (map (lambda (base) - (string-append base version "/racket-src.tgz")) - %installer-mirrors)) - (sha256 - (base32 - "0jdr0y7scvv2a3sq456ifrgq0yfsbiwavdf2m86zmrapp481mby4")) - (snippet - #~(begin - (use-modules (guix build utils) - (ice-9 match) - (ice-9 regex)) - ;; unbundle minimal Racket - (for-each delete-file-recursively - '("collects" - "doc" - "etc" - "README" - "src")) - ;; unbundle package sources included elsewhere - (with-directory-excursion "share/pkgs" - (for-each delete-file-recursively - '#+%main-repo-main-distribution-pkgs)) - #t)))) + (source #f) (inputs - `(("cairo" ,cairo) - ("fontconfig" ,fontconfig) - ("glib" ,glib) - ("glu" ,glu) - ("gmp" ,gmp) - ("gtk+" ,gtk+) ; propagates gdk-pixbuf+svg - ("libjpeg" ,libjpeg-turbo) - ("libpng" ,libpng) - ("libx11" ,libx11) - ("mesa" ,mesa) - ("mpfr" ,mpfr) - ("pango" ,pango) - ("unixodbc" ,unixodbc) - ("libedit" ,libedit))) - (native-inputs - `(("racket" ,racket-minimal) - ("extend-layer" ,extend-layer) - ("main-repo" ,(package-source racket-minimal)))) + (list cairo + fontconfig + glib + glu + gmp + gtk+ ;; propagates gdk-pixbuf+svg + libjpeg-turbo + libpng + libx11 ;; ?? wayland ?? + mesa + mpfr + pango + unixodbc + libedit ;; TODO reconsider in light of expeditor and readline-g= pl + racket-minimal ;; <-- TODO non-tethered layer + (racket-vm-for-system))) (arguments - `(#:phases - (modify-phases %standard-phases - (add-before 'configure 'unpack-packages - (let ((unpack (assoc-ref %standard-phases 'unpack))) - (lambda* (#:key native-inputs inputs outputs #:allow-other-k= eys) - (let* ((racket (assoc-ref (or native-inputs inputs) "racket= ")) - (prefix (assoc-ref outputs "out")) - (pkgs-dir (string-append prefix "/share/racket/pkgs"= ))) - (mkdir-p pkgs-dir) - (copy-recursively - "share/links.rktd" - (string-append prefix "/share/racket/links.rktd")) - (copy-recursively "share/pkgs" pkgs-dir) - ;; NOTE: unpack changes the working directory - (unpack #:source (assoc-ref (or native-inputs inputs) - "main-repo")) - (for-each (lambda (pkg) - (define dest (string-append pkgs-dir "/" pkg)) - (mkdir-p dest) - (copy-recursively (string-append "pkgs/" pkg) - dest)) - ',%main-repo-main-distribution-pkgs) - #t)))) - (replace 'configure - (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) - (let ((racket (assoc-ref (or native-inputs inputs) "racket")) - (prefix (assoc-ref outputs "out"))) - (apply invoke - (string-append racket "/bin/racket") - (assoc-ref inputs "extend-layer") - racket - prefix - (map - (lambda (lib) - (string-append (assoc-ref inputs lib) "/lib")) - '("cairo" - "fontconfig" - "glib" - "glu" - "gmp" - "gtk+" - "libjpeg" - "libpng" - "libx11" - "mesa" - "mpfr" - "pango" - "unixodbc" - "libedit"))) - #t))) - (replace 'build - (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) - (invoke (string-append (assoc-ref (or native-inputs inputs) - "racket") - "/bin/racket") - "--config" - (string-append (assoc-ref outputs "out") - "/etc/racket") - "-l" - "raco" - "setup") - #t)) - (delete 'install)) - ;; we still don't have these: - #:tests? #f)) + (substitute-keyword-arguments (package-arguments racket-minimal) + ((#:configure-flags _ '()) + #~`("--tethered" + "--extra-foreign-lib-search-dirs" + ,(format #f "~s" + '(#$@(map (lambda (name) + (cond + ((this-package-input name) + =3D> (cut file-append <> "/lib")) + (else + (raise-exception + (make-exception + (make-assertion-failure) + (make-exception-with-message + "missing input to the 'racket' packa= ge") + (make-exception-with-irritants + (list name))))))) + '("cairo" + "fontconfig-minimal" ;; aka fontconfig + "glib" + "glu" + "gmp" + "gtk+" + "libjpeg-turbo" + "libpng" + "libx11" + "mesa" + "mpfr" + "pango" + "unixodbc" + "libedit")))))) + ((#:make-flags _ '()) + #~`("main-distribution")) + ((#:phases parent-phases #~%standard-phases) + #~(modify-phases #$parent-phases + (delete 'unpack) + (replace 'build + (lambda args + (mkdir-p (string-append #$output "/lib/racket/pkgs")) + (for-each + (match-lambda + ((name src) + (copy-recursively + src + (string-append #$output "/lib/racket/pkgs/" name)))) + '(#$@main-distribution-packages)))))))) (synopsis "Programmable programming language in the Scheme family") (description "Racket is a general-purpose programming language in the Scheme famil= y, @@ -539,82 +224,900 @@ (define dest (string-append pkgs-dir "/" pkg)) DrRacket IDE, libraries for GUI and web programming, and implementations of languages such as Typed Racket, R5RS and R6RS Scheme, Algol 60, and Datalo= g."))) =20 - -(define extend-layer +(define make-installation-layer.rkt (scheme-file - "extend-layer.rkt" + "make-installation-layer.rkt" `(module - extend-layer racket/base + make-installation-layer racket/base (require racket/cmdline racket/match racket/file + racket/port racket/list racket/pretty) - (define config-file-pth - "etc/racket/config.rktd") (define (build-path-string . args) (path->string (apply build-path args))) (define rx:racket ;; Guile's reader doesn't support #rx"racket" (regexp "racket")) - (command-line - #:args (parent-layer prefix . lib-dir*) - (let* ([config - (for/fold - ([config (file->value (build-path parent-layer - config-file-pth))]) - ([spec (in-list - '((lib-dir lib-search-dirs "lib/racket") - (share-dir share-search-dirs "share/racket") - (links-file - links-search-files - "share/racket/links.rktd") - (pkgs-dir pkgs-search-dirs "share/racket/pkgs") - (bin-dir bin-search-dirs "bin") - (man-dir man-search-dirs "share/man") - (doc-dir doc-search-dirs "share/doc/racket") - (include-dir - include-search-dirs - "include/racket")))]) - (match-define (list main-key search-key pth) spec) - (hash-set* - config - main-key - (build-path-string prefix pth) - search-key - (list* #f - (hash-ref config - main-key - (build-path-string parent-layer pth)) - (filter values (hash-ref config search-key null))))= )] - [config - (hash-set config - 'apps-dir - (build-path-string prefix "share/applications"))] - [config - ;; place new foreign lib-search-dirs before old - ;; foreign dirs, but after Racket layers - (let-values - ([(rkt extra) - (partition (lambda (pth) - (or (not pth) - (regexp-match? rx:racket pth))) - (hash-ref config 'lib-search-dirs))]) - (hash-set config + (define tethered? #f) + (define parent #f) + (define extra-foreign-lib-search-dirs '()) + (define-values [vm-dir prefix] + (command-line + #:once-each + [("--tethered") "create a tethered layer" + (set! tethered? #t)] + [("--parent") dir "path of parent layer, if any" + (set! parent dir)] + [("--extra-foreign-lib-search-dirs") dir-list + "foreign library directories, as a list of strings in `read` synt= ax" + (set! extra-foreign-lib-search-dirs + (call-with-input-string dir-list read))] + #:args (vm-dir prefix) + (values vm-dir prefix))) + (let* ([config + (for/fold + ([config (file->value + (if parent + (build-path parent "etc/racket/config.rktd") + (build-path vm-dir "etc/config.rktd")))]) + ([spec + (in-list + '((lib-dir lib-search-dirs "lib/racket" "lib") + (share-dir share-search-dirs "share/racket" "share") + (links-file links-search-files + "lib/racket/links.rktd" + "share/links.rktd") + (pkgs-dir pkgs-search-dirs "lib/racket/pkgs" "share/pkg= s") + ;; Partial workaround for: + ;; https://github.com/racket/racket/issues/4133 + #;(bin-dir bin-search-dirs "bin" "bin") + (bin-dir bin-search-dirs "unused-untethered-bin" "bin") + (man-dir man-search-dirs "share/man" "share/man") + (doc-dir doc-search-dirs "share/doc/racket" "doc") + (include-dir include-search-dirs + "include/racket" + "include")))]) + (match-define (list main-key search-key pth vm-pth) spec) + (hash-set* + config + main-key + (build-path-string prefix pth) + search-key + (list* #f + (hash-ref config + main-key + (lambda () + (if parent + (build-path-string parent pth) + (build-path-string vm-dir vm-pth)))) + (filter values (hash-ref config search-key null)))))] + [config + (hash-update config 'lib-search-dirs - (append rkt - lib-dir* - extra)))] - [bin-dir - (hash-ref config 'bin-dir)] - [config - (hash-set* config - 'config-tethered-console-bin-dir bin-dir - 'config-tethered-gui-bin-dir bin-dir)] - [new-config-pth - (build-path prefix config-file-pth)]) - (make-parent-directory* new-config-pth) - (call-with-output-file* - new-config-pth - (lambda (out) - (pretty-write config out)))))))) + (lambda (dirs) + ;; add after other layers, but before older + ;; foreign lib search directories + (define-values [rkt old-foreign-dirs] + (partition (lambda (pth) + (or (not pth) + (regexp-match? rx:racket pt= h))) + dirs)) + (append rkt + extra-foreign-lib-search-dirs + old-foreign-dirs)))] + [config + (hash-set* config + 'apps-dir + (build-path-string prefix "share/applications") + 'absolute-installation? #t + ;; Let Guix coexist with other installation + ;; methods without clobbering user-specific packag= es + ;; This could be set in various places, but doing + ;; it here is convienient, at least until we suppo= rt + ;; cross-compilation. + 'installation-name + (string-append (version) + "-guix" + (match (system-type 'gc) + ['cgc "-cgc"] + ;; workaroung Guile reader/printe= r: + ['|3m| "-bc"] + [_ ""])))] + [config + (cond + [tethered? + ;; Partial workaround for: + ;; https://github.com/racket/racket/issues/4133 + #;(define bin-dir (hash-ref config 'bin-dir)) + (define bin-dir (build-path-string prefix "bin")) + (hash-set* config + 'config-tethered-apps-dir (hash-ref config 'apps= -dir) + 'config-tethered-console-bin-dir bin-dir + 'config-tethered-gui-bin-dir bin-dir)] + [else + config])]) + (define new-config-pth + (build-path prefix "etc/racket/config.rktd")) + (make-parent-directory* new-config-pth) + (call-with-output-file* + new-config-pth + (lambda (out) + (pretty-write config out))))))) + +(define-public main-distribution-packages + (let* ((%racket-version (package-version (racket-vm-for-system))) + (%racket-commit (string-append "v" %racket-version))) + ;; on release, commit will be %racket-commit + (append-map + (match-lambda + ((source . pkgs) + (map (match-lambda + ((? string? name) + (list name (file-append source (string-append "/" name)))) + ((name ".") + (list name source)) + ((name rel-path) + (list name (file-append source (string-append "/" rel-path= ))))) + pkgs))) + `((,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/2d") + (commit %racket-commit))) + (sha256 (base32 + "1zzcz5qyjv7syi41vb8jkxjp1rqgj61zbsdrg0nlc4qy9qsafzgr"= )) + (file-name + (git-file-name "racket-2d" %racket-version))) + "2d" "2d-doc" "2d-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/algol60") + (commit %racket-commit))) + (sha256 (base32 + "09kj6asypmc24n29w0izc9p0q8hpga2hpkchsypfwn5c8zpvihlx"= )) + (file-name + (git-file-name "racket-algol60" %racket-version))) + ("algol60" ".")) + (,(package-source (racket-vm-for-system)) + ("at-exp-lib" "pkgs/at-exp-lib") + ("compiler" "pkgs/compiler") + ("compiler-lib" "pkgs/compiler-lib") + ("net" "pkgs/net") + ("net-doc" "pkgs/net-doc") + ("net-lib" "pkgs/net-lib") + ("racket-doc" "pkgs/racket-doc") + ("racket-index" "pkgs/racket-index") + ("sandbox-lib" "pkgs/sandbox-lib") + ("zo-lib" "pkgs/zo-lib")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/cext-lib") + (commit %racket-commit))) + (sha256 (base32 + "00w38jpv88fpl4pgj6ndnysvn0s21rjvj0xhznay80msan0vc341"= )) + (file-name (git-file-name "racket-cext-lib" %racket-version))) + "cext-lib" "dynext-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/class-iop") + (commit %racket-commit))) + (sha256 (base32 + "08z57q83cr7wnh6g8ah3hdhmsmf9zp1jfs7yvxv188l3hzvygy5l"= )) + (file-name (git-file-name "racket-class-iop" %racket-version))) + "class-iop-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/compatibility") + (commit "37f11132cdad7ef27386b68383d073f275d67c31"))) + (sha256 (base32 + "0bfqwscjpyi325br5pa6g62g9c8lq18a80zp5g3d2qzn3n3mi6x0"= )) + (file-name (git-file-name "racket-compatibility" %racket-versio= n))) + "compatibility" "compatibility-doc" "compatibility-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/contract-profile") + (commit "95d980a076126b8e4e4284e912f2a7d9d3ab6860"))) + (sha256 (base32 + "1xm2z8g0dpv5d9h2sg680vx1a8ix9gbsdpxxb8qv1w7akp73paj3"= )) + (file-name + (git-file-name "racket-contract-profile" %racket-version))) + ("contract-profile" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/data") + (commit "e32d012b394e32e102e8a9adfcc885bb0541ab51"))) + (sha256 (base32 + "10iabgrk9alaggvksnyb0hdq7f1p30pq6pq2bcakvhzpxwiv1f55"= )) + (file-name (git-file-name "racket-data" %racket-version))) + "data" "data-doc" "data-enumerate-lib" "data-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/datalog") + (commit "7d160a86451af8298093d07674a2eb0e1a0161a4"))) + (sha256 (base32 + "0n5j5gnqh7g31mvgx19ggl18hirzbvq2r189lbngmnrmbc7b73fp"= )) + (file-name (git-file-name "racket-datalog" %racket-version))) + ("datalog" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/db") + (commit %racket-commit))) + (sha256 (base32 + "1n02ja0yj3mjjhmz0yv04yfhyvrsznbljn8bjviyfxnm4xf9rcc5"= )) + (file-name (git-file-name "racket-db" %racket-version))) + "db" "db-doc" "db-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/deinprogramm") + (commit %racket-commit))) + (sha256 (base32 + "1is6fapgv6rxfjz47nh6qf3kh7y7sjdinakaxqffi46gf1al8prd"= )) + (file-name (git-file-name "racket-deinprogramm" %racket-version= ))) + "deinprogramm" "deinprogramm-signature") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/distributed-places") + (commit %racket-commit))) + (sha256 (base32 + "1dajpkj9balqcpv6cdk9hwjz592h1vq8rrx5vncariiac4vbdpa0"= )) + (file-name + (git-file-name "racket-distributed-places" %racket-version))) + "distributed-places" "distributed-places-doc" "distributed-places-= lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/draw") + (commit %racket-commit))) + (sha256 (base32 + "1xgjfbh70hqw67z88iqqajg98d04qwbzn6im2wj47rs28jxlm9ly"= )) + (file-name (git-file-name "racket-draw" %racket-version))) + "draw" "draw-doc" "draw-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/drracket") + (commit %racket-commit))) + (sha256 (base32 + "0m3l4an3nq2ycd1h287s1az2v2zprjbzd8if2x7d5r71vaj4i00c"= )) + (file-name (git-file-name "racket-drracket" %racket-version))) + "drracket" + "drracket-plugin-lib" + "drracket-tool" + "drracket-tool-doc" + "drracket-tool-lib" + "drracket-tool-text-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/ds-store") + (commit "949ca63dd00522b3ab8aec2d71c543ece8266872"))) + (sha256 (base32 + "0ajr27kipp4dr1qlisaghsb3h7lhhjwrfw2r79b5myczsa1mp661"= )) + (file-name (git-file-name "racket-ds-store" %racket-version))) + "ds-store" "ds-store-doc" "ds-store-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/eli-tester") + (commit "036e07d43a1f478ea1750881d5591d983ce1ffaf"))) + (sha256 (base32 + "0icx6wn14gjm8kdmq1jppqgq87sxkras4qb5xmdr6wigxafhjqyk"= )) + (file-name (git-file-name "racket-eli-tester" %racket-version))) + ("eli-tester" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/eopl") + (commit %racket-commit))) + (sha256 (base32 + "1fmiixj6rxsgzwvgva8lvrvv0gl49v2405mp3s0i7ipis5c4n27s"= )) + (file-name (git-file-name "racket-eopl" %racket-version))) + ("eopl" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/errortrace") + (commit %racket-commit))) + (sha256 (base32 + "14m7rhaxngj36070iw15am434hm438pfgmwjfsiqhsglz4pcxhip"= )) + (file-name (git-file-name "racket-errortrace" + (package-version (racket-vm-for-syste= m))))) + "errortrace" "errortrace-doc" "errortrace-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/expeditor") + (commit %racket-commit))) + (sha256 (base32 + "07djzxs6307l51mcsk3yr2g4g47ayxa3878g7sf5xhqdr4hd9vxf"= )) + (file-name (git-file-name "racket-expeditor" %racket-version))) + "expeditor" "expeditor-doc" "expeditor-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/frtime") + (commit %racket-commit))) + (sha256 (base32 + "0ydz2yn8vvv6z7brwlswcyx0f31a6y6d443i89rysfvd2xkhpfd5"= )) + (file-name (git-file-name "racket-frtime" %racket-version))) + ("frtime" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/future-visualizer") + (commit %racket-commit))) + (sha256 (base32 + "1758qq769m0r14xf64sl2ix2l9z340kvapar0j7s5kdg42lmvnhm"= )) + (file-name + (git-file-name "racket-future-visualizer" %racket-version))) + "future-visualizer" "future-visualizer-pict" "future-visualizer-ty= ped") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/games") + + (commit %racket-commit))) + (sha256 (base32 + "0kpn3izlx1ccd0pj0dnvmnrhny51b85xy418a7psj70lz8j8415d"= )) + (file-name (git-file-name "racket-games" %racket-version))) + ("games" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/gui") + (commit %racket-commit))) + (sha256 (base32 + "1x33jgrx3r32k7hgwr591z3xqv1m2r5nc4km2fnxv0ak2xa0j3gj"= )) + (patches + ;; remove in Racket 8.5 + ;; see https://github.com/racket/racket/issues/4133 + (search-patches "racket-gui-tethered-launcher-backport.patch")) + (file-name (git-file-name "racket-gui" %racket-version))) + "gui" "gui-doc" "gui-lib" "tex-table") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/gui-pkg-manager") + (commit %racket-commit))) + (sha256 (base32 + "1ji9448d723nklqvycwdswj0ni28sabrncag14f9mx47did5myb5"= )) + (file-name + (git-file-name "racket-gui-pkg-manager" %racket-version))) + "gui-pkg-manager-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/htdp") + (commit %racket-commit))) + (sha256 (base32 + "0r4ykybcpr10y2db9rlza9pr0xh58nd7ac389mjcxp8g386hgihl"= )) + (file-name (git-file-name "racket-htdp" %racket-version))) + "htdp" "htdp-doc" "htdp-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/html") + (commit %racket-commit))) + (sha256 (base32 + "18n1jnjgzfknc8nv8dppi85nb8q08gqdwkg6hfjk08x0p00anx2x"= )) + (file-name (git-file-name "racket-html" %racket-version))) + "html" "html-doc" "html-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/icons") + (commit %racket-commit))) + (sha256 (base32 + "1s5a6j11fg3fdr6b7vm2q7q178d7q8b8igy73bs211r27qrd1gg7"= )) + (file-name (git-file-name "racket-icons" %racket-version))) + ("icons" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/images") + (commit %racket-commit))) + (sha256 (base32 + "0rpjxqw34bq5m08kh1ldl1mr7s9z1lyydxxcyzb292kqh9qiqvfl"= )) + (file-name (git-file-name "racket-images" %racket-version))) + "images" "images-doc" "images-gui-lib" "images-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/lazy") + (commit %racket-commit))) + (sha256 (base32 + "176ylzgbdsbmqknpihaz519afq71pyjkv1h87j5v8jfbpbddyfsf"= )) + (file-name (git-file-name "racket-lazy" %racket-version))) + ("lazy" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/macro-debugger") + (commit %racket-commit))) + (sha256 (base32 + "14hyrwbkffr61fk44l02xb47bhv5zccw0ymaa9kxld86hvyqhqbm"= )) + (file-name (git-file-name "racket-macro-debugger" %racket-versi= on))) + "macro-debugger" "macro-debugger-text-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/main-distribution") + (commit %racket-commit))) + (sha256 (base32 + "0m2n9s32s8a4a2gn4ywrm9l8jycdm5ayi5w9kh5wchhrrw7qzq7y"= )) + (file-name + (git-file-name "racket-main-distribution" %racket-version))) + ("main-distribution" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/make") + (commit %racket-commit))) + (sha256 (base32 + "10852fj30bz5r46c3d99s37fkgy5yh44gb01j29sf3kxnhi0g2sa"= )) + (file-name (git-file-name "racket-make" %racket-version))) + ("make" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/math") + (commit %racket-commit))) + (sha256 (base32 + "02sqbnvxvmvslk33b44fx4v93zafcvhva0cx8z21jqbl5wp217ac"= )) + (file-name (git-file-name "racket-math" %racket-version))) + "math" "math-doc" "math-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/mysterx") + (commit %racket-commit))) + (sha256 (base32 + "11p9jzrafw0hizhl0cs4sxx7rv281185q8hryic2rpk0kzjdyr48"= )) + (file-name (git-file-name "racket-mysterx" %racket-version))) + ("mysterx" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/mzcom") + (commit %racket-commit))) + (sha256 (base32 + "0rc9pfj7gwm5azghqvcibz6si1x5s2v8mr2yngk7ssq9gzfbi6a4"= )) + (file-name (git-file-name "racket-mzcom" %racket-version))) + ("mzcom" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/mzscheme") + (commit %racket-commit))) + (sha256 (base32 + "192c52zi726h5wjamxrhivjw2waq1im0zpyxhbrkrxknm8x84bs9"= )) + (file-name (git-file-name "racket-mzscheme" %racket-version))) + "mzscheme" "mzscheme-doc" "mzscheme-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/RenaissanceBug/racket-cookies") + (commit %racket-commit))) + (sha256 (base32 + "0k0hifxhywl5c3hjcaiizc098dpyk001d981p572gly116yvjxc1"= )) + (file-name + (git-file-name "RenaissanceBug-racket-cookies" %racket-version= ))) + "net-cookies" "net-cookies-doc" "net-cookies-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/stamourv/optimization-coach") + (commit %racket-commit))) + (sha256 (base32 + "0b27sw48d7rhz0hin88c7rbr9vpg1c23sn82nd4jkmq54h6gasr1"= )) + (file-name + (git-file-name "stamourv-optimization-coach" %racket-version))) + ("optimization-coach" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/option-contract") + (commit %racket-commit))) + (sha256 (base32 + "026b7n5l0c3024nymshz8zp1yhn493rdzgpflzfd52hj7awafqhk"= )) + (file-name + (git-file-name "racket-option-contract" %racket-version))) + "option-contract" "option-contract-doc" "option-contract-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/parser-tools") + (commit %racket-commit))) + (sha256 (base32 + "08pvz4zramirzm3j64hbhjm0mmh5zfy37iv4s3vmq0rj49cr8fl3"= )) + (file-name (git-file-name "racket-parser-tools" %racket-version= ))) + "parser-tools" "parser-tools-doc" "parser-tools-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/pconvert") + (commit %racket-commit))) + (sha256 (base32 + "00czi0p399mmyrvxyrs5kniizpkqfxyz2ncxqi2jy79a7wk79pb1"= )) + (file-name (git-file-name "racket-pconvert" %racket-version))) + "pconvert-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/pict") + (commit %racket-commit))) + (sha256 (base32 + "0g1iwdr6qh1xb0crhj96830vjjnbds409xbpqn7j5sh0ksy6vr5x"= )) + (file-name (git-file-name "racket-pict" %racket-version))) + "pict" "pict-doc" "pict-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/pict-snip") + (commit %racket-commit))) + (sha256 (base32 + "081nwiy4a0n4f7xws16hqbhf0j3kz5alizndi3nnyr3chm4kng6x"= )) + (file-name (git-file-name "racket-pict-snip" %racket-version))) + "pict-snip" "pict-snip-doc" "pict-snip-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/picturing-programs") + (commit %racket-commit))) + (sha256 (base32 + "1g6xr39hx1j03gb3d4dljm3v91xcj2gfpq3dgy5xvplzr6cmmxgr"= )) + (file-name + (git-file-name "racket-picturing-programs" %racket-version))) + ("picturing-programs" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/plai") + (commit %racket-commit))) + (sha256 (base32 + "0i983sh0r0zm2ng4j44m5aw9669kh5fhp91bzpc9jm280rfcqvyl"= )) + (file-name (git-file-name "racket-plai" %racket-version))) + "plai" "plai-doc" "plai-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/planet") + (commit %racket-commit))) + (sha256 (base32 + "0r2yqrzrmdjjyr14k6hhlzc5kzrcx3583m1s02mhrcmpfw0s85w9"= )) + (file-name (git-file-name "racket-planet" %racket-version))) + "planet" "planet-doc" "planet-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/plot") + (commit %racket-commit))) + (sha256 (base32 + "07kq32si34ybcwz8idxxcrzssg8diyrp1nfgkcj0mmvr45321zm7"= )) + (file-name (git-file-name "racket-plot" %racket-version))) + "plot" "plot-compat" "plot-doc" "plot-gui-lib" "plot-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/preprocessor") + (commit %racket-commit))) + (sha256 (base32 + "1p5aid58ifnjy4xl0ysh85cq39k25661v975jrpk182z3k5621mg"= )) + (file-name (git-file-name "racket-preprocessor" %racket-version= ))) + ("preprocessor" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/profile") + (commit %racket-commit))) + (sha256 (base32 + "179i86lyby29nywz60l4vnadi02w8b12h7501nm5h5g4pq9jjmbb"= )) + (file-name (git-file-name "racket-profile" %racket-version))) + "profile" "profile-doc" "profile-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/Metaxal/quickscript") + (commit %racket-commit))) + (sha256 (base32 + "100g3yqhbjdq06b6l6d72ywsw29awgy8crqg33wj7h12xq07nzcr"= )) + (file-name (git-file-name "Metaxal-quickscript" %racket-version= ))) + ("quickscript" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/r5rs") + (commit %racket-commit))) + (sha256 (base32 + "1g3cysj7z88r38vkzvi8g2fb2hn4yg1fdhy5smxw303jxgl3inp6"= )) + (file-name (git-file-name "racket-r5rs" %racket-version))) + "r5rs" "r5rs-doc" "r5rs-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/r6rs") + (commit %racket-commit))) + (sha256 (base32 + "0b1ymzdp10r0flw2acbidjsh5ma1pm5hy54jss37sxf89z3xbvm4"= )) + (file-name (git-file-name "racket-r6rs" %racket-version))) + "r6rs" "r6rs-doc" "r6rs-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/jeapostrophe/racket-cheat") + (commit %racket-commit))) + (sha256 (base32 + "06wcj558rzkbl2bwkmikyspya9v1f4iwlzwnwxpkc33h2xapwabr"= )) + (file-name + (git-file-name "jeapostrophe-racket-cheat" %racket-version))) + ("racket-cheat" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/racklog") + (commit %racket-commit))) + (sha256 (base32 + "1rgrvwy3kr9b9w5cghsffiv3ly00yfvvzr5xaaw83g1w7yin0mnb"= )) + (file-name (git-file-name "racket-racklog" %racket-version))) + ("racklog" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/rackunit") + (commit %racket-commit))) + (sha256 (base32 + "057z31rja6h3nabh5b2xgwfrzmlm6h1cv1qcgf3xfy4g2q5dqn5p"= )) + (file-name (git-file-name "racket-rackunit" %racket-version))) + "rackunit" + "rackunit-doc" + "rackunit-gui" + "rackunit-lib" + "rackunit-plugin-lib" + "rackunit-typed" + "schemeunit" + "testing-util-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/readline") + (commit %racket-commit))) + (sha256 (base32 + "13kbcn2wchv82d709mw3r8n37bk8iwq0y4kpvm9dbzx0w2pxkfwn"= )) + (file-name (git-file-name "racket-readline" %racket-version))) + "readline" "readline-doc" "readline-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/realm") + (commit %racket-commit))) + (sha256 (base32 + "0hxcgla08iack54j8v40fj51811chpy66ym2zq76zb52c7kzn0hi"= )) + (file-name (git-file-name "racket-realm" %racket-version))) + ("realm" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/redex") + (commit %racket-commit))) + (sha256 (base32 + "0vlgxbnbgrlihk1hh5zd6hsc4566ldi4q76f87z5vai54dxkwy2f"= )) + (file-name (git-file-name "racket-redex" %racket-version))) + "redex" + "redex-benchmark" + "redex-doc" + "redex-examples" + "redex-gui-lib" + "redex-lib" + "redex-pict-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/sasl") + (commit %racket-commit))) + (sha256 (base32 + "0ibh4wb4gn8pggx6gkv4vk4d6rwzn5nrvjibhvkzhaynf6lhb824"= )) + (file-name (git-file-name "racket-sasl" %racket-version))) + "sasl" "sasl-doc" "sasl-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/scheme-lib") + (commit %racket-commit))) + (sha256 (base32 + "0pcf0y8rp4qyjhaz5ww5sr5diq0wpcdfrrnask7zapyklzx1jx8x"= )) + (file-name (git-file-name "racket-scheme-lib" %racket-version))) + ("scheme-lib" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/scribble") + (commit %racket-commit))) + (sha256 (base32 + "0rgvnsykrxkah6s5fw1vyp9lxsb4z9w6hgwk5j6wbwjp2gsfczbm"= )) + (file-name (git-file-name "racket-scribble" %racket-version))) + "scribble" + "scribble-doc" + "scribble-html-lib" + "scribble-lib" + "scribble-text-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/serialize-cstruct-lib") + (commit %racket-commit))) + (sha256 (base32 + "1rq3n1fa7ldjwx3lrh9ybhig7jlsw1crpzyklbzp3xqdw6jymfnz"= )) + (file-name + (git-file-name "racket-serialize-cstruct-lib" %racket-version)= )) + ("serialize-cstruct-lib" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/sgl") + (commit %racket-commit))) + (sha256 (base32 + "0nkymhdyjrwi5h199j4w5zh7y3x3ai42gsiwxzh0hy7yqrqqg9zv"= )) + (file-name (git-file-name "racket-sgl" %racket-version))) + ("sgl" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/shell-completion") + (commit %racket-commit))) + (sha256 (base32 + "04m144gy2mp4fiq6rcbf12wjr8mws8k9scfhg9lc38vqppp4lxsj"= )) + (file-name + (git-file-name "racket-shell-completion" %racket-version))) + ("shell-completion" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/simple-tree-text-markup") + (commit %racket-commit))) + (sha256 (base32 + "0fyd9gfz6bnv0m1901wv5mnhc05rm8hw9i6ddrqx33hs6qsg2zqr"= )) + (file-name + (git-file-name "racket-simple-tree-text-markup" %racket-versio= n))) + "simple-tree-text-markup" + "simple-tree-text-markup-doc" + "simple-tree-text-markup-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/slatex") + (commit "47e1d3e3e33d826bc2b26f9e8998eb235b23a9a5"))) + (sha256 (base32 + "0pkm2isbbdk63slrbsxcql7rr0wdrw5kapw1xq4ps5k8dhlzv8x0"= )) + (file-name (git-file-name "racket-slatex" %racket-version))) + ("slatex" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/slideshow") + (commit %racket-commit))) + (sha256 (base32 + "1znv1i2d0610hhy71q932xy7wka00q3q50in1xfnk8ibg7nzkagm"= )) + (file-name (git-file-name "racket-slideshow" %racket-version))) + "slideshow" "slideshow-doc" "slideshow-exe" "slideshow-lib" + "slideshow-plugin") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/snip") + (commit %racket-commit))) + (sha256 (base32 + "01r9wc5xr3q3n4yyif6j0a37rgdzmpslxn05k13ksik73b3wj6hj"= )) + (file-name (git-file-name "racket-snip" %racket-version))) + "snip" "snip-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/typed-racket") + (commit %racket-commit))) + (sha256 (base32 + "1462kj9yswsxbnw71casylzlvhd7cxrml2v9j7rcsnn9hmrqx4vv"= )) + (file-name (git-file-name "racket-typed-racket" %racket-version= ))) + "source-syntax" + "typed-racket" + "typed-racket-compatibility" + "typed-racket-doc" + "typed-racket-lib" + "typed-racket-more") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/srfi") + (commit %racket-commit))) + (sha256 (base32 + "0cga4ijid6lg5j68cvdfs4xr69rsyzw7d7lixr3i866kran61sys"= )) + (patches + ;; remove in Racket 8.5 + ;; see https://github.com/racket/srfi/pull/15 + (search-patches "racket-srfi-fsdg-backport.patch")) + (file-name (git-file-name "racket-srfi" %racket-version))) + "srfi" "srfi-doc" "srfi-lib" "srfi-lite-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/string-constants") + (commit %racket-commit))) + (sha256 (base32 + "1qizjq4n0hzdgdcjjpr94464gsywpsk2g9mnvwzqr7dcqbrsfvn6"= )) + (file-name + (git-file-name "racket-string-constants" %racket-version))) + "string-constants" "string-constants-doc" "string-constants-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/swindle") + (commit %racket-commit))) + (sha256 (base32 + "164gdsphjzdl2vv7zxz7dfk9jwax8njpmim6sidm8qz8a8589y67"= )) + (file-name (git-file-name "racket-swindle" %racket-version))) + ("swindle" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/syntax-color") + (commit %racket-commit))) + (sha256 (base32 + "1vf2fc3qvx8a1igi7swsg8gaqhx786sa0vqxd18xhbsidfgb5ywp"= )) + (file-name (git-file-name "racket-syntax-color" %racket-version= ))) + "syntax-color" "syntax-color-doc" "syntax-color-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/trace") + (commit %racket-commit))) + (sha256 (base32 + "070ihla5j796hdarn5wxdwn4xj0xnkm50shgh49jy994mribvhia"= )) + (file-name (git-file-name "racket-trace" %racket-version))) + ("trace" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/unix-socket") + (commit %racket-commit))) + (sha256 (base32 + "02dfwas5ynbpyz74w9kwb4wgb37y5wys7svrlmir8k0n9ph9vq0y"= )) + (file-name (git-file-name "racket-unix-socket" %racket-version)= )) + "unix-socket" "unix-socket-doc" "unix-socket-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/web-server") + (commit %racket-commit))) + (sha256 (base32 + "1zgb6jl7zx6258ljs8f3lvryrq5n5zpd71dqzr698m92kw3x2pkn"= )) + (file-name (git-file-name "racket-web-server" %racket-version))) + "web-server" "web-server-doc" "web-server-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/wxme") + (commit %racket-commit))) + (sha256 (base32 + "1qp5gr9gqsakiq3alw6m4yyv5vw4i3hp4y4nhq8vl2nkjmirvn0b"= )) + (file-name (git-file-name "racket-wxme" %racket-version))) + "wxme" "wxme-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/xrepl") + (commit %racket-commit))) + (sha256 (base32 + "12zjgsy5zqm3fck3ihg4a70wj56s2cnnjyb4jlfi5nnsfqyrnxg3"= )) + (file-name (git-file-name "racket-xrepl" %racket-version))) + "xrepl" "xrepl-doc" "xrepl-lib"))))) --=20 2.32.0