如何将这个Java示例翻译成惯用的Clojure?

时间:2011-12-28 10:15:09

标签: java clojure

在我看过的Clojure示例中,大多数编写Java示例X的方法都是整齐的片段或算法。我想知道如何使用Clojure构建程序。我的工作Java示例只有81行,但显示了一个与MessageServer对象交互的User对象。另外从空格分隔的文本文件中加载对象。也可以想象必须在User上添加更多字段和方法。

如何在惯用 Clojure中编写此Java程序?

// To run User.java, just do:
// % echo "iradik 555-5555" > users.txt &&  javac User.java && java User users.txt 555-5555
// Result should be:
// Messages for user iradik with phone 555-5555 are Hello!, Hello Again!

import java.io.*;
import java.util.*;

public class User {

    public static class PhoneNumberNotFoundException extends RuntimeException { }

    String      id;
    String      phoneNumber;
    String[]    messages;

    private static Map<String, User> PHONE_MAP = new HashMap<String, User>();

    public void getTextMessages() {
        if (messages == null || MessageServer.isChanged(this)) {
            MessageServer.getMessages(this);
        }
    }

    public void printTextMessages() {
         StringBuilder builder = new StringBuilder();
         if (messages.length > 0) {
             builder.append(messages[0]); 
         } 
         for (int i = 1; i < messages.length; ++i) {
             builder.append(", ");
             builder.append(messages[i]);
         }
         System.out.println("Messages for user " + id + " with phone " + phoneNumber + " is " + builder.toString());
    }

    public static User getUserForPhoneNumber(String phoneNumber) {
        User user = PHONE_MAP.get(phoneNumber);
        if (user == null) { throw new PhoneNumberNotFoundException(); }
        return user;
    }

    public static void initializeFromFile(String filename) throws IOException {
        FileInputStream fstream = new FileInputStream(filename);
        BufferedReader br = new BufferedReader(new InputStreamReader(fstream));
        String strLine;
        while ((strLine = br.readLine()) != null)   {
            String[] d = strLine.split(" ");

            User user          = new User();
            user.id            = d[0];
            user.phoneNumber   = d[1];

            PHONE_MAP.put(user.phoneNumber, user);
       }
       in.close();
    }

    /** 
     * Run this:
     *   echo "steve 555-5555" > users.txt &&  javac User.java && java User users.txt 555-5555
     */
     public static void main(String[] args) throws IOException {
         User.initializeFromFile(args[0]);
         User user = User.getUserForPhoneNumber(args[1]);
         user.getTextMessages();
         user.printTextMessages();
     }
}

class MessageServer {
    static boolean isChanged(User user) {
        return true;
    }

    static void getMessages(User user) {
        user.messages = new String[] {"Hello!", "Hello Again!"};
    }
}

1 个答案:

答案 0 :(得分:10)

这里有一些代码片段,希望足以让你入门。我已将一些用户放入文件resources/users.txt

steve 555-5551234
bill 555-4441234
linus 555-3331234

您可以通过repl而不是命令行来试验代码

(ns textmsgs.core
  (:require [clojure.data.csv :as csv]
            [clojure.java.io :as io]))

(defrecord User [id phone])

(defn users-from-file
  "Reads a space delimited file of users"
  [filename]
  (with-open [r (io/reader filename)]
    (doall
      (map (partial apply ->User)
           (csv/read-csv r :separator \space)))))

(defn print-text-messages
  "Prints all the text messages for user"
  [user]
  (printf "Messages for %s with phone %s is %s"
          (:id user) (:phone user) (apply str (interpose \, (:messages user)))))

;; This is an in memory phone book
(def phone-db
  (agent (into {}
               (map #(vector (:phone %) %)
                    (users-from-file "resources/users.txt")))))

(defn text
  "Send a text message to a number"
  [number msg]
  (send phone-db
        (fn [db] 
          (if (contains? db number)
            (update-in db [number :messages] conj msg)
            (do (println "No such number" number)
                db)))))

;; Some things to try: 
;; (text "555-3331234" "Hey linus")
;; (print-text-messages (@phone-db "555-3331234"))