在我看过的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!"};
}
}
答案 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"))