#clojure logs

2012-10-09

00:02technomancyTimMc: unfortunately if you need something to work in the presence of profile operations you have to express it in terms of profiles
00:02akhudekcallen: "If the LEIN_NO_DEV environment variable is not set, the server will monitor your source directory for file modifications, and any altered files will automatically be reloaded."
00:02akhudekhttps://github.com/weavejester/lein-ring
00:03technomancyTimMc: so if you can use leiningen.core.project/add-profiles then it'll get preserved properly
00:03callenakhudek: hrm.
00:03technomancythe problem is that there's no way to reverse an operation like merging a profile, so we have to just save the pristine copy and operate on that
00:03callennow I just have to figure out how to start the jetty server.
00:03akhudekcallen: lein ring server
00:04akhudekit starts a jetty server
00:04technomancyI really don't get the point of keeping your dev jetty in a different process from your repl
00:04callen'ring' is not a task. See 'lein help'.
00:04callenakhudek: ^^
00:04friocallen: get lein2 :)
00:04callenfrio: I am in lein2, that's why it broke
00:04friooh? that works for me...
00:04technomancycallen: just start jetty from your repl
00:05technomancyit's easy
00:05callentechnomancy: that's what I've resorted to.
00:05akhudektechnomancy: I like starting from the repl myself, though I haven't been abel to convince many others of this
00:05technomancycallen: it's so much simpler
00:06technomancykeeping it in a separate process maybe makes sense if you use textmate or notepad or something, but if you have editor integration you should use it.
00:06callenoh you start it from your nrepl-jack-in
00:06technomancyyup
00:06technomancy(start-jetty #'app {:port 8080 :join? false}) or whatever
00:07callentechnomancy: do you use 'raw' ring, Noir, or something else?
00:08callenwell that was a fail, I edited code and it didn't reload.
00:08callenso going back to my question, how do I make it auto-reload?
00:08akhudekcallen: if you are doing the repl route, you can reload most functions in the standard way
00:08callenC-x C-e on my handler failed.
00:09akhudekbut routes and enlive templates area bit different
00:09callenclojure.lang.Compiler$CompilerException: java.lang.IllegalStateException: index already refers to: #'reminders.core/index in namespace
00:09callen...not helpful.
00:09callenso how do I auto-reload my code...routed handlers included?
00:10akhudekcallen: could try wrap-reload, though I have not managed to get it to reload routes for some reason
00:10akhudekoddly enough the lein-ring plugin does seem to work
00:10akhudekhttp://clojuredocs.org/ring/ring.middleware.reload/wrap-reload
00:10akhudeksorry, that's outdated
00:10akhudekhold on
00:11callenif it doesn't reload the routes, it's not incredibly useful to me.
00:11akhudeksee the bottom here: https://github.com/ring-clojure/ring/wiki/Interactive-Development
00:13akhudekthen be sure to reload you entire namespace
00:13TimMctechnomancy: Thanks, that gives me a good start. I guess I can't reasonably make something that's compatible with both 1.x and 2.x, so I'll branch lein-otf.
00:13akhudekas to your question about noir vs ring, I prefer ring + compojure to noir myself.
00:14tomojare fn* and loop* the only recur points?
00:15callenokay, I got it to do what I want now
00:15callenI got lein ring server to work.
00:15callenit seemed to auto-reload my code so that seems kosher now.
00:15callenakhudek: thank you.
00:22zackzackzackHow do I make it so I can define what happens when I call nth on a datatype or record?
00:25trevor`How do people do JDBC CallableStatements in Clojure?
00:26tomojthis feels somewhat wrong https://gist.github.com/9f89e03eb42bef6ddeab ?
00:31callenwell. lobos seems nice enough.
00:31callenis lobos what most people use for migrations?
00:32zackzackzacktomoj: Which walk is walk?
00:32zackzackzackw/walk I maen
00:32zackzackzack*mean
00:33tomojw is clojure.walk
00:33tomojwell it's definitely wrong because I don't deref the Reduced
00:33tomojbut seems kinda weird to use Reduced
00:39zackzackzackWhy not this? https://gist.github.com/1d4e89438b8c2bb4d210
00:39zackzackzackHmm
00:39zackzackzackIt doesn't stop though
00:39zackzackzackNevermind
01:02callenhow do I get trailing slashes to work in ring?
01:08tomojzackzackzack: I felt like there should be a simpler way to write it, too
01:11tomojI don't have w/walk at the top because f should be able to stop on the root form too
01:12xeqicallen: the slashes should show up in the :uri
01:12xeqiif you want to act the same as the non slash, you could use a middleware to change it
01:12xeqior redirect
01:14xeqihttps://github.com/noir-clojure/lib-noir/blob/master/src/noir/util/middleware.clj#L28 is one example
01:14tomojshoot, I wish if were a macro for if*
01:15tomojoh, no I don't
01:21tomojis it an acceptable use of with-redefs to redefine macroexpand-1 to cljs.analyzer/macroexpand-1?
01:22zackzackzacktomoj: maybe realize it as a list and then do a search through it with a take while or something?
01:23tomojfor the stoppable walk?
01:23tomoj"stop" there means "don't descend into the form f returned"
01:25tomoje.g. in my impl, if (reduced? (f form)), then the walk will not descend into (f form), but all the siblings of (f form) are still walked
01:40zackzackzackAny particular reason why protocols don't support variadic (& rest) arguments?
01:49SegFaultAX|workWhen looping and destructuring a list, what is the most idiomatic way to stop when you've reached the end of the list? I usually use something like (loop [[h & t :as c] (if (empty? c) ... (recur ...)))
01:52SegFaultAX|workSomehow that feels more verbose than it needs to be.
01:53FrozenlockSegFaultAX|work: Isn't there 'while'?
01:55FrozenlockIf it can help: http://clojuredocs.org/clojure_core/clojure.core/take-while
02:01SegFaultAX|workFrozenlock: That doesn't really address my question at all.
02:05tomoj&(loop [[h & t] [1 2 3]] (if t (recur t) h))
02:05lazybot⇒ 3
02:22wingyhow do i interact with XML responses?
02:23wingysome services only provide XML :/
02:42zoldar|awaywingy: define "interact"
02:42wingyzoldar|away: working with xml like i can do with json responses
02:42wingyreading elements, attributes .. setting values etc
02:42wingysave data to db
02:43wingycreating new attributes and elements as well
02:43wingyreminds me about DOM manipulation but I have never worked with XML responses
02:44wingyhow does everyone handle XML resonses in clj/java land
02:44zoldarwingy: my bet would be on this: https://github.com/clojure/data.xml
02:45wingycool
02:46tomoj"Wrong number of args (-1) passed to: core$map"
02:46tomojinteresting
02:47tomoj(defmacro foo [] `(~@(map)))
02:47tomoj(that one has -2 args)
03:00wingyzoldar: clj has basic ops built in http://clojuredocs.org/clojure_core/clojure.xml
03:01wingyi might just use that one
03:03tomojthere is also clojure.zip/xml-zip and clojure.data.zip.xml
03:03wingyi wonder why clojure has different projects for xml though
03:04wingythey have those you mentioned but also https://github.com/clojure/data.xml
03:04wingyits in the clojure github project
03:04wingydoes anyone here know why?
03:06tomojclojure.xml uses SAX, clojure.data.xml uses StAX
03:24wingytomoj: i c
04:05gtuckerkellogg,(doc repl)
04:05clojurebotI don't understand.
04:05gtuckerkellogg,(doc doc)
04:05clojurebot"([name]); Prints documentation for a var or special form given its name"
04:21bairuihas anyone here used both clojure and newlisp? have you written serious apps in both? any constructive observations / criticisms / comparisons?
04:22bairui(no, i'm not trying to start a war - i happen to like both)
04:25muckerbairui: what type of app ? newlisp is a scripting language. clojure from the start is a general language that lets take adv of jvm
04:26bairuimucker: no limits on type of app; only that both should be... suitable to the language/platform and be of reasonable size - not just tutorials / toys.
04:27bairuimucker: i concede that clojure has the awesome power of all those jvm libs behind it - that is certainly something newlisp has much less of (exhaustive set of libs)
04:30michaelr525hello\
04:31bairuii saw a presentation on seesaw a few days ago - it looks very pretty. Is seesaw THE recommended way to do GUIs in clojure now?
04:35muckerbairui: in my experience, no matter what the recommended way, there is some struggle ;)
04:36bairui:-( ain't it always so
04:37clgvIs it right that setting *unchecked-math* to true has no effect when I use primitives and type hints anyway?
04:38bairuii dabbled with haskell a while back and noticed they were trying to forge a new path in functional guis... what was that called again? reactive? is there a clojure attempt at this? is it mature/operational?
04:38bairuii infer from your previous answer that even if there is one... it's no silver bullet :)
04:40tomojincidentally I am working on a library (not published yet) inspired by reactive, but a very long time till I get to swing, probably never. dom and canvas are early targets
04:40muckerbairui: :) don't be afraid to port haskell ideas to clojure
04:41bairuilol; my haskell skills are akin to that of a child with large coloured blocks; and that is being disingenuous to the child.
04:41tomojswing would be interesting though.. or maybe android someday
04:42tomojI bet with some synchrony there reactive's behaviors are nicer than in cljs
04:42clgvbairui: seesaw is awesome if you want to build a Swing GUI - but I only used it for some smal GUIs yet
04:42bairuias i understand it, there already are several swing interfaces - seesaw being one, no?
04:42bairuiclgv: cool; the presentation i saw on it made it look quite cool. I haven't yet built a gui with seesaw, but i am itching to do so. I have a newlisp app that i will port to clojure/seesaw.
04:43bairuiclgv: are you implying there are alternatives to wanting a 'swing' gui?
04:45muckerbairui: you can use java classes in clojure, so that's one way ... donno alternatives to seesaw
04:45clgvbairui: swing is the easiest way since its built-in. there is SWT which is used by eclipse
04:45bairuimucker: actually, i was wondering about alternatives to swing - does anybody still write guis in awt directly?!
04:45bairuii hadn't heard of swt
04:46clgvnow you have ;)
04:46muckerbairui: awt is a big NO
04:46bairuiheh :) good
04:46clgvI think java world is either swing or swt
04:49michaelr525re
04:50bairuiok, thanks, clgv. I'll make a note to look at swt, but i'll try seesaw first.
04:52clgvbairui: yeah try seesaw first. I don't know if there is any clojure lib that provides an interface for swt
04:52bairuicool
05:21wingyhow can i convert a string with base64?
05:27tomojhttps://github.com/clojure/data.codec
05:27tomoj(String. (encode (.getBytes "foo"))) for example
05:31wingytomoj: ah
05:31wingy(ring.util.codec/base64-encode (.getBytes "adasd")) this worked great as well
06:45augustlwhen I build with "lein ring uberwar", everything in {:profile {:dev {:resource-paths [...]}}} gets added to the war
06:45augustlhow do I build a "production war"?
06:48augustlit also contains my dev dependencies, so "lein ring uberwar" seems to assume I want to use the dev profile
06:48tomojtry `lein with-profile production ring uberwar`
06:49augustltomoj: "'ring' is not a task. See 'lein help'." hehe
06:51tomojhmm
06:51clgvis ring also a :dev dependency? ;)
06:51tomojI found `lein with-profile production lein ring uberwar` somewhere
06:52augustlno, it's a plugin - :plugins [[lein-ring "0.7.1"]]
06:52augustlclgv: ^^
06:52clgvoutside of :dev?
06:52augustlyes
06:52augustltomoj: same thing, "lein is not a task"
06:52tomojthat one makes sense
06:53augustlagreed :)
06:53clgvwhat does `lein with-profile production help` list you?
06:54augustlclgv: https://www.refheap.com/paste/5616
06:54clgvlein-ring should be listed there, right?
06:55augustlno idea :)
06:55augustlit's not listed with just "lein help"
06:55augustlsec :P
06:56tomojworks for me
06:56augustlworks for me too
06:56augustlgoodie!
06:57augustlis it possible to default to the production for just "lein ring uberwar" so we don't make the mistake to build with the dev env?
06:58clgvI think that is an error in the plugin implementation - lein uberjar for example excludes the :dev profile
06:58clgvaugustl: I think you can define an alias that automatically uses the production profile
06:59augustlclgv: I'll look that up, thanks
07:06augustlresource-paths in leiningen just adds those folders to the classpath, right?
07:23clgvaugustl: no, it also includes thos folders in the jar
07:41djpowellanyone know how to dynamically construct a bunch of OR'd together clauses in Korma?
07:42djpowelli can easily take my clauses and reduce over the query applying k/where to it
07:42djpowellbut i'm not sure how to do something similar with OR
07:52clgvdjpowell: you could generate a list of your or-clauses using the symbol 'or and where* instead of where
08:00djpowellclgv: hmm, not quite figured out how to use where*
08:20djpowellok, got it sorted. just about.
08:22clgvdjpowell: with where*?
08:38nkozawhere I can report a clojurescript documentation bug? The issues tab in the github page seems disabled
08:38gfredericksdev.clojure.org/jira
08:41nkozathanks
08:48augustlwould be nice if the issues tab in github could be enabled, but link to an external issue tracker instead, since so many people seem to default to look up issue trackers on github repos
09:01djpowellclgv: yeah, with where*; i pretty much did a macroexpand on where, and duplicated the result. bit ugly cause it uses stiff in engine and fns
10:01edward_Hi guys, I'm just wondering, in case statement, how can I do nothing for one case?
10:01clgvedward_: do not add the statement
10:02cshelldo nothing or return nothing?
10:02edward_hmmm sorry I'm new to clojure so I guess return nothing since clojure is functional :D
10:03cshellexclude the statement or return nil
10:04antares_edward_: return nil
10:05edward_hmm like (nil)?
10:05edward_and how can I exclude the statement?
10:05antares_edward_: nil is not a function, just nil
10:05cshelljust nil
10:05clgv(case v 10 11, 11 nil, 12 13, 42)
10:06edward_oh haha forgot () is calling function
10:18pandeirohow do i view the dep tree with lein?
10:20cshell you can generate the pom then run mvn dependency:tree
10:20cshellbut lein probably has an easier way
10:22jsabeaudrypandeiro, https://github.com/the-kenny/lein-deps-tree
10:24nkozapandeiro: lein deps :tree (at least with lein 2)
10:26augustlhttps://www.refheap.com/paste/5620 weird stack trace.. If anyone has got some suggestions I'm all ears
10:27pandeirojsabeaudry: nkoza: thanks
10:29augustlis there a way to get column info in stack traces? servlet.clj file that seems to cause the error has only one long line in it (it's a generated file)
10:30antares_augustl: you are replacing clojure.core/list with myapp.views.attendants/list. This probably confuses the compiler (which relies on parts of clojure.core for some bits)
10:30jsabeaudryaugustl, I beleive that is coming in 1.5
10:31antares_augustl: add (:refer-clojure :exclude [list]). Column numbers are coming in the next release.
10:32WokenFuryhas anyone used Noir validations with enlive? if I try to access noir.validation/errors? in a defsnippet it turns out that noir.validation/*errors* is unbound, outside of a defsnippet it's bound.
10:32augustlyay for column numbers :)
10:33augustlantares_: the redefine of clojure.core/list wasn't the problem
10:33augustlstill getting the same error after adding (:refer-clojure :exclude [list]), the warning is no longer there so it was picked up
10:34clgvWokenFury: usually the problem is that those variables are not bound outside a request
10:34augustlantares_: oh I was getting another error from another file. Fixed them all, now it works, thanks.
10:35WokenFuryclgv: my defsnippet is called from within a noir/defpage though, so the request is definitely active and *errors* is bound in the defpage
10:38clgvWokenFury: maybe defsnippet tries to use *errors* on macro expansion time?
10:39clgvI dont know how defsnippet works ;)
10:40antares_WokenFury: you can also try http://clojurevalidations.info, it is a completely standalone library, no implicit use of vars (otherwise noir.validation is just as good)
10:43WokenFurylooks like someone else ran into this. let me test snippets outside of deftemplate https://github.com/cgrand/enlive/issues/30
10:45edward_hmm, is there any other way of "do nothing" instead of returning nil in clojure?
10:47augustledward_: depends on what you're working with I guess
10:47jsabeaudryedward_, removing the statement
10:47augustledward_: + returns 0 with no arguments, which will cause it to "do nothing"
10:47jsabeaudryaugustl, taking note of that for 4clojure :)
10:47antares_edward_: in Clojure, you primarily work with returned values. Everything is an expression. So returning nil, 0 or any other sensible value is typically how you do it.
10:48augustljsabeaudry: :D
10:49edward_ya but the problem is, I'm working with enlive, and I have this case statement. For one case I can't return nil cuz that would literally render nil in the frontpage
10:49antares_edward_: if you want a function that "does nothing", there is clojure.core/identity that takes something and returns exactly what it is given.
10:49edward_oh nice !
10:49antares_edward_: use an empty string
10:50edward_hmm it gives me indexoutofbounds if i use empty string, but let me try identity first
10:50edward_nice it worked just the way I wanted :D
10:50edward_Thanks guys
10:53pandeirodrewr: can i ask you a postal/javax.mail question? do you know why MimeMultipart parts are sometimes encoded as base64 and sometimes as 7bit?
10:57WokenFurygrrrr. having major regrets about rewriting this hiccup code in enlive. less code in enlive, but more random explosions
11:01drewrpandeiro: I don't know off the top of my head; can you give me an example of the two?
11:02pandeirodrewr: so i'm looking through postal/message.clj... when it calls (.attachFile msg "foo.png"), the result MimeBodyPart ends up yielding an instance of com.sun.mail.util.BASE64DecoderStream
11:03pandeirobut at the repl, when I manually do the same, the MimeBodyPart.getContent() yields a regular InputStream
11:03pandeiroi am trying to debug some problems with using BASE64DecoderStream in another lib, and I am baffled at the seemingly random results
11:05pandeiroit seems like with postal, and with mail clients like Alpine too, plaintext files end up encoded as 7bit (SharedByteArrayInputStream instances), while binaries like pdfs and pngs end up as BASE64DecoderStream
11:06pandeiroyet if you do (.getContent (doto (javax.mail.internet.MimeBodyPart.) (.attachFile "foo.pdf"))), you get an instance of FileInputStream
11:07drewrthat all sounds right to me
11:07pandeirohow is it determining which to encode as which, and why the different behavior at the REPL and in message.clj?
11:09pandeirois there somewhere postal 'hints' to javax.mail.internet.MimeBodyPart that it should encode those binaries as base64 instead of FileInputStream? or does FileInputStream get converted magically when you do Transport/send or something?
11:09drewrno, that's all javamail
11:11pandeirodamn i am stumped by this... anyway sorry for bothering ya
11:13arrdem,(= identity (fn [x] x))
11:13clojurebotfalse
11:27Kototamahi, how can I make th equivalent JS call "new Backbone.View({})" in clojurescript?
11:30ohpauleezKototama: If you can require the Backbone namespace (if it's setup like a Closure lib), you would require it and then do: (Backbone.View. {})
11:32ohpauleezIf it's a singleton and you're using a function call, you might end up with something like (.View Backbone {})
11:34Kototamadon't I need prefix Backbone with js/Backbone?
11:34Kototamaand how can I specify that the call is a 'new' ?
11:34Kototama.View will just invoke the function no?
11:37nDuffKototama: (View.) constructs a new object.
11:37nDuffKototama: ...as opposed to .View
11:37ohpauleezKototama: Right, like my first example
11:37nDuffahh.
11:37Kototamaok but if I don't required the lib but used a dynamically loaded library
11:37nDuff...so, ohpauleez's answer looks right.
11:38nDuffthe "." being on the end specifies that it's a new.
11:38Kototama(js/Backbone/View.) won't work
11:39ohpauleezKototama: If you're using it that way: (js/Backbone.View. {})
11:39nDuff...well, that's a Clojure {}, not a JS {}, no?
11:39ohpauleezbut that's not advised - you're going to have to externs that stuff
11:39Kototamayeah okk I'm just playing with existing code to see what I could do with clojurescript
11:40Kototamabecause JS makes me cry everytime I forget that the context of 'this' has changed :-s
11:41Kototamaah! js/Backbone.View works but if I remember correctly this is some new syntax, not clojure comptible
11:42ohpauleezKototama: That's regular Clojure code, JVM interop works very similarly, with the exception of the js/ piece
11:43KototamanDuff: you'right {} is passed as a cljs.core.ObjMap
11:43ohpauleezthe reason for periods and not slashes happens because you're using js/ and you're accessing a constructor, not hitting an aliased namespace
11:43Kototamaohpauleez: ok i need to relook at that because I didn't write any niterop code since a long time
11:43clojurebotprimetime |is| <lowlycoder> i'm not convined clojure is ready for primetime until i see facebook apps in clojure
11:44ohpauleezKototama: (js-obj) I believe is the form, but you're probably better off extending appropriate protocols to Backbone stuff
11:44Kototamawell you're right java.lang.Integer just uses plain dot and is clojure
11:44Kototamayep
11:45Kototamanot sure how to do that in clojurescript
11:45ohpauleezKototama: The same way you do it in Clojure
11:46ohpauleezlet me get you an example
11:46ohpauleezKototama: http://shoreleave.github.com/shoreleave-browser/#shoreleave.browser.cookies
11:47drewrpandeiro: sry, I would look into it more but I can't atm
11:47ohpauleezHere I extend Closure's Cookies support, so I can use map-like lookups
11:48SegFaultAX|workHas anyone else seen Brendan Eich's talk at Strange Loop about JavaScript?
11:48Kototamawow it looks really easy
11:49ohpauleezvery easy
11:50Kototamabut this would not really create new Backbone.Views / Models but only add clojurescript methods to the backbone types right?
11:50Kototamaso that I call count or whatever on the models
11:51Kototama+could
11:51ohpauleezKototama: You would do something like: (def cookies (goog.net.Cookies. js/document))
11:51ohpauleezor wrap the constructor call
11:51SegFaultAX|workIt seems like they've just taken a random smattering of features from Python and Ruby and added them to JavaScript haphazardly.
11:52ohpauleezand then with the protocols extended to the object in Backbone, you can use standard Clojure functions on them
11:52ohpauleeztreating views like maps, vectors, whatever you want
11:52ohpauleezSegFaultAX|work: Who has? Backbone?
11:53SegFaultAX|workohpauleez: The ECMAScript team.
11:53Kototamaok but the render function for instance for views should be dispatched on instances; not on the type
11:53ohpauleezahh yes, the new specs are adopting a lot of things that are prevalent in other circles and patching up some oddities in the spec
11:53Kototamait's like the method of an object basically
11:54SegFaultAX|workohpauleez: Check it - http://brendaneich.github.com/Strange-Loop-2012/#/
11:54SegFaultAX|workohpauleez: Slides on his talk at Strange Loop about features coming in ES6 and ES7.
11:54ohpauleeznutty, I definitely will
11:54SegFaultAX|workohpauleez: Don't get me wrong, I'm glad they're doing it. It might actually make JS a sensible language to some degree. But the selection of features is pretty random. Maybe that's a good thing?
11:55duck1123there are protocol extensions to backbone?
11:55Kototamafor instance you can't do that with extend-type http://paste2.org/p/2316251 right?
11:56KototamaI need to call the extend function first to create instances of views and only then I would be able to user the generic function defined by extend-type for it
11:56antoineB,(nth 2 [:a :b :c])
11:56clojurebot#<ClassCastException java.lang.ClassCastException: clojure.lang.PersistentVector cannot be cast to java.lang.Number>
11:57Kototamabut the specific render function needs to be passed in the hash of the extend call, right?
11:57antoineB,(nth [:a :b :c] 2)
11:57clojurebot:c
11:57duck1123Kototama: Here's how I've been using Backbone w/ cljs https://github.com/duck1123/jiksnu/blob/pending/src-cljs/jiksnu/model.cljs
11:59Kototamaduck1123: really helpfull thank you
11:59duck1123I made my own backbone ns so I could easily reference those classes
12:00duck1123next step will be a macro to make those model defs really pretty
12:00TimMcclojurebot: Why so sad?
12:00clojurebotNo entiendo
12:01Kototamaduck1123: and then do a lib that I can import ;-)
12:01jconnolly,(nth [:a :b :c] 2)
12:01clojurebot:c
12:01duck1123Kototama: That'll be the idea
12:01duck1123in the mean time, feel free to steal any of that you find useful
12:02Kototamathank you I'll have a look at that
12:04duck1123if you hold on, I have new stuff to push
12:04antoineBdo you know any big application done in clojurescript?
12:07Kototamaduck1123: i'm not in the hurry, I will have a look at it tomorrow
12:07fckwHi there.
12:07fckwGot a FP question:
12:07fckwI have a map with key-value pairs.
12:07KototamaI need to see If I stick to JS until the end of the project or switch to ClojureScript to preserve my calm :-)
12:07duck1123Kototama: well, it's all there on the pending branch now. you can see it in action at http://renfer.name/
12:08fckwI want to apply some function (e.g. inc) to all the values of the elements and then return the new map.
12:08fckwThere must be an easy way to do this, but I don't get it right now.
12:08fckwUsing the val function returns only a seq of values - not what I want.
12:08fckwSorry, I meant: Using the vals function.
12:09Kototamasomething like (map inc (vals coll)) ?
12:09fckwYes, something like this.
12:09lynaghkHas anyone gotten tagged literals working within a REPL (i.e., not using the data_readers.clj file)?
12:09fckwBut then returning the whole map, not only a seq of (changed) values.
12:10lynaghkI'm binding *data-readers* as instructed in the docs but my tags don't get picked up.
12:11Kototamalook at reduce-kv I guess
12:11jkkramerlynaghk: are you using lein repl (reply)?
12:11fckwThe background to my question is, that I want to html-escape all values in the params-map I get through a ring post requrest.
12:11lynaghkjkkramer: I'm using swank
12:11jkkramerlynaghk: got a paste-able snippet?
12:11lynaghkjkkramer: sure, give me a sec.
12:13Kototama(reduce-kv (fn [acc k v] (assoc acc k (inc v))) {} {:one 1 :two 2})
12:14lynaghkjkkramer: https://www.refheap.com/paste/5622
12:14fckw@Kototama: I have to try this out, thanks for your suggestion.
12:15lynaghkjkkramer: passing the var (e.g., #'map->A) doesn't make a difference either.
12:15fckw@Kototama: Thanks! I did not know about reduce-kv until now.
12:15lynaghkjkkramer: nor does namespacing the tag
12:15Kototamait's relatively new it was introduce in 1.4
12:15hiredmanlynaghk: I have
12:16hiredmanlynaghk: I set! *data-readers*
12:17hiredmanlynaghk: https://gist.github.com/3859794
12:17fckwI believe it could be done even shorter somehow, but I cannot see a solution right now.
12:17lynaghkhiredman: that works, thanks! Shouldn't the binding form work as well, though?
12:17hiredmanlynaghk: no idea
12:17jkkramerlynaghk: tagged literals can't be used that way. the binding happens after the code has been read. this will work but doesn't necessarily solve your problem: (with-bindings {#'*data-readers* {'A map->A}} (read-string "#A {:foo 1}"))
12:17jkkrameryeah, see hireman's thing
12:18lynaghkjkkramer: okay, that makes sense.
12:18lynaghkjkkramer, hireman: thanks.
12:31fckwAh, here we go, there is an update-in function.
12:31fckwThis might be handy.
12:41fckwCan anyone explain me why this code does not work: (def my-map {:one 1 :two 2 :three 3})
12:42fckw(update-in my-map (keys my-map) inc)
12:42fckwI get a NullPointerException.
12:42clgvfckw: you misunderstood update-in
12:42hiredmanthe keys you pass to update-in are expected to describe a path through a nested structure of maps
12:42clgvfckw: update-in is for nested maps
12:43fckwOh gosh. So is there really no simple "update" function?
12:43clgv&(update-in {:a {:b 1} :c {:d 0}} [:a :b] inc)
12:43lazybot⇒ {:a {:b 2}, :c {:d 0}}
12:43fckwUpdating all values in a map?
12:44clgvyou can use reduce-kv like: ##(reduce-kv (fn [m, k, v] (assoc m k (inc v))) {} {:a 0 :b 2})
12:44lazybot⇒ {:b 3, :a 1}
12:44fckwAs it seems I really have to unpack each value of a key-value pair and then associate the changed values with a new map.
12:44fckwYes, I already was told so. Is this the standard way of doing updates to all values in a map?
12:45fckwCreating a new, empty map and re-associating the changed key-value-pairs?
12:45clgvfckw: from a structure-sharing point of view: you cant share structure if you update every value
12:45fckwHm, that's true.
12:45duck1123no matter how you slice it, sooner or later, the code is going to loop every key and perform the operation in turn
12:45fckwOk, thanks for your answer.
12:46clgvyou can build a function from the above reduce-kv snippet for convenience
12:46technomancy,((comp inc {:a 0 :b 2}) :b)
12:46clojurebot3
12:46technomancybut then it's not a map anymore
12:46dnolenfckw: even if you were doing this in an imperative language you'd still have to loop over all the keys and mutate each entry.
12:48fckwBut why can I do a map or apply on a list, but not something similar on a map?
12:48fckwWould be nice: Applying a change to each element (e.g. its value) in a map using the map function.
12:48SegFaultAX|workfckw: Sounds like you want fmap.
12:49technomancyfckw: part of the point of map is that it's lazy
12:49arrdem,(let [m {:a 1 :b 2 :c 3}] (zip-map (keys m) (map inc (vals m))))
12:49clojurebot#<CompilerException java.lang.RuntimeException: Unable to resolve symbol: zip-map in this context, compiling:(NO_SOURCE_PATH:0)>
12:49arrdem,(let [m {:a 1 :b 2 :c 3}] (zipmap (keys m) (map inc (vals m))))
12:49clojurebot{:b 3, :c 4, :a 2}
12:49clgvfckw: (defn update-map [m f] (reduce-kv (fn [m, k, v] (assoc m k (f v))) {} m) voila! but maybe you should add transients
12:49duck1123performing an op on every vaule in a map isn't as common of a need IMO
12:49technomancyanyway, I agree that map-keys and map-vals would be nice, but at that point it's different from clojure.core/map
12:50fckwI cannot find a fmap function?
12:50dnolenfckw: you can map over a map - but map always returns lazy seqs - so you'll have to do some of the things shown above to get back to a map.
12:52fckwI wrote above that the background of my question is that I have a ring POST request giving me a parameters map and I want to html-escape all values in the parameters map.
12:52fckwBut anyway, reduce-kv seems the way to go.
12:52clgvfckw: yeah, I think thats the reason why it was added in 1.4 ^^
12:57SegFaultAX|workfckw: Clojure has a Functor library that provides fmap.
12:57SegFaultAX|workfckw: Clojure contrib, rather.
12:58fckwHere is my new function that escapes html:
12:58fckw(defn- with-html-escaped [params]
12:58fckw@SeqFaultAX: I'll have a look, thanks.
13:00clgv~contrib ;)
13:00clojurebotlatest contrib is 947
13:00clgvoops
13:00clgv~contrib
13:00clojurebotMonolithic clojure.contrib has been split up in favor of smaller, actually-maintained libs. Transition notes here: http://dev.clojure.org/display/design/Where+Did+Clojure.Contrib+Go
13:00TimMcclojurebot: forget latest contrib |is| 947
13:00clojurebotI forgot that latest contrib is 947
13:00fckwThere is the fmap function: http://richhickey.github.com/clojure-contrib/generic.functor-api.html
13:00lazybotNooooo, that's so out of date! Please see instead http://clojure.github.com/clojure-contrib/generic.functor-api.html and try to stop linking to rich's repo.
13:01clgvfckw: better use the update-map I gave you above ^^
13:04fckw@clgv: Yes, I'll use the reduce-kv as you suggested because prefer not to rely on clojure-contrib. But for the future a fmap functor would be really nice.
13:06SegFaultAX|workfckw: Functors are just things that can be mapped over. fmap is the generic map function for this mappable things. Eg fmap :: (Functor f) => (a -> b) -> f a -> f b
13:06zerokarmaleftfckw: as clgv said, you might want to add transients, frequencies in core is a good example of how to do that
13:07SegFaultAX|workfckw: In the case of clojure, "mappable things" applies broadly to all sequence/collection/container types.
13:10fckwYes, using transient maps seems like a good idea when html-escaping parameter maps that are being sent from the client.
13:11fckwI'll have to read up the corresponding topics.
13:22ppppaulhey
13:22ppppaulanyone here use clutch?
13:28pandeiroppppaul: yeah
13:28ppppaulpandeiro, have you done anything with attachments?
13:28pandeiroppppaul: ha, yeah been debugging something involving attachments for almost 2 weeks
13:28ppppaulhmmm
13:29pandeiromy problem is with a particular input stream type, usually it has worked fine in the past
13:30ppppaulok. i am pushing 23k attachments at 250megs into a doc (this is not an issue for me with couchdb). my issue is that i'm using node.couchapp, and it's a toy and breaks. it is keeping too much useless data in memory and i'm debugging it now. i've used clutch a bit (when it was young), and i'm wondering if i would have a lot of pain in trying to emulate couchapp with it, or is someone has already done the dirty work...
13:33pandeiroppppaul: i haven't done the dirty work but tbh i'd do it with bash+curl
13:34pandeiroclutch can probably handle it, and would be infinitely more malleable i imagine
13:34pandeiroah i meant to say bash + curl + underscore-cli (vital ingredient)
13:34pandeirofor slicing through the json etc
13:37ppppaulbash/curl... how would that handle pusing 23k docs?
13:37ppppauli mean files
13:37duck1123pandeiro: thanks for pointing out underscore-cli
13:37nDuffppaul: ...eh, that's not really a question that can be answered; depends on the specific requirements.
13:38nDuffpppaul: the case where it _wouldn't_ be adequate is if you needed things like session keepalive.
13:38ppppaulhmmm... i guess i would have some commandline thing to base64 all the files?
13:38nDuffppppaul: Huh? curl can manage encoding itself.
13:38nDuff...anyhow, #bash -> thataway.
13:38ppppaulnDuff i am bash noob :)
13:39ppppaulwow, i was really hoping to avoid bash scripts... but if you guys say this is the way to go, then i guess i'll do it...
13:39jsabeaudrypppaul, clojure is over-rated, use bash
13:41jweissis there a non-chunked lazy sequence? http://www.infoq.com/news/2009/12/clojure-11-rc1-transients "An interface to force single-item consumption of chunked seqs is still being designed."
13:41ppppaulwell, i mainly need to push a dir into couchdb preserving relative paths
13:42nDuffjweiss: can be done using lazy-seq, yes.
13:42duck1123jweiss: I use this to unchunk my seqs https://github.com/duck1123/ciste/blob/master/src/ciste/routes.clj#L75
13:42pandeiroppppaul: i am also bash-averse
13:43pandeirobut i will post my code, hold on
13:43jweissnDuff: duck1123: so, does lazy-seq alone not do it then?
13:44nDuffjweiss: depends on what you mean by "lazy-seq alone".
13:44nDuffjweiss: ...I mean, if you use lazy-seq to attach a new head to a chunked lazy sequence, then only that head will be unchunked.
13:45pandeiroppppaul: http://sprunge.us/LWCg?bash
13:45jweissnDuff: i have a long-running fn "lrf". if I call (take 5 (map lrf (iterate inc 1))) how can i make sure lrf only gets called 5 times
13:45jweissinstead of 32
13:46nDuffjweiss: see what duck1123 gave you.
13:46jweissok thanks
13:47jweissnDuff: so it would be (take 5 (lazier (map ...)) ?
13:48duck1123jweiss: that should do it
13:48jweissduck1123: great, thank you
13:48amalloyjweiss: iterate isn't chunked
13:48nDuffpandeiro: ...so, if I were doing my #bash curmudgeon thing, I'd have some quibbles about writing status information to stdout, using $(cat ...) in place of $(<...), and not indenting after using newline continuations, but that looks pretty good.
13:48jweissamalloy: map doesn't do any extra chunking?
13:49amalloynothing (afaik) ever makes a sequence become chunked
13:49amalloythere are only chunked sequence-producers, and functions which retain chunkiness
13:49jweissso i guess i would want to know if map does that :)
13:49dnolenjweiss: chunking is a property of the collection - range, vector etc
13:49amalloyit does, but you don't care
13:49duck1123amalloy: in my case, it was a map over a literal vector that makes it chunked
13:50amalloywell yep, that'll do it
13:50jweissamalloy: i'm not sure why i don't care, but i'll take your word for it and try it without worrying about it and see if it happens
13:50pandeironDuff: thanks, i def _do_ need a bash mentor
13:50amalloyjweiss: because you're calling map on iterate
13:50pandeiroand #bash is scary
13:50amalloyif you were calling map on something else, you might care
13:51amalloybtw there's https://github.com/flatland/useful/blob/develop/src/useful/seq.clj#L178 in useful
13:51jweissamalloy: well, that was just an example, i'll really just be doing something more like (repeatedly 5 lrf)
13:51amalloy(unchunk coll) and (lazy (foo) (bar) (baz)) are both relevant
13:52jweissamalloy: that looks the same as the earlier posted function 'lazier'
13:52amalloyit probably is
13:53duck1123there are some slight differences, which seems interesting
13:53amalloyduck1123: the version in ciste is not as good
13:53amalloybecause it forces realization of the first element unconditionally
13:53duck1123interesting. good to know
13:54ppppaulthanks pandeiro
13:54amalloyplus depending on useful seems like a better way to get a lazy-sequence operation than depending on ciste's routes lib
13:54amalloy(from jweiss's point of view)
13:55duck1123very true. Thinking on depending on useful myself actually
13:55pandeiroppppaul: ignore the debug statements and other bad forms nDuff mentioned ;)
13:55duck1123since I never have it required, I'm sure I'm missing out in several places
13:56amalloyduck1123: tbh the most-used thing in useful is probably ?, my debug macro
13:57ppppaulpandeiro, the .couchrc is a file with 1 line of text?
13:58ppppaullike, it wants localhost:5984/db_name ?
13:59pandeiroppppaul: http://user:pass@host:port
13:59ppppauli see
14:00pandeiroppppaul: you could update it to automatically iterate over entire directories and stuff...
14:00pandeirobut for me that ended up being more useful than the whole couchapp/nodecouchapp chain for most of what i do
14:01Licenseribdknox ping :)
14:02jweissamalloy: is ? sort of like tracing functions but on the form level?
14:02amalloyjweiss: it's just a slightly less-awful version of debug printf
14:03amalloy(? (foo bar)) evaluates the same as (foo bar), and also prints "(foo bar) is 10"
14:03jweissamalloy: ah i see, you don't call it from the repl, you embed it in your code?
14:03amalloyyep
14:04duck1123how does it compare to clojure.tools.logging/spy (aside from the log vs. print)
14:06amalloynot much difference. it handles exceptions a little better, but for me the important gain is i don't have to figure out clojure.tools.logging
14:07amalloyi suspect it also aligns a bit better for large expressions/values, but that's just based on reading the code for spy
14:08duck1123I had a similar macro that I used that put the output on the same line, but I abandoned it in favor of the logging version
14:08pandeironDuff: sorry for bash question, but i can't find anything on google about why u would use $(<cat...) instead of $(cat...)
14:09nDuffpandeiro: the latter requires exec'ing an external tool
14:09nDuffpandeiro: if you run 'type cat', you'll see it's /bin/cat, not a bash built-in command.
14:09pandeiroah sure ok
14:09nDuffoh, and it's not $(<cat file), it's $(<file)
14:10jweissis there a suggested way to bind up functions with some args already fixed? eg, i have an http client but want to fix the username and password so they don't have to be specified each time. i know I can use a var and binding form, but that can get ugly with multithreaded apps. i guess i could generate a map with the functions in it. that seems awkward too.
14:10nDuffjweiss: sounds like you want partial?
14:10jweissnDuff: yeah, partial will create the functions, but then how do i make them accessible
14:10pandeironDuff: but with non-internal stuff, $(cmd ...) would be an appropriate way to store cmd output into a variable?
14:11nDuffjweiss: One approach I've taken in the past is to have a top-level def of a future which retrieves the configuration on first use.
14:12nDuffpandeiro: Yes.
14:12jweissnDuff: i would want to support multiple configurations at the same time, but not necessarily on a per-thread basis
14:13nDuffjweiss: Ahh; that is indeed more interesting, then.
14:13jweissthat's why i shy away from using a var
14:13jweissi think maybe i'll just return a map like {:get <fn> :post <fn> ... {
14:13jweiss}
14:20jlewiswhat's the idiomatic way to check if something is callable?
14:22amalloy&(doc ifn?)
14:22lazybot⇒ "([x]); Returns true if x implements IFn. Note that many data structures (e.g. sets and maps) implement IFn"
14:22jlewisthanks!
14:26Licenserhmm if ifn? is the idiomatic way would (try () true (catch _ false)) the idiotic way?
14:33ziltiWhen using lein-ring uberwar, the resources folder doesn't get included into the war file. Is that a known problem? How do I fix that?
14:39ziltiSometimes that stuff feels like it never gets used in production.
14:42ulathhi, i have a large text, and this text's parts are depends on some variables (conditions) and in the future these variables can increase and static part of the text will need to be conditional (dynamic). what is the best solution for problems like these?
14:44pjstadig,(time (dotimes [_ 1000000] (object-array [1])))
14:44clojurebot"Elapsed time: 308.76889 msecs"
14:44pjstadig,(time (dotimes [_ 1000000] (object-array (rseq [1]))))
14:44clojurebot"Elapsed time: 123.725152 msecs"
14:45pjstadigthere's a riddle for you
14:45pjstadigto which i know the answer
14:45technomancythat is amazing
14:48ziltiWhat does that underscore do?
14:48scriptorit means the variable is ignored
14:48scriptorwell, more specifically, you don't care about the binding
14:48dnolenzilti: it has no real special meaning - just convention
14:49ppppaulpandeiro, i'm working with your file, but i can't seem to get couch-put/couch-post working
14:51scriptorhmm, where's the rseq class defined?
14:51amalloypjstadig: that's a curious riddle
14:52amalloyscriptor: APersistentVector$RSeq
14:52scriptoryep, thanks
14:52ppppaulpandeiro, are you versioning the file? would you be interested in starting a repo or gist?
14:54ziltiIs someone here working with lein-ring? Because of my problem with the inclusion of the resources directory
14:54amalloyoh. Vector$Seq doesn't implement Counted?!
14:55pjstadigcorrect!
14:55pjstadigwell
14:55pjstadigPersistentVector$ChunkedSeq
14:55pjstadig,(class (seq [1]))
14:55clojurebotclojure.lang.PersistentVector$ChunkedSeq
14:56pjstadig,(instance? clojure.lang.Counted (seq [1]))
14:56clojurebotfalse
14:56pjstadig,(instance? clojure.lang.Counted (rseq [1]))
14:56clojurebottrue
14:56devthanyone know if there's a way to retrieve the source for an entire namespace, similar to clojure.repl/source for vars?
14:57amalloyhah. i didn't even look at ChunkedSeq, so it's lucky APersistentVector$Seq behaves similarly
14:57amalloypjstadig: going to submit a patch to fix that silliness?
14:58pjstadigactually APersistentVector$Seq implements IndexedSeq which implements Counted
14:58amalloyoh, so it does. i didn't expect that, given that APV$RSeq implements IndexedSeq and (explicitly) Counted
14:59amalloymy detective skills are looking more and more like random luck
15:00pandeiroppppaul: https://github.com/pandeiro/dotstar/blob/master/bash/bash_functions
15:00pjstadigi guess i should open a jira ticket for it
15:00amalloywow, IndexedSeq is interesting. i didn't know that interface existed. and apparently neither did rich, because that index() method is never used anywhere in the clojure sources
15:01dnolenpjstadig: what would the fix be?
15:01amalloywell, i guess that's not true. someone could be using it indirectly via ArraySeq or some other implementing class
15:02amalloynope. lots of definitions of index(), and no uses of it. crazy
15:03pjstadigdnolen: i assume making PersistentVector$ChunkedSeq implement either Counted or IndexedSeq
15:05tomojamalloy: it looks like it was ported from c#?
15:05amalloywhaaaaa?
15:05pjstadighehe
15:06dnolen,(counted (seq (range 32)))
15:06clojurebot#<CompilerException java.lang.RuntimeException: Unable to resolve symbol: counted in this context, compiling:(NO_SOURCE_PATH:0)>
15:06dnolen,(counted? (seq (range 32)))
15:06clojurebotfalse
15:06tomojamalloy: `git log` that file
15:06dnolen^ probably also needs fixing as well then.
15:07pjstadigdnolen: you think?
15:08tomojoh, well, not sure. but there is an almost identical c# file in the same commit that introduced IndexedSeq.java
15:08amalloytomoj: i don't see it
15:08amalloyah
15:09dnolen,(counted? (seq {:foo 1 :bar 2}))
15:09clojurebottrue
15:09pjstadigdnolen: i see this as a regression, because before chunked seqs (object-array [1]) and (object-array (rseq [1])) would have taken roughly the same amount of time
15:09amalloydnolen: agreed that's a good fix, and an implementation can be stolen from me via http://dev.clojure.org/jira/secure/attachment/11447/range-reducer.patch if anyone wants to do it
15:10pjstadigwas range also counted before chunked seqs?
15:12amalloypjstadig: probably not
15:13amalloysince it's in clojure rather than java. unless you mean the super-old clojure.lang.Range, which is indeed Counted
15:14Derylbat23hello
15:14Derylbat23list please ?
15:14hiredman()
15:15dnolenpjstadig: I think the ticket should be general - return counted seqs if the information is available.
15:15dnolenpjstadig: the CLJS persistent data structures exhibit this issue as well - since we just followed Clojure JVMs lead.
15:17TimMc(inc hiredman)
15:17lazybot⇒ 14
15:18hiredmanspeaking of such things
15:19hiredman,(inc (Long/MAX_VALUE))
15:19clojurebot#<ArithmeticException java.lang.ArithmeticException: integer overflow>
15:19hiredmanI guess that is technically correct, a long is a long integer, but :/
15:21TimMcAs long as it doesn't say Integer overflow.
15:24augustlout of curiousity, why does leiningen have (defproject ...) instead of just a plain map?
15:24pjstadig,(unchecked-add Long/MAX_VALUE 1)
15:24clojurebot-9223372036854775808
15:26amalloypjstadig: i think he's just objecting to the message, not the exception
15:26pjstadigamalloy: yeah i was thinking of something else
15:28pjstadig,(unchecked-add (Long. Long/MAX_VALUE) 1)
15:28clojurebot#<ArithmeticException java.lang.ArithmeticException: integer overflow>
15:28pjstadig,(doc unchecked-add)
15:28clojurebot"([x y]); Returns the sum of x and y, both long. Note - uses a primitive operator subject to overflow."
15:29pjstadigwhich i guess is correct if you pay attention to the fact that the docstring says long with a lower case ell
15:30pjstadigi would almost perfer that unchecked-add throw an exception in that case instead of giving me the (slightly different) slow path in the code
15:30pjstadigor have the slow path check if it's a Long and call the overflowing version
15:37pjstadigdnolen: sorry i already created the story, i can see how maybe there should be a more general focus on implementing Counted where appropriate
15:37pjstadigi was also thinking it would be better to have smaller scope
15:37callendoes anyone here use MongoDB with Clojure?
15:37callenif so, is there a recommended library?
15:38augustlcallen: I'm using monger, works fine
15:38augustlI built a small library on top of it though
15:38callenaugustl: that's what I'd been looking at, thanks. Small library?
15:39augustlyeah, it adds stuff like (make-save "collection-name" validator processor)
15:39augustla validator function can add validation errors and stop the save, a processor is pre-insert processing of the data
15:40callenthat makes sense.
15:40augustlthat's essentially it. That allows me to say (def save (make-save ...)) in user.clj, and later call (user/save ...), so I don't have to hardcode the collection everywhere
15:40augustlcallen: also made my library take a db object as the first argument to all operations, to make it functional
15:40augustlrather than a hidden singleton somewhere storing the connection etc.
15:40callenI found the singleton in monger kinda problematic.
15:41callenI tolerated a stateful connection object to MongoDB in Python, but in Clojure it raises my hackles a bit to have a stateful object floating through space like that.
15:41augustlcallen: https://github.com/oiiku/oiiku-mongodb-clojure
15:41augustljust open sourced it, why not ;)
15:41callenaugustl: very cool, thank you.
15:42augustlit's not documented at all though, will make it release quality later, just thought you'd might like to take a look at it
15:42callenaugustl: I'm still less-than-proficient in Clojure, so it'll at least give me something to learn from. TYVM
15:42augustlnp :)
15:43augustlthe validation system should probably be stand-alone too, it's not really mongodb specific
15:43callenaugustl: part of the reason I'm trying to move to clojure, is that I wanted to integrate and compose input/data validation across the frontend and the persistence layer
15:43callenaugustl: doing so in Python where every library is a fiefdom is a sisyphean task.
15:44augustlcallen: using clojurescript for validation on the client side or something, you mean?
15:45dnolencallen: heh, i like that "where every library is fiefdom" ...
15:46callendnolen: ahhh thank you. You're the one that did all that work on pred dispatch and logic right?
15:47dnolencallen: pred dispatch hasn't gotten very far, but yes I work on core.logic/match
15:47callenif so, awesome. Learned a lot from reading your posts about the subject.
15:52callendoes anyone else here use Lobos for migrations? it's not totally clear to me what refer-to does and I'm having a hard time finding it in the code.
15:53augustlcallen: updated the README, at least it doesn't contain non-existing functions in it now ;)
15:56callenin fact, I can only find the refer-to function in the tests. how bizarre.
15:57callenlobos...may not be production ready.
15:58callenaugustl: very cool, haha. Thank you.
16:02TimMccallen: There's also Ragtime and... drift?
16:02callenTimMc: what do you use?
16:02TimMcI don't. :-/
16:03callenTimMc: do you do anything with clojure that needs persistence?
16:03TimMcLast time I tried, I gave up. The things I found were not well documented in terms of their pragmatics, so I decided not to have migrations.
16:03TimMcIt was for a personal project, so I had the luxury of giving up.
16:04callenTimMc: what I'm eventually going to build is semi-serious, so there are tradeoffs to consider here. A half-baked migrations library might be worse than writing my own scripts.
16:07technomancycallen: I definitely support rolling your own; clojars has a simple implementation in two defns
16:08technomancyhttps://github.com/ato/clojars-web/blob/master/src/clojars/db/migrate.clj
16:08technomancymuch easier than trying to comprehend lobos
16:08callentechnomancy: I take it you've tried to go down the lobos rabbit-hole too?
16:09callenin my case, it wouldn't even be in clojure, I'd just do it with sql scripts.
16:09technomancycallen: yeah, I think it's too ambitious among other things
16:09callenI agree. The refer-to functionality is *bizarre*
16:09technomancythere is no way you can abstract away the differences between schema languages of various DBs
16:10callentechnomancy: thank you for the pragmatic note.
16:11TimMcThat's why I tried using ragtime, since it isn't even specific to databases.
16:12thorbjornDXhi, I have a hundred or so lines of defmulti/multimethod statements that basically just does (defmulti somefunc :mykey) (defmethod somefunc :key1 [m] key1-ns/somefunc) ... Is there a macro that I can use to clean this up?
16:12technomancyragtime is pretty good, but it's more complicated because it supports down migrations. in my experience down migrations don't work in practice.
16:12callenI don't like the idea of an unsupervised "down" anyway.
16:13callenI love automation, but it's unrealistic.
16:13technomancyI don't have an answer for migrations on long-lived branches other than "make sure they don't interfere with each other" unfortunately
16:15callentechnomancy: it's case-specific, best to embrace that fact and realize that you have to know what you're doing.
16:16technomancyyeah, I guess beyond a certain complexity you just have to pick the lesser of N evils, which is highly specific to the codebase in question.
16:16pandeirois it possible for cljs (clj) macros to reference cljs files?
16:17dnolenpandeiro: not as far as I know.
16:17S11001001pandeiro: functions, or macros, in said files?
16:17neotykHello Everyone!
16:18neotykwhen extending types in cljs, what is a difference between 'string' and 'js/String'?
16:18dnolenneotyk: if js/String appears in core.cljs probably an oversight, string is preferred
16:18pandeirolike if i wanted to write a specialized test macro that refers to a state atom in my client cljs files?
16:19neotykdnolen: thanks
16:19dnolenpandeiro: then emit the fully qualified symbol to that atom.
16:32ppppaulpandeiro, hey. i realize that i don't know what couch-put or couch-post is supposed to do. would you be able to include some documentation or tests?
16:32antares_Second clojure-doc.org guide is good enough to recommend to people: http://clojure-doc.org/articles/language/polymorphism.html. If someone wants to help expand it, just submit a pull request :)
16:41augustlwhat's a good way to communicate success or error when both cases has data associated with it? For example, putting something in a database and returning the data, vs returning errors if it's wasn't put in the database for some reason
16:41technomancyaugustl: do you know about ex-info?
16:42augustltechnomancy: hmm no
16:43technomancyit's the best
16:44augustlit's not in the cheatsheet, how could I possibly know about it? :)
16:45augustllooks good, except it feels kind of wrong to use exceptions for control flow..
16:45augustlbecause I assume you mean raising an ex-info created exception instead of returning in the event of an error?
16:46Apage43also slingshot builds on that with some more advanced stuff you can catch on predicates or match on the associated data. For example, it was useful for me the other day, to only catch 404's from clj-http
16:46augustlthe error in question is common since it's caused by erronous user input (form validation etc)
16:47Apage43augustl: that seems like a nice place to use it, because the error can be caught at where the response page would be rendered, and use the attached info the highlight the bad field, or something like that, and you don't have to bother with making it possible to thread the error case all the way back
16:49augustlaren't exceptions exceptionally bad for performance though?
16:49augustlpun intended
16:49Apage43that's really the point of exceptions, getting the relevant info about an error to the place in the code where they're going to be handled
16:49technomancyaugustl: I really hope your users aren't submitting bad form values at a rate fast enough for that to be a problem.
16:49technomancyif so you have more serious problems to deal with than exceptions =)
16:50gtrakis there a better way to do this? (read-string (str "::an-ns/" "failed")) -> :fully-qualified-ns/failed ?
16:51augustlI'm currently returning {:success true :data 123} or {:success false :errors "validation errors here.."}, I like that better than exceptions
16:51augustlyou can multimethod over it ec.
16:51augustletc*
16:51loliveirahow do I access a recrd
16:51augustlloliveira: like a map
16:51augustlloliveira: (some-record :field)
16:51technomancyaugustl: the problem there is that you could omit the check for the success field and proceed on faulty data. if you're convinced you will never make that mistake then it could work.
16:52loliveirahow do I access a record method that was added using extend-type in other namespace?
16:52augustltrue, an exception, if uncaught, makes it clear what went wrong
16:53loliveiramore info: http://pastebin.com/RxJbj274
16:54loliveiraI am getting the folioing error: CompilerException java.lang.RuntimeException: Unable to resolve symbol: get-pos in this context
16:55gtrakthis is slightly better: (keyword (namespace `an-na/dummy-symbol) "failed")
16:59ppppaulpandeiro, how do you use your functions? they are sooooooo buggy. i don't think couch-upload works with the latest version of underscore-cli...
17:01Apage43I've tended to do that sort of stuff with clojure
17:09pandeiroppppaul: i never said i could write _software_
17:09augustlI have a map {:foo "bar" :baz 123}, how do I call a function that expects (myfunc "some other arg" :foo "bar" :baz 123) with that map?
17:09ppppaulpandeiro, lol
17:10pandeirocouch-put foo && couch-post foo '{"_id":"bar"}' && couch-upload foo/bar baz.png "image/png" && couch-get foo/bar | underscore pretty
17:10pandeirothe baz.png is on you :)
17:10ppppaulyour couch-upload is buggy. i fixed it... but i also refactored your code a bit
17:11augustlI'm defining the function as (defn myfunc [some-arg & {:keys [foo baz]}] ...)
17:11ppppaulhttps://gist.github.com/3861438
17:11ppppaulpandeiro,
17:12ppppauli got that working to upload a file...
17:12ppppaulso, now time to upload the other 28k files i have
17:12augustl(apply (partial myfunc "test") {:foo "bar" :baz 123}) does not work at least :)
17:13Apage43using couchdb as a file store, eh?
17:14augustlperhaps I should rewrite my function to just take a map as that's my only use case..
17:15aperiodicaugustl: you need to use flatten, it's the worst
17:15aperiodici recommend taking a map instead
17:15augustlaperiodic: doh, I guess that basically turns {:foo 123} into [:foo 123]?
17:16aperiodicaugustl: exactly
17:16Frozenlo`OMG. Damnit I'm dumb. I just realized I can use [{:keys [...]}] instead of [&[{:keys [...]}]]
17:16augustlapplying with [:foo 123] obviously works.. How silly
17:16augustlaperiodic: what's the easiest way to take a single map but still use destructuring? A let block in the body of the fn?
17:16pandeiroppppaul: sorry i'm totally confused by how you renamed stuff
17:17aperiodic,((fn [{:keys [foo]}] foo) {:foo "bar"})
17:17clojurebot"bar"
17:17pandeirobut i promise you if you take the versions from https://github.com/pandeiro/dotstar/blob/master/bash/bash_functions and run the line i wrote above, it works fine
17:18augustlaperiodic: ah of course
17:19ppppaulworks fine on what system? what version of bash? what version of underscore-cli ? lol pandeiro
17:20ppppauli'm on ubuntu, you may be on a mac (tends to be a much older version of bash)
17:20thorbjornDXwhat about 64-bit?
17:22pandeiroppppaul: does ubuntu even use bash? i thought it was dash or something
17:22pipeline/bin/sh is probably ash/dash.
17:22pipelinebut bash is installed at /bin/bash usually
17:46horofoxwhat function does the same of cons but take the parameters in the opposite way
17:46horofoxor append to the end
17:46horofoxof the list
17:46horofox?
17:46dnolenconj
17:47dnolenhorofox: sorry I thought you meant arg order
17:47casionconj appends to the beginning of a list I thought?
17:47dnolenhorofox: you can't append to end of list w/ traversing, Clojure doesn't really provide a operation that does that for lists.
17:47dnolenhorofox: use vectors
17:47dnolenw/o traversing I meant
17:48friodoes clojure have a reverse? (fn rcons [element list] (reverse (con element (reverse list)))) ?
17:48frio(gross solution :))
17:48dnolenfrio: yes, reverse
17:48casionyou could use concat and (list) the asg
17:48casionbut that's a bit silly
17:49horofoxdnolen: i have (cons 3 [1 2])
17:49horofoxdnolen: but it turns [3 1 2]
17:49dnolen,(conj [1 2] 3)
17:49casion,(concat '(1 2) '(3))
17:49clojurebot[1 2 3]
17:49horofoxi want [1 2 3]
17:49clojurebot(1 2 3)
17:49dnolenhorofox: ^
17:49lynaghkdnolen: I got partial map matching added to core.logic the other day---Clojure protocols are so nice! Do you have any pref on a name for the type (PartialMap, PMap, SubMap)? Also, do you want me to inline everything in logic.clj or would you prefer the patch being a whole separate namespace that just calls extend-type a lot?
17:49dnolen,(conj [1 2] 3)
17:49clojurebot[1 2 3]
17:50dnolenlynaghk: protocols rock, they are truly mind blowingly awesome - it's the kind of extensibility you want all of the time :)
17:50dnolenand perf to boot
17:51lynaghkdnolen: yeah, though I was pretty confused for a hot minute as to what was getting unified with what. doesn't help that "u" and "v" are only a few px apart =P
17:51dnolenlynaghk: I'm not surea about the name, the actual name of the type actually concerns me less than a sensible ctor fn
17:51lynaghkdnolen: yeah, I've been thinking the same thing. Within my lib I was thinking about using tagged literals, though that might be too magical for inclusion in core.logic.
17:51dnolenlynaghk: so a better name for the underlying type matter less than - partial-map or sub map or something like that
17:52horofoxYAY THANKS
17:52horofoxjust did my recursive fib implementation
17:52horofoxit looks horrible
17:52lynaghkdnolen: well that and the semantics of whether partial map should apply to any map-like values it may have.
17:53TimMchorofox: I hope it isn't as horrible as this factorial implementation: https://gist.github.com/3036120
17:53horofoxwtf
17:53frioHNNNNGH TimMc
17:53frioI like it!
17:54dnolenlynaghk: I think it should unify with anything that implements IPersistentMap
17:54horofoxhttps://gist.github.com/3861673
17:54horofoxhahahaha
17:54lynaghkdnolen: yeah. But should the unification of the children be partial maps or complete maps? I.e., should the constructor walk the provided map and turn all map-like things into partial maps, or just the toplevel?
17:55dnolenlynaghk: just top level.
17:56lynaghkdnolen: okay. You want everything in the logic.clj or would a new file+namespace be okay?
17:56dnolenlynaghk: lynaghk new namespace is ok, actually preferred since there's going to be some churn soon.
17:57dnolenlynaghk: but I'd like the partial map ctor fn to be in the core namespace of course.
17:57lynaghkdnolen: okay, sounds good to me. I'll get you a patch by the end of the week.
17:57dnolenlynaghk: awesome!
17:57TimMchorofox: How about (+ actual-n next-n) instead of (reduce + [actual-n next-n])?
18:01horofoxTimMc: good
18:01horofoxTimMc: I'm getting the hang of things... hehe, thanks!
18:04TimMchorofox: Some suggestions: https://gist.github.com/3861689
18:04horofoxi will start doing a camping here in #clojure
18:04horofoxTimMc: cool thanks
18:04horofoxTimMc: I will do a better implementation now
18:14TimMchorofox: Also, you seem to be reversing actual-n and next-n in the recursive call, which introduces a bug that appears if you start the list at 2,3 instead of 0,1.
18:15horofoxTimMc: oh, it should start in 0 1 always
18:16horofoxTimMc: I'm going to try by passing only 2 parameters: the list and the amount of numbers to be generated
18:16TimMcHmm, might be wrong about the exact nature of the bug, but you should be able to start from any point along the Fibonacci sequence.
18:19hyPiRionHmm, is there any specific reason merge returns nil instead of {} when given zero arguments?
18:19gtrakwhat do you guys use to test agents?
18:20hyPiRionIt sounds kind of counterintuitive.
18:21gtrakhyPiRion: maybe if you're doing (apply merge ..) it makes sense
18:21gtraknil's always used for seqs instead of an empty-seq too
18:22hyPiRiongtrak: hmm, how come?
18:22gtrak,[(merge nil) (merge nil nil)]
18:22clojurebot[nil nil]
18:22gtrak,[(merge {} nil) (merge nil {})]
18:22clojurebot[{} {}]
18:22hyPiRionah.
18:22gtrakthere's a semantic distinction there
18:23hyPiRion,(doc merge)
18:23clojurebot"([& maps]); Returns a map that consists of the rest of the maps conj-ed onto the first. If a key occurs in more than one map, the mapping from the latter (left-to-right) will be the mapping in the result."
18:24hyPiRionI was more among the lines of why ##(merge) returns nil though.
18:24lazybot⇒ nil
18:24hyPiRions/I/It
18:24gtrakwhat else would it return?
18:24hyPiRion{}
18:24gtrakhow about ##(apply merge [])
18:24lazybot⇒ nil
18:25dnolenhyPiRion: are you running into a case where it matters?
18:25hyPiRiondnolen: If you want to use the new reducers library and use merge as a combine function, you have to modify it because of the zero-argument result.
18:26gtrakwhy?
18:26clojurebotwhy is the ram gone is <reply>I blame UTF-16. http://www.tumblr.com/tagged/but-why-is-the-ram-gone
18:27hiredman,(doc fnil)
18:27clojurebot"([f x] [f x y] [f x y z]); Takes a function f, and returns a function that calls f, replacing a nil first argument to f with the supplied value x. Higher arity versions can replace arguments in the second and third positions (y, z). Note that the function f can take any number of arguments, not just the one(s) being nil-patched."
18:30hyPiRionWell, my real question is whether (merge) returns its identity element.
18:31amalloyhyPiRion: sure it does. (= (merge nil x) (merge x nil) x) for all x
18:32hyPiRionYeah, nevermind. ##(assoc nil 1 2) does return a map.
18:32lazybot⇒ {1 2}
18:32wingywished datomic was schemaless
18:32wingyi cant know all of the attributes in advance
18:34hyPiRionI didn't knew (assoc nil x y) => {x y}. Is that something one should know?
18:35TimMcPick a type, any type!
18:38augustlin a leiningen plugin, how do I load the project itself so that I can resolve it's dependencies etc?
18:40technomancyaugustl: try leiningen.core.eval/eval-in-project
18:40TimMcaugustl: Lein 1.x or 2.x? And do you mean the project.clj data?
18:41augustlTimMc: lein 2
18:42augustlTimMc: and I mean loading the actual library so I can access it
18:42augustltechnomancy: hmm, I just did, and (resolve 'some-dep) returns nil
18:42TimMcaugustl: Remember to require.
18:42augustlah
18:42horofoxhey TimMc
18:43horofoxi did a beautiful implementation
18:43horofoxWTF
18:43TimMcShare!
18:43augustlTimMc: hmm, require fails too
18:44augustlhere's the full plugin https://www.refheap.com/paste/5639, and oiiku-closure-builder-client is a dependency of the project where the plugin is added
18:45devthso RH talks about the importance of values as facts but I just realized I've never seen anything on querying an atom/ref for its value at a given time. is that possible?
18:45horofoxTimMc: https://gist.github.com/3861912
18:46augustlam I doing it the right way?
18:46TimMcaugustl: I don't see anything terribly wrong, so here's some code I wrote that does work: https://github.com/timmc/lein-otf/blob/master/src/lein_otf/loader.clj#L33
18:46rlbdevth: @some-atom
18:46antares_devth: that's what datomic can do, not Clojure. Clojure ref types only have "current" value (which you mutate by referencing a different immutable value)
18:47TimMcaugustl: Wait, that's a single-segment namespace, which could be a problem. And you're trying to resolve the ns itself, and not a member.
18:47rlbdevth: ohh -- you meant varying time...
18:47hiredmandevth: when you get its value, you are getting its at a point in time (now) and because it is a value if you want to hang on to it for later comparison you can
18:47augustlTimMc: hmm, is that a problem? Many of my libs use lib-name instead of lib-name.core
18:47devthrlb: yeah
18:47augustlTimMc: works when running the code normally at lesat :)
18:48devthi thought clojure's persistent data structures would allow you to get past values
18:49hiredmandevth: references provide identities over a series of values
18:49augustldevth: you need to do state manually, it's not a data structure revision tracking system :)
18:49horofoxis there any way to pass a function by parameter(optional) in a function
18:49mikerose357anyone ever used clojure for android applications?
18:49hiredmanif you want to compare the value of an identity now to the value of the identity 5 minutes ago, you have to have the value from 5 minutes ago
18:50devthaugustl: that's reasonable but then my atom is just a "place" for place-oriented-programming
18:50horofox?
18:50devthhiredman: i see
18:50augustltechnomancy: can you see something glaringly wrong with https://www.refheap.com/paste/5639? Getting "Could not locate oiiku_closure_builder_client__init.class or oiiku_closure_builder_client.clj on classpath:"
18:50augustldevth: not sure what you mean
18:51technomancyaugustl: eval-in-project is a function, not a macro
18:51technomancyyou need to quote the code you want evaluated inside the project. have you read the plugin guide?
18:51TimMchorofox: You can use multi-arity functions.
18:51hiredmandevth: have you seen http://www.infoq.com/presentations/Are-We-There-Yet-Rich-Hickey ?
18:51devthin RH's talk of Value of Values he says something like "if you pass me the primary key for a record in a database, what have you conveyed? NOTHING, because the record that ID points to could be completely mutated between the time you sent it and when i read it"
18:51devthso how is sending an Atom any better than sending a primary key?
18:52augustltechnomancy: I have, but thanks :)
18:52devthhiredman: i haven't seen that, no
18:52augustldevth: indeed, an atom is very much now
18:52devthmaybe the point is: don't send atoms, send the value at some point in time.
18:52horofoxTimMc: will do some research about it, thanks!
18:52devthsend the Fact instead of the Container
18:53augustldevth: you very rarely pass atoms around, I think, it's typically a singleton somewhere (def ...)
18:53technomancyaugustl: eval-in-project is more like eval. you have to build up a self-contained form to send to the project.
18:53TimMchorofox: Looking better. What happens if you ask for only n = 1?
18:54horofoxTimMc: I get an error :|
18:54TimMcaugustl: Or they are kept in a local scope.
18:55horofoxTimMc: I can do a if condition and deal with this 1 or 0 behavior
18:55horofoxTimMc: inside fib function
18:55TimMcYep.
18:55horofoxTimMc: I'm actually trying to solve proj euler problem where it's different
18:56augustltechnomancy: makes sense, thanks
18:56horofoxTimMc: i need the sum of all even numbers of the fib sequence where the last fib number is 4 million
18:56horofoxTimMc: but got hooked into how I can implement fib
18:59horofox(take-last 1 [0 1])
18:59horofoxyields (1)
18:59horofoxhow do i take this item out of ()?
18:59horofoxso it becomes 1
18:59horofoxinstead of (1)?
19:00TimMcYou'd call last instead of take-last.
19:00horofoxTimMc: oh yea... i feel so dumb hehe
19:01TimMcIf you didn't have that, you could call first on the '(1).
19:02TimMcIf I were solving that Euler problem, I would probably write a Fibonacci lazy sequence and process it with take-while, filter, and reduce.
19:03augustlthis updated lein plugin https://www.refheap.com/paste/5642 causes "Exception in thread "main" java.lang.ClassNotFoundException: leiningen.oiiku-closure-builder" O_o
19:03augustlany ideas..?
19:03TimMcSorry, that was kind of spoiler-y. :-/
19:05TimMcaugustl: Probably has something to do with do-build not being available inside the project.
19:05technomancyTimMc is right; you need to build up a self-contained form that will evaluate inside the project
19:05augustlah
19:06horofoxTimMc: thanks man! I did the problem! I wouldn't do it if it weren't for you
19:07horofoxTimMc: final solution: https://gist.github.com/3862014
19:08TimMchorofox: OK, *now* try making a version that produces and consumes a lazy-seq of Fibonacci numbers.
19:09kirindave_Ugh. Clojure, not a leading source of pretty fibbonaci impls.
19:09kirindave_Not without lazy seq, at least.
19:10kirindave_Guess my next blog post has gotta be, "The Most Epically Beautiful Fibbonacci"
19:12amalloykirindave_: and you'll just steal the one from rosettacode, right?
19:15augustlso should I update the project for eval-in-project and add the leiningen plugin itself as a dependency in order to get it on the classpath?
19:15TimMchorofox: Here's a version that does what I describe, which you may wish to inspect: https://gist.github.com/3862052
19:16augustladding it as a dependency sounds like a bad idea.. Just adding it to the classpath somehow would be nice
19:16technomancyaugustl: not for a 3-line function; just send it as a form
19:16kirindave_amalloy: Haha, I can do it from memory
19:16augustltechnomancy: it's more than 3 lines though :)
19:17kirindave_amalloy: It's like fibs = 0 : 1 : zipWith (+) fibs (tail fibs) -- DONE AND TAKE THAT
19:17horofoxTimMc: very cool this take-while function
19:18horofoxi have no idea what lazyseq means lol
19:18kirindave_amalloy: But I don't think any rosetta codes were harmed in the making of my fizzbuzz one. Umm… maybe the C one started there?
19:18TimMchorofox: It's a good one to know.
19:18kirindave_amalloy: I think nearly every C programmer will write it the wrong way in the same way.
19:18horofoxin my country people don't even teach lisp :-(
19:18augustlanyone have an example of a leiningen plugin that adds its own utility functions to the project and uses eval-in-project to call them?
19:19AtKaaZhi, how can I do something like this? ##(for [x (range 10) :let [y 1/x] ] y)
19:19AtKaaZ,(for [x (range 10) :let [y 1/x] ] y)
19:19clojurebot#<ExecutionException java.util.concurrent.ExecutionException: java.lang.NumberFormatException: Invalid number: 1/x>
19:20thorbjornDXAtKaaZ: :let [y (/ 1 x)]
19:20TimMcAtKaaZ: 1/x is infix notation, which is not how Lisps work.
19:20AtKaaZoh right, so obvious, thank you
19:20AtKaaZ,(for [x (range 10) :let [y (/ 1 x)] ] y)
19:21clojurebot#<ExecutionException java.util.concurrent.ExecutionException: java.lang.ArithmeticException: Divide by zero>
19:21amalloykirindave_: (map first (iterate (fn [[a b]] [b (+ a b)]) [0 1])) in clojure, though. the haskell/scala version translates very poorly to clojure
19:21thorbjornDXAtKaaZ: it's somewhat weird in this case because clojure supports ratio literals
19:21augustlonly thing I can think of is grepping out the actual plugin entry in :plugins to get the correct version, and add that as a dependency to the project I eval-in-project
19:22AtKaaZthorbjornDX, do you mean 1/2 works but not when 2 is a variable ?
19:22kirindave_amalloy: Did you enjoy my egregious fizzbuzz post?
19:22AtKaaZ,(for [x (range 1 10) :let [y (/ 1 x)] ] y)
19:22kirindave_amalloy: I'm still suffering fallout from it.
19:22clojurebot(1 1/2 1/3 1/4 1/5 ...)
19:22amalloyi don't think i've read it
19:23AtKaaZthorbjornDX, would it work inside a macro maybe?
19:23augustlseems lein-midje does this, except it hardcodes the dependency
19:23horofoxTimMc: isn't this fib implementation slow? Like... (take 5 (fib 1 1))
19:23horofoxcalls fib 5 times?
19:23augustls/dependency/dependency version/
19:24kirindave_amalloy: Ha.
19:24TimMchorofox: take doesn't call the second argument, it accepts the result of evaluating it.
19:25thorbjornDXAtKaaZ: yes, but I don't think that's a smart idea.
19:25TimMcAtKaaZ: No, because the reader is what's complaining.
19:25kirindave_horofox: That is the sort of stuff we trust the JIT to inline. :)
19:25AtKaaZyeah I see it's not working
19:25horofoxkirindave_: oh
19:26AtKaaZbut still, that (/ 1 x) is quite enough
19:26TimMcAtKaaZ: Just be aware that (/ 1 x) gives you a Clojure Ratio, which can be slow to do math with.
19:26kirindave_horofox: Seriously though. No one has any problem writing in Java: for(X x : xs) { x.thingABob() }
19:27kirindave_horofox: It's the price of admission. :)
19:27horofoxkirindave_: i see
19:27AtKaaZtimmc, which one do you think would be slower (I know it's unrelated to what you said): 1/2 or (/ 1 2) where 1 and 2 could be any number
19:28TimMc"Slower"? To do what with?
19:28AtKaaZlike if I wanted to generate numbers like I did in the above for
19:29AtKaaZI'm only trying to realize if 1/x (if it worked) would've been faster than (/ 1 x)
19:29AtKaaZhmm, doesn't seem so
19:30AtKaaZ,(prn 1/1 (/ 1 1))
19:30clojurebot1 1
19:31AtKaaZtimmc, I'm merely experimenting, in my attempts to learn clojure, but it's good to know that math-ing with ratios is slower
19:36TimMcAtKaaZ: Use (/ 1.0 x).
19:37TimMcYou can't programmatically generate forms like 1/2 without using the Clojure reader, so don't.
19:37AtKaaZbut I wanted to keep them rational?
19:37TimMc(and you would still end up with a Ratio)
19:37TimMcOh, then use (/ 1 x).
19:38AtKaaZbut it's still good to know how to make them Double
19:38AtKaaZthanks;)
19:42AtKaaZ,(-> (for [x (range 1 11) :let [y (/ 1.0 x)] ] y) first class)
19:42clojurebotjava.lang.Double
19:42AtKaaZi like this ->
19:43AtKaaZor this:
19:43AtKaaZ,(->> (for [x (range 1 11) :let [y (/ 1 x)] ] y) (map class) )
19:43clojurebot(java.lang.Long clojure.lang.Ratio clojure.lang.Ratio clojure.lang.Ratio clojure.lang.Ratio ...)
19:43AtKaaZit's freaking amazing
19:56RoxxiIf you have a transient set, how can you treat it as a seq?
19:56technomancyIIRC transients are only for putting things in
19:57augustlRoxxi: you have to make it persistent
19:57RoxxiRight, but I'm looping over it, haha.
19:57augustlif by seq you mean persistent seq ;)
19:57Roxxitechnomancy: If transients are only for putting things in, why is there disj! :)
19:59amalloyRoxxi: you can't treat a transient as a seq, because it can change at any time, invalidating the seq wrapped around it
20:00amalloyie, seqs require something persistent to work with
20:01technomancyerhm... not that's not quite right
20:01technomancyyou can seq an array
20:01Roxxiamalloy: Hmm, so it's ok to call persistent! on things, but continue using the operand to persistant as a transient later?
20:02amalloytechnomancy: yes, and you get out a broken seq
20:02technomancythat is to say you can't treat a transient as a seq, but you could in theory wrap a seq around it
20:02technomancyamalloy: fsvo of broken. the seq is still immutable, it just doesn't reflect the contents of what it wraps forever.
20:02technomancyby the same logic line-seq is broken.
20:02AtKaaZnow that's clearler thanks
20:03amalloy&(let [a (into-array [1 2 3]), s (seq a)] (aset a 1 5) s) ;; technomancy, is this really what you mean?
20:03lazybot⇒ (1 5 3)
20:04technomancyamalloy: sure?
20:04amalloythat seq is only immutable in the sense that once you realize an element it is fixed; but realizing it depends on mutable state
20:04technomancyof course.
20:05technomancythat's what seqs are; a snapshot of a traversal of a thing.
20:05amalloybut it's not a snapshot of a traversal: the seq can represent a state that the array was never in
20:06technomancythat's why I said a snapshot of a traversal, not a snapshot of a state
20:07technomancyif you have code that needs it to be otherwise, it's not the seq that's broken, it's the other code.
20:07AtKaaZoh wait so you can still get the seq modified if you modify the original, ah that's not what I understood the first time then
20:10AtKaaZ,(class (seq (into-array [1 2 3])))
20:10clojurebotclojure.lang.ArraySeq
20:14AtKaaZhow can I find all functions dealing with arrays? such as aset
20:15aperiodicAtKaaZ: http://clojure.org/cheatsheet
20:15aperiodicarray stuff is in java interop at the bottom-right
20:15AtKaaZyeah thanks a lot! great stuff
21:04thmzltso is it a bad practice to define tests within source file using (with-test ...)?
21:31xeqithmzlt: I haven't seen it done anywhere
21:31thmzltxeqi: that's why I asked
21:31xeqior setting *load-tests* to false, so I imagine doing that would run the tests for anyone using it (if its a library)
21:37ynnivis there no way to inherit defrecord fields?
21:37ynnivand if not, can I at least specify them with a variable instead of a form?
21:39tomojno
21:39tomojyou could use a macro
22:01ynnivi guess that works
22:07amalloyit's a bit cruel of rich to tell us inheritance is so evil he can't include it in the language, but keep using it all over clojure.lang: it's occasionally a useful tool for avoiding duplication that's really hard to fake
22:09ynnivit would be nice to have inheritance in defrecord
22:09AtKaaZwhat do you mean by "but keep using it all over clojure.lang" in the java code ?
22:09ynnivI'd really be okay if I didn't have to write my own macro to fake it
22:10brehautyes the javacode
22:10ynnivit seems odd that you can't pass a list of fields to defrecord
22:10AtKaaZyou can't?
22:11ynnivit appears that the fields are taken as a form
22:12ynnivi wrote this to expand the variable before defrecord is expanded: https://gist.github.com/3862734
22:14AtKaaZhmm there is no [org.clojure/clojure "1.5.0"] in project.clj with leiningen... only 1.4.0
22:15tomojynniv: why do you want inheritance?
22:15ynnivi have two record types that have a long list of fields that aren't exactly the same
22:15ynnivand I'm trying to de-duplicate
22:15AtKaaZI'd probably want the same thing
22:16tomojbut why do you have two record types with a long list of almost identical fields?
22:16amalloyynniv: you probably just want plain old hashmaps
22:16tomojer, you know what I mean
22:16ynnivto store data?
22:16ynnivi mean, philosophically, there are are things that need to be stored which are very similar but not the same
22:17ynnivdo you think I should use pairs of records, one which is the shared fields, and one which is the remaining fields for that record?
22:18ynnivi could use maps, but I would like better type checking
22:18ynnivas in, i didn't type the wrong field name
22:18ynnivrecords give me compile time sanity checking
22:18brehautrecords dont give you type checking
22:19ynnivthey create multimethods that won't exist if I type them wrong
22:19ynnivwhich is a step up from keywords
22:19thmzltbrehaut: hey give you type-based polymorphism
22:19thmzlt*they
22:19ynnivthey also do that
22:19brehautthmzlt: thats wildly different than type checking
22:20tomojalso, (assoc a-record :a-typo foo) will still succeed
22:20thmzltbrehaut: agreed, but I think that's what ynniv meant
22:22ynnivdoes defrecord not provide field accessors?
22:22ynnivi guess i'm carrying some common lisp baggage
22:23brehautynniv: you just use keywords
22:23brehautthough there are field accessor methods thats not idiomatic
22:23ynnivhrm, not as helpful
22:23brehaut(and potentially slower)
22:23thmzltynniv: but defrecord doesn't work as function
22:23ynnivthmzlt: not sure what you mean
22:23thmzltynniv: (a-record :field) doesn't work
22:24brehautthmzlt: (:field a-record)
22:24ynnivbut (:field a-record) still does, correct?
22:24thmzltynniv: correct
22:25ynnivi suppose that I need to create vars for my field names to prevent typos?
22:25brehautthat would not be especially idiomatic code
22:25brehautbut i guess it would work
22:26ynnivwell, there's nothing to prevent someone else from calling my code with a keyword
22:26ynnivbut this would limit some of the madness
22:26brehautyup
22:26ynnivor I could also generate accessors
22:26hiredmanynniv: you should also wear body armor all the time
22:26brehautideally though you create functions for manipulating your records, so that the implementation doesnt bleed out
22:27hiredmanynniv: you never know
22:27ynnivhiredman: sometimes a good idea!
22:27brehautand look to a future where typed clojure is reasonable to deploy
22:30ynnivbrehaut: i thought that defrecord generated field accessor/modifiers (like CLOS), which is how I ended up here
22:31brehautynniv: it does do that, but you generally dont want to use it
22:32brehautkeywords use an inline cache at the callsite to optimize acccess, and the method form may go via reflection
22:32ynnivah, it makes accessors in Java?
22:33brehautyes, of course
22:41AtKaaZis it PLOP when a ref changes? or is it too silly to ask? PLace Oriented Programming
22:46amalloyIMO it's not a very useful question to ask, but: a ref seems like a place. however, having a place doesn't mean you're doing place-oriented programming
22:47gfredericksyou'd have to orient your code around the place?
22:52AtKaaZwatching this: https://www.youtube.com/watch?v=-6BsiVyC1kM&amp;t=4m10s "anytime new information replaces old information you're doing PLOP"
22:52AtKaaZgfredericks, not really understanding what you ask
22:53gfredericksI was just failing to be clever
22:53AtKaaZlol I think I read that litterally once and I smiled:P
22:54AtKaaZbut there may be some truth in it
22:54tomojwhat's the proposed alternative to PLOP again? VOP?
22:55AtKaaZmultiversion control:)
22:55AtKaaZimutability ?
22:56AtKaaZI have to be honest with you, I pretty much don't know what I'm talking about most of the time :) even though I might've gotten some things right
22:57brehautAtKaaZ: sounds like 99% of every IRC channel ever
22:58AtKaaZamalloy seems right, maybe unless that ref becomes data like I dno, a tree made of refs, refs to refs
22:58gfredericksAtKaaZ: so I think at least you can say that reference types, when not over-used, are a lot safer and simpler than traditional mutability
23:03AtKaaZcan anyone recommend a graph database in clojure ? maybe not a port like neo4j, something simple enough that would be good to hold graph nodes with directed edges between them, and no other data like properties attached to either nodes or edges. I'm currently going for datomic.
23:03Sgeoplace oriented programming? Anything to do with Common Lisp places, setf etc?
23:03AtKaaZSgeo, like updating the same place in a database to replace the old info with new
23:04AtKaaZso PLOP would be a relational database, and VOP(?) would be datomic
23:05AtKaaZ(not restricted to databases though, like PLOP is OO and VOP is clojure)
23:05ynnivit's only PLOP if you overwrite the old value
23:06ynnivyou can organize your db to only add new versions
23:06AtKaaZso it would act like a mvcc database of sorts?
23:08ynnivnot sure what that means
23:08AtKaaZmy problem would forever be how do I go back in time and see a consistent view of the database at any level, not sure yet if I can do it with datomic
23:09AtKaaZynniv, I got what you meant, not sure if it would indeed act like a mvcc multiversioned database as I said
23:09ynnivI'm not familiar with datomic yet, but I often think how nice it would be to use git as a database
23:09scottjAtKaaZ: not sure what you mean by "at any level", but with datomic you can to db.asOf(aDate) I believe
23:10AtKaaZscottj, yes you can that, but the "at any level" would imply some sort of nested transactions, so that the top transaction would include multiple low level ones... I guess it would work if the low ones are only commited when the top one commits
23:14AtKaaZynniv, yeah I thought about that too, I definitely need some kind of git-like database esp. the branching then merging them
23:20lancepantzAtKaaZ: you still there?
23:20AtKaaZyes
23:20AtKaaZi was thinking of a question, in clojure how do you do two threads incrementing the same counter ?
23:20lancepantzAtKaaZ: https://github.com/flatland/jiraph
23:20AtKaaZwith dosync?
23:21AtKaaZlancepantz thanks I'll check
23:21lancepantzwe've been working on it for about 3 years and have it in production
23:21lancepantzit's very actively maintained
23:21lancepantzand faster than neo4j
23:21AtKaaZsounds good!
23:26gfredericksAtKaaZ: two threads incrementing the same counter can be just an atom
23:26TimMcAtKaaZ: Just one counter? Try an atom.
23:26TimMcbah
23:27TimMcYou even won on my screen. I can't claim IRC relativity.
23:27gfredericksoh is it relative? that's good to know for future gloating
23:27thmzltso I want to dispatch a method based on the first argument type (string vs. map), hints?
23:27gfredericksmultimethods or protocols
23:28TimMcgfredericks: Larger IRC servers are distributed as a bunch of nodes connected by a spanning tree.
23:28AtKaaZnice, atoms, STM of clojure good stuff
23:28TimMchence netsplits
23:28gfredericksTimMc: yeah; it makes sense
23:28gfredericksthere could be an eventual consistent ordering
23:29gfredericksbut that would cause weird visual effects
23:29TimMcThere could be, but there isn't.
23:29TimMcInstead, each client just accepts the ordering of messages that it gets.
23:29gfrederickswhy aren't there git-based chat protocols yet?
23:29TimMc"Dude, I can't hear you -- accept my pull request first."
23:30AtKaaZdatomic might be like git but without the ability to do branches, I might be wrong, gotta learn datomic
23:30gfredericksAtKaaZ: you can do "local branches"
23:30ynnivthmzlt: (defmulti f-name type)?
23:30gfredericksbut only one "master" I think
23:31ynnivthmzlt: (defmethod asdf (type {}) [x] 'map)
23:31gfredericksAtKaaZ: where by "local" I mean like temporary in-memory sort of thing
23:31AtKaaZgfredericks, yeah I was about to ask that, something like assume that the db has this data and the execute this query ? I think I saw that somewhere
23:32gfredericksynniv: might want IPersistentMap instead of (type {})
23:32AtKaaZthis new/extra data
23:32gfredericksAtKaaZ: yep
23:32ynnivdepends
23:32thmzltI'm trying to figure out the multimethod syntax
23:32ynnivmaybe there's a string that implements IPersistentMap :-)
23:32gfredericks,(map type [{} (zipmap (range 1000) (range 1000))])
23:33clojurebot(clojure.lang.PersistentArrayMap clojure.lang.PersistentHashMap)
23:33gfredericksynniv: ^ surprises there
23:33ynnivah, good call
23:33ynniv(type {}) isn't stable
23:34ynnivthat's why I wear my noob hat
23:34ynnivhmm, it seems that I have forgotten to wear my noob hat. well, beware!
23:36scottj,(meta ynniv)
23:36clojurebot#<CompilerException java.lang.RuntimeException: Unable to resolve symbol: ynniv in this context, compiling:(NO_SOURCE_PATH:0)>
23:37AtKaaZif I ever want to use the value of the atom before modifying it, do I have to dosync instead ?
23:37AtKaaZassuming 2 threads or so
23:38gfredericksAtKaaZ: no
23:38gfredericksif you want the new value based on the old one, then do it all inside your swap function
23:39AtKaaZbut if I want to use its value to compute something else, twice
23:39AtKaaZand then increment it let's say
23:40gfredericksfor tricksy things like that you can make a more complex atom, e.g. a map with :current-value and :last-value
23:40AtKaaZsay I do two calls where each takes 3 seconds, and each gets passed the value or the atom
23:40gfredericksmake sure the swaps do the right thing, and then you can read the old value after the swap
23:41AtKaaZI'm kind concerned if the other thread can increment the atom between those 2 calls which each takes 3 seconds :)
23:41gfrederickswell only one of them will succeed and the other will retry
23:41AtKaaZbut if I use a dosync block around those 2 calls it will block right?
23:41gfrederickswhat is taking 3 seconds?
23:42AtKaaZlike if in one thread I do two calls and pass that atom, and when these are done then I increment the atom
23:42gfredericksI'm not sure what you mean by "calls" here
23:42gfrederickswhat are you storing in an atom?
23:42AtKaaZbut while thread1 is doing first call, which takes 3 second to compute, can another thread modify the atom so that it's different value for the thread1's second call
23:42AtKaaZit's kinda hypothetical, but it's a counter
23:43AtKaaZ2 threads supposedly increment it by 1
23:43AtKaaZbut 1 thread is slow
23:44TimMcAtKaaZ: dosync doesn't know anything about atoms, and vice versa
23:44TimMcit only coordinates refs, and delays sends to agents
23:44AtKaaZtimmc, I ref then?
23:44gfredericksAtKaaZ: generally you assume that reference types are being updated behind your back
23:44AtKaaZtimmc, I figure maybe in this case I'd have to use dosync, that's mainly what I'm asking
23:44gfredericksif there's some reason you don't want that to happen then I feel like you might be using them wrong
23:45AtKaaZI do assume that that ref to counter would be updated behind my back between those two calls
23:45gfredericksso what's the problem?
23:45AtKaaZbut then if those 2 calls are within a dosync, they would always see the same counter value?
23:45gfredericksyes but you're holding up other threads
23:46AtKaaZis there any way to maybe do that without the holding?
23:46gfrederickswithout getting more concrete I really don't understand the motivation
23:46AtKaaZhmm... get the value before the calls?
23:46AtKaaZyeah you're right
23:47gfredericksyou can read the atom initially and pass that value in with the atom?
23:47AtKaaZI guess in a way I really need to hold the other threads from modifying the counter, cause otherwise it would be like starting off a new branch in a git which is based on now obsolete commit since other thread already updated the counter
23:48gfrederickswhy do the two calls need to have the same basis?
23:48AtKaaZI mean, if I want whatever those long calls are doing to be in sync with the counter
23:48AtKaaZnot sure, but I feel that I may want that hmm
23:49AtKaaZlike maybe they are doing some datomic transactions using that counter
23:49wingysince datomic only holds one level keys i thought that perhaps i wanna use keywords with namespace in my day to day maps in clj land instead of nested maps .. eg. {:name "foo" :address/street "maple street" :address/zip "12345"} instead of {:name "foo" :address {:street "maple street" :zip "12345"}} .. the latter one is compatible with datomic and also it feels like it is easier with one level rather than nested levels .. which one do you
23:49wingyprefer?
23:49AtKaaZone level keys?
23:50gfredericksAtKaaZ: I give up
23:50wingyAtKaaZ: see the example
23:50AtKaaZgfredericks, thank you though
23:51wingyany input?
23:52AtKaaZwingy, I'd prefer the latter, because it seems extensible, tree-like; but that's just me
23:52wingyAtKaaZ: the former looks more treelike :)
23:53AtKaaZmaybe I'm missing something, but the latter :address seems to have an inner {}
23:53wingyoh yeah
23:53wingyi thought the latter was the former :)
23:53AtKaaZso, in your OP the former is compatible ?
23:53AtKaaZwith datomic
23:54wingyOP?
23:54clojurebotoptimizing is http://clojure.org/java_interop#optimization
23:54AtKaaZoriginal post=)
23:54wingyyeah the former is compatible
23:54AtKaaZyeah it makes sense
23:54wingysince you have to declare the keys in advance in the schema
23:54AtKaaZso you'd have to say that :address is a map ?
23:54wingyin a post they said they would make the latter work as well .. but it wont be indexable/searchable though
23:55AtKaaZyeah I was afraid of that
23:55wingythere is no map type atm
23:55wingybut then why have namespaced keys if we dont use them :)
23:55wingyi kinda like flat struture in a way :)
23:56AtKaaZwish it was more tree-like
23:56wingyyeah hope they will support it fully
23:56AtKaaZmaybe you can use db/ref entities and have :address be a db/ref and point to an entity which contains those :street :phone attributes
23:56AtKaaZthis way, you can have tree-like =)
23:57AtKaaZdidn't fully consider the implications of this though
23:57wingygreat idea
23:57wingywhy didn't i think about this :)
23:57AtKaaZyou got lost into details:) I always do that
23:58wingyyeah, nested vs namespaced keys :)