Is it possible to have a macro to use curly brackets {} to indicate a block of statments, so as to replace the 'begin' keyword. Hence, instead of:
(if (condition)
(begin
(statement1)
(statement2)
(statement3)
(statement4))
(else-statement))
we may use:
(if (condition) {
(statement1)
(statement2)
(statement3)
(statement4) }
(else-statement))
How can this be accomplished? Thanks for your answers.
Brackets are used to insert explanations, corrections, clarifications, or comments into quoted material. Brackets are always used in pairs; you must have both an opening and a closing bracket.
In programming, curly braces (the { and } characters) are used in a variety of ways. In C/C++, they are used to signify the start and end of a series of statements. In the following expression, everything between the { and } are executed if the variable mouseDOWNinText is true. See event loop.
The curly brackets are used to denote a block of code in a function. So, say we need a function to calculate the standard error we might do this. The square brackets are used to subset vectors and data frames.
There are no lists or dictionaries in Lua, but a "table" type which serves as both. So curly brackets are used as a table constructor.
This is completely possible, and there are several ways to do it. (Quick note before I start, I'm going to use block
instead of begin
because it behaves better with internal definitions.)
#%app
One slightly hack-y way is to redefine what function application means so that curly-braces are treated specially. You can do this by defining an #%app
macro:
#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
Another way would be to define a new #lang
language and extend the readtable with a different entry for the {
character. Let me go and do that ...
To define a #lang
language, you need to put the reader implementation in your-language/lang/reader.rkt
. Here that's curly-block/lang/reader.rkt
, where the curly-block
directory is installed as a single-collection package (raco pkg install path/to/curly-block
).
curly-block/lang/reader.rkt
;; 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))
Using it:
#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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With