2016-07-14 87 views
1

是否有可能使用大括號{}來指示一組語句,以替換'begin'關鍵字。因此,而不是:花括號{}替換Racket中的'begin'

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

,我們可以使用:

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

這怎麼可能accompalished?感謝您的回答。

回答

5

這是完全可能的,有幾種方法可以做到這一點。 (快速注意到我開始之前,我將使用block而不是begin因爲它的行爲與內部定義更好。)

一個稍微砍-Y的辦法是重新定義什麼功能應用手段,使大括號被處理特別。您可以通過定義一個宏#%app做到這一點:

#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 

另一種方法是定義一個新的#lang語言和延長readtable與該{性格不同的條目。讓我去做這件事......

要定義一個#lang語言,您需要將讀者實現放在your-language/lang/reader.rkt。這裏是curly-block/lang/reader.rkt,其中curly-block目錄作爲單個收集包安裝。

;; 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)) 

使用它:

#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