【问题标题】:LISP recursion using car/cdr使用 car/cdr 的 LISP 递归
【发布时间】:2018-05-08 23:27:36
【问题描述】:

我在使用 LISP 的作业中需要帮助。我需要创建一个程序(两个不同的函数),它可以获取诸如((PRO)(LAN))之类的输出并将其转换为北约(PapaRomeoOscar LimaAlfaNovember)。以及能够将 NATO 转换为英语,((PapaRomeoOscar) (LimaAlfaNovember)) 转换为 pro lan。

它需要使用递归,没有循环,没有任何变量。我的教授学习了一周的 LISP 并向我们展示了基本程序。我对这个一无所知。

我的想法是,我需要将列表组合在一起,然后取出列表的汽车并使用 if 语句检查它:

(if (= car(L1 L2) "i")
  (format -t “India ”)
(format -t ""))

然后递归地获取列表的 cdr 以递归方式传递它。任何帮助都会非常有帮助。我一直在网上寻找示例代码,但找不到类似的东西。我去了她的办公时间,她说我们应该根据她的笔记知道如何做,这是简单的阶乘函数。

然后为了将北约转换为英文,我认为您需要对列表进行 cons,采取列表中的汽车。然后取汽车的车,并使用与上述类似的 if 语句。然后取出 cdr 并递归地将其传回。我不确定代码的外观,所以我需要很多帮助。提前致谢!

【问题讨论】:

  • “((PRO)(LAN))”是什么意思?那应该是一个字符串吗?数据结构?
  • 所有说明都说,它是否将输入作为短语并将其北约代码显示为字符串
  • 请仔细阅读您的作业。在第一种情况下,输入是由单个字符命名的符号列表,在第二种情况下是由 NATO 字符名称命名的符号列表。在这两种情况下,输出都是一个字符串。
  • 哇;一位知道 Lisp 实际上循环的 Lisp 教授。

标签: recursion lisp


【解决方案1】:
(if (= car(L1 L2) "i")
  (format -t “India ”)
(format -t ""))

这个sn-p的一些问题:

  • (= car (L1 L2) "i") 读作:将函数 = 应用于三个参数:名为 car(L1 L2)"i" 的变量,其中 (L1 L2) 是将函数 L1 应用于参数L2。如果要获取列表的car,请使用(car list)

  • = 仅适用于数字:传递任何其他内容(如字符串)将无法按预期工作。比较字符串时使用string=,或者更好的是,在这一步不要使用字符串。参见例如assocsymbol-namestring-capitalize

  • (format -t "") 中的 -t 不正确。如果要写入新字符串,请使用nil。如果要输出到标准输出,请使用t

  • (format -t “India“):注意您使用的是 引号,这不是您应该在程序中使用的引号 (")。此外,您总是打印一个空格,如果您想将不同的单词连接在一起,这是一个问题,如作业中所述(例如"AlfaBeta")。

【讨论】:

  • 只在单词之间而不是在单词之后而不是在整个句子之后添加空格是另一个不平凡的复杂问题,直接“car/cdr”递归不容易做到。
【解决方案2】:

您正在使用 C 语法编写 Lisp。不要那样做。甚至不要认为您可以使用 algol 经验,例如。你知道 Python 的 C 语言,因为虽然 C、C++、perl 和 python 属于 Alhol 语言的同一个家族,但 Lisp 不是。过去我花了一些时间才找到for 循环。其实一年多了。

我认为也许输入应该是'((p r o) (l a n)) 而不是'((pro)(lan))。这些大大改变了您的需求。

您是否了解作业中的输入/输出?由于您正在打印到标准输出而不是返回,这是否意味着您应该从标准输入读取输入而不是函数中的参数?例如。想象一下这个反转列表的函数:

(defun my-reverse (list)
  (labels ((helper (list acc)
              (if (endp list)
                  acc
                  (helper (cdr list) (cons (car list) acc)))))
    (helper list '())))

(my-reverse '(1 2 3)) ; ==> (3 2 1)

这不会读取或打印任何内容,除了 REPL 会打印函数调用的返回值。

您需要将问题分解为更简单的问题。所以想象一下我为一个符号做这件事。例如。 (to-nato 'p) ; ==> papa 那么你就有了可以在递归函数中使用的东西来翻译结构。

祝你好运!

【讨论】:

    【解决方案3】:

    一、算法

    看来你明白它的原理了。递归遍历列表是一个非常常见的习惯用法是 Lisp:你获取一个列表,用它的FIRST 做某事,然后用REST 调用你自己(CAR/CDR 是遗留名称,我更喜欢使用更多尽可能有意义)。

    (defun print-every (objects)
      (print (first objects))
      (print-every (rest objects)))
    

    当你在递归时,你唯一需要做的就是在某个地方终止,通常当给你的列表是空列表时(注意,(rest '())(),所以如果一个函数只是在其余部分上递归列表中,它永远不会停止)。

    (defun print-every (objects)
      (when objects
        (print (first objects))
        (print-every (rest objects))))
    

    如果您需要从整个操作中收集结果,通常的方法是使用 accumulator,这是一个 累加该结果的函数参数。 p>

    (defun add-every (numbers &optional sum)
      (if numbers
          (add-every (rest numbers (+ (first numbers) sum))
          sum))
    

    二、语法

    与任何其他编程语言一样,您需要格外小心,不要在语言 B 中使用语言 A 的内容。

    -t 之类的破折号开头的参数是您将在 bash 中看到的,而不是在 Lisp 中。 (format t "foo") 将打印 foo(和换行符)。

    在 Lisp 中,(foo bar(1 2) 3)NOT 将参数 12 提供给函数 bar。如果你愿意,你的代码需要是(foo (bar 1 2) 3)

    另外,在 Lisp 中,括号和空格是什么单独的表达式。所以'(pro) 是一个包含ONE 符号的列表,而'(p r o) 是一个包含三个 符号的列表。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-03-20
      • 2021-08-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-23
      • 1970-01-01
      • 2016-06-10
      相关资源
      最近更新 更多