2012-04-23 7 views
1

は、私は、インデックスワード機能の中にパイプに品詞関数の出力をしようとして使用して出力結果を印刷しています( - >)スレッドマクロ:- >(スレッド)マクロを使用してClojure iterator-seqをパイプする方法は?

(defn parts-of-speech [] 
    (seq (. POS values))) 

(defn index-words [pos] 
    (iterator-seq (. dict getIndexWordIterator pos))) 

(-> (parts-of-speech) index-words println) 

しかし、インデックスの言葉をfuncはiterator-seqを返します。私はClojureを初めて使用しているので、このコンテキストで反復する方法はわかりません。

EDIT:提案ごとにコードが更新されました。

UPDATE:私は来

(->> (parts-of-speech) (map index-words) (map println) doall) 

(doseq [w (map index-words (parts-of-speech))] 
    (println w)) 

:@kotarakと@のjayunit100とコメント@ sw1nnからと@のマルコ・topolnikから回答へ

おかげで、私は仕事、少なくとも2つのバリエーションを持っていますこの質問の私の目標は、より多くの慣用的なClojureを書くためにスレッドマクロを理解することです(スレッドマクロを試す前に、複数のdoseqletを使って各シーケンスをループしていました)。

コメントから、スレッドマクロはこれを行うための最も慣用的な方法ではないかもしれませんが、私はそれを理解してこのギャップを埋めることができるようにする方法を見たいと思います。

(doseq [w (map index-words (parts-of-speech))] 
    (println (count w))) 

;= 117798 
;= 11529 
;= 21479 
;= 4481 

どのようになります:4つの項目のシーケンスを返し、あなたが(println (count w))代わりの(println w)をすれば、あなたはそれではなく一つの連続配列より4つの系列の数を出力します見ることができます(parts-of-speech)また

、 4つのシーケンスの内容を印刷するのではなく、単語の1つの連続したストリームを印刷するように上記を修正しますか?

