2013-05-21 25 views
5

私は、CLに基づく楽曲のビジュアルプログラミング環境を使っています。私は3つの要素(1 2 3)が評価されるたびに、1,2,3,1,2,3など、その時点で1つの数値を返すという関数を作成しようとしています。 Common Lisp a Gentle Introductionでは、シャープ等価表記を使用して循環リストを作成することは可能だが、それらの使用方法の詳細はわかりません。 私は実際にそれ用に設計されたオブジェクトを使ってプログラムに実際のLispコードを挿入することができます。Common Lispでの循環リスト

+3

[Lispサイクリックリスト](http://stackoverflow.com/q/15536​​564/1281433)と[Sharpsign Equal-Signリーダーマクロの例](http://stackoverflow.com/q/12649290/1281433)も参照してください。 )。 –

答えて

8

Sharpsign Equal-Signの表記では、#0=(1 2 3 . #0#)と表記されています。​​は、あなたが望んでいた、円形のリストを返します呼び出し、その後

(defun circular (first &rest rest) 
    (let ((items (cons first rest))) 
    (setf (cdr (last items)) items))) 

:ここ

は、与えられた引数から、このようなリストを作成する機能です。 carcdrを使って要素の無限を繰り返し処理してください。

そして、あなたが本当に引数を取らず、コールごとに次の項目を返すイテレータ関数をしたい場合は、ここにあなたがそれを行う可能性があります方法は次のとおりです。

(defun make-iter (list) 
    (lambda() 
    (pop list))) 
+1

LETではなくPROG1を使用できます。 –

+2

@ThomasBartscherありがとう!今実装されています。 (実際に私はRainerの答えを見て、ポップは私が何をしているのと同じことをしているようですが、それはSchemerがCLを書くときに起こることです;-)) –

+1

私はそれを考えませんでした。ニース! –

10
CL-USER 3 > (defun circular (items) 
       (setf (cdr (last items)) items) 
       items) 
CIRCULAR 

CL-USER 4 > (setf *print-circle* t) 
T 

CL-USER 5 > (circular (list 1 2 3)) 
#1=(1 2 3 . #1#) 

例:

CL-USER 16 > (setf c1 (circular (list 1 2 3))) 
#1=(1 2 3 . #1#) 

CL-USER 17 > (pop c1) 
1 

CL-USER 18 > (pop c1) 
2 

CL-USER 19 > (pop c1) 
3 

CL-USER 20 > (pop c1) 
1 

他:

CL-USER 6 > '#1=(1 2 3 . #1#) 
#1=(1 2 3 . #1#) 

少しのCLOSが追加されました:

(defclass circular() 
    ((items :initarg :items))) 

(defmethod initialize-instance :after ((c circular) &rest initargs) 
    (setf (slot-value c 'items) (circular (slot-value c 'items)))) 

(defmethod next-item ((c circular)) 
    (prog1 (first (slot-value c 'items)) 
    (setf (slot-value c 'items) 
      (rest (slot-value c 'items))))) 

CL-USER 7 > (setf circ1 (make-instance 'circular :items (list 1 2 3))) 
#<CIRCULAR 40200017CB> 

CL-USER 8 > (next-item circ1) 
1 

CL-USER 9 > (next-item circ1) 
2 

CL-USER 10 > (next-item circ1) 
3 

CL-USER 11 > (next-item circ1) 
1 

CL-USER 12 > (next-item circ1) 
2 
+0

ありがとう、これは非常に便利です。 –

+0

このタイプのものについてもっと学ぶのに役立つお勧めの本やサイトがありますか? –

+1

巡回表現にLet Over Lambdaのセクションがあります:http://letoverlambda.com/index.cl/guest/chap4.html#sec_5 –

0

ここは、Lispの循環リストのために作られたアイデアです。

;;; Showing structure of the list 
;;; (next prev is-end val) 

; create items 
setf L-0 (L-1 L-3 t "L-0 sentry") ; this will be the sentry item so know where to stop 
setf L-1 (L-2 L-0 nil "L-1") 
setf L-2 (L-3 L-1 nil "L-2") 
setf L-3 (L-0 L-2 nil "L-3") 

; how to access L-2 from L-0 
eval (first (eval (first L-0))) 

; result: (L-3 L-1 NIL "L-2") 

アイテムの追加、削除、アクセスにdefun関数を使用していません。私が与えたことは、あなたがこの種の循環リストのために定義した関数で何をする必要があるかを示すのに十分であると考えています。これは私にとってリスナーで働くように見えました。