define-typed: checking values on proc entry and exit
"Dr. Arne Babenhauserheide" <[email protected]>
| Newsgroups | gmane.lisp.guile.user |
|---|---|
| Message-ID | <[email protected]> |
Hi, in #guile on IRC¹, old talked about Typed Racket so I thought whether that could be done with define-syntax-rule. So I created define-typed. This is also on my website², but I wanted to share and discuss it here. I follow the format by [sph-sc], a Scheme to C compiler. It declares types after the function definition like this: ┌──── │ (define (hello typed-world) (string? string?) │ typed-world) └──── ┌──── │ (define-syntax-rule (define-typed (procname args ...) (ret? types ...) body ...) │ (begin │ (define (procname args ...) │ ;; define a helper pro │ (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 ((res (helper))) │ ;; typecheck the result │ (unless (ret? res) │ (error "type error: return value ~a does not match ~a" │ res ret?)) │ ;; return the result │ res)) │ ;; add procedure properties │ (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, 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)) └──── This should automate some of the guards of [Optimizing Guile Scheme], so the compiler can optimize more (i.e. if you check for `real?') but keep in mind that these checks are not free: only typecheck outside tight loops. They provide a type boundary instead of forcing explicit static typing. Also you can do more advanced checks by providing your own test procedures and validating your API more elegantly, but these then won’t help the compiler produce faster code. But keep in mind that this does not actually provide static program analysis like while-you-write type checks. It’s simply [syntactic sugar] for a boundary through which only allowed values can pass. Thanks to program flow analysis by the just-in-time compiler, it can make your code faster, but that’s not guaranteed. It may be useful for your next API definition. My question now: do you have an idea for a better name than define-typed? [sph-sc] <https://github.com/sph-mn/sph-sc> [Optimizing Guile Scheme] <https://dthompson.us/posts/optimizing-guile-scheme.html> [syntactic sugar] <http://www.phyast.pitt.edu/~micheles/scheme/scheme12.html#are-macros-just-syntactic-sugar> ¹ https://web.libera.chat/?nick=Wisp|?#guile ² https://www.draketo.de/software/guile-snippets#define-typed Best wishes, Arne
signature.asc
(application/pgp-signature, 1.1 KB)
-----BEGIN PGP SIGNATURE----- iQJEBAEBCAAuFiEE801qEjXQSQPNItXAE++NRSQDw+sFAmY90RMQHGFybmVfYmFi QHdlYi5kZQAKCRAT741FJAPD68BVD/9pMyDh+oejCgoMW3g21hsAk01uHNcN5PDz rsiRG0QSAZSROEvBg0ZQmuLKzbPB83rY7O0P9ReEu3MSoWlTDt3RyCWq20zopcpZ HfSCExu1to4OYIhr2XxMjMnJ8QzlNvquDNSzMxdrC6/9HcXTkUpRopQqP+fZmb21 etBQGYNjZgcW2JSWG6N/A5on54aLCjuCP6i+lOBidIB5Tys34DW7/Xy2lxCFCpma ljJbBgOYkxZprLz4I32m8Q6TW/mjmsWLIbf7W0GAzZyME8lnjHs7hu3/hJxgD7Yi T6/QF+c1gCv2L+322/h5ICSNt8KSNh1FdZhJt/ITeBMExCI6zY6c0FP1M5VSwCMG 7Aw28EJfLz3ZrKhJJ9+XWmVBq2y0pl3yGpcCqkrKrVxrbm3tq7wlq/cdaZedurjd mHz6bYzH4lnmzz/4DeKJsp041Ox2IQQOITEukMAXplr1Anyx0GW5Qe4uzVHOJMYI i03/C0AoCU17Pvi6m8O1jMNGwb3vmIyPQy3Rdy/ac9R53x8HKHM9XjRy8mmQRkR3 M1oKZQd4PtdwXGpn3cTFHciUVG3KeuOVRrJfaJDJ02iPO9hdAY1fnzdHiZ0G0Hcv F0H/EnI/b61w7OY9orFmvereJWWXLjVZbhqESHWXj/2/SpWUgAeoodyeEOAMfuq1 OVAHbtG/AIjEBAEBCAAuFiEE3Si95tmHXKvOSosd3M8NswvBBUgFAmY90RcQHGFy bmVfYmFiQHdlYi5kZQAKCRDczw2zC8EFSMOxA/0WN72BK1RuV2lxB9Xhc5SVlC7f lgxgjA/jsWxB07+9QjAMYXI7NWxSA8Fk7gXEyexOyn4S7EDPZ0umGSZZee+Qt19a eE9SsF/ifB+aYzMLzRmLe7EUuNEHM5xkK4sDdRIITwS1jL+UJQqwmuVYUshgNshI 72Y8hsv5ZPwIroL6TQ== =HmTX -----END PGP SIGNATURE-----