Damon Snyder <drsny...@gmail.com> writes: > One of the decisions I wasn't sure about was whether to use a protocol > or a struct map for the (socket, reader, writer) tuple. I started > using a struct-map and then switched over to defprotocol/defrecord. > See > https://github.com/drsnyder/beanstalk/blob/82f301f1f825bb05aa14d85a220ec57c1dea61b2/src/beanstalk/core.clj#L117 > for the definition.
Struct maps were in the language for a long time before defrecord was added. Records are supposed to replace them for most purposes. So if in doubt between the two use a defrecord. The decision tree is basically: * Am I implementing a data structure (like a hash-map or vector)? => Use deftype. * Do I need to use polymorphism? => Use defrecord. * Otherwise => Use a normal hash-map instance. I'd probably also try to implement basic functionality against an existing Java or Clojure interface where possible. For example for close you could use the java.io.Closeable interface. If possible (I'm not familiar with beanstalk's model) I'd also try to implement parts of java.util.Queue. That way you could use the object with existing code that knows how to use those interfaces. You can still have Clojure helper functions to avoid clients having to do type-hinting and so the functions can be used first-class. Just define the helpers against the interface: (defn close [^java.io.Closeable closeable] (.close closeable)) What you've got seems pretty reasonable though. If I were writing client code using your library, I guess I'd consume it something like this: (ns myapp (:require [beanstalk.core :as bs])) (def *running* true) (with-open [q (bs/new-beanstalk ...)] (while *running* (let [[id len] (bs/reserve q)] (do-some-work (bs/peek q id)) (bs/bury q id))) I wonder if there's room for some higher-level helpers in your library? For example if the above pattern is really common would something along these lines be useful: (defn do-work "Grabs work items from the queue and processes them with f. Stops when f returns false." [queue f] (while (let [[id len] (reserve queue) result (f (peek queue id))] (bury queue id) result))) Perhaps in a new thread? Perhaps you need a try/catch to release failed jobs or something? Whatever makes sense for the normal beanstalk usage pattern. Would it make sense to implement clojure.lang.Seqable for a pull-style interface? (map f queue) (doseq [job queue] (f job)) (let [some-jobs (take 10 queue)] ...) -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en