2016-05-10 8 views
1

リストにマップするが、リスト内の要素インデックスを追跡したい。Common LispのPython enumerate()analog

私はの線に沿って何かを行うことができますPythonで

:私はの線に沿って何かにそれを翻訳しようとしていた

map(lambda (idx, elt): "Elt {0}: {1}".format(idx, elt), enumerate(mylist)) 

を:

(mapcar-something (lambda (elt idx) (format nil "Elt ~D: ~S" idx elt)) 
        '(a b c d)) 

期待される結果:

("Elt 0: A" "Elt 1: B" "Elt 2: C" "Elt 3: D") 

しかし、私が使用すべきmapcar-something関数を見つけることができません。それを自分で実装する必要がありますか(ループ経由か多分)。

+0

'let'ブロックにラップしてnの変数をラムダから取得し、ラムダが呼び出されるたびにその値をインクリメントします。私は内蔵されているとは思わない。 – MicroVirus

答えて

0

Common LispのLOOPマクロを自動的に保つことができますインデックスのトラック。

(loop for elt in '(a b c d) and idx from 0 
     collect (operation-on idx elt)) 

LOOP 1によって自動的増加fromで初期化変数。 andによってそれらが導入された場合、両方の割り当て(配列の要素とインデックス)はネストではなく一度に起こります。

したがって、列挙関数はのラインに沿って次のようになりますのCommon Lispの表現で

(defun enumerate (list &optional (first-index 0)) 
    (loop for elt in list and idx from first-index 
    collect (cons idx elt))) 

、おそらくの線に沿ってマクロを定義することは有用であろう:

(defmacro with-enumerated-list ((list elt idx &key (first-index 0)) &body body) 
    `(loop for ,elt in ,list and ,idx from ,first-index 
    collect (progn ,@body))) 

この場合、列挙関数を次のように減らすことができます:

(defun enumerate (list &optional (first-index 0)) 
    (with-enumerated-list (list elt idx :first-index first-index) 
    (cons idx elt))) 
+0

典型的な問題:あなた自身のコードを試していない。 ** 2番目のENUMERATE関数は動作しません。**マクロは必要ありません。マクロのインターフェイスは醜いです。エラーチェックもなく、単純なLOOPに比べて付加価値がありません。悪い:あなたが体を定義する方法は、多くの問題を引き起こします(あなたはなぜそれを見ることができますか?)マクロを導入することで、1つのバグとランダムなバグの原因を導入しました。 –

+0

@RainerJoswigは、それを改善しようとするよりもdownvoteの方が価値があることはとても悪い答えですか?私は自分のコードを試してみましたが、悪い反復をコピーしたようです。それが提供する価値は、言語固有のイディオムであり、多分、あまり意味がないかもしれない。マクロが醜い理由についてのあなたの推論がそれに衛生の欠如に頼っているなら、それは良いことも悪いこともあります。なぜあなたの強く否定的な意見ですか? – ssice

+0

LOOP構文はWITH-ENUMERATED-LISTにリークします。あなたはあれが見えますか?そうでなければ、私は次のコメントでどのようにあなたを示します。 –

6
CL-USER 25 > (defun iota (n) 
       (loop for i below n collect i)) 
IOTA 

CL-USER 26 > (iota 4) 
(0 1 2 3) 

CL-USER 27 > (mapcar (lambda (elt idx) 
         (format nil "Elt ~D: ~S" idx elt)) 
        '(a b c d) 
        (iota 4)) 
("Elt 0: A" "Elt 1: B" "Elt 2: C" "Elt 3: D") 

または

CL-USER 28 > (loop for elt in '(a b c d) and idx from 0 
        collect (format nil "Elt ~D: ~S" idx elt)) 
("Elt 0: A" "Elt 1: B" "Elt 2: C" "Elt 3: D") 
+0

私は、 'と' idx from 0'が毎回idxを自動的に1ずつ増やすことを知らなかった。 – ssice

0

あなたの元の例のように見える何かをしたい場合:

(defun enumerate (function list) 
    (let ((idx 0)) 
    (loop for elt in list 
     collect (funcall function elt idx) 
     do (incf idx)))) 

あなたの例を:

(enumerate (lambda (elt idx) (format nil "Elt ~D: ~S" idx elt)) 
      '(a b c d)) 
=> ("Elt 0: A" "Elt 1: B" "Elt 2: C" "Elt 3: D") 
+0

Rainerの2番目のコード例は、incfをループ実装に処理することで改善され、Pythonでの使用に近い、プログラマから隠蔽されています。 – ssice