BTW:上記のコードは、MIT Java WordNetライブラリ(http://projects.csail.mit.edu/jwi/)をラップしています。

+0

質問はまだ開いていますか?これは正しいコードのようです。シーケンスは印刷されませんか?あなたのコメントに答えるには:クローーザではイテレータを使用しません。 Seq反復は 'doseq'で達成されます。あなたが望むなら、あなたは '(doseq [w(インデックス単語(品詞)](println w))'と言うことができます。 –

+0

ネイティブJava配列のBTW反復処理は、clojure - すべて* seqable *、つまり。 –

答えて

6

seqsとiterator-seqの関係は次のとおりです。iterator-seqイテレータからseqを作成します。

ここでは冗長なことを許していますが、「iterator-seqの出力をどのように反復するか」という質問に答えるには、最初にiterator-seqを呼び出す必要がある理由を明確に定義する必要があります。 :

Clojureでは、iterator-seqオブジェクトをあまり頻繁に作成する必要はありません。 clojureは "反復可能な" Javaオブジェクトに対する反復処理をかなり手軽に処理できるので(http://clojuredocs.org/clojure_core/clojure.core/iterator-seq参照)しかし、イテレータ自体は反復可能ではありません。
これを完全に理解するには、イテレータとイテレータの違いを理解する必要があります。これは主に、Javaの世界でセマンティクスを一貫性があり、直感的に保つためです。Why is Java's Iterator not an Iterable?

「seq」とは何ですか?

clojureには、JavaのIteratorインターフェイスより高い抽象化があります。これはISeqのものです。 iterator-seqは、私たちのためにISeqを作成します。このISeqオブジェクトは、アイテムの順次リストに対して動作する多くのClojure関数で使用できるようになりました。

user=> (iterator-seq (.iterator (new java.util.ArrayList ["A" "B"]))) 
("A" "B") 
;Thus, we now have an ISeq implementation derived from an iterator. 

このように、あなたの「反復子-seqの」機能は、JavaのイテレータからであるあなたのためにClojureの「シーケンス」を作成しています。明確にするために - エラーメッセージを、私たちは、「反復子-seqの」非反復可能なオブジェクト上で有益である呼び出すとき:

user=> (iterator-seq "ASDF")           
java.lang.ClassCastException: java.lang.String cannot be cast to java.util.Iterator (NO_SOURCE_FILE:0) 

これは、「反復子-seqの」機能は、入力としてjava.util.Iteratorのが必要であることを教えてくれる。あなたが持つかもしれない

次の論理的な質問は次のとおりです。

は、なぜ我々はイテレータからの配列を作成する必要がありますか?どのようにseq抽象化とJavaのイテレータ抽象化とは異なるのでしょうか?

Iterableインターフェイスは、ClojureのISeqほど抽象的ではありません。たとえば、Stringsを考えてみましょう。明らかに、文字列は連続しています。しかし、Javaではiterableではありません。配列についても同じことが言えます。 ClojureのWebサイトから

「seqがJavaの参照配列上で動作し、反復可能オブジェクトと文字列ライブラリの残りの多くは、これらの機能の上に構築されているので、ClojureのアルゴリズムでJavaオブジェクトを使用するための大きなサポートがあります。 "

したがって、iterator-seqの目的は、イテレータオブジェクトをシーケンス抽象化に「ラップ」することです。この抽象化は、すべての機能の機能を活用することができます。

http://clojure.org/sequencesからイテレータ-seqの

の役割の定義:

"配列関数は、コレクションにISEQの適切なの実装をもたらします。"あなたのケースでは

、我々はそれを言うことができます。

「イテレータ-seqの機能は、お使いのgetIndexWordsIteratorためISEQの実装を生成します」。

最後に、seqをどのように反復処理できますか?

この質問には、文脈を考慮して慎重に回答する必要があります。

確かに反復は可能ですが、クロージャーの主な関心事ではなく、実際にはあなたの後ろではないかもしれません。 iterator-seqはすでにSEQを作成しているので、Clojureの関数演算子(リストの理解、マップ関数など)を使用してseqを使用できます。これにより、手動反復の必要性がなくなります。

たとえば、多くの場合、の値を検索するためにリストを反復処理します。Clojureのでは、我々はフィルタ機能を使用して て値を見つけることができます。

user=> (filter #(= \A %) (seq "ABCD")) 
(\A) 

よりもむしろフィルタリング、は多分私達は新しいコレクションに結果を格納、それぞれ1繰り返し処理を経由して複数のオブジェクトに関数を適用したいです。ここでも、この必要性は、ないClojureの中で明示的な反復を介して行うこと:

user=> (map #(.hashCode %) (seq "ABCZ")) 
(65 66 67 90) 

最後に、あなたが本当にあなたのコレクションを手動で反復処理する必要がある場合は、手動で、尾は、再帰的に横断するためにループRECURの構文を使用することができますシーケンス、一度に1つの要素:http://clojure.org/functional_programming#Functional%20Programming--Recursive%20Looping。または、標準の再帰呼び出しを使用できます。

+0

ありがとうございました。私はこれを持っています: ( - >> (map-index-words)(map-println)doall)これは、2つの問題が残っている点を除いて、動作します。1.個々の単語の代わりに1つのシーケンスをプリントアウトしています。 - >フォームの代わりに - >フォームを使用するように変更する方法はまだ不明です。 – espeed

+0

もう一つの重要な違いは、イテレータは変更可能であり( '.next()'呼び出しはイテレータの状態を変更する)、 'seq'sは不変で永続的です。 – ivant

+0

@ espeed:中間出力を見ることができるように、 - >>の代わりに中間のprintステートメントでletを使ってみることができますか?私はスレッド演算子の代わりにletを使うことをお勧めします。 – jayunit100

2

実際にあなたの関数を呼び出す必要があります。現時点では、ファンクションparts-of-speechindex-wordsに合格しています。

(defn parts-of-speech 
    [] 
    (.values POS)) 

(defn index-words 
    [pos] 
    (iterator-seq (.getIndexWordIterator dict pos))) 

(-> (parts-of-speech) index-words println) 

parts-of-speechの括弧に注意してください。また、使用しているinterop構文はかなり古いことに注意してください。

+0

ありがとう、今私は "Ledu.mit.jwi.item.POS;をedu.mit.jwi.item.POSにキャストできません" – espeed

+0

[L ;クラス名の配列 – sw1nn

+0

ありがとうございました - 元の質問に戻りました。配列とイテレータをこの繰り返しで繰り返すにはどうすればいいですか? – espeed

関連する問題