I'm trying to recall why we exposed make-promise? It was only used as
an example and not a pre-defined procedure in R5RS.
We modeled the delayed evaluation off of SRFI 45, which also does not
include this procedure.
Note SRFI 155 - Promises shares this same make-promise "feature" with R7RS.
I don't think this is broken, per se, and would not normally be
something to consider as an erratum, although the inconsistency in the
sample implementation offers leverage. Keep in mind that although
promises are not guaranteed to be a disjoint _type_, `promise?` must
be accurate.
So while I think I would prefer your suggestion I'm not sure we can justify it.
On 03/08/2021 07:37, Marc Nieper-Wißkirchen wrote:
> The "obvious axiom" is the following:
>
> (force (make-promise obj)) => obj
>
> In R7RS, this axiom is violated because make-promise has to return a
> promise unchanged:
>
> (force (make-promise (make-promise obj))) => obj
Is there anything this is *useful* for? I mean, it smacks to me of a bit
of Perl-esque "do what I mean" thing, like making (+ "1" 1) => 2.
I suspect that it's quite important (to the correct functioning of most
code involving promises) that the code "knows" whether a value is a
promise or not, rather than having maybe-promises flying around. In
which case, applying make-promise to a promise would be a deliberate act
done with the intention of creating a two-layer-deep promise, rather
than done deliberately as a no-op. And something that blindly applies
make-promise to unknown things as part of some generic data structure or
algorithm is going to force the promises and expect to get the original
values back, as per the "obvious axiom".
--
Alaric Snell-Pym (M0KTN neé M7KIT)
http://www.snell-pym.org.uk/alaric/
--
You received this message because you are subscribed to a topic in the Google Groups "scheme-reports-wg1" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/scheme-reports-wg1/bQcQZK3GBHw/unsubscribe.
To unsubscribe from this group and all its topics, send an email to scheme-reports-...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/scheme-reports-wg1/90e40646-88cc-6fc5-7561-92010013cc86%40snell-pym.org.uk.
On Tue, Aug 3, 2021 at 6:03 PM Marc Nieper-Wißkirchen
<marc....@gmail.com> wrote:
>
> Am Di., 3. Aug. 2021 um 10:46 Uhr schrieb Alex Shinn <alex...@gmail.com>:
>>
>> I don't think this is broken, per se, and would not normally be
>> something to consider as an erratum, although the inconsistency in the
>> sample implementation offers leverage. Keep in mind that although
>> promises are not guaranteed to be a disjoint _type_, `promise?` must
>> be accurate.
>
> Right, but the latter doesn't help much. For example, an implementation could also declare (some) integers to be promises (interpreting them as indices in a lookup table for already forced promises). Or, only a slight variation of the sample implementation in SRFI 45 will turn every pair into a promise.
Integers could not be used because then `promise?` would be broken.
Given a predicate distinguishing elements of a non-disjoint type, one
could consider 3 approaches:
1. Ambiguous with some existing type, such as integers or procedures.
The description of the predicate should indicate this with clear
warnings as for string cursors in SRFI 130, e.g. saying "_can_ be a
string-cursor".
2. A transparent subset of some existing type, such as tagged vectors.
Both `new-type?` and `vector?` will return true for instances, so the
former should take precedence. Instances of this type can be forged,
but otherwise false positives would not normally occur in practice.
3. An opaque subset of some existing type, such as procedures tracked
in a global weak hash table. The same caveats as the above approach
apply, but instances cannot be forged.
As there is no warning or discussion of false positives for `promise?`
I would argue the first approach is not a realistic option. In R5RS,
where there was no `promise?` procedure, the first approach of course
was allowed and widely used.
Given a predicate distinguishing elements of a non-disjoint type, onecould consider 3 approaches:
1. Ambiguous with some existing type, such as integers or procedures.
The description of the predicate should indicate this with clear
warnings as for string cursors in SRFI 130, e.g. saying "_can_ be a
string-cursor".
2. A transparent subset of some existing type, such as tagged vectors.
Both `new-type?` and `vector?` will return true for instances, so the
former should take precedence. Instances of this type can be forged,
but otherwise false positives would not normally occur in practice.
3. An opaque subset of some existing type, such as procedures tracked
in a global weak hash table. The same caveats as the above approach
apply, but instances cannot be forged.
As there is no warning or discussion of false positives for `promise?`
I would argue the first approach is not a realistic option. In R5RS,
where there was no `promise?` procedure, the first approach of course
was allowed and widely used.In R7RS, all three approaches are allowed.
PS Note that R7RS also permits that implementations let promise? returns true for every object.
On Tue, Aug 3, 2021 at 10:34 AM Marc Nieper-Wißkirchen <marc....@gmail.com> wrote:Given a predicate distinguishing elements of a non-disjoint type, onecould consider 3 approaches:
1. Ambiguous with some existing type, such as integers or procedures.
The description of the predicate should indicate this with clear
warnings as for string cursors in SRFI 130, e.g. saying "_can_ be a
string-cursor".
2. A transparent subset of some existing type, such as tagged vectors.
Both `new-type?` and `vector?` will return true for instances, so the
former should take precedence. Instances of this type can be forged,
but otherwise false positives would not normally occur in practice.
3. An opaque subset of some existing type, such as procedures tracked
in a global weak hash table. The same caveats as the above approach
apply, but instances cannot be forged.
As there is no warning or discussion of false positives for `promise?`
I would argue the first approach is not a realistic option. In R5RS,
where there was no `promise?` procedure, the first approach of course
was allowed and widely used.In R7RS, all three approaches are allowed.That turns out not to be the case.The canons of interpretation provide (among other things), that the text of a provision must be interpreted as a whole, and that the provisions of a text should be interpreted in a way that renders them compatible, not contradictory (see <https://www.law.uh.edu/faculty/adjunct/dstevenson/2018Spring/CANONS%20OF%20CONSTRUCTION.pdf>).The definition of make-promise is: "The promise? procedure returns #t if its argument is a promise, and #f otherwise. Note that promises are not necessarily disjoint from other Scheme types such as procedures." Interpreting the second sentence to allow promises to be indistinguishable from some other type, per approach 1, would render the two sentences contradictory. Therefore, that interpretation is disallowed unless no other interpretation is available. We do, in fact, have two other interpretations available, namely 2 and 3.
I agree that approach 2 produces a lower quality of implementation than approach 3, and approach 4 (disjoint types) is better than either. But QOI has nothing to do with conformance.PS Note that R7RS also permits that implementations let promise? returns true for every object.I also deny this. While it is true that constructs other than delay, delay-force, and make-promise might in principle create a promise, promise? and force are applicable only to promises. (The three extensions to force listed, including the one that allows forcing a non-promise to return the non-promise are not normative, simply a statement of what some implementations do or have done.)
Objection, your honor! Why would, if promise? yielded #t for all lists, the two sentences be rendered contradictory?As long as every list can be interpreted (via force and delay-force) as a promise, there's no contradiction at all.
On Tue, Aug 3, 2021 at 11:34 PM Marc Nieper-Wißkirchen
<marc....@gmail.com> wrote:
>
> In R7RS, all three approaches are allowed.
You can't take the one statement that "promises are not necessarily
disjoint" as license to do anything. As John says, you have to
consider the full system. I don't see how you could represent
promises as integers and not have a completely broken implementation.
On Wed, Aug 4, 2021 at 3:15 PM Marc Nieper-Wißkirchen
<marc....@gmail.com> wrote:
>
> The decision not to do anything with make-promise would leave it in a state where it is essentially useless.
make-promise was always useless - it shouldn't have been added ;)
I'm trying to recall why we exposed make-promise? It was only used as
an example and not a pre-defined procedure in R5RS.
We modeled the delayed evaluation off of SRFI 45, which also does not
include this procedure.