[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: define-typed: checking values on proc entry and exit
From: |
Dr. Arne Babenhauserheide |
Subject: |
Re: define-typed: checking values on proc entry and exit |
Date: |
Tue, 14 May 2024 03:34:46 +0200 |
User-agent: |
mu4e 1.12.4; emacs 30.0.50 |
Vivien Kraus <vivien@planete-kraus.eu> writes:
> Hello!
>
> This is an interesting approach, thank you.
>
> Le vendredi 10 mai 2024 à 09:47 +0200, Dr. Arne Babenhauserheide a
> écrit :
>> │ ;; get the result
>> │ (let ((res (helper)))
>> │ ;; typecheck the result
>> │ (unless (ret? res)
>> │ (error "type error: return value ~a does not match ~a"
>> │ res ret?))
>> │ ;; return the result
>> │ res))
>
> A nice improvement would be to support multiple return values, for
> instance by using call-with-values, and checking the return value with
> (apply ret? res) instead of (ret? res).
>
> What do you think?
That’s a nice idea!
With some experimentation I got it working:
┌────
│ (import (srfi :11 let-values))
│ (define-syntax-rule (define-typed (procname args ...) (ret? types ...) body
...)
│ (begin
│ (define (procname args ...)
│ ;; create a sub-procedure to run after typecheck
│ (define (helper)
│ body ...)
│ ;; use a typecheck prefix for the arguments
│ (map (λ (type? argument)
│ (unless (type? argument)
│ (error "type error ~a ~a" type? argument)))
│ (list types ...) (list args ...) )
│ ;; get the result
│ (let-values ((res (helper)))
│ ;; typecheck the result
│ (unless (apply ret? res)
│ (error "type error: return value ~a does not match ~a"
│ res ret?))
│ ;; return the result
│ (apply values res)))
│ ;; add procedure properties via an inner procedure
│ (let ((helper (lambda (args ...) body ...)))
│ (set-procedure-properties! procname (procedure-properties helper))
│ ;; preserve the name
│ (set-procedure-property! procname 'name 'procname))))
└────
This supports most features of regular define like docstrings, procedure
properties, multiple values (thanks to Vivien!), and so forth.
┌────
│ (define-typed (hello typed-world) (string? string?)
│ typed-world)
│ (hello "typed")
│ ;; => "typed"
│ (hello 1337)
│ ;; => type error ~a ~a #<procedure string? (_)> 1337
│ (define-typed (hello typed-world) (string? string?)
│ "typed"
│ #((props))
│ typed-world)
│ (procedure-properties hello)
│ ;; => ((name . hello) (documentation . "typed") (props))
│ (define-typed (multiple-values num) ((λ(a b) (> a b)) number?)
│ (values (* 2 (abs num)) num))
│ (multiple-values -3)
│ ;; => 6
│ ;; => -3
└────
Best wishes,
Arne
signature.asc
Description: PGP signature