Search code examples
macrosschemeread-eval-print-loopr5rs

How to map a macro over a list - or - How to use macros to define data types


I like to build a REPL with my own datatypes, but I don't like to write all the same pattern functions over and over again.

So this is a nut, which bothers me.

I got my own set of primitive datatypes (define primitives '("mytrue" "myfalse" "mynumber" ...))

Also I have (define primitiveTesters (list "mytrue?" "myfalse?" "mynumber?" ... )

The problem now is, I just want to apply (map) or a macro to get the datatype? procedurces, which basically just checks if the car of record (mynumber . ( . )) exists.

So something similar like (mynumber? (car (mynumber.(1.))) => #t in the end. But for this I need (define mynumber? (lambda (...)(...))

My define-batching macro looks like this, but I just have no luck to infuse the <variable>.

(define-syntax define-batching
(syntax-rules () 
((_ value expr)(define value expr))
((_ value) value)
((_ value1 value2 ...)  (begin (define value1 expr) (define-batching test2...)))
))

So have I reached a dead end of scheme ?

I've seen something similar, I think in Emacs Lisp.

What I am looking for in the end is:

 (define checker '(audi? volkswagen? mercedes?))
 (define datatype '(audi volkswagen mercedes))

 (map define-checker checker datatype )
 or
 (define-checker (car checker) (car datatype))

Solution

  • If I understood the question right, you need a macro to define your own type checkers?

    Here is one way to do it:

    (define-syntax define-checker
      (syntax-rules ()
        [(define-checker name tag)
         (define (name object)
           (and (list? object)
                (not (null? object))
                (eq? (car object) 'tag)))]))
    
    (define-checker my-car? car)
    
    (my-car? '(car audi black))   ; evaluates to #t
    (my-car? '(truck ford pink))  ; evaluates to #f
    

    Addendum:

    If you write

    (define checker '(audi? volkswagen? mercedes?))
    (define datatype '(audi volkswagen mercedes))
    

    the values will become available at runtime. Therefore you need to a different approach.

    You could for example write:

    (define-checker+datatype (audi? audi) (volkswagen? volkswagen?))
    

    Here is the code:

    (define-syntax define-checker
      (syntax-rules ()
        [(define-checker name tag)
         (define (name object)
           (and (list? object)
                (not (null? object))
                (eq? (car object) 'tag)))]))
    
    
    (define-syntax define-checkers+datatype
      (syntax-rules ()
        [(define-checkers+datatype (name tag) ...)
         (begin
           (define-checker name tag)
           ...)]))
    
    (define-checkers+datatype (audi? audi) (wv? wv))
    
    
    (audi? '(audi black))