Created
May 9, 2010 02:30
-
-
Save masaedw/394909 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; 最後のデータが保存されちゃう問題についての再現コード | |
;; | |
;; ★やりたいこと | |
;; | |
;; サーバから次のようなデータ(¥n区切りの文字列)が送られてくる | |
;; aaa | |
;; bbb | |
;; ccc | |
;; end | |
;; ddd | |
;; end | |
;; eee | |
;; fff | |
;; ggg | |
;; end | |
;; アプリケーション的には end には何の意味もないが、 | |
;; サーバは end を区切りとしてデータをまとめて送ってくる。 | |
;; | |
;; ナイーブにサーバから送られてきたデータを逐次処理すると、 | |
;; ((aaa bbb ccc end) (ddd end) (eee fff ggg end) ...) | |
;; というシーケンスになるので、これをflattenしたものを返すAPIを作りたい | |
;; | |
;; ★期待される動作 | |
;; | |
;; end が送られた時点で、そのendまでの行について処理が行われる | |
;; | |
;; ★このスクリプトを使ったテスト方法 | |
;; | |
;; myflatten を myflatten-good か myflatten-bad か選ぶ | |
;; ↓こんな感じ | |
;; (def myflatten myflatten-good) | |
;; ;;(def myflatten myflatten-bad) | |
;; | |
;; 起動 | |
;; $ lein repl seq.clj | |
;; | |
;; 別ターミナルからtelnet接続 | |
;; $ telnet localhost6666 | |
;; | |
;; 適当な行を入力してendを入力する。 | |
;; | |
;; myflatten-goodのときは、endを入力した時点で、そのendまでの内容がechoされる | |
;; myflatten-bad のときは、endを入力すると、その前のendまでの内容がechoされる | |
;; | |
;; なぜなんでしょうか??? | |
;; | |
(use 'clojure.contrib.server-socket) | |
(import (java.io BufferedReader | |
InputStreamReader | |
PrintWriter | |
OutputStreamWriter)) | |
(defn take-to-first | |
"Returns a lazy sequence of successive items from coll up to | |
and including the point at which it (pred item) returns true. | |
pred must be free of side-effects." | |
[pred coll] | |
(lazy-seq | |
(when-let [s (seq coll)] | |
(if-not (pred (first s)) | |
(cons (first s) (take-to-first pred (rest s))) | |
(list (first s)))))) | |
(defn partition-when | |
"Applies f to each value in coll, splitting it each time f returns | |
true. Returns a lazy seq of lazy seqs." | |
[f coll] | |
(lazy-seq | |
(when-let [s (seq coll)] | |
(let [run (take-to-first f s) | |
res (drop (count run) s)] | |
(cons run (partition-when f res)))))) | |
;; なんかうまくいかない版 | |
(defn myflatten-bad [lst] | |
(lazy-seq | |
(if (empty? lst) lst | |
(let [[x & xs] lst] | |
(if (seq? x) | |
(concat (myflatten-bad x) (myflatten-bad xs)) | |
(cons x (myflatten-bad xs))))))) | |
;; うまくいく版 | |
(defn myflatten-good [lst] | |
(lazy-seq | |
(if (empty? lst) lst | |
(let [x (first lst) | |
xs (rest lst)] | |
(if (seq? x) | |
(concat (myflatten-good x) (myflatten-good xs)) | |
(cons x (myflatten-good xs))))))) | |
(def myflatten myflatten-good) | |
;;(def myflatten myflatten-bad) | |
(defn server-stream [sequence] (partition-when #(= "end" %) sequence)) | |
(defn echo-server [in out] | |
(let [reader (BufferedReader. (InputStreamReader. in)) | |
writer (PrintWriter. (OutputStreamWriter. out) true)] | |
(doseq [line (myflatten (server-stream (line-seq reader)))] | |
(.println writer (str "=> " line)) | |
))) | |
(create-server 6666 echo-server) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
clojure-1.2.0でないとそもそもうまく動きません。