Some initial comments Daphne Preston-Kendal (04 Apr 2026 10:01 UTC)
Re: Some initial comments Andrew Tropin (07 Apr 2026 11:29 UTC)
Re: Some initial comments Daphne Preston-Kendal (29 Jul 2026 20:17 UTC)
Re: Some initial comments Vincent Manis (he/him) (29 Jul 2026 21:03 UTC)
Re: Some initial comments Wolfgang Corcoran-Mathe (01 Aug 2026 16:16 UTC)

Re: Some initial comments Daphne Preston-Kendal 29 Jul 2026 20:16 UTC

Hiya,

As promised, albeit somewhat belated, some further comments – now on the latest draft:

1. It is not possible to implement current-test-runner / set-current-test-runner! in portable Scheme

In R7RS there is no way to set the value of a parameter object apart from its default value (given at make-parameter time) and local rebinding with parameterize. Either set-current-test-runner! cannot exist, or current-test-runner is not a parameter object.

The recommendation ‘Libraries that provide a test runner should call set-current-test-runner! upon loading so that end users need not configure it manually’ which appears to be the raison d’être for set-current-test-runner! is ill advised in any case. Loading a library should not, in general, affect global state in a way that could lead to conflicts depending on the order of library instantiation, because the order of library instantiation is unspecified in Scheme.

I would simply delete the set-current-test-runner! procedure.

2. The 'metadata syntax is insensible and also seems not implementable in R7RS small

It is hard to tell at a glance what the intention of the 'metadata syntax used in ‘test’ and ‘suite’ is. On inspection, it appears that it must be recognized at the syntactic level, not at run time; otherwise ‘test’ and ‘suite’ could not have bodies (they could not begin with definitions). However the use of ‘quote’ only makes sense in an expression context where the quoted datum could be the return value of an expression evaluation.

The use of ‘quote’ implies somehow that the keyword ‘metadata’ should be matched by its symbolic name, but syntax-rules – the only macro system in R7RS small – is not capable of doing this.

No other syntax in Scheme works this way, so it’s hard for me to tell what the intention of the spec authors is here in terms of how the 'metadata ‘keyword’ is supposed to be recognized by the implementation.

The best solution in my view would be to have separate exported names for ‘test’ and ‘suite’ with and without metadata, rather than combine them into two forms. So there might be, omitting for simplicity the case of an empty context:

(test <<description>> (<<context>>) <<body>>)
(test-with-metadata <<description>> (<<context>>) <<metadata>> <<body>>)

(suite <<description>> <<body>>)
(suite-with-metadata <<description>> <<metadata>> <<body>>)

[where <<metadata>> is an expression which evaluates to the metadata to be used – incidentally, the 'quote issue is likely only the most obvious symptom of a thoroughgoing flaw in this SRFI’s spec text, which is the failure to distinguish syntactic forms from the values they evaluate to as expressions, a vital distinction when new syntax is defined. consider adopting the report style of consecutive sections on Syntax and Semantics]

Another option would be to export a ‘metadata’ auxiliary syntactic keyword, which *can* be matched by binding by syntax-rules. The precedent of R6RS define-record-type then says that the syntax should be e.g.

(test <<description>> (<<context>>) <<body>>)
(test <<description>> (<<context>>) (metadata <<metadata expression>>) <<body>>)

or even for the latter

(test <<description>> (context <<context expression>>) (metadata <<metadata expression>>) <<body>>)

where either clause could be optional.

3. Ad hoc alists where records should maybe be used

I am less sure about this one. There can be good reasons to stick to using the basic Scheme datum types instead of requiring (imported) access to a particular record type, mainly that it is the only way in R7RS small Scheme to create a protocol in which different components can interact without having to import a common library which defines and exports a record type. (R6RS has nongenerative record types for this, which is a preferable solution where available.)

But in general, I get icky feelings about alists with specifically defined symbolic keys. This is what records are for. (There also seems to be no reason to limit the type of user-defined ‘metadata’ to an alist, for that matter – why not let users supply any arbitrary object as their metadata?)

If you intend test suites and runner implementations to be able to interact without actually importing (srfi :269), there is a good excuse for using alists. Otherwise, records are type safe unlike alists, faster than alists, use less memory than alists, and are generally cleaner.

I may yet find some more things to complain about ;-), but those are the ones that I spotted on a quick skim of this latest draft. (Apologies for not flagging those earlier that were there right from the start.)

Daphne