3

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) を呼び出すだけです。どんな助けでも大歓迎です!ありがとう。

4

1 に答える 1

6

map遅延操作です。つまり、必要になるまで実行されません。repl から呼び出されると、返された値を出力する必要があるため、repl によって評価されます。

doall遅延操作の実行を強制するために使用できます。

(doall (map ... ))

doseqよりもむしろ使用する方が良いでしょうmapmap一連の値を別の一連の値に変換するためのものであり、一連の値に対してdoseq操作を実行するためのものであり、それはあなたがしたいことです。

(doseq [ch (:channels server)]
  (write conn (str "JOIN " ch)))
于 2012-11-12T03:41:47.040 に答える