Java のソケット実装を使用して単純な IRC 接続を維持する方法を示したブログ投稿の例 (ただし、現在は取得できないようです) から恥知らずにこのコードのほとんどすべてを取り上げました。
この例を少しいじっていると、一連のチャンネルに参加したいという問題に遭遇しました。私が最初に考えたのは、チャネルのベクトルをサーバー var に格納し、パターンが一致したときにそれを分解することでした。ただし、これまでのところ機能していません。マップを書き込み関数の裸の呼び出しに変更すると、問題なく動作します。ただし、書き込み関数のマッピングが機能していないようで、その理由がわかりません。興味深いことに、アクティブな接続を実行している repl にマップの呼び出しをコピー アンド ペーストすると、それが機能します... これは cond のスコープで発生しているためですか? ref が責任を負う可能性がありますか? 私は Clojure に侵入したばかりなので、まだ物事を理解しようとしています。
コードは次のとおりです。
(ns irc
(:import (java.net Socket)
(java.io PrintWriter InputStreamReader BufferedReader)))
(def server {:server "irc.example.net"
:port 6667
:channels ["#a" "#b"]})
(def client {:realname "Lambda Bot" :nick "lambdabot"})
(declare conn-handler)
(defn in [a b]
(re-find (re-pattern a) b))
(defn startswith [a b]
(in (str "^" a) b))
(defn connect [server]
(let [socket (Socket. (:server server) (:port server))
in (BufferedReader. (InputStreamReader. (.getInputStream socket)))
out (PrintWriter. (.getOutputStream socket))
conn (ref {:in in :out out})]
(doto (Thread. #(conn-handler conn server)) (.start))
conn))
(defn write [conn msg]
(println msg)
(doto (:out @conn)
(.println (str msg "\r"))
(.flush)))
(defn conn-handler [conn server]
(while (nil? (:exit @conn))
(let [msg (.readLine (:in @conn))]
(println msg)
(cond
(startswith "ERROR :Closing Link:" msg)
(dosync (alter conn merge {:exit true}))
(in " 001 " msg)
;; this guy below doesn't seem to work at all
(map #(write conn (str "JOIN " %)) (:channels server))
;; this guy on the other hand seems to work fine
;;(write conn (str "JOIN " (first (:channels server))))
(startswith "PING" msg)
(write conn (str "PONG " (re-find #":.*" msg)))))))
(defn login [conn user]
(write conn (str "NICK " (:nick user)))
(write conn (str "USER " (:nick user) " 0 * :" (:realname user))))
これを実行するには、(def irc (connect server)) と (login irc client) を呼び出すだけです。どんな助けでも大歓迎です!ありがとう。