Le samedi 27 août 2016 03:54:00 UTC+2, Anthony Carrico a écrit :
> On 08/26/2016 11:10 AM, Matthias Felleisen wrote:
> Likewise. Can you say something for us lurkers about the use cases? Do
> you think it is workable to have an identifier act as a type expander,
> match expander, normal macro and identifier macro?
Think about a struct defined using `(struct s ([field : type] …))`. The
identifier `s` has a special meaning when used as a type or a match pattern,
can be called as a function, or used as an identifier whose value is a
function, e.g. in `(map s '(vals …) '(more-vals …))`.
I'm currently developing an Algebraic Data Types library [1] similar to the one
by Andrew Kent [2], but with the following features:
* Structure types work like prefab structs, but with field names: two structure
types in two different files are identical if they have the same field names
and field types (without the need to declare them beforehand).
* Constructor tags work like symbols: two constructor types in two different
files are identical if they have the same tag name and content type (without
the need to declare them beforehand).
* The same constructor can belong to two distinct variant types, i.e. variants
are just unions of constructors. In contrast, most implementations allow a
constructor to be present in only a single variant.
With the multi-id library, I can define the `s1` structure as a type-expander,
match-expander, macro and identifier macro, so that the code at [2] works. I
included the whole file at the end of this message.
It is similarly possible to define a constructor `c` as a type-expander,
match-expander, macro and identifier macro, so that you can write:
(match (ann (c 1 2 3) (c Number Number Number))
[(c x y z) (+ x y z)])
Note that the phc-adt package isn't quite ready yet, it should be reasonably
stable in a week or so.
[1] : https://github.com/jsmaniac/phc-adt.git
[2] : https://github.com/andmkent/datatype.git
[3] :
https://github.com/jsmaniac/phc-adt/blob/master/test/mailing-list-example/example.rkt
#lang typed/racket
;; phc-adt sets registers some information in its support files when it
;; encounters new structure types, so this file has to be compiled twice
;; in DrRacket (not on the command-line). The first compilation will fail,
;; it is normal and expected (but it should soon give a better error message)
(require type-expander multi-id phc-adt typed/rackunit)
(adt-init)
;; This internally does
;; (define-multi-id s1
;; #:type-expander (λ (stx) …)
;; #:match-expander (λ (stx) …)
;; #:call (λ (stx) …)
;; #:id (λ (stx) …))
(define-structure s1 [a : Number] [b : String])
;; The "structure" identifier is also a multi-id, for on-the-fly usage of a
;; structure as a type, match pattern, constructor function or instance creation
(: foo (→ (U
;; type-expander: s1
s1
;; type-expander: (structure [field : type] …)
(structure [a : Number] [c : Symbol]))
Number))
(define (foo s)
(match s
;; match-expander: (s1 pat ...)
[(s1 (? number? the-a) the-b) (+ the-a (string-length the-b))]
;; match-expander: (structure field-name …)
[(structure a c) (+ a (string-length (symbol->string c)))]))
(define instances
(append
;; identifier macro: s1, to pretend it's a function
(map s1
(range 5)
'("x" "xx" "xxx" "xxxx" "xxxxx"))
;; macro: (s1 args …), to pretend it's a function call
(list (s1 42 "Why does six times nine equal forty two?"))
;; macro: (structure [field : type] …), produces a bulder function
(map (structure [a : Number] [c : Symbol])
(reverse (range 5))
'(x xx xxx xxxx xxxxx))
;; macro: (structure [field value] …) or (structure [field : type value]),
;; produces an instance
(list (structure [a pi] [c 'three-fourteen]))))
(check-equal? (map foo instances)
(append '(1 3 5 7 9)
'(82)
'(5 5 5 5 5)
'(17.141592653589793)))
--
You received this message because you are subscribed to the Google Groups
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.