是否存在用于从列表中弹出第n个元素的通用lisp宏? [英] Is there a common lisp macro for popping the nth element from a list?

查看:86
本文介绍了是否存在用于从列表中弹出第n个元素的通用lisp宏?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对Common Lisp的场景非常了解,我似乎找不到一种快速的方法来从列表中获取第n个元素并将其同时从列表中删除.我已经完成了,但是还不很漂亮,我真正想要的是"pop"之类的东西,但是有第二个参数:

I'm pretty fresh to the Common Lisp scene and I can't seem to find an quick way to get the nth element from a list and remove it from said list at the same time. I've done it, but it ain't pretty, what I'd really like is something like "pop" but took a second parameter:

(setf x '(a b c d))
(setf y (popnth 2 x))
; x is '(a b d)
; y is 'c

我很确定"popnth"必须是一个宏,以防参数为0且行为必须类似于"pop".

I'm pretty sure that "popnth" would have to be a macro, in case the parameter was 0 and it had to behave like "pop".

这是我的第一个废话:

(defmacro popnth (n lst)
  (let ((tempvar (gensym)))
    `(if (eql ,n 0)
      (pop ,lst)
      (let ((,tempvar (nth ,n ,lst)))
        (setf (cdr (nthcdr ,(- n 1) ,lst)) (nthcdr ,(+ n 1) ,lst))
        ,tempvar))))

推荐答案

我想出了一个比第一次尝试有效的解决方案:

I came up with a solution that is a little more efficient than my first attempt:

(defmacro popnth (n lst)
  (let ((t1 (gensym))(t2 (gensym)))
    `(if (eql ,n 0)
      (pop ,lst)
      (let* ((,t1 (nthcdr (- ,n 1) ,lst))
              (,t2 (car (cdr ,t1))))
        (setf (cdr ,t1) (cddr ,t1))
        ,t2))))

这里正在发挥作用:

[2]> (defparameter *list* '(a b c d e f g))
*LIST*
[3]> (popnth 3 *list*)
D
[4]> *list*
(A B C E F G)
[5]> (popnth 0 *list*)
A
[6]> *list*
(B C E F G)

这篇关于是否存在用于从列表中弹出第n个元素的通用lisp宏?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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