這是完全可能的,有幾種方法可以做到這一點。 (快速注意到我開始之前,我將使用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