[plt-scheme] Fun with paren-shape
Matthias Felleisen skrev:
> Why don't you add | so that you can write [ n | (< 0 n 11)] ? -- Matthias
This version support:
> [n : (< n 10)]
(0 1 2 3 4 5 6 7 8 9)
Numbers are accumulated in the list while (< n 10) is true.
> [n : (< n 10) (even? n)]
(0 2 4 6 8)
The list accumulation runs while (< n 10).
The elements must fullfill the predicate (even? n).
> [n : (< n 100) (< 5 n 15)]
(6 7 8 9 10 11 12 13 14)
/Jens Axel
(module index mzscheme
(provide (rename my-app #%app))
(require-for-syntax (lib "stx.ss" "syntax"))
(define (interval n m)
(cond
[(>= n m) '()]
[(< n m) (cons n (interval (+ n 1) m))]))
(define-syntax (my-app stx)
(define (bracket-shaped? stx)
(equal? (syntax-property stx 'paren-shape) #\[))
(define (brackets? parens)
(syntax-case parens ()
[(x) (bracket-shaped? parens)]
[_ #f]))
(define (range? stx)
(syntax-case* stx (..) module-or-top-identifier=?
[(a .. b) (bracket-shaped? stx)]
[_ #f]))
(define (handle-brackets exprs)
; vector brackets
(let loop ([exprs exprs]
[prev-exprs '()])
(cond
[(null? exprs)
(reverse prev-exprs)]
[(null? (cdr exprs))
(loop (cdr exprs) (cons (car exprs) prev-exprs))]
[(not (brackets? (cadr exprs)))
(loop (cdr exprs) (cons (car exprs) prev-exprs))]
[else
(loop (cddr exprs)
(cons (quasisyntax/loc (cadr exprs)
(vector-ref #,(car exprs) #,@(cadr exprs)))
prev-exprs))])))
(define (handle-ranges exprs)
(let loop ([exprs exprs]
[prev-exprs '()])
(cond
[(null? exprs)
(reverse prev-exprs)]
[(not (range? (car exprs)))
(loop (cdr exprs) (cons (car exprs) prev-exprs))]
[else
(with-syntax ([[from .. to] (car exprs)])
(loop (cdr exprs)
(cons (syntax/loc (car exprs)
(interval from to))
prev-exprs)))])))
(syntax-case* stx (.. :) module-or-top-identifier=?
[(_ a .. b)
(bracket-shaped? stx)
(quasisyntax/loc stx
(interval a b))]
[(_ n : while-pred-expr)
(bracket-shaped? stx)
(quasisyntax/loc stx
(let loop ([n 0])
(if while-pred-expr
(cons n (loop (+ n 1)))
'())))]
[(_ n : while-pred-expr filter-expr)
(bracket-shaped? stx)
(quasisyntax/loc stx
(let loop ([n 0])
(if while-pred-expr
(if filter-expr
(cons n (loop (+ n 1)))
(loop (+ n 1)))
'())))]
[(_ expr . more )
(or (ormap brackets? (cddr (syntax->list stx)))
(ormap range? (cdr (syntax->list stx))))
(with-syntax ([(expr ...)
(handle-ranges
(handle-brackets
(cdr (syntax->list stx))))])
(quasisyntax/loc stx
(#%app expr ...)))]
[(_ . more)
(syntax/loc stx
(#%app . more))])))
(require index)
(define (sum xs)
(apply + xs))
[1 .. 11]
(sum [1 .. 11])
(define v (vector 'a 'b 'c))
(list v[0] v[1] v[2])
(define (len o)
(cond
[(pair? o) (length o)]
[(vector? o) (vector-length o)]
[(string? o) (string-length o)]
[(bytes? o) (bytes-length o)]
[else (error 'len "I give up" o)]))
(define v1 (vector 1 0 1))
(define v2 (vector 2 3 4))
(define (dot-product v1 v2)
(sum (map (λ (i) (* v1[i] v2[i]))
[0 .. (len v1)])))
(dot-product v1 v2)