You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Common Lisp中cond操作符语法错误排查:重构BST函数遇问题

Hey there! Let's break down what's going on with your percolate function refactor and those Common Lisp cond syntax issues.

Why Your First Refactored Code Throws an Error

The problem is extra parentheses in your first cond clause. You wrapped the test expression (and (null (node-l bst)) (null (node-r bst))) in an extra set of brackets, turning it into ((and ...)) as the first element of the clause.

Common Lisp interprets this as an attempt to call the result of (and ...) (which is a boolean, t or nil) as a function. Since booleans aren't callable functions, you get that confusing error saying the and expression should be a lambda.

Fixing it is simple—just remove the extra layer of parentheses from the first clause:

(defun percolate (bst) ; [6,7,7a]
  (cond ((and (null (node-l bst)) (null (node-r bst))) nil)
        ((null (node-l bst)) (rperc bst))
        ((null (node-r bst)) (lperc bst))
        (t (if (zerop (random 2)) (lperc bst) (rperc bst)))))

Common Lisp cond Standard Syntax

You weren't off-base with wanting to use cond exclusively—you just mixed up the clause structure. The standard format for each cond clause is:

(test-form result-form1 result-form2 ...)
  • test-form: Any valid Lisp expression that evaluates to true (non-nil) or false (nil).
  • result-form...: Expressions to run in order if test-form is true; the last one's value is returned as the clause's result.
  • The (t ...) clause acts as a catch-all, running if all previous tests fail.

The key takeaway: Don't wrap your test-form in extra parentheses unless the test itself requires them (like combining checks with and/or).

Your Misconceptions

  1. You added unnecessary parentheses around the test expression in the first clause, leading to an accidental function call attempt.
  2. In your second code snippet, you confused variable references with function calls: (both-null nil) tries to invoke both-null as a function (with nil as an argument), but both-null is just a boolean variable holding t or nil.

A Polished, Fully cond-Based Version

If you want to eliminate the final if entirely for consistency, you can extend the cond to handle the random case too:

(defun percolate (bst) ; [6,7,7a]
  (cond ((and (null (node-l bst)) (null (node-r bst))) nil)
        ((null (node-l bst)) (rperc bst))
        ((null (node-r bst)) (lperc bst))
        ((zerop (random 2)) (lperc bst))
        (t (rperc bst))))

This version is clean, follows standard syntax, and makes the logical flow explicit.

Fixing Your Second Code Snippet

If you prefer extracting the checks into variables with let, just adjust the cond clauses to reference the variables directly (no function call syntax):

(defun percolate (bst) ; [6,7,7a]
  (let ((both-null (and (null (node-l bst)) (null (node-r bst))))
        (l-null (null (node-l bst)))
        (r-null (null (node-r bst))))
    (cond (both-null nil)
          (l-null (rperc bst))
          (r-null (lperc bst))
          (t (if (zerop (random 2)) (lperc bst) (rperc bst))))))

This works correctly and avoids the function call mistake from your original version.

内容的提问来源于stack exchange,提问作者mwal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 09:21:28