lambda - 避免 funcall 的双重调用
问题描述
考虑 Lisp 中的以下函数定义:
(defun Fct(F L) (cond ((null L) nil) ((funcall F (car L)) (cons (funcall F (car L)) (Fct F (cdr L)) ) ) (T nil) ) )
给出一个避免双重调用的解决方案
(funcall F (car L))
。你不会使用 set,setq,setf。证明答案。
这就是我重新定义函数的方式:
(defun Fct2(F L)
(funcall #'(lambda (x)
(cond
((null L) nil)
(x (cons x (Fct2 F (cdr L)) ) )
(T nil)
)
)
(F (car L))
)
)
我工作,但我看不到后面是否没有更多的双重呼叫。我还看到有人以另一种方式做到这一点:
(defun redefine(f l)
(funcall #' (lambda (x)
(cond
((null l) nil)
(x (cons x (Fct f (cdr l))))
(t nil)
)
)
(funcall f (car l))
)
)
(使用旧的 Fct 里面)
但我认为 Fct2 是继续进行的好方法。我想听听一些意见。
解决方案
该函数fct
将一个函数f
和一个列表L
作为参数,并返回一个t
s 列表,其中元素的L
计算结果为真值,f
直到
用完L
为止,或者一个元素的计算结果为假F
。
例如:
(fct #'plusp '(1 2 -3 4 10)) => (t t),
(fct #'listp '((1 2 3) 4 '(a))) => (t),
(fct #'listp nil) => nil.
函数fct2
和redefine
不满足这种行为。
为了避免多次计算表达式,只需将计算表达式的结果绑定到符号。考虑以下实现预期结果的实现:
(defun fct-2 (func list)
(when list
(let ((head (funcall func (car list))))
(when head
(cons head (fct-2 func (cdr list)))))))
when
当您有一个没有 else 部分的 if 表单时,该宏特别有用。在中,我们将稍后使用fct-2
的结果绑定(funcall func (car list))
到
其中。head
旁注:
- Commonlisp 为函数和变量提供了单独的命名空间,因此我们可以毫无问题地使用
list
变量名之类的名称,这可以使程序更清晰,而不是L
列表之类的名称。 - 查看https://mumble.net/~campbell/scheme/style.txt和https://lisp-lang.org/style-guide/获取有关编写和格式化(常见)lisp 程序的指南。
推荐阅读
- java - 颜色/RGB INT 转换器
- javascript - Svelte 应用程序错误:未完成的待办事项未返回
- regex - 在 Flutter 中验证 TextFormField - 这个正则表达式有什么问题?
- python - 使用开始和结束时间按所有小时和类别列分组
- firebase - 将图像从颤振上传到火力基地(没有任何反应)
- python - 如何在日期时间索引上加入 2 个数据框
- android - 我在 Android Studio 的“运行”Logcat 中看不到应用错误
- javascript - 在将 redux 与 reactJs 一起使用时,我是否应该绝对避免道具传递?
- python - 如何使用 discord.py 中的参数循环异步函数?
- quill - QuillJS:如何为描边颜色添加格式