commit eb1a555fba36e7eda3964d22ddda4d86dfb45efc
parent a6f77aabdfd2d03685b4c5601fc87f41a398d937
Author: Arthur A. Gleckler <arthurgleckler@users.noreply.github.com>
Date: Tue, 18 Aug 2015 11:37:37 -0700
Merge pull request #3 from TaylanUB/master
Incorporate Taylan's changes for fourth draft.
Diffstat:
2 files changed, 49 insertions(+), 7 deletions(-)
diff --git a/srfi-123.html b/srfi-123.html
@@ -89,11 +89,15 @@ struct ;=> #(a (x y #u8(4 2 3)) c)</code></pre>
;does something else.</code></pre>
<p>Valid types for <code>object</code> are: bytevectors, hashtables, pairs, strings, vectors, non-opaque record types, and SRFI-4 vectors if present. Only hashtables are a sparse type. Implementations are encouraged to expand this list of types with any further types they support.</p>
<p>Valid types for <code>field</code> depend on the type of <code>object</code>. For bytevectors, hashtables, strings, vectors, and SRFI-4 vectors, refer to their respective <code>*-ref</code> procedures. For pairs, refer to <code>list-ref</code>. For records, symbols that correspond with the record type's field names are allowed.</p>
+<p>The <code>ref</code> procedure has an associated SRFI-17 setter, although the one of <code>ref*</code> is strictly more powerful.</p>
+<pre><code>(define vec (vector 0 1 2))
+(set! (ref vec 0) 3)
+vec ;=> #(3 1 2)</code></pre>
<ul>
<li><code>(ref* object field field* ...)</code> (procedure)</li>
<li><code>(~ object field field* ...)</code></li>
</ul>
-<p>The semantics is of this procedure is as follows:</p>
+<p>The semantics of this procedure is as follows:</p>
<pre><code>(ref* object field) = (ref object field)
(ref* object field field+ ...) = (ref* (ref object field) field+ ...)</code></pre>
<p>It has an associated SRFI-17 setter, which does the expected thing:</p>
@@ -105,17 +109,21 @@ struct ;=> #(a (x y #u8(4 2 3)) c)</code></pre>
<li><code>(register-getter-with-setter! type getter sparse?)</code> (procedure)</li>
</ul>
<p>Registers a new type/getter/setter triple for the dynamic dispatch. <code>Type</code> is a type predicate, <code>getter</code> is a procedure that has a setter associated with it, and <code>sparse?</code> is a Boolean indicating whether the type is a sparse type (see <code>ref</code> specification).</p>
+<p>The getter will be called with two arguments: the object whose field should be accessed, and an object identifying the field to be accessed. The setter will be called with one additional argument which is the value to be assigned to the given field of the given object.</p>
+<p><strong>Warning:</strong> This procedure is strictly meant for when defining a new disjoint type, which isn't already handled by <code>ref</code>. In practice, this means it should only be used with newly defined opaque record types, or types defined with some implementation-specific method which, unlike <code>define-record-type</code>, doesn't automatically register a getter and setter for the type. If any two type predicates registered with the system both return true for any Scheme object, the behavior is undefined. (A custom getter or setter may, however, dispatch to different actions based on some property of the given object, based on the <code>field</code> argument, or based on anything else.)</p>
+<p>It is conceivable that this method will become deprecated after a system has been invented which ties together the definition of a new opaque record type with the definitions of its getter and setter. This is considered outside the scope of this SRFI.</p>
<h2 id="considerations-when-using-as-a-library">Considerations when using as a library</h2>
<p>The intent of this SRFI is to encourage Scheme systems to extend their standard library in accordance with the above specification. On the meanwhile, the reference implementation can be used as a separate library, but certain considerations apply.</p>
<p>The <code>define-record-type</code> export of the library conflicts with the one in <code>(scheme base)</code>, so either has to be renamed, or more typically, the one from <code>(scheme base)</code> excluded.</p>
-<p>Record types not defined with the <code>define-record-type</code> exported by this library won't work with <code>ref</code> and <code>ref*</code>.</p>
+<p>Record types not defined with the <code>define-record-type</code> exported by this library won't work with <code>ref</code>, <code>ref*</code>, or their setters.</p>
<h2 id="implementation">Implementation</h2>
<p>A reference implementation as a library is found in the version control repository of this SRFI.</p>
<p>It might be desirable for Scheme systems to offer a more efficient <code>type-of</code> procedure than the one used in this implementation, which in the worst case consumes linear time with regard to the number of types (including every record type) within the system, albeit with a very small constant factor: one call to each type predicate.</p>
<h2 id="acknowledgments">Acknowledgments</h2>
<p>Thanks to Jorgen Schäfer for inspiring me to write this SRFI and making the initial suggestion for the <code>ref</code> procedure and ternary <code>set!</code> syntax, as well as providing continuous input.</p>
-<p>The <code>ref*</code> procedure with its <code>~</code> synonym and SRFI-17 setter (which replaced the initially considered ternary <code>set!</code> syntax) seems to have first appeared in Gauche. Thanks to Shiro Kawai: <a href="http://blog.practical-scheme.net/gauche/20100428-shorter-names" class="uri">http://blog.practical-scheme.net/gauche/20100428-shorter-names</a></p>
+<p>The <code>ref*</code> procedure with its <code>~</code> synonym and SRFI-17 setter (which replaced the initially considered ternary <code>set!</code> syntax) seems to have first appeared in Gauche. Thanks to Shiro Kawai and Issac Trotts: <a href="http://blog.practical-scheme.net/gauche/20100428-shorter-names" class="uri">http://blog.practical-scheme.net/gauche/20100428-shorter-names</a></p>
<p>Thanks to Evan Hanson for the idea of using a throw-away <code>define</code> in the expansion of <code>define-record-type</code> so as not to disturb a sequence of internal definitions.</p>
+<p>Thanks to Vincent St-Amour, Eli Barzilay, and others in the Racket IRC channel for raising my awareness against action-at-a-distance bugs that might result from abuse of the imperative <code>register-getter-with-setter!</code>.</p>
<p>Thanks also to everyone else on the discussion mailing list for their input.</p>
<h2 id="copyright-and-license">Copyright and license</h2>
<p>Copyright (C) Taylan Ulrich Bayırlı/Kammer (2015). All Rights Reserved.</p>
diff --git a/srfi-123.md b/srfi-123.md
@@ -141,7 +141,7 @@ the same key, is more common.)
Integration with SRFI-105
--------------------------------------
+-------------------------
The `ref*` procedure is a good candidate for SRFI-105's
`$bracket-apply$`. Indeed the reference implementation exports
@@ -199,10 +199,17 @@ to their respective `*-ref` procedures. For pairs, refer to
`list-ref`. For records, symbols that correspond with the record
type's field names are allowed.
+The `ref` procedure has an associated SRFI-17 setter, although the one
+of `ref*` is strictly more powerful.
+
+ (define vec (vector 0 1 2))
+ (set! (ref vec 0) 3)
+ vec ;=> #(3 1 2)
+
- `(ref* object field field* ...)` (procedure)
- `(~ object field field* ...)`
-The semantics is of this procedure is as follows:
+The semantics of this procedure is as follows:
(ref* object field) = (ref object field)
(ref* object field field+ ...) = (ref* (ref object field) field+ ...)
@@ -225,6 +232,28 @@ Registers a new type/getter/setter triple for the dynamic dispatch.
associated with it, and `sparse?` is a Boolean indicating whether the
type is a sparse type (see `ref` specification).
+The getter will be called with two arguments: the object whose field
+should be accessed, and an object identifying the field to be
+accessed. The setter will be called with one additional argument
+which is the value to be assigned to the given field of the given
+object.
+
+**Warning:** This procedure is strictly meant for when defining a new
+disjoint type, which isn't already handled by `ref`. In practice,
+this means it should only be used with newly defined opaque record
+types, or types defined with some implementation-specific method
+which, unlike `define-record-type`, doesn't automatically register a
+getter and setter for the type. If any two type predicates registered
+with the system both return true for any Scheme object, the behavior
+is undefined. (A custom getter or setter may, however, dispatch to
+different actions based on some property of the given object, based on
+the `field` argument, or based on anything else.)
+
+It is conceivable that this method will become deprecated after a
+system has been invented which ties together the definition of a new
+opaque record type with the definitions of its getter and setter.
+This is considered outside the scope of this SRFI.
+
Considerations when using as a library
--------------------------------------
@@ -239,7 +268,7 @@ in `(scheme base)`, so either has to be renamed, or more typically,
the one from `(scheme base)` excluded.
Record types not defined with the `define-record-type` exported by
-this library won't work with `ref` and `ref*`.
+this library won't work with `ref`, `ref*`, or their setters.
Implementation
@@ -264,13 +293,18 @@ making the initial suggestion for the `ref` procedure and ternary
The `ref*` procedure with its `~` synonym and SRFI-17 setter (which
replaced the initially considered ternary `set!` syntax) seems to have
-first appeared in Gauche. Thanks to Shiro Kawai:
+first appeared in Gauche. Thanks to Shiro Kawai and Issac Trotts:
<http://blog.practical-scheme.net/gauche/20100428-shorter-names>
Thanks to Evan Hanson for the idea of using a throw-away `define` in
the expansion of `define-record-type` so as not to disturb a sequence
of internal definitions.
+Thanks to Vincent St-Amour, Eli Barzilay, and others in the Racket IRC
+channel for raising my awareness against action-at-a-distance bugs
+that might result from abuse of the imperative
+`register-getter-with-setter!`.
+
Thanks also to everyone else on the discussion mailing list for their
input.