繁体   English   中英

方案:用于代码重复的宏或高阶函数?

[英]Scheme: macros or higher order functions for code duplication?

我想得到一个 function 的结果,它调用一个 shell 命令并返回一个字符串。 我正在使用球拍,这是我的第一次尝试:

(define (run-function)
  (let*
    ([stdout (some-function)]
     [output (process-string stdout)])
  ;; many more lines...
  output))

它似乎工作得很好,但假设我想为许多其他 shell 命令编写类似于run-function

为了避免代码重复,我可以像这样定义一个更通用的 function:

(define (shell cmd)
  (let*
    ([stdout (cmd)]
     [output (process-string stdout)])
  ;; many more lines...
  output))

然后调用例如(shell ls)(shell pwd)

另一种方法是使用一个简单的宏:

(define-syntax shell
  (syntax-rules ()
    [(shell cmd)
     (let*
       ([stdout (cmd)]
        [output (process-string stdout)])
       ;; many more lines...
       output)]))

这也将具有允许更通用语法的优点,例如我可以轻松更改宏,以便它需要尽可能多的参数(命令),但我确信可以通过编写更高的顺序来复制相同的行为function 更明智。

问:与宏相比,编写高阶 function 的优缺点是什么? 两者之间有明显的赢家吗?

我同意@MLavrentyev 所说的话,“如果可以的话,请使用 function”。

球拍风格指南还说:

尽可能定义函数,或者在函数可以使用时不要引入宏。

但为什么? 一个原因是,如果您将shell写为 function,您可以将shell传递给其他函数。 您可以通过标识符宏功能对宏执行相同的操作,但这样做要困难得多(无论如何您最终都会有效地创建 function)。

另一个原因是使用宏会使编译后的代码比使用函数大。 这是因为宏在编译时被扩展,然后扩展的代码被编译(在 Racket BC 中为字节码,在 Racket CS 中为机器码)。 所以就好像你一遍又一遍地写(let*...) 如果您分发已编译或可执行的 Racket 程序,您不会希望大小很大。

事实上,编写宏时的一个好习惯是尽量将代码填充到函数中。 而不是写:

(define-syntax-value (debug code)
  (let ([val code])
    (printf "~a evaluates to ~a\n" (quote code) val)
    val))

最好把它写成:

(define (debug-core expr val)
  (printf "~a evaluates to ~a\n" expr val)
  val)

(define-syntax-value (debug code)
  (debug-core (quote code) code))

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM