Han*_*Sun 3 lisp scheme racket
原始脚本是这样的:
#lang racket
(for ([i (in-range 3)])
(for ([j (in-range 9)])
(display "X"))
(display "\n"))
(for ([i (in-range 6)])
(for ([j (in-range 3)])
(display " "))
(for ([j (in-range 3)])
(display "X"))
(for ([j (in-range 3)])
(display " "))
(display "\n"))
(for ([i (in-range 3)])
(for ([j (in-range 9)])
(display "X"))
(display "\n"))
Run Code Online (Sandbox Code Playgroud)
输出是:
XXXXXXXXX
XXXXXXXXX
XXXXXXXXX
XXX
XXX
XXX
XXX
XXX
XXX
XXXXXXXXX
XXXXXXXXX
XXXXXXXXX
Run Code Online (Sandbox Code Playgroud)
我想知道我是否可以使用这样的DSL重写它:
(define a
"3 9 X
6 3 b 3 X 3 b
3 9 X")
Run Code Online (Sandbox Code Playgroud)
然后:
(interpret a)
Run Code Online (Sandbox Code Playgroud)
绘制此图表.
有谁知道最好的方法是什么?
要解决这类问题,首先要描述一种数据类型,它可以捕获您在DSL中所需的操作,而不是专注于表面语法.一旦掌握了数据类型,就应该可以更轻松地解决问题.
乍一看,我们可以用您的语言设计3种基本形式:
我们可以用原始字符串和结构来表示这个不相交的类.让我们将这个类称为"pexpr",作为"可打印的expr".在代码中:
;; An pexpr is one of the following:
;; * a primitive string,
;; * a seq, or
;; * a repeat
(struct seq (bodies) #:transparent) ;; bodies is a list of pexpr
(struct repeat (n body) #:transparent) ;; n is a number, body is a pexpr
Run Code Online (Sandbox Code Playgroud)
它可能有助于将一些辅助函数作为缩写,因为"seq"和"repeat"本身有点啰嗦.
;; For convenience, we define some abbreviations s and r for seq and repeat,
;; respectively.
(define (s . bodies)
(seq bodies))
(define (r n . bodies)
(repeat n (seq bodies)))
Run Code Online (Sandbox Code Playgroud)
您的示例"I"字符串可以写成:
(define an-example
(s
(r 3 (r 9 "X") "\n")
(r 6 (r 3 " ") (r 3 "X") "\n")
(r 3 (r 9 "X") "\n")))
Run Code Online (Sandbox Code Playgroud)
请注意,此编码具有新行的显式表示,仅从表面语法中隐含.然后它成为解析器的工作,在表面语法中取代线并将它们变成pexprs,但这不应该太困难.希望.:)
无论如何,解释函数变成了填充模板的细节,如下所示:
(define (interpret pexpr)
(match pexpr
[(? string?)
...]
[(struct seq (bodies))
...]
[(struct repeat (n body))
...]))
Run Code Online (Sandbox Code Playgroud)
哪个'...'应该很容易填写.
这种问题的解决方法是如何设计程序和编程语言:应用和解释.我建议看看它们:它们是好东西.