2015-05-13 3 views
0

Я пытаюсь создать функцию, которая создает список всех подсписок в данном списке.Как создать список подписок в Lisp без карты?

То, что я имею в виду, когда у меня есть список:

(4 (a g b) g (1 2 3) g (4 5 6)) 

Я хочу список:

((a g b) (1 2 3) (4 5 6)) 

То, что я получил на данный момент:

(defun unterlisten_zurueckgeben (lst) 
    (let (unterlisten) 
    (cond ((endp lst) nil) 
      ((listp (first lst)) 
      (or (unterlisten_zurueckgeben (first lst)) 
       (setq unterlisten (cons (first lst) (unterlisten_zurueckgeben (rest lst)))))) 
      (t (unterlisten_zurueckgeben (rest lst)))) 
    unterlisten)) 

, похоже, не работает, и я не могу найти свою ошибку.

+0

Неясно, что вы имеете в виду под «списком подсписков в списке». Вы должны привести пример. – tonso

+0

Я имею в виду, когда у меня есть список: '(4 (agb) g (1 2 3) g (4 5 6))' Я хочу список: '((agb) (1 2 3) (4 5 6)) ' –

ответ

2

Таким образом, вы хотите сохранить только подсписку. Вы можете легко сделать это с remove-if:

(defun remove-atoms (lst) 
    (remove-if #'atom lst)) 

В вашем рекурсивной коде есть проблема с:

(or (unterlisten_zurueckgeben (first lst)) 
    (setq unterlisten (cons (first lst) 
          (unterlisten_zurueckgeben (rest lst)))))) 

Здесь, если результат (unterlisten_zurueckgeben (first lst)) не пустой список (например, список. со списком), то это будет результат всего этого.

Если это не nil, то вы измените местного привязки underlisten к тому, что, как представляется, хорошо результат.

С cond является не выражение хвоста. Результатом функции всегда является то, что underlisten есть. Таким образом, для случая по умолчанию, когда вы просто рекурсируете с остальной частью списка, результат никогда не возвращается, так как он вернет nil (начальное значение underlisten).

Таким образом, даже ваш рекурсивный ролл своего собственного решения является гораздо более сложным, чем он должен быть:

(defun remove-atoms (lst) 
    (cond ((endp lst) nil) 
     ((listp (first lst)) 
     (cons (first lst) (remove-atoms (rest lst)))) 
     (t (remove-atoms (rest lst))))) 
+0

После долгого размышления я понял, что в то время как это, а второй ответ тоже является ответом на мой вопрос, ответ не помогает мне в большой картине, поскольку вопрос, который я задал, не был тем, что поможет мне решить мою общую проблему. –

+1

@EviLGaMer Теперь, это то, что называется проблемой [XY] (http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem) (т. Е. Вместо того, чтобы задавать свою актуальную проблему, вы ставите проблема, связанная с возможным решением) – Sylwester

+0

Закончил то, что я пытался сделать в трех строках после долгих и упорных размышлений. То, что я хотел сделать, - написать функцию, которая упростит арифметическое выражение, написанное в виде списка с подсписками aka '(+ 3 5 (- 7 4) x 8 9 (* 3 5 f)), насколько это возможно. –

3

Если это так, вы можете написать:

(defun unterlisten-zurueckgeben (lst) 
    (remove-if-not #'listp lst)) 
; or use #'consp if you don't want empty sublists 

Обратите внимание, что в Лиспе предпочтительный способ для объединения идентификаторов является использование тире вместо подчеркивания.