2012-10-09
| 00:02 | technomancy | TimMc: unfortunately if you need something to work in the presence of profile operations you have to express it in terms of profiles |
| 00:02 | akhudek | callen: "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:02 | akhudek | https://github.com/weavejester/lein-ring |
| 00:03 | technomancy | TimMc: so if you can use leiningen.core.project/add-profiles then it'll get preserved properly |
| 00:03 | callen | akhudek: hrm. |
| 00:03 | technomancy | the 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:03 | callen | now I just have to figure out how to start the jetty server. |
| 00:03 | akhudek | callen: lein ring server |
| 00:04 | akhudek | it starts a jetty server |
| 00:04 | technomancy | I really don't get the point of keeping your dev jetty in a different process from your repl |
| 00:04 | callen | 'ring' is not a task. See 'lein help'. |
| 00:04 | callen | akhudek: ^^ |
| 00:04 | frio | callen: get lein2 :) |
| 00:04 | callen | frio: I am in lein2, that's why it broke |
| 00:04 | frio | oh? that works for me... |
| 00:04 | technomancy | callen: just start jetty from your repl |
| 00:05 | technomancy | it's easy |
| 00:05 | callen | technomancy: that's what I've resorted to. |
| 00:05 | akhudek | technomancy: I like starting from the repl myself, though I haven't been abel to convince many others of this |
| 00:05 | technomancy | callen: it's so much simpler |
| 00:06 | technomancy | keeping 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:06 | callen | oh you start it from your nrepl-jack-in |
| 00:06 | technomancy | yup |
| 00:06 | technomancy | (start-jetty #'app {:port 8080 :join? false}) or whatever |
| 00:07 | callen | technomancy: do you use 'raw' ring, Noir, or something else? |
| 00:08 | callen | well that was a fail, I edited code and it didn't reload. |
| 00:08 | callen | so going back to my question, how do I make it auto-reload? |
| 00:08 | akhudek | callen: if you are doing the repl route, you can reload most functions in the standard way |
| 00:08 | callen | C-x C-e on my handler failed. |
| 00:09 | akhudek | but routes and enlive templates area bit different |
| 00:09 | callen | clojure.lang.Compiler$CompilerException: java.lang.IllegalStateException: index already refers to: #'reminders.core/index in namespace |
| 00:09 | callen | ...not helpful. |
| 00:09 | callen | so how do I auto-reload my code...routed handlers included? |
| 00:10 | akhudek | callen: could try wrap-reload, though I have not managed to get it to reload routes for some reason |
| 00:10 | akhudek | oddly enough the lein-ring plugin does seem to work |
| 00:10 | akhudek | http://clojuredocs.org/ring/ring.middleware.reload/wrap-reload |
| 00:10 | akhudek | sorry, that's outdated |
| 00:10 | akhudek | hold on |
| 00:11 | callen | if it doesn't reload the routes, it's not incredibly useful to me. |
| 00:11 | akhudek | see the bottom here: https://github.com/ring-clojure/ring/wiki/Interactive-Development |
| 00:13 | akhudek | then be sure to reload you entire namespace |
| 00:13 | TimMc | technomancy: 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:13 | akhudek | as to your question about noir vs ring, I prefer ring + compojure to noir myself. |
| 00:14 | tomoj | are fn* and loop* the only recur points? |
| 00:15 | callen | okay, I got it to do what I want now |
| 00:15 | callen | I got lein ring server to work. |
| 00:15 | callen | it seemed to auto-reload my code so that seems kosher now. |
| 00:15 | callen | akhudek: thank you. |
| 00:22 | zackzackzack | How do I make it so I can define what happens when I call nth on a datatype or record? |
| 00:25 | trevor` | How do people do JDBC CallableStatements in Clojure? |
| 00:26 | tomoj | this feels somewhat wrong https://gist.github.com/9f89e03eb42bef6ddeab ? |
| 00:31 | callen | well. lobos seems nice enough. |
| 00:31 | callen | is lobos what most people use for migrations? |
| 00:32 | zackzackzack | tomoj: Which walk is walk? |
| 00:32 | zackzackzack | w/walk I maen |
| 00:32 | zackzackzack | *mean |
| 00:33 | tomoj | w is clojure.walk |
| 00:33 | tomoj | well it's definitely wrong because I don't deref the Reduced |
| 00:33 | tomoj | but seems kinda weird to use Reduced |
| 00:39 | zackzackzack | Why not this? https://gist.github.com/1d4e89438b8c2bb4d210 |
| 00:39 | zackzackzack | Hmm |
| 00:39 | zackzackzack | It doesn't stop though |
| 00:39 | zackzackzack | Nevermind |
| 01:02 | callen | how do I get trailing slashes to work in ring? |
| 01:08 | tomoj | zackzackzack: I felt like there should be a simpler way to write it, too |
| 01:11 | tomoj | I don't have w/walk at the top because f should be able to stop on the root form too |
| 01:12 | xeqi | callen: the slashes should show up in the :uri |
| 01:12 | xeqi | if you want to act the same as the non slash, you could use a middleware to change it |
| 01:12 | xeqi | or redirect |
| 01:14 | xeqi | https://github.com/noir-clojure/lib-noir/blob/master/src/noir/util/middleware.clj#L28 is one example |
| 01:14 | tomoj | shoot, I wish if were a macro for if* |
| 01:15 | tomoj | oh, no I don't |
| 01:21 | tomoj | is it an acceptable use of with-redefs to redefine macroexpand-1 to cljs.analyzer/macroexpand-1? |
| 01:22 | zackzackzack | tomoj: maybe realize it as a list and then do a search through it with a take while or something? |
| 01:23 | tomoj | for the stoppable walk? |
| 01:23 | tomoj | "stop" there means "don't descend into the form f returned" |
| 01:25 | tomoj | e.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:40 | zackzackzack | Any particular reason why protocols don't support variadic (& rest) arguments? |
| 01:49 | SegFaultAX|work | When 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:52 | SegFaultAX|work | Somehow that feels more verbose than it needs to be. |
| 01:53 | Frozenlock | SegFaultAX|work: Isn't there 'while'? |
| 01:55 | Frozenlock | If it can help: http://clojuredocs.org/clojure_core/clojure.core/take-while |
| 02:01 | SegFaultAX|work | Frozenlock: That doesn't really address my question at all. |
| 02:05 | tomoj | &(loop [[h & t] [1 2 3]] (if t (recur t) h)) |
| 02:05 | lazybot | ⇒ 3 |
| 02:22 | wingy | how do i interact with XML responses? |
| 02:23 | wingy | some services only provide XML :/ |
| 02:42 | zoldar|away | wingy: define "interact" |
| 02:42 | wingy | zoldar|away: working with xml like i can do with json responses |
| 02:42 | wingy | reading elements, attributes .. setting values etc |
| 02:42 | wingy | save data to db |
| 02:43 | wingy | creating new attributes and elements as well |
| 02:43 | wingy | reminds me about DOM manipulation but I have never worked with XML responses |
| 02:44 | wingy | how does everyone handle XML resonses in clj/java land |
| 02:44 | zoldar | wingy: my bet would be on this: https://github.com/clojure/data.xml |
| 02:45 | wingy | cool |
| 02:46 | tomoj | "Wrong number of args (-1) passed to: core$map" |
| 02:46 | tomoj | interesting |
| 02:47 | tomoj | (defmacro foo [] `(~@(map))) |
| 02:47 | tomoj | (that one has -2 args) |
| 03:00 | wingy | zoldar: clj has basic ops built in http://clojuredocs.org/clojure_core/clojure.xml |
| 03:01 | wingy | i might just use that one |
| 03:03 | tomoj | there is also clojure.zip/xml-zip and clojure.data.zip.xml |
| 03:03 | wingy | i wonder why clojure has different projects for xml though |
| 03:04 | wingy | they have those you mentioned but also https://github.com/clojure/data.xml |
| 03:04 | wingy | its in the clojure github project |
| 03:04 | wingy | does anyone here know why? |
| 03:06 | tomoj | clojure.xml uses SAX, clojure.data.xml uses StAX |
| 03:24 | wingy | tomoj: i c |
| 04:05 | gtuckerkellogg | ,(doc repl) |
| 04:05 | clojurebot | I don't understand. |
| 04:05 | gtuckerkellogg | ,(doc doc) |
| 04:05 | clojurebot | "([name]); Prints documentation for a var or special form given its name" |
| 04:21 | bairui | has anyone here used both clojure and newlisp? have you written serious apps in both? any constructive observations / criticisms / comparisons? |
| 04:22 | bairui | (no, i'm not trying to start a war - i happen to like both) |
| 04:25 | mucker | bairui: what type of app ? newlisp is a scripting language. clojure from the start is a general language that lets take adv of jvm |
| 04:26 | bairui | mucker: 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:27 | bairui | mucker: 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:30 | michaelr525 | hello\ |
| 04:31 | bairui | i 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:35 | mucker | bairui: in my experience, no matter what the recommended way, there is some struggle ;) |
| 04:36 | bairui | :-( ain't it always so |
| 04:37 | clgv | Is it right that setting *unchecked-math* to true has no effect when I use primitives and type hints anyway? |
| 04:38 | bairui | i 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:38 | bairui | i infer from your previous answer that even if there is one... it's no silver bullet :) |
| 04:40 | tomoj | incidentally 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:40 | mucker | bairui: :) don't be afraid to port haskell ideas to clojure |
| 04:41 | bairui | lol; my haskell skills are akin to that of a child with large coloured blocks; and that is being disingenuous to the child. |
| 04:41 | tomoj | swing would be interesting though.. or maybe android someday |
| 04:42 | tomoj | I bet with some synchrony there reactive's behaviors are nicer than in cljs |
| 04:42 | clgv | bairui: seesaw is awesome if you want to build a Swing GUI - but I only used it for some smal GUIs yet |
| 04:42 | bairui | as i understand it, there already are several swing interfaces - seesaw being one, no? |
| 04:42 | bairui | clgv: 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:43 | bairui | clgv: are you implying there are alternatives to wanting a 'swing' gui? |
| 04:45 | mucker | bairui: you can use java classes in clojure, so that's one way ... donno alternatives to seesaw |
| 04:45 | clgv | bairui: swing is the easiest way since its built-in. there is SWT which is used by eclipse |
| 04:45 | bairui | mucker: actually, i was wondering about alternatives to swing - does anybody still write guis in awt directly?! |
| 04:45 | bairui | i hadn't heard of swt |
| 04:46 | clgv | now you have ;) |
| 04:46 | mucker | bairui: awt is a big NO |
| 04:46 | bairui | heh :) good |
| 04:46 | clgv | I think java world is either swing or swt |
| 04:49 | michaelr525 | re |
| 04:50 | bairui | ok, thanks, clgv. I'll make a note to look at swt, but i'll try seesaw first. |
| 04:52 | clgv | bairui: yeah try seesaw first. I don't know if there is any clojure lib that provides an interface for swt |
| 04:52 | bairui | cool |
| 05:21 | wingy | how can i convert a string with base64? |
| 05:27 | tomoj | https://github.com/clojure/data.codec |
| 05:27 | tomoj | (String. (encode (.getBytes "foo"))) for example |
| 05:31 | wingy | tomoj: ah |
| 05:31 | wingy | (ring.util.codec/base64-encode (.getBytes "adasd")) this worked great as well |
| 06:45 | augustl | when I build with "lein ring uberwar", everything in {:profile {:dev {:resource-paths [...]}}} gets added to the war |
| 06:45 | augustl | how do I build a "production war"? |
| 06:48 | augustl | it also contains my dev dependencies, so "lein ring uberwar" seems to assume I want to use the dev profile |
| 06:48 | tomoj | try `lein with-profile production ring uberwar` |
| 06:49 | augustl | tomoj: "'ring' is not a task. See 'lein help'." hehe |
| 06:51 | tomoj | hmm |
| 06:51 | clgv | is ring also a :dev dependency? ;) |
| 06:51 | tomoj | I found `lein with-profile production lein ring uberwar` somewhere |
| 06:52 | augustl | no, it's a plugin - :plugins [[lein-ring "0.7.1"]] |
| 06:52 | augustl | clgv: ^^ |
| 06:52 | clgv | outside of :dev? |
| 06:52 | augustl | yes |
| 06:52 | augustl | tomoj: same thing, "lein is not a task" |
| 06:52 | tomoj | that one makes sense |
| 06:53 | augustl | agreed :) |
| 06:53 | clgv | what does `lein with-profile production help` list you? |
| 06:54 | augustl | clgv: https://www.refheap.com/paste/5616 |
| 06:54 | clgv | lein-ring should be listed there, right? |
| 06:55 | augustl | no idea :) |
| 06:55 | augustl | it's not listed with just "lein help" |
| 06:55 | augustl | sec :P |
| 06:56 | tomoj | works for me |
| 06:56 | augustl | works for me too |
| 06:56 | augustl | goodie! |
| 06:57 | augustl | is 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:58 | clgv | I think that is an error in the plugin implementation - lein uberjar for example excludes the :dev profile |
| 06:58 | clgv | augustl: I think you can define an alias that automatically uses the production profile |
| 06:59 | augustl | clgv: I'll look that up, thanks |
| 07:06 | augustl | resource-paths in leiningen just adds those folders to the classpath, right? |
| 07:23 | clgv | augustl: no, it also includes thos folders in the jar |
| 07:41 | djpowell | anyone know how to dynamically construct a bunch of OR'd together clauses in Korma? |
| 07:42 | djpowell | i can easily take my clauses and reduce over the query applying k/where to it |
| 07:42 | djpowell | but i'm not sure how to do something similar with OR |
| 07:52 | clgv | djpowell: you could generate a list of your or-clauses using the symbol 'or and where* instead of where |
| 08:00 | djpowell | clgv: hmm, not quite figured out how to use where* |
| 08:20 | djpowell | ok, got it sorted. just about. |
| 08:22 | clgv | djpowell: with where*? |
| 08:38 | nkoza | where I can report a clojurescript documentation bug? The issues tab in the github page seems disabled |
| 08:38 | gfredericks | dev.clojure.org/jira |
| 08:41 | nkoza | thanks |
| 08:48 | augustl | would 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:01 | djpowell | clgv: 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:01 | edward_ | Hi guys, I'm just wondering, in case statement, how can I do nothing for one case? |
| 10:01 | clgv | edward_: do not add the statement |
| 10:02 | cshell | do nothing or return nothing? |
| 10:02 | edward_ | hmmm sorry I'm new to clojure so I guess return nothing since clojure is functional :D |
| 10:03 | cshell | exclude the statement or return nil |
| 10:04 | antares_ | edward_: return nil |
| 10:05 | edward_ | hmm like (nil)? |
| 10:05 | edward_ | and how can I exclude the statement? |
| 10:05 | antares_ | edward_: nil is not a function, just nil |
| 10:05 | cshell | just nil |
| 10:05 | clgv | (case v 10 11, 11 nil, 12 13, 42) |
| 10:06 | edward_ | oh haha forgot () is calling function |
| 10:18 | pandeiro | how do i view the dep tree with lein? |
| 10:20 | cshell | you can generate the pom then run mvn dependency:tree |
| 10:20 | cshell | but lein probably has an easier way |
| 10:22 | jsabeaudry | pandeiro, https://github.com/the-kenny/lein-deps-tree |
| 10:24 | nkoza | pandeiro: lein deps :tree (at least with lein 2) |
| 10:26 | augustl | https://www.refheap.com/paste/5620 weird stack trace.. If anyone has got some suggestions I'm all ears |
| 10:27 | pandeiro | jsabeaudry: nkoza: thanks |
| 10:29 | augustl | is 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:30 | antares_ | 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:30 | jsabeaudry | augustl, I beleive that is coming in 1.5 |
| 10:31 | antares_ | augustl: add (:refer-clojure :exclude [list]). Column numbers are coming in the next release. |
| 10:32 | WokenFury | has 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:32 | augustl | yay for column numbers :) |
| 10:33 | augustl | antares_: the redefine of clojure.core/list wasn't the problem |
| 10:33 | augustl | still getting the same error after adding (:refer-clojure :exclude [list]), the warning is no longer there so it was picked up |
| 10:34 | clgv | WokenFury: usually the problem is that those variables are not bound outside a request |
| 10:34 | augustl | antares_: oh I was getting another error from another file. Fixed them all, now it works, thanks. |
| 10:35 | WokenFury | clgv: my defsnippet is called from within a noir/defpage though, so the request is definitely active and *errors* is bound in the defpage |
| 10:38 | clgv | WokenFury: maybe defsnippet tries to use *errors* on macro expansion time? |
| 10:39 | clgv | I dont know how defsnippet works ;) |
| 10:40 | antares_ | 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:43 | WokenFury | looks like someone else ran into this. let me test snippets outside of deftemplate https://github.com/cgrand/enlive/issues/30 |
| 10:45 | edward_ | hmm, is there any other way of "do nothing" instead of returning nil in clojure? |
| 10:47 | augustl | edward_: depends on what you're working with I guess |
| 10:47 | jsabeaudry | edward_, removing the statement |
| 10:47 | augustl | edward_: + returns 0 with no arguments, which will cause it to "do nothing" |
| 10:47 | jsabeaudry | augustl, taking note of that for 4clojure :) |
| 10:47 | antares_ | 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:48 | augustl | jsabeaudry: :D |
| 10:49 | edward_ | 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:49 | antares_ | 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:49 | edward_ | oh nice ! |
| 10:49 | antares_ | edward_: use an empty string |
| 10:50 | edward_ | hmm it gives me indexoutofbounds if i use empty string, but let me try identity first |
| 10:50 | edward_ | nice it worked just the way I wanted :D |
| 10:50 | edward_ | Thanks guys |
| 10:53 | pandeiro | drewr: 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:57 | WokenFury | grrrr. having major regrets about rewriting this hiccup code in enlive. less code in enlive, but more random explosions |
| 11:01 | drewr | pandeiro: I don't know off the top of my head; can you give me an example of the two? |
| 11:02 | pandeiro | drewr: 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:03 | pandeiro | but at the repl, when I manually do the same, the MimeBodyPart.getContent() yields a regular InputStream |
| 11:03 | pandeiro | i am trying to debug some problems with using BASE64DecoderStream in another lib, and I am baffled at the seemingly random results |
| 11:05 | pandeiro | it 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:06 | pandeiro | yet if you do (.getContent (doto (javax.mail.internet.MimeBodyPart.) (.attachFile "foo.pdf"))), you get an instance of FileInputStream |
| 11:07 | drewr | that all sounds right to me |
| 11:07 | pandeiro | how is it determining which to encode as which, and why the different behavior at the REPL and in message.clj? |
| 11:09 | pandeiro | is 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:09 | drewr | no, that's all javamail |
| 11:11 | pandeiro | damn i am stumped by this... anyway sorry for bothering ya |
| 11:13 | arrdem | ,(= identity (fn [x] x)) |
| 11:13 | clojurebot | false |
| 11:27 | Kototama | hi, how can I make th equivalent JS call "new Backbone.View({})" in clojurescript? |
| 11:30 | ohpauleez | Kototama: 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:32 | ohpauleez | If it's a singleton and you're using a function call, you might end up with something like (.View Backbone {}) |
| 11:34 | Kototama | don't I need prefix Backbone with js/Backbone? |
| 11:34 | Kototama | and how can I specify that the call is a 'new' ? |
| 11:34 | Kototama | .View will just invoke the function no? |
| 11:37 | nDuff | Kototama: (View.) constructs a new object. |
| 11:37 | nDuff | Kototama: ...as opposed to .View |
| 11:37 | ohpauleez | Kototama: Right, like my first example |
| 11:37 | nDuff | ahh. |
| 11:37 | Kototama | ok but if I don't required the lib but used a dynamically loaded library |
| 11:37 | nDuff | ...so, ohpauleez's answer looks right. |
| 11:38 | nDuff | the "." being on the end specifies that it's a new. |
| 11:38 | Kototama | (js/Backbone/View.) won't work |
| 11:39 | ohpauleez | Kototama: If you're using it that way: (js/Backbone.View. {}) |
| 11:39 | nDuff | ...well, that's a Clojure {}, not a JS {}, no? |
| 11:39 | ohpauleez | but that's not advised - you're going to have to externs that stuff |
| 11:39 | Kototama | yeah okk I'm just playing with existing code to see what I could do with clojurescript |
| 11:40 | Kototama | because JS makes me cry everytime I forget that the context of 'this' has changed :-s |
| 11:41 | Kototama | ah! js/Backbone.View works but if I remember correctly this is some new syntax, not clojure comptible |
| 11:42 | ohpauleez | Kototama: That's regular Clojure code, JVM interop works very similarly, with the exception of the js/ piece |
| 11:43 | Kototama | nDuff: you'right {} is passed as a cljs.core.ObjMap |
| 11:43 | ohpauleez | the reason for periods and not slashes happens because you're using js/ and you're accessing a constructor, not hitting an aliased namespace |
| 11:43 | Kototama | ohpauleez: ok i need to relook at that because I didn't write any niterop code since a long time |
| 11:43 | clojurebot | primetime |is| <lowlycoder> i'm not convined clojure is ready for primetime until i see facebook apps in clojure |
| 11:44 | ohpauleez | Kototama: (js-obj) I believe is the form, but you're probably better off extending appropriate protocols to Backbone stuff |
| 11:44 | Kototama | well you're right java.lang.Integer just uses plain dot and is clojure |
| 11:44 | Kototama | yep |
| 11:45 | Kototama | not sure how to do that in clojurescript |
| 11:45 | ohpauleez | Kototama: The same way you do it in Clojure |
| 11:46 | ohpauleez | let me get you an example |
| 11:46 | ohpauleez | Kototama: http://shoreleave.github.com/shoreleave-browser/#shoreleave.browser.cookies |
| 11:47 | drewr | pandeiro: sry, I would look into it more but I can't atm |
| 11:47 | ohpauleez | Here I extend Closure's Cookies support, so I can use map-like lookups |
| 11:48 | SegFaultAX|work | Has anyone else seen Brendan Eich's talk at Strange Loop about JavaScript? |
| 11:48 | Kototama | wow it looks really easy |
| 11:49 | ohpauleez | very easy |
| 11:50 | Kototama | but this would not really create new Backbone.Views / Models but only add clojurescript methods to the backbone types right? |
| 11:50 | Kototama | so that I call count or whatever on the models |
| 11:51 | Kototama | +could |
| 11:51 | ohpauleez | Kototama: You would do something like: (def cookies (goog.net.Cookies. js/document)) |
| 11:51 | ohpauleez | or wrap the constructor call |
| 11:51 | SegFaultAX|work | It seems like they've just taken a random smattering of features from Python and Ruby and added them to JavaScript haphazardly. |
| 11:52 | ohpauleez | and then with the protocols extended to the object in Backbone, you can use standard Clojure functions on them |
| 11:52 | ohpauleez | treating views like maps, vectors, whatever you want |
| 11:52 | ohpauleez | SegFaultAX|work: Who has? Backbone? |
| 11:53 | SegFaultAX|work | ohpauleez: The ECMAScript team. |
| 11:53 | Kototama | ok but the render function for instance for views should be dispatched on instances; not on the type |
| 11:53 | ohpauleez | ahh 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:53 | Kototama | it's like the method of an object basically |
| 11:54 | SegFaultAX|work | ohpauleez: Check it - http://brendaneich.github.com/Strange-Loop-2012/#/ |
| 11:54 | SegFaultAX|work | ohpauleez: Slides on his talk at Strange Loop about features coming in ES6 and ES7. |
| 11:54 | ohpauleez | nutty, I definitely will |
| 11:54 | SegFaultAX|work | ohpauleez: 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:55 | duck1123 | there are protocol extensions to backbone? |
| 11:55 | Kototama | for instance you can't do that with extend-type http://paste2.org/p/2316251 right? |
| 11:56 | Kototama | I 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:56 | antoineB | ,(nth 2 [:a :b :c]) |
| 11:56 | clojurebot | #<ClassCastException java.lang.ClassCastException: clojure.lang.PersistentVector cannot be cast to java.lang.Number> |
| 11:57 | Kototama | but the specific render function needs to be passed in the hash of the extend call, right? |
| 11:57 | antoineB | ,(nth [:a :b :c] 2) |
| 11:57 | clojurebot | :c |
| 11:57 | duck1123 | Kototama: Here's how I've been using Backbone w/ cljs https://github.com/duck1123/jiksnu/blob/pending/src-cljs/jiksnu/model.cljs |
| 11:59 | Kototama | duck1123: really helpfull thank you |
| 11:59 | duck1123 | I made my own backbone ns so I could easily reference those classes |
| 12:00 | duck1123 | next step will be a macro to make those model defs really pretty |
| 12:00 | TimMc | clojurebot: Why so sad? |
| 12:00 | clojurebot | No entiendo |
| 12:01 | Kototama | duck1123: and then do a lib that I can import ;-) |
| 12:01 | jconnolly | ,(nth [:a :b :c] 2) |
| 12:01 | clojurebot | :c |
| 12:01 | duck1123 | Kototama: That'll be the idea |
| 12:01 | duck1123 | in the mean time, feel free to steal any of that you find useful |
| 12:02 | Kototama | thank you I'll have a look at that |
| 12:04 | duck1123 | if you hold on, I have new stuff to push |
| 12:04 | antoineB | do you know any big application done in clojurescript? |
| 12:07 | Kototama | duck1123: i'm not in the hurry, I will have a look at it tomorrow |
| 12:07 | fckw | Hi there. |
| 12:07 | fckw | Got a FP question: |
| 12:07 | fckw | I have a map with key-value pairs. |
| 12:07 | Kototama | I need to see If I stick to JS until the end of the project or switch to ClojureScript to preserve my calm :-) |
| 12:07 | duck1123 | Kototama: well, it's all there on the pending branch now. you can see it in action at http://renfer.name/ |
| 12:08 | fckw | I want to apply some function (e.g. inc) to all the values of the elements and then return the new map. |
| 12:08 | fckw | There must be an easy way to do this, but I don't get it right now. |
| 12:08 | fckw | Using the val function returns only a seq of values - not what I want. |
| 12:08 | fckw | Sorry, I meant: Using the vals function. |
| 12:09 | Kototama | something like (map inc (vals coll)) ? |
| 12:09 | fckw | Yes, something like this. |
| 12:09 | lynaghk | Has anyone gotten tagged literals working within a REPL (i.e., not using the data_readers.clj file)? |
| 12:09 | fckw | But then returning the whole map, not only a seq of (changed) values. |
| 12:10 | lynaghk | I'm binding *data-readers* as instructed in the docs but my tags don't get picked up. |
| 12:11 | Kototama | look at reduce-kv I guess |
| 12:11 | jkkramer | lynaghk: are you using lein repl (reply)? |
| 12:11 | fckw | The 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:11 | lynaghk | jkkramer: I'm using swank |
| 12:11 | jkkramer | lynaghk: got a paste-able snippet? |
| 12:11 | lynaghk | jkkramer: sure, give me a sec. |
| 12:13 | Kototama | (reduce-kv (fn [acc k v] (assoc acc k (inc v))) {} {:one 1 :two 2}) |
| 12:14 | lynaghk | jkkramer: https://www.refheap.com/paste/5622 |
| 12:14 | fckw | @Kototama: I have to try this out, thanks for your suggestion. |
| 12:15 | lynaghk | jkkramer: passing the var (e.g., #'map->A) doesn't make a difference either. |
| 12:15 | fckw | @Kototama: Thanks! I did not know about reduce-kv until now. |
| 12:15 | lynaghk | jkkramer: nor does namespacing the tag |
| 12:15 | Kototama | it's relatively new it was introduce in 1.4 |
| 12:15 | hiredman | lynaghk: I have |
| 12:16 | hiredman | lynaghk: I set! *data-readers* |
| 12:17 | hiredman | lynaghk: https://gist.github.com/3859794 |
| 12:17 | fckw | I believe it could be done even shorter somehow, but I cannot see a solution right now. |
| 12:17 | lynaghk | hiredman: that works, thanks! Shouldn't the binding form work as well, though? |
| 12:17 | hiredman | lynaghk: no idea |
| 12:17 | jkkramer | lynaghk: 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:17 | jkkramer | yeah, see hireman's thing |
| 12:18 | lynaghk | jkkramer: okay, that makes sense. |
| 12:18 | lynaghk | jkkramer, hireman: thanks. |
| 12:31 | fckw | Ah, here we go, there is an update-in function. |
| 12:31 | fckw | This might be handy. |
| 12:41 | fckw | Can anyone explain me why this code does not work: (def my-map {:one 1 :two 2 :three 3}) |
| 12:42 | fckw | (update-in my-map (keys my-map) inc) |
| 12:42 | fckw | I get a NullPointerException. |
| 12:42 | clgv | fckw: you misunderstood update-in |
| 12:42 | hiredman | the keys you pass to update-in are expected to describe a path through a nested structure of maps |
| 12:42 | clgv | fckw: update-in is for nested maps |
| 12:43 | fckw | Oh gosh. So is there really no simple "update" function? |
| 12:43 | clgv | &(update-in {:a {:b 1} :c {:d 0}} [:a :b] inc) |
| 12:43 | lazybot | ⇒ {:a {:b 2}, :c {:d 0}} |
| 12:43 | fckw | Updating all values in a map? |
| 12:44 | clgv | you can use reduce-kv like: ##(reduce-kv (fn [m, k, v] (assoc m k (inc v))) {} {:a 0 :b 2}) |
| 12:44 | lazybot | ⇒ {:b 3, :a 1} |
| 12:44 | fckw | As 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:44 | fckw | Yes, I already was told so. Is this the standard way of doing updates to all values in a map? |
| 12:45 | fckw | Creating a new, empty map and re-associating the changed key-value-pairs? |
| 12:45 | clgv | fckw: from a structure-sharing point of view: you cant share structure if you update every value |
| 12:45 | fckw | Hm, that's true. |
| 12:45 | duck1123 | no matter how you slice it, sooner or later, the code is going to loop every key and perform the operation in turn |
| 12:45 | fckw | Ok, thanks for your answer. |
| 12:46 | clgv | you can build a function from the above reduce-kv snippet for convenience |
| 12:46 | technomancy | ,((comp inc {:a 0 :b 2}) :b) |
| 12:46 | clojurebot | 3 |
| 12:46 | technomancy | but then it's not a map anymore |
| 12:46 | dnolen | fckw: 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:48 | fckw | But why can I do a map or apply on a list, but not something similar on a map? |
| 12:48 | fckw | Would be nice: Applying a change to each element (e.g. its value) in a map using the map function. |
| 12:48 | SegFaultAX|work | fckw: Sounds like you want fmap. |
| 12:49 | technomancy | fckw: part of the point of map is that it's lazy |
| 12:49 | arrdem | ,(let [m {:a 1 :b 2 :c 3}] (zip-map (keys m) (map inc (vals m)))) |
| 12:49 | clojurebot | #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: zip-map in this context, compiling:(NO_SOURCE_PATH:0)> |
| 12:49 | arrdem | ,(let [m {:a 1 :b 2 :c 3}] (zipmap (keys m) (map inc (vals m)))) |
| 12:49 | clojurebot | {:b 3, :c 4, :a 2} |
| 12:49 | clgv | fckw: (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:49 | duck1123 | performing an op on every vaule in a map isn't as common of a need IMO |
| 12:49 | technomancy | anyway, I agree that map-keys and map-vals would be nice, but at that point it's different from clojure.core/map |
| 12:50 | fckw | I cannot find a fmap function? |
| 12:50 | dnolen | fckw: 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:52 | fckw | I 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:52 | fckw | But anyway, reduce-kv seems the way to go. |
| 12:52 | clgv | fckw: yeah, I think thats the reason why it was added in 1.4 ^^ |
| 12:57 | SegFaultAX|work | fckw: Clojure has a Functor library that provides fmap. |
| 12:57 | SegFaultAX|work | fckw: Clojure contrib, rather. |
| 12:58 | fckw | Here is my new function that escapes html: |
| 12:58 | fckw | (defn- with-html-escaped [params] |
| 12:58 | fckw | @SeqFaultAX: I'll have a look, thanks. |
| 13:00 | clgv | ~contrib ;) |
| 13:00 | clojurebot | latest contrib is 947 |
| 13:00 | clgv | oops |
| 13:00 | clgv | ~contrib |
| 13:00 | clojurebot | Monolithic 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:00 | TimMc | clojurebot: forget latest contrib |is| 947 |
| 13:00 | clojurebot | I forgot that latest contrib is 947 |
| 13:00 | fckw | There is the fmap function: http://richhickey.github.com/clojure-contrib/generic.functor-api.html |
| 13:00 | lazybot | Nooooo, 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:01 | clgv | fckw: better use the update-map I gave you above ^^ |
| 13:04 | fckw | @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:06 | SegFaultAX|work | fckw: 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:06 | zerokarmaleft | fckw: as clgv said, you might want to add transients, frequencies in core is a good example of how to do that |
| 13:07 | SegFaultAX|work | fckw: In the case of clojure, "mappable things" applies broadly to all sequence/collection/container types. |
| 13:10 | fckw | Yes, using transient maps seems like a good idea when html-escaping parameter maps that are being sent from the client. |
| 13:11 | fckw | I'll have to read up the corresponding topics. |
| 13:22 | ppppaul | hey |
| 13:22 | ppppaul | anyone here use clutch? |
| 13:28 | pandeiro | ppppaul: yeah |
| 13:28 | ppppaul | pandeiro, have you done anything with attachments? |
| 13:28 | pandeiro | ppppaul: ha, yeah been debugging something involving attachments for almost 2 weeks |
| 13:28 | ppppaul | hmmm |
| 13:29 | pandeiro | my problem is with a particular input stream type, usually it has worked fine in the past |
| 13:30 | ppppaul | ok. 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:33 | pandeiro | ppppaul: i haven't done the dirty work but tbh i'd do it with bash+curl |
| 13:34 | pandeiro | clutch can probably handle it, and would be infinitely more malleable i imagine |
| 13:34 | pandeiro | ah i meant to say bash + curl + underscore-cli (vital ingredient) |
| 13:34 | pandeiro | for slicing through the json etc |
| 13:37 | ppppaul | bash/curl... how would that handle pusing 23k docs? |
| 13:37 | ppppaul | i mean files |
| 13:37 | duck1123 | pandeiro: thanks for pointing out underscore-cli |
| 13:37 | nDuff | ppaul: ...eh, that's not really a question that can be answered; depends on the specific requirements. |
| 13:38 | nDuff | pppaul: the case where it _wouldn't_ be adequate is if you needed things like session keepalive. |
| 13:38 | ppppaul | hmmm... i guess i would have some commandline thing to base64 all the files? |
| 13:38 | nDuff | ppppaul: Huh? curl can manage encoding itself. |
| 13:38 | nDuff | ...anyhow, #bash -> thataway. |
| 13:38 | ppppaul | nDuff i am bash noob :) |
| 13:39 | ppppaul | wow, 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:39 | jsabeaudry | pppaul, clojure is over-rated, use bash |
| 13:41 | jweiss | is 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:41 | ppppaul | well, i mainly need to push a dir into couchdb preserving relative paths |
| 13:42 | nDuff | jweiss: can be done using lazy-seq, yes. |
| 13:42 | duck1123 | jweiss: I use this to unchunk my seqs https://github.com/duck1123/ciste/blob/master/src/ciste/routes.clj#L75 |
| 13:42 | pandeiro | ppppaul: i am also bash-averse |
| 13:43 | pandeiro | but i will post my code, hold on |
| 13:43 | jweiss | nDuff: duck1123: so, does lazy-seq alone not do it then? |
| 13:44 | nDuff | jweiss: depends on what you mean by "lazy-seq alone". |
| 13:44 | nDuff | jweiss: ...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:45 | pandeiro | ppppaul: http://sprunge.us/LWCg?bash |
| 13:45 | jweiss | nDuff: 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:45 | jweiss | instead of 32 |
| 13:46 | nDuff | jweiss: see what duck1123 gave you. |
| 13:46 | jweiss | ok thanks |
| 13:47 | jweiss | nDuff: so it would be (take 5 (lazier (map ...)) ? |
| 13:48 | duck1123 | jweiss: that should do it |
| 13:48 | jweiss | duck1123: great, thank you |
| 13:48 | amalloy | jweiss: iterate isn't chunked |
| 13:48 | nDuff | pandeiro: ...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:48 | jweiss | amalloy: map doesn't do any extra chunking? |
| 13:49 | amalloy | nothing (afaik) ever makes a sequence become chunked |
| 13:49 | amalloy | there are only chunked sequence-producers, and functions which retain chunkiness |
| 13:49 | jweiss | so i guess i would want to know if map does that :) |
| 13:49 | dnolen | jweiss: chunking is a property of the collection - range, vector etc |
| 13:49 | amalloy | it does, but you don't care |
| 13:49 | duck1123 | amalloy: in my case, it was a map over a literal vector that makes it chunked |
| 13:50 | amalloy | well yep, that'll do it |
| 13:50 | jweiss | amalloy: 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:50 | pandeiro | nDuff: thanks, i def _do_ need a bash mentor |
| 13:50 | amalloy | jweiss: because you're calling map on iterate |
| 13:50 | pandeiro | and #bash is scary |
| 13:50 | amalloy | if you were calling map on something else, you might care |
| 13:51 | amalloy | btw there's https://github.com/flatland/useful/blob/develop/src/useful/seq.clj#L178 in useful |
| 13:51 | jweiss | amalloy: well, that was just an example, i'll really just be doing something more like (repeatedly 5 lrf) |
| 13:51 | amalloy | (unchunk coll) and (lazy (foo) (bar) (baz)) are both relevant |
| 13:52 | jweiss | amalloy: that looks the same as the earlier posted function 'lazier' |
| 13:52 | amalloy | it probably is |
| 13:53 | duck1123 | there are some slight differences, which seems interesting |
| 13:53 | amalloy | duck1123: the version in ciste is not as good |
| 13:53 | amalloy | because it forces realization of the first element unconditionally |
| 13:53 | duck1123 | interesting. good to know |
| 13:54 | ppppaul | thanks pandeiro |
| 13:54 | amalloy | plus depending on useful seems like a better way to get a lazy-sequence operation than depending on ciste's routes lib |
| 13:54 | amalloy | (from jweiss's point of view) |
| 13:55 | duck1123 | very true. Thinking on depending on useful myself actually |
| 13:55 | pandeiro | ppppaul: ignore the debug statements and other bad forms nDuff mentioned ;) |
| 13:55 | duck1123 | since I never have it required, I'm sure I'm missing out in several places |
| 13:56 | amalloy | duck1123: tbh the most-used thing in useful is probably ?, my debug macro |
| 13:57 | ppppaul | pandeiro, the .couchrc is a file with 1 line of text? |
| 13:58 | ppppaul | like, it wants localhost:5984/db_name ? |
| 13:59 | pandeiro | ppppaul: http://user:pass@host:port |
| 13:59 | ppppaul | i see |
| 14:00 | pandeiro | ppppaul: you could update it to automatically iterate over entire directories and stuff... |
| 14:00 | pandeiro | but for me that ended up being more useful than the whole couchapp/nodecouchapp chain for most of what i do |
| 14:01 | Licenser | ibdknox ping :) |
| 14:02 | jweiss | amalloy: is ? sort of like tracing functions but on the form level? |
| 14:02 | amalloy | jweiss: it's just a slightly less-awful version of debug printf |
| 14:03 | amalloy | (? (foo bar)) evaluates the same as (foo bar), and also prints "(foo bar) is 10" |
| 14:03 | jweiss | amalloy: ah i see, you don't call it from the repl, you embed it in your code? |
| 14:03 | amalloy | yep |
| 14:04 | duck1123 | how does it compare to clojure.tools.logging/spy (aside from the log vs. print) |
| 14:06 | amalloy | not 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:07 | amalloy | i suspect it also aligns a bit better for large expressions/values, but that's just based on reading the code for spy |
| 14:08 | duck1123 | I 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:08 | pandeiro | nDuff: sorry for bash question, but i can't find anything on google about why u would use $(<cat...) instead of $(cat...) |
| 14:09 | nDuff | pandeiro: the latter requires exec'ing an external tool |
| 14:09 | nDuff | pandeiro: if you run 'type cat', you'll see it's /bin/cat, not a bash built-in command. |
| 14:09 | pandeiro | ah sure ok |
| 14:09 | nDuff | oh, and it's not $(<cat file), it's $(<file) |
| 14:10 | jweiss | is 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:10 | nDuff | jweiss: sounds like you want partial? |
| 14:10 | jweiss | nDuff: yeah, partial will create the functions, but then how do i make them accessible |
| 14:10 | pandeiro | nDuff: but with non-internal stuff, $(cmd ...) would be an appropriate way to store cmd output into a variable? |
| 14:11 | nDuff | jweiss: 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:12 | nDuff | pandeiro: Yes. |
| 14:12 | jweiss | nDuff: i would want to support multiple configurations at the same time, but not necessarily on a per-thread basis |
| 14:13 | nDuff | jweiss: Ahh; that is indeed more interesting, then. |
| 14:13 | jweiss | that's why i shy away from using a var |
| 14:13 | jweiss | i think maybe i'll just return a map like {:get <fn> :post <fn> ... { |
| 14:13 | jweiss | } |
| 14:20 | jlewis | what's the idiomatic way to check if something is callable? |
| 14:22 | amalloy | &(doc ifn?) |
| 14:22 | lazybot | ⇒ "([x]); Returns true if x implements IFn. Note that many data structures (e.g. sets and maps) implement IFn" |
| 14:22 | jlewis | thanks! |
| 14:26 | Licenser | hmm if ifn? is the idiomatic way would (try () true (catch _ false)) the idiotic way? |
| 14:33 | zilti | When 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:39 | zilti | Sometimes that stuff feels like it never gets used in production. |
| 14:42 | ulath | hi, 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:44 | pjstadig | ,(time (dotimes [_ 1000000] (object-array [1]))) |
| 14:44 | clojurebot | "Elapsed time: 308.76889 msecs" |
| 14:44 | pjstadig | ,(time (dotimes [_ 1000000] (object-array (rseq [1])))) |
| 14:44 | clojurebot | "Elapsed time: 123.725152 msecs" |
| 14:45 | pjstadig | there's a riddle for you |
| 14:45 | pjstadig | to which i know the answer |
| 14:45 | technomancy | that is amazing |
| 14:48 | zilti | What does that underscore do? |
| 14:48 | scriptor | it means the variable is ignored |
| 14:48 | scriptor | well, more specifically, you don't care about the binding |
| 14:48 | dnolen | zilti: it has no real special meaning - just convention |
| 14:49 | ppppaul | pandeiro, i'm working with your file, but i can't seem to get couch-put/couch-post working |
| 14:51 | scriptor | hmm, where's the rseq class defined? |
| 14:51 | amalloy | pjstadig: that's a curious riddle |
| 14:52 | amalloy | scriptor: APersistentVector$RSeq |
| 14:52 | scriptor | yep, thanks |
| 14:52 | ppppaul | pandeiro, are you versioning the file? would you be interested in starting a repo or gist? |
| 14:54 | zilti | Is someone here working with lein-ring? Because of my problem with the inclusion of the resources directory |
| 14:54 | amalloy | oh. Vector$Seq doesn't implement Counted?! |
| 14:55 | pjstadig | correct! |
| 14:55 | pjstadig | well |
| 14:55 | pjstadig | PersistentVector$ChunkedSeq |
| 14:55 | pjstadig | ,(class (seq [1])) |
| 14:55 | clojurebot | clojure.lang.PersistentVector$ChunkedSeq |
| 14:56 | pjstadig | ,(instance? clojure.lang.Counted (seq [1])) |
| 14:56 | clojurebot | false |
| 14:56 | pjstadig | ,(instance? clojure.lang.Counted (rseq [1])) |
| 14:56 | clojurebot | true |
| 14:56 | devth | anyone know if there's a way to retrieve the source for an entire namespace, similar to clojure.repl/source for vars? |
| 14:57 | amalloy | hah. i didn't even look at ChunkedSeq, so it's lucky APersistentVector$Seq behaves similarly |
| 14:57 | amalloy | pjstadig: going to submit a patch to fix that silliness? |
| 14:58 | pjstadig | actually APersistentVector$Seq implements IndexedSeq which implements Counted |
| 14:58 | amalloy | oh, so it does. i didn't expect that, given that APV$RSeq implements IndexedSeq and (explicitly) Counted |
| 14:59 | amalloy | my detective skills are looking more and more like random luck |
| 15:00 | pandeiro | ppppaul: https://github.com/pandeiro/dotstar/blob/master/bash/bash_functions |
| 15:00 | pjstadig | i guess i should open a jira ticket for it |
| 15:00 | amalloy | wow, 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:01 | dnolen | pjstadig: what would the fix be? |
| 15:01 | amalloy | well, i guess that's not true. someone could be using it indirectly via ArraySeq or some other implementing class |
| 15:02 | amalloy | nope. lots of definitions of index(), and no uses of it. crazy |
| 15:03 | pjstadig | dnolen: i assume making PersistentVector$ChunkedSeq implement either Counted or IndexedSeq |
| 15:05 | tomoj | amalloy: it looks like it was ported from c#? |
| 15:05 | amalloy | whaaaaa? |
| 15:05 | pjstadig | hehe |
| 15:06 | dnolen | ,(counted (seq (range 32))) |
| 15:06 | clojurebot | #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: counted in this context, compiling:(NO_SOURCE_PATH:0)> |
| 15:06 | dnolen | ,(counted? (seq (range 32))) |
| 15:06 | clojurebot | false |
| 15:06 | tomoj | amalloy: `git log` that file |
| 15:06 | dnolen | ^ probably also needs fixing as well then. |
| 15:07 | pjstadig | dnolen: you think? |
| 15:08 | tomoj | oh, well, not sure. but there is an almost identical c# file in the same commit that introduced IndexedSeq.java |
| 15:08 | amalloy | tomoj: i don't see it |
| 15:08 | amalloy | ah |
| 15:09 | dnolen | ,(counted? (seq {:foo 1 :bar 2})) |
| 15:09 | clojurebot | true |
| 15:09 | pjstadig | dnolen: 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:09 | amalloy | dnolen: 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:10 | pjstadig | was range also counted before chunked seqs? |
| 15:12 | amalloy | pjstadig: probably not |
| 15:13 | amalloy | since it's in clojure rather than java. unless you mean the super-old clojure.lang.Range, which is indeed Counted |
| 15:14 | Derylbat23 | hello |
| 15:14 | Derylbat23 | list please ? |
| 15:14 | hiredman | () |
| 15:15 | dnolen | pjstadig: I think the ticket should be general - return counted seqs if the information is available. |
| 15:15 | dnolen | pjstadig: the CLJS persistent data structures exhibit this issue as well - since we just followed Clojure JVMs lead. |
| 15:17 | TimMc | (inc hiredman) |
| 15:17 | lazybot | ⇒ 14 |
| 15:18 | hiredman | speaking of such things |
| 15:19 | hiredman | ,(inc (Long/MAX_VALUE)) |
| 15:19 | clojurebot | #<ArithmeticException java.lang.ArithmeticException: integer overflow> |
| 15:19 | hiredman | I guess that is technically correct, a long is a long integer, but :/ |
| 15:21 | TimMc | As long as it doesn't say Integer overflow. |
| 15:24 | augustl | out of curiousity, why does leiningen have (defproject ...) instead of just a plain map? |
| 15:24 | pjstadig | ,(unchecked-add Long/MAX_VALUE 1) |
| 15:24 | clojurebot | -9223372036854775808 |
| 15:26 | amalloy | pjstadig: i think he's just objecting to the message, not the exception |
| 15:26 | pjstadig | amalloy: yeah i was thinking of something else |
| 15:28 | pjstadig | ,(unchecked-add (Long. Long/MAX_VALUE) 1) |
| 15:28 | clojurebot | #<ArithmeticException java.lang.ArithmeticException: integer overflow> |
| 15:28 | pjstadig | ,(doc unchecked-add) |
| 15:28 | clojurebot | "([x y]); Returns the sum of x and y, both long. Note - uses a primitive operator subject to overflow." |
| 15:29 | pjstadig | which i guess is correct if you pay attention to the fact that the docstring says long with a lower case ell |
| 15:30 | pjstadig | i 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:30 | pjstadig | or have the slow path check if it's a Long and call the overflowing version |
| 15:37 | pjstadig | dnolen: sorry i already created the story, i can see how maybe there should be a more general focus on implementing Counted where appropriate |
| 15:37 | pjstadig | i was also thinking it would be better to have smaller scope |
| 15:37 | callen | does anyone here use MongoDB with Clojure? |
| 15:37 | callen | if so, is there a recommended library? |
| 15:38 | augustl | callen: I'm using monger, works fine |
| 15:38 | augustl | I built a small library on top of it though |
| 15:38 | callen | augustl: that's what I'd been looking at, thanks. Small library? |
| 15:39 | augustl | yeah, it adds stuff like (make-save "collection-name" validator processor) |
| 15:39 | augustl | a validator function can add validation errors and stop the save, a processor is pre-insert processing of the data |
| 15:40 | callen | that makes sense. |
| 15:40 | augustl | that'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:40 | augustl | callen: also made my library take a db object as the first argument to all operations, to make it functional |
| 15:40 | augustl | rather than a hidden singleton somewhere storing the connection etc. |
| 15:40 | callen | I found the singleton in monger kinda problematic. |
| 15:41 | callen | I 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:41 | augustl | callen: https://github.com/oiiku/oiiku-mongodb-clojure |
| 15:41 | augustl | just open sourced it, why not ;) |
| 15:41 | callen | augustl: very cool, thank you. |
| 15:42 | augustl | it'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:42 | callen | augustl: I'm still less-than-proficient in Clojure, so it'll at least give me something to learn from. TYVM |
| 15:42 | augustl | np :) |
| 15:43 | augustl | the validation system should probably be stand-alone too, it's not really mongodb specific |
| 15:43 | callen | augustl: 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:43 | callen | augustl: doing so in Python where every library is a fiefdom is a sisyphean task. |
| 15:44 | augustl | callen: using clojurescript for validation on the client side or something, you mean? |
| 15:45 | dnolen | callen: heh, i like that "where every library is fiefdom" ... |
| 15:46 | callen | dnolen: ahhh thank you. You're the one that did all that work on pred dispatch and logic right? |
| 15:47 | dnolen | callen: pred dispatch hasn't gotten very far, but yes I work on core.logic/match |
| 15:47 | callen | if so, awesome. Learned a lot from reading your posts about the subject. |
| 15:52 | callen | does 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:53 | augustl | callen: updated the README, at least it doesn't contain non-existing functions in it now ;) |
| 15:56 | callen | in fact, I can only find the refer-to function in the tests. how bizarre. |
| 15:57 | callen | lobos...may not be production ready. |
| 15:58 | callen | augustl: very cool, haha. Thank you. |
| 16:02 | TimMc | callen: There's also Ragtime and... drift? |
| 16:02 | callen | TimMc: what do you use? |
| 16:02 | TimMc | I don't. :-/ |
| 16:03 | callen | TimMc: do you do anything with clojure that needs persistence? |
| 16:03 | TimMc | Last 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:03 | TimMc | It was for a personal project, so I had the luxury of giving up. |
| 16:04 | callen | TimMc: 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:07 | technomancy | callen: I definitely support rolling your own; clojars has a simple implementation in two defns |
| 16:08 | technomancy | https://github.com/ato/clojars-web/blob/master/src/clojars/db/migrate.clj |
| 16:08 | technomancy | much easier than trying to comprehend lobos |
| 16:08 | callen | technomancy: I take it you've tried to go down the lobos rabbit-hole too? |
| 16:09 | callen | in my case, it wouldn't even be in clojure, I'd just do it with sql scripts. |
| 16:09 | technomancy | callen: yeah, I think it's too ambitious among other things |
| 16:09 | callen | I agree. The refer-to functionality is *bizarre* |
| 16:09 | technomancy | there is no way you can abstract away the differences between schema languages of various DBs |
| 16:10 | callen | technomancy: thank you for the pragmatic note. |
| 16:11 | TimMc | That's why I tried using ragtime, since it isn't even specific to databases. |
| 16:12 | thorbjornDX | hi, 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:12 | technomancy | ragtime is pretty good, but it's more complicated because it supports down migrations. in my experience down migrations don't work in practice. |
| 16:12 | callen | I don't like the idea of an unsupervised "down" anyway. |
| 16:13 | callen | I love automation, but it's unrealistic. |
| 16:13 | technomancy | I don't have an answer for migrations on long-lived branches other than "make sure they don't interfere with each other" unfortunately |
| 16:15 | callen | technomancy: it's case-specific, best to embrace that fact and realize that you have to know what you're doing. |
| 16:16 | technomancy | yeah, 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:16 | pandeiro | is it possible for cljs (clj) macros to reference cljs files? |
| 16:17 | dnolen | pandeiro: not as far as I know. |
| 16:17 | S11001001 | pandeiro: functions, or macros, in said files? |
| 16:17 | neotyk | Hello Everyone! |
| 16:18 | neotyk | when extending types in cljs, what is a difference between 'string' and 'js/String'? |
| 16:18 | dnolen | neotyk: if js/String appears in core.cljs probably an oversight, string is preferred |
| 16:18 | pandeiro | like if i wanted to write a specialized test macro that refers to a state atom in my client cljs files? |
| 16:19 | neotyk | dnolen: thanks |
| 16:19 | dnolen | pandeiro: then emit the fully qualified symbol to that atom. |
| 16:32 | ppppaul | pandeiro, 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:32 | antares_ | 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:41 | augustl | what'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:41 | technomancy | augustl: do you know about ex-info? |
| 16:42 | augustl | technomancy: hmm no |
| 16:43 | technomancy | it's the best |
| 16:44 | augustl | it's not in the cheatsheet, how could I possibly know about it? :) |
| 16:45 | augustl | looks good, except it feels kind of wrong to use exceptions for control flow.. |
| 16:45 | augustl | because I assume you mean raising an ex-info created exception instead of returning in the event of an error? |
| 16:46 | Apage43 | also 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:46 | augustl | the error in question is common since it's caused by erronous user input (form validation etc) |
| 16:47 | Apage43 | augustl: 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:49 | augustl | aren't exceptions exceptionally bad for performance though? |
| 16:49 | augustl | pun intended |
| 16:49 | Apage43 | that'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:49 | technomancy | augustl: I really hope your users aren't submitting bad form values at a rate fast enough for that to be a problem. |
| 16:49 | technomancy | if so you have more serious problems to deal with than exceptions =) |
| 16:50 | gtrak | is there a better way to do this? (read-string (str "::an-ns/" "failed")) -> :fully-qualified-ns/failed ? |
| 16:51 | augustl | I'm currently returning {:success true :data 123} or {:success false :errors "validation errors here.."}, I like that better than exceptions |
| 16:51 | augustl | you can multimethod over it ec. |
| 16:51 | augustl | etc* |
| 16:51 | loliveira | how do I access a recrd |
| 16:51 | augustl | loliveira: like a map |
| 16:51 | augustl | loliveira: (some-record :field) |
| 16:51 | technomancy | augustl: 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:52 | loliveira | how do I access a record method that was added using extend-type in other namespace? |
| 16:52 | augustl | true, an exception, if uncaught, makes it clear what went wrong |
| 16:53 | loliveira | more info: http://pastebin.com/RxJbj274 |
| 16:54 | loliveira | I am getting the folioing error: CompilerException java.lang.RuntimeException: Unable to resolve symbol: get-pos in this context |
| 16:55 | gtrak | this is slightly better: (keyword (namespace `an-na/dummy-symbol) "failed") |
| 16:59 | ppppaul | pandeiro, 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:01 | Apage43 | I've tended to do that sort of stuff with clojure |
| 17:09 | pandeiro | ppppaul: i never said i could write _software_ |
| 17:09 | augustl | I 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:09 | ppppaul | pandeiro, lol |
| 17:10 | pandeiro | couch-put foo && couch-post foo '{"_id":"bar"}' && couch-upload foo/bar baz.png "image/png" && couch-get foo/bar | underscore pretty |
| 17:10 | pandeiro | the baz.png is on you :) |
| 17:10 | ppppaul | your couch-upload is buggy. i fixed it... but i also refactored your code a bit |
| 17:11 | augustl | I'm defining the function as (defn myfunc [some-arg & {:keys [foo baz]}] ...) |
| 17:11 | ppppaul | https://gist.github.com/3861438 |
| 17:11 | ppppaul | pandeiro, |
| 17:12 | ppppaul | i got that working to upload a file... |
| 17:12 | ppppaul | so, now time to upload the other 28k files i have |
| 17:12 | augustl | (apply (partial myfunc "test") {:foo "bar" :baz 123}) does not work at least :) |
| 17:13 | Apage43 | using couchdb as a file store, eh? |
| 17:14 | augustl | perhaps I should rewrite my function to just take a map as that's my only use case.. |
| 17:15 | aperiodic | augustl: you need to use flatten, it's the worst |
| 17:15 | aperiodic | i recommend taking a map instead |
| 17:15 | augustl | aperiodic: doh, I guess that basically turns {:foo 123} into [:foo 123]? |
| 17:16 | aperiodic | augustl: exactly |
| 17:16 | Frozenlo` | OMG. Damnit I'm dumb. I just realized I can use [{:keys [...]}] instead of [&[{:keys [...]}]] |
| 17:16 | augustl | applying with [:foo 123] obviously works.. How silly |
| 17:16 | augustl | aperiodic: what's the easiest way to take a single map but still use destructuring? A let block in the body of the fn? |
| 17:16 | pandeiro | ppppaul: sorry i'm totally confused by how you renamed stuff |
| 17:17 | aperiodic | ,((fn [{:keys [foo]}] foo) {:foo "bar"}) |
| 17:17 | clojurebot | "bar" |
| 17:17 | pandeiro | but 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:18 | augustl | aperiodic: ah of course |
| 17:19 | ppppaul | works fine on what system? what version of bash? what version of underscore-cli ? lol pandeiro |
| 17:20 | ppppaul | i'm on ubuntu, you may be on a mac (tends to be a much older version of bash) |
| 17:20 | thorbjornDX | what about 64-bit? |
| 17:22 | pandeiro | ppppaul: does ubuntu even use bash? i thought it was dash or something |
| 17:22 | pipeline | /bin/sh is probably ash/dash. |
| 17:22 | pipeline | but bash is installed at /bin/bash usually |
| 17:46 | horofox | what function does the same of cons but take the parameters in the opposite way |
| 17:46 | horofox | or append to the end |
| 17:46 | horofox | of the list |
| 17:46 | horofox | ? |
| 17:46 | dnolen | conj |
| 17:47 | dnolen | horofox: sorry I thought you meant arg order |
| 17:47 | casion | conj appends to the beginning of a list I thought? |
| 17:47 | dnolen | horofox: you can't append to end of list w/ traversing, Clojure doesn't really provide a operation that does that for lists. |
| 17:47 | dnolen | horofox: use vectors |
| 17:47 | dnolen | w/o traversing I meant |
| 17:48 | frio | does clojure have a reverse? (fn rcons [element list] (reverse (con element (reverse list)))) ? |
| 17:48 | frio | (gross solution :)) |
| 17:48 | dnolen | frio: yes, reverse |
| 17:48 | casion | you could use concat and (list) the asg |
| 17:48 | casion | but that's a bit silly |
| 17:49 | horofox | dnolen: i have (cons 3 [1 2]) |
| 17:49 | horofox | dnolen: but it turns [3 1 2] |
| 17:49 | dnolen | ,(conj [1 2] 3) |
| 17:49 | casion | ,(concat '(1 2) '(3)) |
| 17:49 | clojurebot | [1 2 3] |
| 17:49 | horofox | i want [1 2 3] |
| 17:49 | clojurebot | (1 2 3) |
| 17:49 | dnolen | horofox: ^ |
| 17:49 | lynaghk | dnolen: 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:49 | dnolen | ,(conj [1 2] 3) |
| 17:49 | clojurebot | [1 2 3] |
| 17:50 | dnolen | lynaghk: protocols rock, they are truly mind blowingly awesome - it's the kind of extensibility you want all of the time :) |
| 17:50 | dnolen | and perf to boot |
| 17:51 | lynaghk | dnolen: 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:51 | dnolen | lynaghk: I'm not surea about the name, the actual name of the type actually concerns me less than a sensible ctor fn |
| 17:51 | lynaghk | dnolen: 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:51 | dnolen | lynaghk: so a better name for the underlying type matter less than - partial-map or sub map or something like that |
| 17:52 | horofox | YAY THANKS |
| 17:52 | horofox | just did my recursive fib implementation |
| 17:52 | horofox | it looks horrible |
| 17:52 | lynaghk | dnolen: well that and the semantics of whether partial map should apply to any map-like values it may have. |
| 17:53 | TimMc | horofox: I hope it isn't as horrible as this factorial implementation: https://gist.github.com/3036120 |
| 17:53 | horofox | wtf |
| 17:53 | frio | HNNNNGH TimMc |
| 17:53 | frio | I like it! |
| 17:54 | dnolen | lynaghk: I think it should unify with anything that implements IPersistentMap |
| 17:54 | horofox | https://gist.github.com/3861673 |
| 17:54 | horofox | hahahaha |
| 17:54 | lynaghk | dnolen: 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:55 | dnolen | lynaghk: just top level. |
| 17:56 | lynaghk | dnolen: okay. You want everything in the logic.clj or would a new file+namespace be okay? |
| 17:56 | dnolen | lynaghk: lynaghk new namespace is ok, actually preferred since there's going to be some churn soon. |
| 17:57 | dnolen | lynaghk: but I'd like the partial map ctor fn to be in the core namespace of course. |
| 17:57 | lynaghk | dnolen: okay, sounds good to me. I'll get you a patch by the end of the week. |
| 17:57 | dnolen | lynaghk: awesome! |
| 17:57 | TimMc | horofox: How about (+ actual-n next-n) instead of (reduce + [actual-n next-n])? |
| 18:01 | horofox | TimMc: good |
| 18:01 | horofox | TimMc: I'm getting the hang of things... hehe, thanks! |
| 18:04 | TimMc | horofox: Some suggestions: https://gist.github.com/3861689 |
| 18:04 | horofox | i will start doing a camping here in #clojure |
| 18:04 | horofox | TimMc: cool thanks |
| 18:04 | horofox | TimMc: I will do a better implementation now |
| 18:14 | TimMc | horofox: 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:15 | horofox | TimMc: oh, it should start in 0 1 always |
| 18:16 | horofox | TimMc: I'm going to try by passing only 2 parameters: the list and the amount of numbers to be generated |
| 18:16 | TimMc | Hmm, 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:19 | hyPiRion | Hmm, is there any specific reason merge returns nil instead of {} when given zero arguments? |
| 18:19 | gtrak | what do you guys use to test agents? |
| 18:20 | hyPiRion | It sounds kind of counterintuitive. |
| 18:21 | gtrak | hyPiRion: maybe if you're doing (apply merge ..) it makes sense |
| 18:21 | gtrak | nil's always used for seqs instead of an empty-seq too |
| 18:22 | hyPiRion | gtrak: hmm, how come? |
| 18:22 | gtrak | ,[(merge nil) (merge nil nil)] |
| 18:22 | clojurebot | [nil nil] |
| 18:22 | gtrak | ,[(merge {} nil) (merge nil {})] |
| 18:22 | clojurebot | [{} {}] |
| 18:22 | hyPiRion | ah. |
| 18:22 | gtrak | there's a semantic distinction there |
| 18:23 | hyPiRion | ,(doc merge) |
| 18:23 | clojurebot | "([& 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:24 | hyPiRion | I was more among the lines of why ##(merge) returns nil though. |
| 18:24 | lazybot | ⇒ nil |
| 18:24 | hyPiRion | s/I/It |
| 18:24 | gtrak | what else would it return? |
| 18:24 | hyPiRion | {} |
| 18:24 | gtrak | how about ##(apply merge []) |
| 18:24 | lazybot | ⇒ nil |
| 18:25 | dnolen | hyPiRion: are you running into a case where it matters? |
| 18:25 | hyPiRion | dnolen: 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:26 | gtrak | why? |
| 18:26 | clojurebot | why is the ram gone is <reply>I blame UTF-16. http://www.tumblr.com/tagged/but-why-is-the-ram-gone |
| 18:27 | hiredman | ,(doc fnil) |
| 18:27 | clojurebot | "([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:30 | hyPiRion | Well, my real question is whether (merge) returns its identity element. |
| 18:31 | amalloy | hyPiRion: sure it does. (= (merge nil x) (merge x nil) x) for all x |
| 18:32 | hyPiRion | Yeah, nevermind. ##(assoc nil 1 2) does return a map. |
| 18:32 | lazybot | ⇒ {1 2} |
| 18:32 | wingy | wished datomic was schemaless |
| 18:32 | wingy | i cant know all of the attributes in advance |
| 18:34 | hyPiRion | I didn't knew (assoc nil x y) => {x y}. Is that something one should know? |
| 18:35 | TimMc | Pick a type, any type! |
| 18:38 | augustl | in a leiningen plugin, how do I load the project itself so that I can resolve it's dependencies etc? |
| 18:40 | technomancy | augustl: try leiningen.core.eval/eval-in-project |
| 18:40 | TimMc | augustl: Lein 1.x or 2.x? And do you mean the project.clj data? |
| 18:41 | augustl | TimMc: lein 2 |
| 18:42 | augustl | TimMc: and I mean loading the actual library so I can access it |
| 18:42 | augustl | technomancy: hmm, I just did, and (resolve 'some-dep) returns nil |
| 18:42 | TimMc | augustl: Remember to require. |
| 18:42 | augustl | ah |
| 18:42 | horofox | hey TimMc |
| 18:43 | horofox | i did a beautiful implementation |
| 18:43 | horofox | WTF |
| 18:43 | TimMc | Share! |
| 18:43 | augustl | TimMc: hmm, require fails too |
| 18:44 | augustl | here'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:45 | devth | so 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:45 | horofox | TimMc: https://gist.github.com/3861912 |
| 18:46 | augustl | am I doing it the right way? |
| 18:46 | TimMc | augustl: 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:46 | rlb | devth: @some-atom |
| 18:46 | antares_ | 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:47 | TimMc | augustl: 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:47 | rlb | devth: ohh -- you meant varying time... |
| 18:47 | hiredman | devth: 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:47 | augustl | TimMc: hmm, is that a problem? Many of my libs use lib-name instead of lib-name.core |
| 18:47 | devth | rlb: yeah |
| 18:47 | augustl | TimMc: works when running the code normally at lesat :) |
| 18:48 | devth | i thought clojure's persistent data structures would allow you to get past values |
| 18:49 | hiredman | devth: references provide identities over a series of values |
| 18:49 | augustl | devth: you need to do state manually, it's not a data structure revision tracking system :) |
| 18:49 | horofox | is there any way to pass a function by parameter(optional) in a function |
| 18:49 | mikerose357 | anyone ever used clojure for android applications? |
| 18:49 | hiredman | if 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:50 | devth | augustl: that's reasonable but then my atom is just a "place" for place-oriented-programming |
| 18:50 | horofox | ? |
| 18:50 | devth | hiredman: i see |
| 18:50 | augustl | technomancy: 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:50 | augustl | devth: not sure what you mean |
| 18:51 | technomancy | augustl: eval-in-project is a function, not a macro |
| 18:51 | technomancy | you need to quote the code you want evaluated inside the project. have you read the plugin guide? |
| 18:51 | TimMc | horofox: You can use multi-arity functions. |
| 18:51 | hiredman | devth: have you seen http://www.infoq.com/presentations/Are-We-There-Yet-Rich-Hickey ? |
| 18:51 | devth | in 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:51 | devth | so how is sending an Atom any better than sending a primary key? |
| 18:52 | augustl | technomancy: I have, but thanks :) |
| 18:52 | devth | hiredman: i haven't seen that, no |
| 18:52 | augustl | devth: indeed, an atom is very much now |
| 18:52 | devth | maybe the point is: don't send atoms, send the value at some point in time. |
| 18:52 | horofox | TimMc: will do some research about it, thanks! |
| 18:52 | devth | send the Fact instead of the Container |
| 18:53 | augustl | devth: you very rarely pass atoms around, I think, it's typically a singleton somewhere (def ...) |
| 18:53 | technomancy | augustl: eval-in-project is more like eval. you have to build up a self-contained form to send to the project. |
| 18:53 | TimMc | horofox: Looking better. What happens if you ask for only n = 1? |
| 18:54 | horofox | TimMc: I get an error :| |
| 18:54 | TimMc | augustl: Or they are kept in a local scope. |
| 18:55 | horofox | TimMc: I can do a if condition and deal with this 1 or 0 behavior |
| 18:55 | horofox | TimMc: inside fib function |
| 18:55 | TimMc | Yep. |
| 18:55 | horofox | TimMc: I'm actually trying to solve proj euler problem where it's different |
| 18:56 | augustl | technomancy: makes sense, thanks |
| 18:56 | horofox | TimMc: i need the sum of all even numbers of the fib sequence where the last fib number is 4 million |
| 18:56 | horofox | TimMc: but got hooked into how I can implement fib |
| 18:59 | horofox | (take-last 1 [0 1]) |
| 18:59 | horofox | yields (1) |
| 18:59 | horofox | how do i take this item out of ()? |
| 18:59 | horofox | so it becomes 1 |
| 18:59 | horofox | instead of (1)? |
| 19:00 | TimMc | You'd call last instead of take-last. |
| 19:00 | horofox | TimMc: oh yea... i feel so dumb hehe |
| 19:01 | TimMc | If you didn't have that, you could call first on the '(1). |
| 19:02 | TimMc | If I were solving that Euler problem, I would probably write a Fibonacci lazy sequence and process it with take-while, filter, and reduce. |
| 19:03 | augustl | this updated lein plugin https://www.refheap.com/paste/5642 causes "Exception in thread "main" java.lang.ClassNotFoundException: leiningen.oiiku-closure-builder" O_o |
| 19:03 | augustl | any ideas..? |
| 19:03 | TimMc | Sorry, that was kind of spoiler-y. :-/ |
| 19:05 | TimMc | augustl: Probably has something to do with do-build not being available inside the project. |
| 19:05 | technomancy | TimMc is right; you need to build up a self-contained form that will evaluate inside the project |
| 19:05 | augustl | ah |
| 19:06 | horofox | TimMc: thanks man! I did the problem! I wouldn't do it if it weren't for you |
| 19:07 | horofox | TimMc: final solution: https://gist.github.com/3862014 |
| 19:08 | TimMc | horofox: OK, *now* try making a version that produces and consumes a lazy-seq of Fibonacci numbers. |
| 19:09 | kirindave_ | Ugh. Clojure, not a leading source of pretty fibbonaci impls. |
| 19:09 | kirindave_ | Not without lazy seq, at least. |
| 19:10 | kirindave_ | Guess my next blog post has gotta be, "The Most Epically Beautiful Fibbonacci" |
| 19:12 | amalloy | kirindave_: and you'll just steal the one from rosettacode, right? |
| 19:15 | augustl | so 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:15 | TimMc | horofox: Here's a version that does what I describe, which you may wish to inspect: https://gist.github.com/3862052 |
| 19:16 | augustl | adding it as a dependency sounds like a bad idea.. Just adding it to the classpath somehow would be nice |
| 19:16 | technomancy | augustl: not for a 3-line function; just send it as a form |
| 19:16 | kirindave_ | amalloy: Haha, I can do it from memory |
| 19:16 | augustl | technomancy: it's more than 3 lines though :) |
| 19:17 | kirindave_ | amalloy: It's like fibs = 0 : 1 : zipWith (+) fibs (tail fibs) -- DONE AND TAKE THAT |
| 19:17 | horofox | TimMc: very cool this take-while function |
| 19:18 | horofox | i have no idea what lazyseq means lol |
| 19:18 | kirindave_ | 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:18 | TimMc | horofox: It's a good one to know. |
| 19:18 | kirindave_ | amalloy: I think nearly every C programmer will write it the wrong way in the same way. |
| 19:18 | horofox | in my country people don't even teach lisp :-( |
| 19:18 | augustl | anyone 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:19 | AtKaaZ | hi, how can I do something like this? ##(for [x (range 10) :let [y 1/x] ] y) |
| 19:19 | AtKaaZ | ,(for [x (range 10) :let [y 1/x] ] y) |
| 19:19 | clojurebot | #<ExecutionException java.util.concurrent.ExecutionException: java.lang.NumberFormatException: Invalid number: 1/x> |
| 19:20 | thorbjornDX | AtKaaZ: :let [y (/ 1 x)] |
| 19:20 | TimMc | AtKaaZ: 1/x is infix notation, which is not how Lisps work. |
| 19:20 | AtKaaZ | oh right, so obvious, thank you |
| 19:20 | AtKaaZ | ,(for [x (range 10) :let [y (/ 1 x)] ] y) |
| 19:21 | clojurebot | #<ExecutionException java.util.concurrent.ExecutionException: java.lang.ArithmeticException: Divide by zero> |
| 19:21 | amalloy | kirindave_: (map first (iterate (fn [[a b]] [b (+ a b)]) [0 1])) in clojure, though. the haskell/scala version translates very poorly to clojure |
| 19:21 | thorbjornDX | AtKaaZ: it's somewhat weird in this case because clojure supports ratio literals |
| 19:21 | augustl | only 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:22 | AtKaaZ | thorbjornDX, do you mean 1/2 works but not when 2 is a variable ? |
| 19:22 | kirindave_ | amalloy: Did you enjoy my egregious fizzbuzz post? |
| 19:22 | AtKaaZ | ,(for [x (range 1 10) :let [y (/ 1 x)] ] y) |
| 19:22 | kirindave_ | amalloy: I'm still suffering fallout from it. |
| 19:22 | clojurebot | (1 1/2 1/3 1/4 1/5 ...) |
| 19:22 | amalloy | i don't think i've read it |
| 19:23 | AtKaaZ | thorbjornDX, would it work inside a macro maybe? |
| 19:23 | augustl | seems lein-midje does this, except it hardcodes the dependency |
| 19:23 | horofox | TimMc: isn't this fib implementation slow? Like... (take 5 (fib 1 1)) |
| 19:23 | horofox | calls fib 5 times? |
| 19:23 | augustl | s/dependency/dependency version/ |
| 19:24 | kirindave_ | amalloy: Ha. |
| 19:24 | TimMc | horofox: take doesn't call the second argument, it accepts the result of evaluating it. |
| 19:25 | thorbjornDX | AtKaaZ: yes, but I don't think that's a smart idea. |
| 19:25 | TimMc | AtKaaZ: No, because the reader is what's complaining. |
| 19:25 | kirindave_ | horofox: That is the sort of stuff we trust the JIT to inline. :) |
| 19:25 | AtKaaZ | yeah I see it's not working |
| 19:25 | horofox | kirindave_: oh |
| 19:26 | AtKaaZ | but still, that (/ 1 x) is quite enough |
| 19:26 | TimMc | AtKaaZ: Just be aware that (/ 1 x) gives you a Clojure Ratio, which can be slow to do math with. |
| 19:26 | kirindave_ | horofox: Seriously though. No one has any problem writing in Java: for(X x : xs) { x.thingABob() } |
| 19:27 | kirindave_ | horofox: It's the price of admission. :) |
| 19:27 | horofox | kirindave_: i see |
| 19:27 | AtKaaZ | timmc, 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:28 | TimMc | "Slower"? To do what with? |
| 19:28 | AtKaaZ | like if I wanted to generate numbers like I did in the above for |
| 19:29 | AtKaaZ | I'm only trying to realize if 1/x (if it worked) would've been faster than (/ 1 x) |
| 19:29 | AtKaaZ | hmm, doesn't seem so |
| 19:30 | AtKaaZ | ,(prn 1/1 (/ 1 1)) |
| 19:30 | clojurebot | 1 1 |
| 19:31 | AtKaaZ | timmc, I'm merely experimenting, in my attempts to learn clojure, but it's good to know that math-ing with ratios is slower |
| 19:36 | TimMc | AtKaaZ: Use (/ 1.0 x). |
| 19:37 | TimMc | You can't programmatically generate forms like 1/2 without using the Clojure reader, so don't. |
| 19:37 | AtKaaZ | but I wanted to keep them rational? |
| 19:37 | TimMc | (and you would still end up with a Ratio) |
| 19:37 | TimMc | Oh, then use (/ 1 x). |
| 19:38 | AtKaaZ | but it's still good to know how to make them Double |
| 19:38 | AtKaaZ | thanks;) |
| 19:42 | AtKaaZ | ,(-> (for [x (range 1 11) :let [y (/ 1.0 x)] ] y) first class) |
| 19:42 | clojurebot | java.lang.Double |
| 19:42 | AtKaaZ | i like this -> |
| 19:43 | AtKaaZ | or this: |
| 19:43 | AtKaaZ | ,(->> (for [x (range 1 11) :let [y (/ 1 x)] ] y) (map class) ) |
| 19:43 | clojurebot | (java.lang.Long clojure.lang.Ratio clojure.lang.Ratio clojure.lang.Ratio clojure.lang.Ratio ...) |
| 19:43 | AtKaaZ | it's freaking amazing |
| 19:56 | Roxxi | If you have a transient set, how can you treat it as a seq? |
| 19:56 | technomancy | IIRC transients are only for putting things in |
| 19:57 | augustl | Roxxi: you have to make it persistent |
| 19:57 | Roxxi | Right, but I'm looping over it, haha. |
| 19:57 | augustl | if by seq you mean persistent seq ;) |
| 19:57 | Roxxi | technomancy: If transients are only for putting things in, why is there disj! :) |
| 19:59 | amalloy | Roxxi: you can't treat a transient as a seq, because it can change at any time, invalidating the seq wrapped around it |
| 20:00 | amalloy | ie, seqs require something persistent to work with |
| 20:01 | technomancy | erhm... not that's not quite right |
| 20:01 | technomancy | you can seq an array |
| 20:01 | Roxxi | amalloy: Hmm, so it's ok to call persistent! on things, but continue using the operand to persistant as a transient later? |
| 20:02 | amalloy | technomancy: yes, and you get out a broken seq |
| 20:02 | technomancy | that is to say you can't treat a transient as a seq, but you could in theory wrap a seq around it |
| 20:02 | technomancy | amalloy: fsvo of broken. the seq is still immutable, it just doesn't reflect the contents of what it wraps forever. |
| 20:02 | technomancy | by the same logic line-seq is broken. |
| 20:02 | AtKaaZ | now that's clearler thanks |
| 20:03 | amalloy | &(let [a (into-array [1 2 3]), s (seq a)] (aset a 1 5) s) ;; technomancy, is this really what you mean? |
| 20:03 | lazybot | ⇒ (1 5 3) |
| 20:04 | technomancy | amalloy: sure? |
| 20:04 | amalloy | that seq is only immutable in the sense that once you realize an element it is fixed; but realizing it depends on mutable state |
| 20:04 | technomancy | of course. |
| 20:05 | technomancy | that's what seqs are; a snapshot of a traversal of a thing. |
| 20:05 | amalloy | but it's not a snapshot of a traversal: the seq can represent a state that the array was never in |
| 20:06 | technomancy | that's why I said a snapshot of a traversal, not a snapshot of a state |
| 20:07 | technomancy | if you have code that needs it to be otherwise, it's not the seq that's broken, it's the other code. |
| 20:07 | AtKaaZ | oh 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:10 | AtKaaZ | ,(class (seq (into-array [1 2 3]))) |
| 20:10 | clojurebot | clojure.lang.ArraySeq |
| 20:14 | AtKaaZ | how can I find all functions dealing with arrays? such as aset |
| 20:15 | aperiodic | AtKaaZ: http://clojure.org/cheatsheet |
| 20:15 | aperiodic | array stuff is in java interop at the bottom-right |
| 20:15 | AtKaaZ | yeah thanks a lot! great stuff |
| 21:04 | thmzlt | so is it a bad practice to define tests within source file using (with-test ...)? |
| 21:31 | xeqi | thmzlt: I haven't seen it done anywhere |
| 21:31 | thmzlt | xeqi: that's why I asked |
| 21:31 | xeqi | or setting *load-tests* to false, so I imagine doing that would run the tests for anyone using it (if its a library) |
| 21:37 | ynniv | is there no way to inherit defrecord fields? |
| 21:37 | ynniv | and if not, can I at least specify them with a variable instead of a form? |
| 21:39 | tomoj | no |
| 21:39 | tomoj | you could use a macro |
| 22:01 | ynniv | i guess that works |
| 22:07 | amalloy | it'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:09 | ynniv | it would be nice to have inheritance in defrecord |
| 22:09 | AtKaaZ | what do you mean by "but keep using it all over clojure.lang" in the java code ? |
| 22:09 | ynniv | I'd really be okay if I didn't have to write my own macro to fake it |
| 22:10 | brehaut | yes the javacode |
| 22:10 | ynniv | it seems odd that you can't pass a list of fields to defrecord |
| 22:10 | AtKaaZ | you can't? |
| 22:11 | ynniv | it appears that the fields are taken as a form |
| 22:12 | ynniv | i wrote this to expand the variable before defrecord is expanded: https://gist.github.com/3862734 |
| 22:14 | AtKaaZ | hmm there is no [org.clojure/clojure "1.5.0"] in project.clj with leiningen... only 1.4.0 |
| 22:15 | tomoj | ynniv: why do you want inheritance? |
| 22:15 | ynniv | i have two record types that have a long list of fields that aren't exactly the same |
| 22:15 | ynniv | and I'm trying to de-duplicate |
| 22:15 | AtKaaZ | I'd probably want the same thing |
| 22:16 | tomoj | but why do you have two record types with a long list of almost identical fields? |
| 22:16 | amalloy | ynniv: you probably just want plain old hashmaps |
| 22:16 | tomoj | er, you know what I mean |
| 22:16 | ynniv | to store data? |
| 22:16 | ynniv | i mean, philosophically, there are are things that need to be stored which are very similar but not the same |
| 22:17 | ynniv | do 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:18 | ynniv | i could use maps, but I would like better type checking |
| 22:18 | ynniv | as in, i didn't type the wrong field name |
| 22:18 | ynniv | records give me compile time sanity checking |
| 22:18 | brehaut | records dont give you type checking |
| 22:19 | ynniv | they create multimethods that won't exist if I type them wrong |
| 22:19 | ynniv | which is a step up from keywords |
| 22:19 | thmzlt | brehaut: hey give you type-based polymorphism |
| 22:19 | thmzlt | *they |
| 22:19 | ynniv | they also do that |
| 22:19 | brehaut | thmzlt: thats wildly different than type checking |
| 22:20 | tomoj | also, (assoc a-record :a-typo foo) will still succeed |
| 22:20 | thmzlt | brehaut: agreed, but I think that's what ynniv meant |
| 22:22 | ynniv | does defrecord not provide field accessors? |
| 22:22 | ynniv | i guess i'm carrying some common lisp baggage |
| 22:23 | brehaut | ynniv: you just use keywords |
| 22:23 | brehaut | though there are field accessor methods thats not idiomatic |
| 22:23 | ynniv | hrm, not as helpful |
| 22:23 | brehaut | (and potentially slower) |
| 22:23 | thmzlt | ynniv: but defrecord doesn't work as function |
| 22:23 | ynniv | thmzlt: not sure what you mean |
| 22:23 | thmzlt | ynniv: (a-record :field) doesn't work |
| 22:24 | brehaut | thmzlt: (:field a-record) |
| 22:24 | ynniv | but (:field a-record) still does, correct? |
| 22:24 | thmzlt | ynniv: correct |
| 22:25 | ynniv | i suppose that I need to create vars for my field names to prevent typos? |
| 22:25 | brehaut | that would not be especially idiomatic code |
| 22:25 | brehaut | but i guess it would work |
| 22:26 | ynniv | well, there's nothing to prevent someone else from calling my code with a keyword |
| 22:26 | ynniv | but this would limit some of the madness |
| 22:26 | brehaut | yup |
| 22:26 | ynniv | or I could also generate accessors |
| 22:26 | hiredman | ynniv: you should also wear body armor all the time |
| 22:26 | brehaut | ideally though you create functions for manipulating your records, so that the implementation doesnt bleed out |
| 22:27 | hiredman | ynniv: you never know |
| 22:27 | ynniv | hiredman: sometimes a good idea! |
| 22:27 | brehaut | and look to a future where typed clojure is reasonable to deploy |
| 22:30 | ynniv | brehaut: i thought that defrecord generated field accessor/modifiers (like CLOS), which is how I ended up here |
| 22:31 | brehaut | ynniv: it does do that, but you generally dont want to use it |
| 22:32 | brehaut | keywords use an inline cache at the callsite to optimize acccess, and the method form may go via reflection |
| 22:32 | ynniv | ah, it makes accessors in Java? |
| 22:33 | brehaut | yes, of course |
| 22:41 | AtKaaZ | is it PLOP when a ref changes? or is it too silly to ask? PLace Oriented Programming |
| 22:46 | amalloy | IMO 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:47 | gfredericks | you'd have to orient your code around the place? |
| 22:52 | AtKaaZ | watching this: https://www.youtube.com/watch?v=-6BsiVyC1kM&t=4m10s "anytime new information replaces old information you're doing PLOP" |
| 22:52 | AtKaaZ | gfredericks, not really understanding what you ask |
| 22:53 | gfredericks | I was just failing to be clever |
| 22:53 | AtKaaZ | lol I think I read that litterally once and I smiled:P |
| 22:54 | AtKaaZ | but there may be some truth in it |
| 22:54 | tomoj | what's the proposed alternative to PLOP again? VOP? |
| 22:55 | AtKaaZ | multiversion control:) |
| 22:55 | AtKaaZ | imutability ? |
| 22:56 | AtKaaZ | I 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:57 | brehaut | AtKaaZ: sounds like 99% of every IRC channel ever |
| 22:58 | AtKaaZ | amalloy seems right, maybe unless that ref becomes data like I dno, a tree made of refs, refs to refs |
| 22:58 | gfredericks | AtKaaZ: 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:03 | AtKaaZ | can 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:03 | Sgeo | place oriented programming? Anything to do with Common Lisp places, setf etc? |
| 23:03 | AtKaaZ | Sgeo, like updating the same place in a database to replace the old info with new |
| 23:04 | AtKaaZ | so PLOP would be a relational database, and VOP(?) would be datomic |
| 23:05 | AtKaaZ | (not restricted to databases though, like PLOP is OO and VOP is clojure) |
| 23:05 | ynniv | it's only PLOP if you overwrite the old value |
| 23:06 | ynniv | you can organize your db to only add new versions |
| 23:06 | AtKaaZ | so it would act like a mvcc database of sorts? |
| 23:08 | ynniv | not sure what that means |
| 23:08 | AtKaaZ | my 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:09 | AtKaaZ | ynniv, I got what you meant, not sure if it would indeed act like a mvcc multiversioned database as I said |
| 23:09 | ynniv | I'm not familiar with datomic yet, but I often think how nice it would be to use git as a database |
| 23:09 | scottj | AtKaaZ: not sure what you mean by "at any level", but with datomic you can to db.asOf(aDate) I believe |
| 23:10 | AtKaaZ | scottj, 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:14 | AtKaaZ | ynniv, yeah I thought about that too, I definitely need some kind of git-like database esp. the branching then merging them |
| 23:20 | lancepantz | AtKaaZ: you still there? |
| 23:20 | AtKaaZ | yes |
| 23:20 | AtKaaZ | i was thinking of a question, in clojure how do you do two threads incrementing the same counter ? |
| 23:20 | lancepantz | AtKaaZ: https://github.com/flatland/jiraph |
| 23:20 | AtKaaZ | with dosync? |
| 23:21 | AtKaaZ | lancepantz thanks I'll check |
| 23:21 | lancepantz | we've been working on it for about 3 years and have it in production |
| 23:21 | lancepantz | it's very actively maintained |
| 23:21 | lancepantz | and faster than neo4j |
| 23:21 | AtKaaZ | sounds good! |
| 23:26 | gfredericks | AtKaaZ: two threads incrementing the same counter can be just an atom |
| 23:26 | TimMc | AtKaaZ: Just one counter? Try an atom. |
| 23:26 | TimMc | bah |
| 23:27 | TimMc | You even won on my screen. I can't claim IRC relativity. |
| 23:27 | gfredericks | oh is it relative? that's good to know for future gloating |
| 23:27 | thmzlt | so I want to dispatch a method based on the first argument type (string vs. map), hints? |
| 23:27 | gfredericks | multimethods or protocols |
| 23:28 | TimMc | gfredericks: Larger IRC servers are distributed as a bunch of nodes connected by a spanning tree. |
| 23:28 | AtKaaZ | nice, atoms, STM of clojure good stuff |
| 23:28 | TimMc | hence netsplits |
| 23:28 | gfredericks | TimMc: yeah; it makes sense |
| 23:28 | gfredericks | there could be an eventual consistent ordering |
| 23:29 | gfredericks | but that would cause weird visual effects |
| 23:29 | TimMc | There could be, but there isn't. |
| 23:29 | TimMc | Instead, each client just accepts the ordering of messages that it gets. |
| 23:29 | gfredericks | why aren't there git-based chat protocols yet? |
| 23:29 | TimMc | "Dude, I can't hear you -- accept my pull request first." |
| 23:30 | AtKaaZ | datomic might be like git but without the ability to do branches, I might be wrong, gotta learn datomic |
| 23:30 | gfredericks | AtKaaZ: you can do "local branches" |
| 23:30 | ynniv | thmzlt: (defmulti f-name type)? |
| 23:30 | gfredericks | but only one "master" I think |
| 23:31 | ynniv | thmzlt: (defmethod asdf (type {}) [x] 'map) |
| 23:31 | gfredericks | AtKaaZ: where by "local" I mean like temporary in-memory sort of thing |
| 23:31 | AtKaaZ | gfredericks, 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:32 | gfredericks | ynniv: might want IPersistentMap instead of (type {}) |
| 23:32 | AtKaaZ | this new/extra data |
| 23:32 | gfredericks | AtKaaZ: yep |
| 23:32 | ynniv | depends |
| 23:32 | thmzlt | I'm trying to figure out the multimethod syntax |
| 23:32 | ynniv | maybe there's a string that implements IPersistentMap :-) |
| 23:32 | gfredericks | ,(map type [{} (zipmap (range 1000) (range 1000))]) |
| 23:33 | clojurebot | (clojure.lang.PersistentArrayMap clojure.lang.PersistentHashMap) |
| 23:33 | gfredericks | ynniv: ^ surprises there |
| 23:33 | ynniv | ah, good call |
| 23:33 | ynniv | (type {}) isn't stable |
| 23:34 | ynniv | that's why I wear my noob hat |
| 23:34 | ynniv | hmm, it seems that I have forgotten to wear my noob hat. well, beware! |
| 23:36 | scottj | ,(meta ynniv) |
| 23:36 | clojurebot | #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: ynniv in this context, compiling:(NO_SOURCE_PATH:0)> |
| 23:37 | AtKaaZ | if I ever want to use the value of the atom before modifying it, do I have to dosync instead ? |
| 23:37 | AtKaaZ | assuming 2 threads or so |
| 23:38 | gfredericks | AtKaaZ: no |
| 23:38 | gfredericks | if you want the new value based on the old one, then do it all inside your swap function |
| 23:39 | AtKaaZ | but if I want to use its value to compute something else, twice |
| 23:39 | AtKaaZ | and then increment it let's say |
| 23:40 | gfredericks | for tricksy things like that you can make a more complex atom, e.g. a map with :current-value and :last-value |
| 23:40 | AtKaaZ | say I do two calls where each takes 3 seconds, and each gets passed the value or the atom |
| 23:40 | gfredericks | make sure the swaps do the right thing, and then you can read the old value after the swap |
| 23:41 | AtKaaZ | I'm kind concerned if the other thread can increment the atom between those 2 calls which each takes 3 seconds :) |
| 23:41 | gfredericks | well only one of them will succeed and the other will retry |
| 23:41 | AtKaaZ | but if I use a dosync block around those 2 calls it will block right? |
| 23:41 | gfredericks | what is taking 3 seconds? |
| 23:42 | AtKaaZ | like if in one thread I do two calls and pass that atom, and when these are done then I increment the atom |
| 23:42 | gfredericks | I'm not sure what you mean by "calls" here |
| 23:42 | gfredericks | what are you storing in an atom? |
| 23:42 | AtKaaZ | but 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:42 | AtKaaZ | it's kinda hypothetical, but it's a counter |
| 23:43 | AtKaaZ | 2 threads supposedly increment it by 1 |
| 23:43 | AtKaaZ | but 1 thread is slow |
| 23:44 | TimMc | AtKaaZ: dosync doesn't know anything about atoms, and vice versa |
| 23:44 | TimMc | it only coordinates refs, and delays sends to agents |
| 23:44 | AtKaaZ | timmc, I ref then? |
| 23:44 | gfredericks | AtKaaZ: generally you assume that reference types are being updated behind your back |
| 23:44 | AtKaaZ | timmc, I figure maybe in this case I'd have to use dosync, that's mainly what I'm asking |
| 23:44 | gfredericks | if there's some reason you don't want that to happen then I feel like you might be using them wrong |
| 23:45 | AtKaaZ | I do assume that that ref to counter would be updated behind my back between those two calls |
| 23:45 | gfredericks | so what's the problem? |
| 23:45 | AtKaaZ | but then if those 2 calls are within a dosync, they would always see the same counter value? |
| 23:45 | gfredericks | yes but you're holding up other threads |
| 23:46 | AtKaaZ | is there any way to maybe do that without the holding? |
| 23:46 | gfredericks | without getting more concrete I really don't understand the motivation |
| 23:46 | AtKaaZ | hmm... get the value before the calls? |
| 23:46 | AtKaaZ | yeah you're right |
| 23:47 | gfredericks | you can read the atom initially and pass that value in with the atom? |
| 23:47 | AtKaaZ | I 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:48 | gfredericks | why do the two calls need to have the same basis? |
| 23:48 | AtKaaZ | I mean, if I want whatever those long calls are doing to be in sync with the counter |
| 23:48 | AtKaaZ | not sure, but I feel that I may want that hmm |
| 23:49 | AtKaaZ | like maybe they are doing some datomic transactions using that counter |
| 23:49 | wingy | since 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:49 | wingy | prefer? |
| 23:49 | AtKaaZ | one level keys? |
| 23:50 | gfredericks | AtKaaZ: I give up |
| 23:50 | wingy | AtKaaZ: see the example |
| 23:50 | AtKaaZ | gfredericks, thank you though |
| 23:51 | wingy | any input? |
| 23:52 | AtKaaZ | wingy, I'd prefer the latter, because it seems extensible, tree-like; but that's just me |
| 23:52 | wingy | AtKaaZ: the former looks more treelike :) |
| 23:53 | AtKaaZ | maybe I'm missing something, but the latter :address seems to have an inner {} |
| 23:53 | wingy | oh yeah |
| 23:53 | wingy | i thought the latter was the former :) |
| 23:53 | AtKaaZ | so, in your OP the former is compatible ? |
| 23:53 | AtKaaZ | with datomic |
| 23:54 | wingy | OP? |
| 23:54 | clojurebot | optimizing is http://clojure.org/java_interop#optimization |
| 23:54 | AtKaaZ | original post=) |
| 23:54 | wingy | yeah the former is compatible |
| 23:54 | AtKaaZ | yeah it makes sense |
| 23:54 | wingy | since you have to declare the keys in advance in the schema |
| 23:54 | AtKaaZ | so you'd have to say that :address is a map ? |
| 23:54 | wingy | in a post they said they would make the latter work as well .. but it wont be indexable/searchable though |
| 23:55 | AtKaaZ | yeah I was afraid of that |
| 23:55 | wingy | there is no map type atm |
| 23:55 | wingy | but then why have namespaced keys if we dont use them :) |
| 23:55 | wingy | i kinda like flat struture in a way :) |
| 23:56 | AtKaaZ | wish it was more tree-like |
| 23:56 | wingy | yeah hope they will support it fully |
| 23:56 | AtKaaZ | maybe 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:56 | AtKaaZ | this way, you can have tree-like =) |
| 23:57 | AtKaaZ | didn't fully consider the implications of this though |
| 23:57 | wingy | great idea |
| 23:57 | wingy | why didn't i think about this :) |
| 23:57 | AtKaaZ | you got lost into details:) I always do that |
| 23:58 | wingy | yeah, nested vs namespaced keys :) |