执行一个函数,直到返回nil,将其值收集到一个列表中 [英] Executes a function until it returns a nil, collecting its values into a list

查看:75
本文介绍了执行一个函数,直到返回nil,将其值收集到一个列表中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我从 XKCD的Hofstadter漫画中得到了这个主意;在(任何)Lisp方言中创建条件循环的最佳方法是什么,该条件循环执行一个函数,直到返回NIL,这时它将返回的值收集到列表中.

I got this idea from XKCD's Hofstadter comic; what's the best way to create a conditional loop in (any) Lisp dialect that executes a function until it returns NIL at which time it collects the returned values into a list.

对于那些没有看过这个笑话的人,道格拉斯·霍夫施塔特的八字"自传由六个词组成:我很元,甚至这个缩写"都包含笑话的延续:(有些奇怪meta-paraprosdokian?)是Meta"吗?开个玩笑就是自传实际上是我是如此的Meta,即使这个首字母缩写是Meta".但是为什么不更深入呢?

For those who haven't seen the joke, it's goes that Douglas Hofstadter's "eight-word" autobiography consists of only six words: "I'm So Meta, Even This Acronym" containing continuation of the joke: (some odd meta-paraprosdokian?) "Is Meta" — the joke being that the autobiography is actually "I'm So Meta, Even This Acronym Is Meta". But why not go deeper?

假定首字母缩略词功能META从字符串中创建首字母缩写词并将其拆分为单词,如果字符串中仅包含一个单词,则返回NIL:

Assume the acronymizing function META that creates an acronym from a string and splits it into words, returns NIL if the string contains but one word:

(meta "I'm So Meta, Even This Acronym") ⇒ "Is Meta"
(meta (meta "I'm So Meta, Even This Acronym")) ⇒ "Im"
(meta (meta (meta "I'm So Meta, Even This Acronym"))) ⇒ NIL

(meta "GNU is Not UNIX") ⇒ "GNU"
(meta (meta "GNU is Not UNIX")) ⇒ NIL

现在我正在寻找如何实现函数,以便:

Now I'm looking for how to implement a function so that:

(so-function #'meta "I'm So Meta, Even This Acronym") 
⇒ ("I'm So Meta, Even This Acronym" "Is Meta" "Im")
(so-function #'meta "GNU is Not Unix")
⇒ ("GNU is Not Unix" "GNU")

做到这一点的最好方法是什么?

What's the best way of doing this?

推荐答案

这很容易.我不想写一个解决方案,所以我会写-但是它将是笨拙的elisp版本,如果您遵循以下步骤,可能会导致意想不到的启发:

This is easy. I don't want to write a solution, so instead I will -- but it'll be the crappy elisp version, which might lead to unexpected enlightenment if you'll follow through:

(defun so-function (f str)
  (let (x '())
    (while str (setq x (cons str x)) (setq str (funcall f str)))
    (reverse x)))

要尝试此操作,您将需要meta,但我不知道您如何决定将空格放置在何处,因此我会伪造它:

To try this out you'll need that meta, but I don't know how you'd decide where to put the spaces, so instead I'll fake it:

(defun meta (x)
  (cadr (assoc x '(("I'm So Meta, Even This Acronym" "Is Meta")
                   ("Is Meta" "Im")
                   ("GNU is Not UNIX" "GNU")))))

这使您想要的代码起作用.至于启蒙-尝试编写它而不是您想要的东西,so-function将是一个高阶函数-它将像这样工作:

This makes the code that you want work. As for the enlightenment -- try to write it so instead of what you want, so-function will be a higher order function -- one that will work like this:

(funcall (so-function #'meta) "GNU is Not UNIX")

或者,在Scheme中:

or, in Scheme:

((so-function meta) "GNU is Not UNIX")

这里最大的提示是您不能用简单的elisp做到(至少不是没有cl库的技巧).为了获得充分的信誉,请避免出现突变-这将导致您以自然的方式在Scheme中编写它,甚至看起来比setq版本更具可读性.

The big hint here is that you can't do it in plain elisp (at least not without tricks from the cl library). To get full credit, avoid the mutations -- this will lead to the natural way you'd write it in Scheme, and might even look more readable than the setq version.

这篇关于执行一个函数,直到返回nil,将其值收集到一个列表中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