gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-03 21:42:52 25 4
gpt4 key购买 nike

我想获取调用 shell 命令并返回字符串的函数的结果。
我正在使用 Racket ,这是我的第一次尝试:

(define (run-function)
(let*
([stdout (some-function)]
[output (process-string stdout)])
;; many more lines...
output))
它似乎工作得很好,但假设我想编写类似于 run-function 的函数对于许多其他 shell 命令。
为了避免代码重复,我可以定义一个更通用的函数,如下所示:
(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)]))

这也有允许使用更通用语法的优点,例如我可以轻松更改宏,以便根据需要使用尽可能多的参数(命令),但我确信可以通过编写更高的顺序来复制相同的行为更明智地发挥作用。
问:编写高阶函数与宏的优缺点是什么?两者之间有明显的赢家吗?

最佳答案

我同意什么@MLavrentyev said , “如果可以,请使用函数”。
the Racket style guide还说:

Define functions when possible, Or, do not introduce macros when functions will do.


但为什么?原因之一是,如果你写 shell作为函数,您可以通过 shell到其他功能。您可以通过 identifier macro 对宏执行相同的操作。功能,但这样做要困难得多(无论如何您最终都会有效地创建一个函数)。
另一个原因是使用宏会使编译后的代码比使用函数更大。这是因为宏在编译时被扩展,然后扩展的代码被编译(在 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))

关于macros - 方案:用于代码复制的宏或高阶函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66376735/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com