Lisp 中的递归并制作我自己的长度函数

Recursion in Lisp and making my own length function

我正在尝试在 lisp 中创建自己的 length/2 函数(它允许您查找列表的长度)并且遇到问题。

如果我要在 java 中对此进行编程,我会创建一个全局索引变量

that = 0

然后在方法中我会做

if(list.equal(null))
{
    return index;
}
else
{
    index++;
    return functioname(tail of list) ;
}. 

显然这不是实际的 java 语法,但我只是想传达我想在 lisp 中应用的逻辑。

我的主要问题是 lisp 中的 ifs 只允许你做

if test expression
    then do something
else
    do something else

当我正在尝试做的时候

if test expression
    then do something
else
    do 2x something

有什么方法可以在 lisp 中完成这个,或者有更好的方法来解决这个问题吗?

递归执行:

len(list):
    if list is null
        return 0
    else
        remove first_item from list
        return 1 + len(list)


(define (length items)
  (if (null? items)
      0
      (+ 1
         (length (cdr items)))))


(length (list 1 2 3))

3

或使用set!:

(define count 0)

(define (length items)
  (when (not (null? items))
    (set! count (+ count 1))
    (length (cdr items))))

(length (list 1 2 3 4 5))

count

5

Scheme 有特殊的运算符 begin(Common Lisp 等价物是 progn),它可以让你对按顺序执行的表达式进行分组,returns 最后一个。

(if (null? items)
    0
    (begin (set! index (+ 1 index))
           (my-length (cdr items))
           index))

如果 if 表达式 returns nil 在 false 条件下,那么你也可以使用 when (如 Rahn 的回答),它更紧凑.

也就是说,拥有一个全局变量,或者任何变量,其值被改变(这是变量的目的)并不是 Lisp/recursive 做事的方式。 (全局变量在任何语言中都不是什么好东西。)Rahn 的第一个例子是任何有经验的 Lisp 程序员都会做的唯一方法。

在我上面的示例中,如果将 1 添加到 (my-length (cdr items)),则 (set! index (+ 1 index))index)) 行以及全局变量 index 是完全不需要的。如果列表为空,则长度为零;否则,长度为 1 + 列表尾部的长度。