#clojure logs

2009-09-20

00:36danlei`what would be a quick fix (if possible without getting down to the java level) for JComboBoxes double entry bug?
03:02mortonJohnson(defn hello [] "Hello Everybody")
03:30CalJohn_In clojure, is it true that STM types can be read without a transaction?
03:30CalJohn_unlike haskell's STM
03:39ChousukeCalJohn_: yes.
03:40CalJohn_can you atomically read while applying a non-atomic transformation?
03:42Chousukethe reference is conceptually something like a "pointer" to an immutable value
03:42Chousukeso "reading" it is just a dereferencing operation
03:42Chousukeand once you have the value, nothing can change it
03:42CalJohn_right, right
03:42CalJohn_ok
05:07rafsoakenHow do I catch a say ArrayIndexOutOfBoundsException?
05:08rafsoakennever mind, found it..
05:30jamesswifthi folks, i was asking today about 'trie's and if anyone here could provide an example of how you would transform the inTree to the outTree http://paste.lisp.org/display/87340
05:30jamesswiftthe #haskell foks gave me a nice example in that language but i would like to have ine for clojure
06:28ben_mHey there :) When I edit a file in vim, can I somehow run an interactive clj in another terminal with the file I'm editing and then just reload that when I change something?
06:29ben_mNevermind, (load-file "foo.clj") works :)
07:38cow-orkerwill there be a non-private assert-args anytime soon?
07:39Chousukeyou could use the pre- and postcondition support
07:39ChousukeI wonder if it's documented anywhere :P
07:40cow-orkerhmm.... I haven't seen it, but that doesn't mean it's not documented somewhere :-)
07:42Chousukethe only mention I've seen of it is in the commit logs :)
07:42cow-orkerI'll have a look there .... thanks!
07:43Chousukesearch for ":pre" in the logs
07:43Chousukethat'll find it
07:43cow-orkerthanks a lot!
07:58cow-orker:pre and :post cleaned up the code quite a bit! :-)
10:34ankouhi, the documentation says that the parameter of memoize should be refererentially transparent but is this a requirement?(I want to use it for loading a file which is not a pure function but a candidate for remembering the output)
10:42durka42ankou: as long as you don't care that the function's output won't change if a file's content changes behind its back
11:13alinphi
11:13alinpis there a way to force evaluation for a function ?
11:14alinpI mean ... for map for instance
11:14alinpis it possible ?
11:14alinp,(doc map)
11:14clojurebot"([f coll] [f c1 c2] [f c1 c2 c3] [f c1 c2 c3 & colls]); Returns a lazy sequence consisting of the result of applying f to the set of first items of each coll, followed by applying f to the set of second items in each coll, until any one of the colls is exhausted. Any remaining items in other colls are ignored. Function f should accept number-of-colls arguments."
11:14alinpI don't want to return a lazy seq ...
11:14alinpI want to return a seq ... evaluated
11:16alinpthe reason why I want that is ...
11:16alinpwhen calling time function for a map, it will not return the actual time took for the map to be executed
11:17alinpsame for pmap
11:17xdphello,drawString slow down my application, howto fix it?
11:17danleialinp: why not wrap it in a doall?
11:18alinpdanlei: thanks :)
11:18alinpthis is what I tried to find out
11:18danleiok. there's also dorun, if it's all about side effects ...
11:18xdpany alternative to drawString in java?
11:19xdphmm
11:21xdpany swing wrapper in clojure by now?
11:25xdpor swt?
12:21thesnowdogAt the risk of being jumped on, is there a list of "Clojure success stories"? As cheesy as it may be, management types love this stuff. I couldn't find it but my google foo is weak.
12:29thesnowdogben_m: I gather you've found vim-clojure?
12:29clojurebotGesundheit!
13:29manic12is there any swing example code in clojure?
13:29LauJensenIs the JVM Video up somewhere yet ?
14:25ben_mthesnowdog: Why do you ask? :)
16:46ordnungswidrigHow must a multimethod dispatch function be written? What are the params passed to it? The actual params that the multifunction is invoked with?
16:47ordnungswidrigI keep getting "Wrong number of args passed to: user$fn"
16:49Chousukeyes
16:49ordnungswidrigI used (defmulti foo first)
16:50Chousukethen you would call (foo [1 2 3 4]) or something
16:50Chousukeand the dispatch value would be "1"
16:50ordnungswidrigok
16:50ordnungswidrigwithout the explicit seq would (defmulti foo (fn [&rest] (first rest))) do?
16:51Chousukeyes.
16:51Chousukethough I think you need a space after the & :)
16:52ordnungswidrigAnd with an explicit dispatch keyword: (defmulti foo [ type & rest] type) ?
16:52Chousukeyeah
16:52ordnungswidrigwhere type is a namespace keyword and I have a hierachy built using derive?
16:52Chousukethough both type and rest shadow core functions :P
16:53Chousukeordnungswidrig: it can be anything
16:53ordnungswidrigah the shadows.
16:54ordnungswidrighttp://gist.github.com/189297
16:54manic12are there any good examples of using gen-class ?
16:55Chousukeordnungswidrig: the defmethods need to take the shape parameter too
16:56Chousukeso (defmethod draw ::shape [_ x y] "shape") -> now you can call (draw ::shape x y)
16:58ordnungswidrigNow I see the light!
16:58ordnungswidrig:-) That makes sens as the method can now acces the dispatch value it was called for.
16:58Chousukeor you could do something like (defmulti draw type) and then (defmethod draw ::rect [rectangle] "rectangle") and ensure that rectangles have ::rect as their :tag metadata
16:59ordnungswidrig:tag metadata?
16:59Chousuke(doc type)
16:59clojurebot"([x]); Returns the :type metadata of x, or its Class if none"
16:59Chousukeoh wait, it was :type :P
17:01Chousukeanyway, (draw (with-meta something-representing-a-rectangle {:type ::rect}))
17:01ordnungswidrigah, I see.
17:01Chousuke(or you can have a make-rect that attaches the metadata for you
17:01Chousuke) :P
17:02ordnungswidrigsomething like that, yes. I'll try. Designing a non-oo api is nothing I've done in the last 5 years.
17:03Chousukewell, defmethods used like this are quite a lot like OO in a sense.
17:03Chousukebut all your objects are immutable values, not something that can change so I guess the program ends up quite different :)
17:04ordnungswidrigYes, actually I'm desiging a litte rest framework remotely resembling erlangs webmachine. Every resource is represented by a collection of functions (calculate etag, does-resource-exist etc.)
17:05ordnungswidrigWhat I'm doing is to provide reasonable default implementations and a single resource can take the defaults and decorate / replace them with the actual implementation for it
17:06Chousukehmm
17:06ordnungswidrigI thought of making each decision point function a multimethod and dispatching on a namespace keyword representing the resource
17:07Chousukethat might work
17:07Chousukethough what will you do if you want to use functions from different namespaces?
17:07ordnungswidrigI though namespace keywords would do the trick?
17:08ChousukeI mean, if you want to dispatch to one namespace for one of the functions and to another for some other.
17:08ChousukeI guess that might just not happen :/
17:12ordnungswidrigHmm, basically there will be a default dispatch value for the default implementation and I assume that all methods defined for a single disptach value are in the same namespace.
17:13Chousukeright. though actually WHERE they are defined does not matter. :) just as long as there is a definition for a certain dispatch value
17:13ordnungswidrig...or a dispatch value that matches with isa?
17:13Chousukeyeah.
17:14Chousukeyou can manually define a dispatch value "outside" your namespace if you just write it out in full. ie. (defmethod foo :some.external.namespace/dispatch-key [] ...)
17:15ordnungswidrigBut (derive :orders :some.namespace/ressource) and (defmulti :orders) will do and pickup the defaults for .../ressource as well?
17:16Chousukewell, derivation doesn't "inherit" anything
17:17Chousukeit just provides the default in case there's no more specific implementation
17:17ordnungswidrigYes, I meant the default implementaion
17:18Chousukeso in that case if you didn't do (defmethod :orders [] ...), it would use the fuction for :some.namespace/resource
17:18duck11231Is it possible to re-def a defmulti without losing the associated defmethods?
17:19ChousukeI don't think so :/
17:19duck11231I have some of my defmethods in other files, and when I re-eval the base file, I lose some of my handlers
17:21Chousukeduck11231: I suppose the solution to that would be to define the multimethod in some other file that doesn't need to be re-evaluated :P
17:22ordnungswidrigChousuke: hehe, "header files"
17:22ChousukeI suppose you could do some hackery to get the methods currently defined for the multi and then set them up again manually after the multimethod has been redefined...
17:22Chousukethe MultiFn class has .getMethodTable and .getPreferTable and .addMethod and .preferMethod... :)
17:23duck11231I think I need to write an emacs keybinding to send a complete reload of my base namespace. I don't like using C-M-x because I lose linenumbers, so I usually C-c C-l
17:26ordnungswidrigist there something like "underive" in the repl?
17:27ordnungswidrig*slapmyhead* underive
17:27Chousuke:)
17:28pixelmanTrouble starting swank. Shouldn't I be able to do (start-swank) when i (use 'swank.swank) ?
17:33pixelmandoh! it was called (start-server ...
17:37ordnungswidrighmm, emacs shows the matching opening parent only when I'm on the character _after_ the closing parent. is this the default?
17:45ben_mWhat's the difference between an atom and a ref?
17:45ben_m(I'm reading 'Programming Clojure' and it wasn't explained yet)
17:47hiredmanclojurebot: atom vs. ref?
17:47clojurebotI don't understand.
17:47hiredmanclojurebot: atom vs. ref is <reply>http://groups.google.com/group/clojure/msg/fd0371eb7238e933
17:47clojurebotAck. Ack.
17:47Chousukeben_m: changes to refs are coordinated, changes to atoms are not
17:48Chousukethough that might be an oversimplification
17:48ben_mSo atoms are not exactly threadsafe?
17:48Chousukewell, they are atomic
17:49ben_mDoesn't ring a bell, but I will look it up :)
17:49Chousukeit means that you won't see a "half-value"
17:51Chousukebut the point is that if you have two atoms, there's no way to get a consistent snapshot of them both "at the same time", so to speak
17:51ben_mI see
17:51Chousukewhereas with refs you can do the reads in a transaction and if anything changes the refs in the middle, the read gets retried until you get a consistent result
17:52hiredmanif you have two queues, and those two queues are in atoms, if you take an item from one, and put it in the other, it is possible for other operations to be interleaved between the take and the push, so there is a time when the thing you are swapping is in neither queue
17:52rafsoakenHow can i construct a hash-map from (1 \a 2 \b) ?
17:52Chousukerafsoaken: apply hash-map :)
17:52rafsoakenobvious when you think about it :) thx
17:53hiredmanif you do the same thing with queues in refs, the whole unit of work happens at once
17:53ben_mChousuke: hiredman: Thanks, I think I understand :)
17:53rafsoaken,(apply hash-map (1 \a 2 \b))
17:53clojurebotjava.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IFn
17:53manic12where is an example of the use of the :constructors keyword in gen-class?
17:53rafsoaken,(apply hash-map (list 1 \a 2 \b))
17:53clojurebot{1 \a, 2 \b}
17:53hiredmanrafsoaken: whole 'nother problem
17:54rafsoakenyeah, sorry wanted to try clojurebot desperately
17:54Chousuke,(into {} (partition 2 '[a 1 b 2 c 3]))
17:54clojurebotjava.lang.ClassCastException: clojure.lang.Symbol cannot be cast to java.util.Map$Entry
17:54Chousukewait, what.
17:54ben_m(into {} works just like a cast, right?
17:54hiredmanusing numbers as keys in a map has issues
17:55ben_mIn other languages.
17:55Chousukeben_m: cast? no.
17:55hiredmaneh?
17:55Chousukeben_m: into actually builds the map
17:55hiredman~def into
17:55Chousuke,(into {} (partition 2 [1 2 3 4]))
17:55clojurebotjava.lang.ClassCastException: java.lang.Integer cannot be cast to java.util.Map$Entry
17:55Chousukewhy doesn't that work? :/
17:56hiredman,(partition 2 [1 2 3 4])
17:56clojurebot((1 2) (3 4))
17:56Chousuke,(into {} [[1 2] [3 4]])
17:56clojurebot{3 4, 1 2}
17:56hiredman,(int {} (map vec (partition 2 [1 2 3 4])))
17:56clojurebotjava.lang.IllegalArgumentException: Wrong number of args passed to: core$fn
17:56hiredman,(into {} (map vec (partition 2 [1 2 3 4])))
17:56clojurebot{3 4, 1 2}
17:57Chousukeanyway, using into might be better if you're building a big map from a large seq
17:57Chousukesince IIRC apply holds on to the head of the sequence, while into does not.
17:59manic12where are some examples hiding of the use of gen-class, specifically the :constructor and :init keywords ?
17:59rafsoakenthanks Chousuke & hiredman~
17:59rafsoakens/~/!
18:00manic12anyone?
18:04manic12should I just write my class in java and then use the java interop capabilities?
18:05ben_mHow would the defmulti call look like if I want to use a meta tag as dispatch function? (My terminology might be wrong here)
18:06ben_mFor example (doesn't work obviously): (defmulti sound ^{:animal-type}) (defmethod sound ^{:animal-type :dog} [] (println "Bark"))
18:08Chousukeben_m: (defmulti sound (fn [thing] (:animal-type (meta thing))))
18:08ben_mOoh :)
18:08Chousukeor (defmulti sound (comp :animal-type meta)) :)
18:09Chousukeand then (defmethod sound ::dog [thing] "bark")
18:09ben_mNow that confuses me :)
18:10ben_mWhat's the ::dog doing?
18:10Chousukeit's the type tag
18:10Chousukesimilar to :dog, but ::dog is automatically namespace-qualified
18:10ben_mI should probably keep reading the book before I ask question :D
18:10Chousuke,'::foo
18:10clojurebot:sandbox/foo
18:10ben_m,':foo
18:10clojurebot:foo
18:13ben_mThanks for your help :)
18:13ben_mGood night.
18:18manic12i want to override a constructor, how do i do that?
18:27Chousermanic12: you don't. just provide a function that will act as a factory
18:29Chouserhm, I guess gen-class can provide ctors
18:31manic12and provide a :factory keyword?
18:32Chousermanic12: you're using gen-class?
18:33manic12either gen-class or :gen-class of ns, I don't care
18:35Chouserok, then you can use :constructors to create ctors with whatever signatures you need.
18:35manic12how do I provide the body of the ctor, and how do I call super?
18:37Chouseryou use :init to provide a function that will be called before the object is created, and :post-init to provide a function that will be called after the object is created (and the super called).
18:38manic12ahh! i glossed over that post-init stuff
18:38manic12thank you
18:38emacsenwhat's the cannonoical clojure way to provide validation on an object (eg make sure the values conform to what they should be on a struct)?
18:39Chouserhm... there are validators for reference types, but not for structs as far as I know.
18:39Chouserprobably best to provide a function that should be used for creating the struct, and do any checks there.
18:40emacsenk. I was doing that but then thought there might be a more clojureish way
18:40emacsenI'm doing something simple like stoing lat/longs and want to be sure that the numbers fall within the proper range always
18:44emacsenthe other confusing thing is that for atoms, there's :validator
18:45Chouseremacsen: yeah, reference types have validators
18:45Chouseratoms, refs, agents, etc.
18:46Chousermore critical there, because any function could be used to change it.
18:46emacsenokay... similar dumb question... If I have a struct, is there a function to ask the struct its "structure basis object" name?
18:46Chousernot dumb -- comes up all the time.
18:47Chouserbut a struct basis is not a class. a struct is just a simple optimization of a map.
18:47emacsenso what do I really want?
18:48Chouserif you want to attach a "type" to an object, it's common to use metadata
18:48emacsenoh that's a good idea
18:48Chouser,(type #^{:type ::Foo} {:a 1})
18:48clojurebot:sandbox/Foo
18:49emacsenheh
18:54emacsenthanks for the advice
18:57Chouseryet another reason to have a function to create the things
18:57emacsenright- makes sense
19:55sfuentesi'm a little confused here and i was hoping somebody could help me out here. It seems that some ppl in the clojure community see OOP as not really being a good way of modeling programs. Is this true?
19:55emacsensfuentes: that's a very big simplification, but it's sort of true
19:56dnolensfuentes: and pretty much impossible in Clojure anyway. Clojure doesn't support OO style programming very well. You'll have to explore other approaches.
19:56emacsenmore accurately we'd say that the benefits of OO can be achieved other ways, and the OO model itself causes problems
19:56technomancysfuentes: have you read http://clojure.org/state ?
19:56emacsendnolen: Well, you can do it.. you can call java OOs, etc
19:56emacsenerm java objects
19:57technomancyClojure people don't endorse conflating state and identity, which is something most mainstream OOP implementations do
19:57emacsensfuentes: also, it's a big leap for some people who'd never used CLOS (the Common Lisp object system). if you have, it's a leap, but a smaller one
19:57rlbAlso, some of the very common systems (Java, C++, etc.) are *very* narrow programming models..
19:58rlb(even as far as OOP goes)
19:58emacsenand now sfuentes, I'm afraid we're going to have to pelt stones at you...
19:59sfuentesmy usual thinking is that prog languages are tools and obviously tools are designed for certain tasks. so the challenge for me here is to try to understand where a tool like clojure is better suited.
19:59emacsensfuentes: it's better for data oriented problems
20:00emacsen(though it can do far, far more)
20:00dnolensfuentes: I think the programming language == tool analogy to be very fragile. programming language == factory that generates tools to be a better one.
20:00emacsensfuentes: have you ever used a lisp before?
20:02dnolensfuentes: when you program in something like Java changing the factory is an expensive and sometimes impossible task. Clojure is a just in time factory where many parts are easily reconfigurable.
20:02sfuentesthe only lisp (clisp) i know is from my programming languages cs class
20:02emacsenthey never teach lisp right in school
20:02sfuentesbut i wouldn't say i know the language
20:02rlbFWIW, quite a while back I found the Keene CLOS book to be a good way to see a broader perspective wrt OOP in fairly few pages. Although it may not be as easy if you're not yet familiar with lisp in general.
20:02emacsenor... I shouldn't say never... but they usually teach it poorly and too quickly
20:04emacsensfuentes: it's hard to discuss the benefits of Clojure without someone understanding the benefits of Lisp in general. Lisp isn't easily compatable to other languages because it's a very different style of programming
20:04emacsendifferent than say Python or Ruby, or C
20:04emacsen( I should say "Lisps aren't" rather than "Lisp isn't")
20:05technomancysfuentes: there are real unavoidable problems with concurrency when you mix state and identity like how most OOP does
20:06technomancyyou should read the "State and Identity" essay I linked to
20:07dnolenemacsen: Lisps really are not so different then Python Ruby IMHO. Those are Lispy languages. Clojure's emphasis on FP and concurrency are the more distinguishing traits.
20:07emacsendnolen: we'll have to agree to disagree :)
20:07dnolenemacsen: haha, sure.
20:08sfuentesmy dilemma is in trying to decide on what "tools" to invest my time in
20:08dnolensfuentes: what "tools" are you using now?
20:09sfuentesmostly php :/
20:09dnolenwell Clojure will be serious upgrade for you then ;)
20:09sfuentesnot really by choice, as that knowledge is widely requested
20:10emacsenit's widely requested that you know Clojure?
20:11sfuentesemacsen: no. clojure *appears* to me as being a *newer* skill/tool that has potential ... so obviously it would suit me to get a head start
20:12emacsensfuentes: it's a big jump from PHP. I might suggest trying something like going through technomancy's peepcode video
20:12emacsenand watching the Rich Hickey videos
20:12emacsenand then deciding
20:12sfuentesi did watch one of hickey's videos.
20:13emacsenThe problem is right now there aren't many gentle introductions
20:13sfuentesi even purchased the peepcode video last night.
20:15dnolensfuentes: in order to ease your introduction I would use NetBeans + Enclojure. Though I'm Emacs person myself- I wouldn't recommend it as your introduction to Clojure. If you're doing web dev, you should definitely check out Compojure and/or Ring.
20:17sfuentesi remember fiddling with clisp in college and wondered why it wasn't more widely used in industry. the problem *seemed* to be centered on standard libraries. Clojure seems to have alleviated this by targeting the jvm, so it seems like there's a strong case for a lisp dialect now. That's how I feel now, and that's why i'm thinking about learning clojure.
20:19sfuentesdnolen: Netbeans+Enclojure is what I'm working with right now. Haven't really developed anything meaningful, but that's my dev env
20:19dnolensfuentes: well then you're all set. Learn some Clojure! :)
20:20sfuentesi got one more question
20:23sfuentesbefore i heard of clojure, scala appeared to be the lang to learn from the rest. so now i'm wondering if scala and clojure are alternatives or whether they complement each other in larger systems. I think if I knew more about lisp I would know this, but I don't.
20:25dnolensfuentes: not too many scala people here I don't think. however the my reductive generalization would be: Clojure is a simpler language than Scala but probably just as powerful for writing applications.
20:27sfuentesalot of what i'm hearing seems to be centered around FP vs OOP, and if that's the case, can you say that other functional languages are simple and perhaps even more powerful than OOP languages?
20:28dnolensfuentes: that would be too reductive of a generalization :) not all FP languages are "simple". nor are all OO languages "powerful", PHP case in point.
20:30sfuentesi see. so haskell would not be considered simple, right?
20:31sfuentesbut i'm not sure i would say php is naturally oop
20:31sfuentesby the way, i appreciate you guys taking time to answer my silly questions
20:36ChouserI think the combination of syntax and type system would be enough to consider Haskell more complex than Clojure.
20:37ChouserThough I don't think Clojure's STM could be called simple.
20:38rlbsfuentes: also, in my experience, clojure tries to avoid being too pedantic. If you need mutation, fine. If you want to work in a more java/c++-esque object oriented fashion, you can (to some extent), that's just a very limited application of clojure's multimethods.
20:39rlb(There I'm speaking mostly about dispatch...)
20:40MakoryuHaskell is certainly simple compared to its peers in the imperative world. It has fewer rules with fewer exceptions... Of course, that allows libraries to implement a certain amount of syntax as ordinary functions
20:43sfuentesagain. thank you all for your time and insights.
20:55dthomasIf I do something like (doseq [x (new-huge-lazy-seq)] (stuff-with x)) will the whole sequence end up materialized in memory when iteration terminates? Or are the head elements eligible for the GC after they are operated upon and then forgotten?
20:56dthomasI suspect there is an easy way to test this involving top and (repeatedly).
20:59hiredman
20:59dthomasYeah, I think this is a stupid question.
21:00dthomasLazy sequences still confuse me.
21:20emacsendthomas: lazy sequences still confuse you why
21:20emacsenthat is, what about them confuses you
21:20Makoryudthomas: If you generate a lazy data structure and then explore the structure without letting the reference to the root go out of scope, the whole thing will remain in memory.
21:21Makoryudthomas: Half the point of lazy sequences is that you can recreate them at will if you need them for different purposes, and it won't matter how big the entire thing would be.
21:34dthomasMakoryu: Presumably built-ins like (map) and (for) are not written in such a way that they keep the root around?
21:34dthomas(doseq [x (iterate inc 1)]) doesn't start accumulating memory in my box as it presumably would if something was holding on to the root of the lazy seq made by iterate.
21:36dthomasThat's what was confusing me today.
21:42Chouserdoseq itself won't hold onto the head, so the JVM garbage collection will clean it up as it goes.
21:43Chouserif you did (let [xs (iterate inc 1)] (doseq [x xs])) it would consume memory.
21:58sfuentesi'm embarrased to ask, but can somebody explain this snippet to me: http://pastie.org/624107
21:58sfuentesi'm hung up on the last line
21:59dnolensfuentes: functions (fns) can have multiple arities.
21:59durka42the indentation is done confusingly, but it's a function with multiple arities
22:00durka42so you can call it with no arguments or with one
22:00durka42and if you call it with none, it calls itself with one, namely the String "world"
22:00sfuentesawww i see
22:01sfuentesis there a reason to use hyphex prefix to the function name though?
22:01sfuenteserr hyphen
22:01durka42for gen-classing i believe
22:03sfuenteswhat is that if you don't mind me asking
22:03sfuentesnm. i'll look it up
22:03durka42making a java class from a clojure namespace
22:04hiredman~compile
22:04clojurebotthe unit of compilation in clojure is the namespace. namespaces are compiled (not files). to compile a namspace the namespace needs to be on the classpath and so does ./classes/ (and the directory needs to exist) because clojure writes the class files to that directory. http://clojure.org/compilation
22:05sfuentesgot it. thank you.
22:58interferoncan i convert a struct-map to a vanilla map?
22:59Chouser(into {} my-struct-map)
23:03interferonthanks!
23:05prospero_if I use map over a hash-map, what's the simplest way for that to generate a new hash-map?
23:07prospero_it seems like there should be a simpler way than (apply hash-map (apply concat (map (fn ...) {...})))
23:08dnolenprospero: (into {} ...)
23:08dnolen,(into {} [[:foo 'x] [:bar 'y]])
23:08clojurebot{:bar y, :foo x}
23:09prospero_I knew there was something I was forgetting
23:09prospero_thanks