commit e2da3d0d0bfd1cec8a7f7f0024c5bdfff17e3506
parent c6edf59c603a7661431c61d20eb4b86151e61633
Author: Taylan Ulrich Bayırlı/Kammer <taylanbayirli@gmail.com>
Date: Sun, 16 Aug 2015 15:36:53 +0200
Add support for pairs.
Previously the rationale wrote that supporting pairs is senseless
because car and cdr are already very short words. Things change when
one wants to use the ref* procedure, and it's in the plans to add it to
the specification after all, so this is preliminary to that.
Diffstat:
3 files changed, 32 insertions(+), 14 deletions(-)
diff --git a/srfi-123.html b/srfi-123.html
@@ -27,7 +27,7 @@ class="antispam">nospam</span>srfi.schemers.org</a></code>. To subscribe to the
<p>In contrast, most other languages offer very short and simple syntax for such operations, such as square bracket and dotted notation: <code>object[field]</code> and <code>object.field</code> for access; <code>object[field] = value</code> and <code>object.field = value</code> for modification.</p>
<p>To accommodate, we define a pair of generic accessor and modifier operators that work through type-based dynamic dispatch: <code>(ref object field)</code> for access and <code>(set! object field value)</code> for modification.</p>
<p>We believe the overhead involved in this is negligible in most code-bases, and furthermore a programmer can always fall back to the type-specific accessor and modifier procedures in performance-critical sections of code.</p>
-<p>The operators are specified to work on bytevectors, R6RS hashtables, lists, strings, vectors, and all record types. Some notes on specific types:</p>
+<p>The operators are specified to work on bytevectors, R6RS hashtables, lists/pairs, strings, vectors, and all record types. Some notes on specific types:</p>
<ul>
<li><p>For bytevectors, 8-bit unsigned integer operations are assumed. There is no obvious way to incorporate other bytevector operations into the generalized API, and a programmer is most likely to have single-byte operations in mind when using a generalized API on bytevectors.</p>
<pre><code>(define bv (bytevector 0 1 2 3))
@@ -40,8 +40,9 @@ class="antispam">nospam</span>srfi.schemers.org</a></code>. To subscribe to the
(set! table "foo" "Foobar.")
(ref table "foo") ;=> "Foobar."
(ref table "bar") ;error: Object has no entry for field.</code></pre></li>
-<li><p>Lists are supported by testing the given object for a pair. Pairs themselves are senseless to support because <code>(set! pair car value)</code> contains the same number of words as <code>(set-car! pair value)</code>. In the <code>ref</code> equivalent, it even contains one word more: <code>(ref pair car)</code> vs. <code>(car pair)</code>.</p>
-<pre><code>(ref '(a b c . d) 2) ;=> c</code></pre></li>
+<li><p>When a pair is encountered, the field argument may be the procedures <code>car</code> or <code>cdr</code>, or an integer index indicating the pair should be viewed as the head of a list.</p>
+<pre><code>(ref '(a b c . d) cdr) ;=> (b c . d)
+(ref '(a b c . d) 2) ;=> c</code></pre></li>
<li><p>For records, the accepted values for the <code>field</code> parameter are symbols corresponding to the record type's field names. The overhead involved in looking up the correct accessor of modifier falls under the same rationale as other kinds of overhead involved with this SRFI.</p>
<pre><code>(define-record-type <foo> (make-foo a b) foo?
(a foo-a set-foo-a!)
diff --git a/srfi-123.md b/srfi-123.md
@@ -57,8 +57,8 @@ type-specific accessor and modifier procedures in performance-critical
sections of code.
The operators are specified to work on bytevectors, R6RS hashtables,
-lists, strings, vectors, and all record types. Some notes on specific
-types:
+lists/pairs, strings, vectors, and all record types. Some notes on
+specific types:
- For bytevectors, 8-bit unsigned integer operations are assumed.
There is no obvious way to incorporate other bytevector operations
@@ -84,15 +84,14 @@ types:
(ref table "bar") ;error: Object has no entry for field.
```
-- Lists are supported by testing the given object for a pair. Pairs
- themselves are senseless to support because `(set! pair car value)`
- contains the same number of words as `(set-car! pair value)`. In
- the `ref` equivalent, it even contains one word more:
- `(ref pair car)` vs. `(car pair)`.
+- When a pair is encountered, the field argument may be the procedures
+ `car` or `cdr`, or an integer index indicating the pair should be
+ viewed as the head of a list.
- ```
+ ````
+ (ref '(a b c . d) cdr) ;=> (b c . d)
(ref '(a b c . d) 2) ;=> c
- ```
+ ````
- For records, the accepted values for the `field` parameter are
symbols corresponding to the record type's field names. The
diff --git a/srfi/123.body.scm b/srfi/123.body.scm
@@ -35,6 +35,24 @@
alist)
table))
+(define (pair-ref pair key)
+ (cond
+ ((eqv? car key)
+ (car pair))
+ ((eqv? cdr key)
+ (cdr pair))
+ (else
+ (list-ref pair key))))
+
+(define (pair-set! pair key value)
+ (cond
+ ((eqv? car key)
+ (set-car! pair value))
+ ((eqv? cdr key)
+ (set-cdr! pair value))
+ (else
+ (list-set! pair key value))))
+
;;; SRFI-4 support
(cond-expand
@@ -113,7 +131,7 @@
(append
(list (cons bytevector? bytevector-u8-ref)
(cons hashtable? hashtable-ref)
- (cons pair? list-ref)
+ (cons pair? pair-ref)
(cons string? string-ref)
(cons vector? vector-ref))
srfi-4-getters)))
@@ -123,7 +141,7 @@
(append
(list (cons bytevector? bytevector-u8-set!)
(cons hashtable? hashtable-set!)
- (cons pair? list-set!)
+ (cons pair? pair-set!)
(cons string? string-set!)
(cons vector? vector-set!))
srfi-4-setters)))