[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Contracts macro example
From: |
Maxime Devos |
Subject: |
Re: Contracts macro example |
Date: |
Wed, 20 Jul 2022 10:55:53 +0200 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Thunderbird/91.11.0 |
On 20-07-2022 10:39, Zelphir Kaltstahl wrote:
It would also be nice to define a global 'require' and 'ensure' and
'<?>' somewhere (e.g.: (define-syntax require (identifier-syntax
(syntax-error "'require' can only be used as part of a contract
construct")))), that way, require / ensure / <?> can be renamed during
importing, so all contract things could be prefixed with, say,
contract:.
I thought about implementing <?> for the insertion location of the
result in a predicate, but initially wanted to keep it simple and get
a simple version to work. I think I have seen this for pipelining in
an SRFI before … *checks* … Maybe in
https://srfi.schemers.org/srfi-197/srfi-197.html, or
https://srfi.schemers.org/srfi-26/srfi-26.html, or maybe in some other
repository.
Now that the basic version works, I can try to introduce the placeholder.
The idea is to define these globally in the module, so that they can
be exported separately, so that they can be renamed upon import, correct?
Yes.
How could a macro check, whether it is used inside something else? If
the pattern matching only looks at the form of the macro itself, how
can I get the "context", in which it was used and check, whether that
is inside a `define-with-contract`? I think I have not yet unlocked
that knowledge yet : )
That's one way to implement things (syntax-parameterize sounds useful
here), but that sounds way more complicated than needs to be. All you
need to do is:
* keep the original code
* Add:
(define <?> "consider define-syntax+identifier-syntax+syntax-error
for better error messages but this will do for now)
* Export <?> (at least, once your code is turned into a module, if the
users of define-with-contract are in the same module as
define-with-contract then exporting isn't required though harmless)
* Likewise for 'require' and 'ensure'
By doing that, syntax-rules knows that its '<?>', 'require' and 'ensure'
is not just the symbol '<?>' 'require' and 'ensure', but the
_identifier_ (which keeps being the same identifier after renaming)
'<?>', 'require' and 'ensure'.
(Note that as a consequence, if you do that, (let ((require 0))
(define-with-contract foo (require) (ensure) (lambda _ 0))) will be a
syntax error, because the 'require' in define-with-contract now refers
to the variable 'require' from the let, not the identifier from your
RnRS module).
That's all you need to do (untested)!
Greetings,
Maxime
OpenPGP_0x49E3EE22191725EE.asc
Description: OpenPGP public key
OpenPGP_signature
Description: OpenPGP digital signature