2016-07-14 11 views
1

Ist es möglich, ein Makro zu verwenden, das geschweifte Klammern {} verwendet, um einen Block von Statements anzugeben, um das Schlüsselwort 'begin' zu ersetzen. Daher statt:Lockige Klammern {} zum Ersetzen von 'Begin' im Racket

(if (condition) 
    (begin 
     (statement1) 
     (statement2) 
     (statement3) 
     (statement4)) 
    (else-statement)) 

können wir verwenden:

(if (condition) { 
     (statement1) 
     (statement2) 
     (statement3) 
     (statement4) } 
    (else-statement)) 

Wie dies accompalished werden kann? Danke für deine Antworten.

Antwort

5

Dies ist vollständig möglich, und es gibt mehrere Möglichkeiten, dies zu tun. (Quick Note, bevor ich beginne, werde ich block statt begin verwenden, da es mit internen Definitionen besser verhält.)

Ein leicht hack-y Weg ist, neu zu definieren, welche Funktion Anwendung bedeutet, so dass geschweiften Klammern behandelt werden speziell. Sie können durch Definieren eines #%app Makro dies zu tun:

#lang racket 
(require racket/block syntax/parse/define (prefix-in - racket)) 
;; This #%app macro redefines what function application means so that 
;; { def-or-expr ... } expands into (block def-or-expr ...) 
;; Otherwise it uses normal function application 
(define-syntax-parser #%app 
    [{_ def-or-expr:expr ...} 
    #:when (equal? #\{ (syntax-property this-syntax 'paren-shape)) 
    ;; group them in a block 
    #'(block def-or-expr ...)] 
    [(_ f:expr arg ...) 
    #:when (not (equal? #\{ (syntax-property this-syntax 'paren-shape))) 
    ;; expand to the old #%app form, from (prefix-in - racket) 
    #'(-#%app f arg ...)]) 
;; using it: 
(define (f x) 
    (if (< 5 x) { 
     (define y (- x 5)) 
     (f y) 
     } 
     x)) 
(f 1) ; 1 
(f 5) ; 5 
(f 6) ; 1 
(f 10) ; 5 
(f 11) ; 1 

Eine andere Möglichkeit wäre eine neue #lang Sprache zu definieren und die Readtable mit einem anderen Eintrag für den { Zeichen zu erweitern. Lass mich gehen und das tun ...

Um eine Sprache zu definieren, müssen Sie die Reader-Implementierung in your-language/lang/reader.rkt setzen. Hier ist das curly-block/lang/reader.rkt, wo das Verzeichnis curly-block als Single-Collection-Paket installiert ist.

;; s-exp syntax/module-reader is a language for defining new languages. 
#lang s-exp syntax/module-reader 
racket 
#:wrapper1 (lambda (th) 
      (parameterize ([current-readtable (make-curly-block-readtable (current-readtable))]) 
       (th))) 

;; This extends the orig-readtable with an entry for `{` that translates 
;; { def-or-expr ... } into (block def-or-expr ...) 
(define (make-curly-block-readtable orig-readtable) 
    (make-readtable orig-readtable 
    #\{ 'terminating-macro curly-block-proc)) 

;; This is the function that the new readtable will use when in encounters a `{` 
(define (curly-block-proc char in src ln col pos) 
    ;; This reads the list of things ending with the character that closes `char` 
    ;; The #f means it uses the racket reader for the first step, so that `{` 
    ;; uses the normal behavior, grouping expressions into a reader-level list 
    (define lst (read-syntax/recursive src in char #f)) 
    (cons 'block lst)) 

Mit ihm:

#lang curly-block 
(require racket/block) 
(define (f x) 
    (if (< 5 x) { 
     (define y (- x 5)) 
     (f y) 
     } 
     x)) 
(f 1) ; 1 
(f 5) ; 5 
(f 6) ; 1 
(f 10) ; 5 
(f 11) ; 1 
Verwandte Themen