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.

Reply via email to