2012-10-26
| 00:00 | egghead | ;) |
| 00:00 | Sgeo | Heard of it, didn't pay much attention |
| 00:00 | ynniv | Sgeo: that's what we all want... |
| 00:01 | egghead | Sgeo: they have optional types and mirror-based reflection like strongtalk, but it's a browser thing... |
| 00:01 | Sgeo | I've heaerd of them in the context of Newspeak |
| 00:06 | bfabry | *sigh* nope, lein trampoline repl still gives me a repl that doesn't reload when I tell itto |
| 00:21 | amalloy | i think ynniv missed my point, which was that *especially* if your codebase is mostly correct, any rate of false positives will lead you to get more false positives than true positives |
| 00:55 | uroborus_labs | Does anyone know of a good example of using a jquery plugin with clojurescript? |
| 00:56 | uroborus_labs | I seem to be having trouble mostly with the externs I think... |
| 01:44 | tomoj | standard java.util.concurrent.Future behavior seems to be that .cancel permamently breaks the Future |
| 01:45 | tomoj | shouldn't we get something better for clojure? |
| 01:54 | antares_ | tomoj: what should .cancel do in your opinion? |
| 01:58 | uroborus_labs | Is there a dedicated clojurescript channel? |
| 01:59 | ivan | uroborus_labs: yes but nobody uses it |
| 01:59 | uroborus_labs | Yeah noticed that... |
| 01:59 | uroborus_labs | I have having a lot of trouble getting externs to work with it |
| 01:59 | ivan | nobody uses the channel, that is |
| 02:01 | ivan | uroborus_labs: did you add some :externs to your project.clj for lein-cljsbuild? |
| 02:02 | uroborus_labs | Yup |
| 02:02 | ivan | have you written working externs before? |
| 02:02 | uroborus_labs | I placed the file in resources/externs/myexternfile.js |
| 02:02 | uroborus_labs | Nope |
| 02:02 | uroborus_labs | Does cljsbuild auto scan for changes in project.clj? |
| 02:03 | ivan | I have no idea, I'm only familiar with the vanilla Closure Library toolchain |
| 02:03 | uroborus_labs | ahh ok |
| 02:04 | dnolen | uroborus_labs: have you seen http://lukevanderhart.com/2011/09/30/using-javascript-and-clojurescript.html? |
| 02:04 | dnolen | uroborus_labs: also you should look at how jayq does it. |
| 02:05 | uroborus_labs | Yeah I read that and scaned the jayq source code |
| 02:05 | uroborus_labs | Multiple times |
| 02:05 | uroborus_labs | lol |
| 02:05 | ivan | how do you know your extern isn't working? are you seeing renamed properties in the compiled code? |
| 02:06 | uroborus_labs | Yes |
| 02:06 | dnolen | uroborus_labs: there's also a thread about that on the Clojure ML right now |
| 02:10 | uroborus_labs | ivan: Thanks for the release-notes link. Doing some digging now about the auto extern loading |
| 02:25 | Momol | hi there |
| 02:26 | Momol | is anyone progamming in clojure uses a BSD system ? |
| 02:58 | uroborus_labs | Good lord, 3 hours of BS bug finding on why I was not doing externs correctly when the issue was somewhere in setting cljsbuild compilation from :advanced to :simple |
| 03:00 | uroborus_labs | I should say setting :optimizations |
| 03:00 | tomoj | you abandoned advanced? |
| 03:00 | uroborus_labs | Found this out through testing https://github.com/clojure/clojurescript/tree/master/samples/hello-js |
| 03:00 | uroborus_labs | The examples in the readme failed to work unless advanced was set |
| 03:00 | uroborus_labs | tomoj: Any idea why that would be? |
| 03:00 | uroborus_labs | Or anyone else for that matter? |
| 03:01 | uroborus_labs | I should say, the example while following the readme failed when :optimizations was set to :advanced |
| 03:02 | uroborus_labs | Setting it to :simple both allowed the example to work and fixed the issue I have been stuck on for many many hours. |
| 03:02 | uroborus_labs | Is this a bug? |
| 03:08 | amalloy | Momol: everyone on osx, right? |
| 03:09 | Momol | amalloy: was thinking about openbsd and freebsd |
| 03:09 | amalloy | ~anyone |
| 03:09 | clojurebot | Just a heads up, you're more likely to get some help if you ask the question you really want the answer to, instead of "does anyone ..." |
| 03:13 | Momol | I wanted to know if BSD are a good system for clojure developpment. Java is not popular on these systems so |
| 03:13 | Momol | for linux, you have libraries and all tools to develop quickly in clojure, but I have some doubt on *BSD. Maybe it is complex |
| 03:14 | tkoskine | OpenBSD ports/packages (on -current) have clojure and leiningen. |
| 03:16 | amalloy | the only thing you need is the jre, and a bash interpreter for leiningen |
| 03:17 | amalloy | famous last words maybe, but as far as i know that's all you need |
| 03:23 | Momol | amalloy: and jre isn't a prob on *BSD ? |
| 03:26 | tkoskine | Well, you could go and test it :). If there is a bug the jre maintainers on *BSDs would probably like to know about it. |
| 03:26 | tomoj | was the question about advanced and externs answered? |
| 03:34 | Sgeo | Hmm. |
| 03:35 | Sgeo | Can someone help me please? |
| 03:35 | shachaf | Sorry, Sgeo. |
| 03:35 | Sgeo | I need to know what the likely response would be if I asked, can someone help me please? |
| 03:36 | tomoj | anyone? |
| 03:36 | clojurebot | Just a heads up, you're more likely to get some help if you ask the question you really want the answer to, instead of "does anyone ..." |
| 03:36 | Sgeo | ....I fail at humor |
| 03:36 | tomoj | no, I do |
| 03:36 | shachaf | Nope, it's definitely Sgeo. |
| 03:36 | tomoj | :) |
| 03:36 | Sgeo | I think shachaf is likely to poke fun at me in any event. |
| 03:38 | Sgeo | Which is good, because I like collecting fun, and every planck time of every planck length is an event. |
| 04:02 | tomoj | hmmm https://gist.github.com/32b0838b3d1f6322a10b |
| 04:04 | tomoj | &(next (reductions conj [] [1 2 3])) |
| 04:05 | lazybot | ⇒ ([1] [1 2] [1 2 3]) |
| 04:05 | tomoj | better way? |
| 04:06 | bosie | https://gist.github.com/3957533 why is my output empty? |
| 04:07 | tomoj | for? |
| 04:07 | clojurebot | for is not a loop |
| 04:07 | tomoj | lazy? |
| 04:07 | clojurebot | lazy is hiredman |
| 04:07 | tomoj | :( |
| 04:07 | tomoj | well |
| 04:08 | bosie | tomoj: not sure i understand you ;) |
| 04:08 | bosie | tomoj: because for is lazy, i wrapped it in take |
| 04:08 | tomoj | take is lazy too |
| 04:08 | bosie | dang |
| 04:08 | tomoj | (doseq [x [0 1 2 3] y [3 2 1 0] :while (< 0 x)] (println x y)) |
| 04:09 | bosie | tomoj: right but then i have to change my for loop |
| 04:09 | bosie | tomoj: wouldn't doall do what i want? |
| 04:10 | Sgeo | tomoj, doc is a macro |
| 04:11 | Sgeo | bosie, doall works if you want the results from the for |
| 04:11 | Sgeo | So yes |
| 04:11 | bosie | Sgeo: cheers |
| 04:12 | tomoj | Sgeo: that's not the problem |
| 04:13 | tomoj | bosie: I doubt you want all the nil return values of println |
| 04:13 | tomoj | you can use dorun |
| 04:13 | amalloy | he probably doesn't want the printing effect of println either. just use for and return a bunch of vectors |
| 04:13 | bosie | tomoj: good point |
| 04:14 | Sgeo | bosie, is that your exact code, or is it a substitute for ... hmm |
| 04:14 | Sgeo | Ah. I wasn't sure |
| 04:14 | bosie | Sgeo: exact code. i was just playing with for in the repl |
| 04:14 | Sgeo | Ah |
| 04:14 | Sgeo | Hmm, usually attempting to show a lazy-seq at the REPL forces the lazy-seq to be fully realized |
| 04:15 | Sgeo | Although of course a take would allow for only the realization of ... you get the point |
| 04:16 | bosie | Sgeo: yes, i overlooked that take is lazy too |
| 04:17 | Sgeo | And the fun thing is, by using take at the REPL like that, you actually prevented the entire lazy sequence from the for from being realized |
| 04:17 | bosie | fun isn't the word i would have used ;) |
| 04:19 | bosie | thanks |
| 04:21 | josteink | is there any shell-like command like ls to list out the members of a namespace? |
| 04:22 | tomoj | shell-like? you mean you want to use it from a shell? |
| 04:22 | tomoj | &(keys (ns-publics (find-ns 'clojure.repl))) |
| 04:22 | lazybot | java.lang.SecurityException: You tripped the alarm! ns-publics is bad! |
| 04:23 | josteink | tomoj: a repl often gives me the same feeling as a shell :) |
| 04:23 | josteink | lets see |
| 04:25 | josteink | cool |
| 04:26 | josteink | is there some function to call to get the name/symbol of the current repl namespace? |
| 04:26 | Sgeo | ,*ns* |
| 04:26 | clojurebot | #<Namespace sandbox> |
| 04:27 | josteink | oh |
| 04:27 | josteink | I see |
| 04:27 | josteink | thanks |
| 04:27 | Sgeo | ,(ns-name *ns*) |
| 04:27 | clojurebot | sandbox |
| 04:28 | Sgeo | ,(special-symbol? '*ns*) |
| 04:28 | clojurebot | false |
| 04:30 | tomoj | &(.name *ns*) |
| 04:30 | lazybot | java.lang.SecurityException: You tripped the alarm! class clojure.lang.Namespace is bad! |
| 04:30 | tomoj | :( |
| 04:30 | tomoj | I think namespaces should be Named |
| 04:30 | tomoj | oh |
| 04:30 | tomoj | ns-name |
| 04:31 | Sgeo | It just calls .getName |
| 04:31 | Sgeo | ,(.getName *ns*) |
| 04:31 | clojurebot | sandbox |
| 04:31 | josteink | now if I could find a way to quote that, I would actually have an automated ls command |
| 04:31 | Sgeo | ,(ns-name 'sandbox) |
| 04:31 | clojurebot | sandbox |
| 04:32 | Sgeo | quote? |
| 04:32 | clojurebot | quote is is unsyntax quote and ' |
| 04:32 | tomoj | :( |
| 04:32 | Sgeo | josteink, what do you mena? |
| 04:32 | Sgeo | mean |
| 04:32 | josteink | (ns-name *ns*) => user |
| 04:32 | josteink | I want 'suer |
| 04:32 | josteink | er |
| 04:32 | josteink | 'user |
| 04:33 | Sgeo | Without ' is how symbols typically print |
| 04:33 | Sgeo | Hmm |
| 04:33 | josteink | so that I can pass it to (keys (ns-publics (find-ns NS))) |
| 04:33 | josteink | lets test |
| 04:33 | Sgeo | ,(pr-str 'foo) |
| 04:33 | clojurebot | "foo" |
| 04:33 | Sgeo | ,*print-readably* |
| 04:33 | clojurebot | true |
| 04:33 | josteink | my bad |
| 04:33 | amalloy | josteink: i don't think you understand quoting yet. the value is the symbol user (which doesn't have any special decoration on it); you put the ' in to ask the compiler not to try to evaluate it |
| 04:33 | Sgeo | Somehow I don't think printing the symbol foo as foo is "readable" |
| 04:33 | josteink | (keys (ns-publics (find-ns (ns-name *ns*)))) actually print out things correctly |
| 04:34 | josteink | Sgeo: heh |
| 04:34 | amalloy | Sgeo: of course it is (let [f 'foo] (= f (read-string (pr-str f)))) |
| 04:34 | Sgeo | ,(read-string "foo") |
| 04:34 | clojurebot | foo |
| 04:35 | Sgeo | huh. |
| 04:35 | Sgeo | I have a feeling I'm derping a bit |
| 04:35 | Sgeo | josteink, I have to know why you're doing ns-name then find-ns |
| 04:35 | Sgeo | ,(doc find-ns) |
| 04:35 | clojurebot | "([sym]); Returns the namespace named by the symbol or nil if it doesn't exist." |
| 04:36 | Sgeo | They're approximately inverses |
| 04:36 | josteink | Sgeo: oh I see |
| 04:37 | josteink | agreed. this is much simpler |
| 04:37 | josteink | (defn ls [] (keys (ns-publics *ns*))) |
| 04:40 | Mr_Bond | hey josteink, where are you from? |
| 04:40 | Mr_Bond | Scandinavia? |
| 04:40 | josteink | norway |
| 04:40 | Mr_Bond | Same, kewl ;) |
| 04:41 | josteink | basically just thought it would be useful to have a "ls command" to investigate the namespaces Im in when running tutorials from git-repos |
| 04:41 | josteink | :) |
| 04:42 | josteink | you know, when the tutorial starts with "git clone", "lein repl" and "(load" |
| 04:54 | Mr_Bond | josteink: good idea! :) Clojure is fun, just started learning it my self. |
| 04:55 | Mr_Bond | Only thing that I find difficult, is pinpointing issues turning up in java backtrace |
| 04:55 | josteink | heh |
| 04:55 | tomoj | a hopefully soon-to-be-released library may help with that |
| 04:58 | Mr_Bond | tomoj: yeah, that would be very nice. Is there one on the roadmap? |
| 04:58 | Mr_Bond | I would still use clojure without one. |
| 05:00 | amalloy | tomoj's boundless optimism is an inspiration to us all |
| 05:00 | tomoj | http://www.infoq.com/presentations/Clojure-Stack-Trace |
| 05:04 | josteink | anyone know who runs infoq or what their primary target/aim is? |
| 05:05 | josteink | ive seen it mentioned quite a few times for programming related content and functional programming in paritcular |
| 05:09 | Raynes | josteink: http://www.infoq.com/about |
| 05:10 | josteink | well that was easy :) |
| 05:11 | Raynes | I liked Google currents when my phone had the space to use it. |
| 05:11 | Raynes | That thing sucks up disk like a vacuum cleaner. |
| 05:11 | josteink | heh |
| 05:12 | josteink | I have 6GBs space or so on my galaxy nexus |
| 05:12 | josteink | that should be gooxd enough :) |
| 05:12 | Raynes | I have about 10MB of space on my Evo. |
| 05:12 | josteink | evo.... |
| 05:12 | josteink | is that the carrier-mungled version of the galaxy s1? |
| 05:13 | Raynes | No idea. |
| 05:13 | Raynes | This is the old evo, anywyas. |
| 05:13 | Raynes | anyways* |
| 05:13 | josteink | ah. htc desire |
| 05:13 | Raynes | Not actually mine anymore. Giving it to my mother since I got an iPhone 5 today. |
| 05:13 | josteink | known for its infinitely insufficent storagecapacity |
| 05:13 | Raynes | No kidding. |
| 05:16 | kral | namaste |
| 06:18 | leoncamel | hey. As a newbie, I can def a variable, like this (def a 1). But, how can I *undefine* a ? |
| 06:18 | leoncamel | (def ^:dynamic a 1) |
| 06:19 | leoncamel | sorry, wrong window. :) |
| 06:19 | tomoj | (ns-unmap *ns* 'a) |
| 06:19 | leoncamel | tomoj: OK. cool. thansk. |
| 06:19 | shachaf | You can do that (it seems), but are you sure you want to? |
| 06:20 | tomoj | I understood "undefine" to mean "completely undo the effect of the def on the namespace" |
| 06:20 | tomoj | but I wonder about "make it appear as if the root is unbound" |
| 06:21 | leoncamel | What is the side-effect about (ns-unmap *ns* 'a) ? |
| 06:22 | tomoj | if you do that, evaluating 'a would cause "Unable to resolve symbol: a in this context" |
| 06:22 | tomoj | as if you had never evaluated '(def a 1) |
| 06:23 | leoncamel | I am newbie, just playing in my REPL. When I type "(def a 1)", a quick question just come to my mind: How can I undefine(or remove) symbol a from current environment. |
| 06:24 | tomoj | yes, that sounds like ns-unmap |
| 06:24 | tomoj | (doc ns-unmap) |
| 06:24 | clojurebot | "([ns sym]); Removes the mappings for the symbol from the namespace." |
| 06:24 | leoncamel | tomoj: OK. I got it. |
| 06:25 | tomoj | wow, datomic will not let you stick a long in a double field |
| 06:31 | bosie | tomoj: since you mentioned datomic, how is the "db is effectively local"? |
| 06:31 | tomoj | I like it so far |
| 06:32 | bosie | tomoj: in sql terms, it would query the entire dataset and process it locally? (e.g. apply a filter on it) |
| 06:32 | tomoj | not necessarily the entire index |
| 06:32 | tomoj | er, dataset |
| 06:32 | bosie | no but the entire 'table' |
| 06:32 | tomoj | well there are no tables |
| 06:32 | tomoj | but there are indices |
| 06:32 | bosie | right |
| 06:33 | tomoj | depending on how you write a query, it may not need to fetch much more than needed |
| 06:33 | bosie | tomoj: without processing on the server? |
| 06:34 | tomoj | if by "server" you mean the transactor, it only does writes |
| 06:34 | bosie | ok |
| 06:36 | tomoj | with the free version a peer has to talk to some processes the transactor starts to fetch data |
| 06:36 | bosie | wow |
| 06:36 | bosie | just saw the pricing for datomic pro |
| 06:36 | AtKaaZ | tomoj: what? |
| 06:36 | tomoj | what what |
| 06:37 | AtKaaZ | tomoj: on the free version the transactor fetches the data? ie. reads |
| 06:37 | tomoj | well, I don't understand the internals very well. the free transactor starts processes that listen on 3 ports. the peers have to talk to one or more of those to fetch data from the transactor-local storage |
| 06:38 | tomoj | I suspect one of them is an h2 sql db which the peer talks to, but I'm not sure |
| 06:38 | AtKaaZ | I don't know that many details, but I guess that could still mean that the transactor isn't used to read data ie. queries |
| 06:39 | tomoj | right, that seems likely |
| 06:39 | bosie | AtKaaZ: so if the transactor isn't reading the data, who is? |
| 06:39 | AtKaaZ | as I understand it the peers "talk" directly to the storage (so to speak) |
| 06:40 | tomoj | peers run queries, the transactor handles writes (and sometimes may run queries to service transactions..) |
| 06:40 | tomoj | in pro the transactor and peer machines don't have to communicate directly at all, they just both talk to postgres or dynamodb |
| 06:40 | AtKaaZ | tomoj: like the nested queries? those with d/entity |
| 06:41 | AtKaaZ | tomoj: I mean, when does transactor run queries? |
| 06:41 | tomoj | when a transaction function called in a transaction runs a query |
| 06:41 | bosie | AtKaaZ: http://www.datomic.com/uploads/3/5/9/7/3597326/6646785_orig.jpg |
| 06:42 | AtKaaZ | that makes sense |
| 06:42 | tomoj | like :db.fn/retractEntity probably runs a query to figure out what to retract? |
| 06:43 | tomoj | s/directly at all/directly at all (for queries)/ |
| 06:45 | AtKaaZ | bosie: that Cache you see in peer app server, is reads/queries done by peer (directly getting them from storage/memcached) as I understand it |
| 06:46 | bosie | AtKaaZ: hm, then the arrows are wrong i guess |
| 06:47 | AtKaaZ | bosie: the two arrows point to cache as in: reads from storage/memcached into cache |
| 06:47 | bosie | AtKaaZ: sorry, i misread you |
| 06:48 | AtKaaZ | query gets its data from liveindex+cache, where liveindex would be updated when trasactor did a write |
| 06:50 | AtKaaZ | tomoj: I wonder if a :db.fn with like Thread.sleep can hold the transactor |
| 06:51 | tomoj | I'd think so |
| 06:51 | tomoj | no reason to sleep I can think of |
| 06:51 | tomoj | nothing's going to be different when you wake up |
| 06:52 | AtKaaZ | but I'm just thinking if some evil function would take too long to compute |
| 06:52 | tomoj | yeah, dunno |
| 07:07 | bairui | tomoj: s/foo/foo bar/ == s/foo/& bar/ |
| 07:08 | tomoj | orly |
| 07:08 | bairui | in vim, anyway :) |
| 07:08 | tomoj | neat |
| 07:09 | tomoj | sed too |
| 07:09 | bairui | yep; sed: vim, I am your father. |
| 07:11 | bairui | well... grandfather? ancestor? |
| 07:11 | AtKaaZ | no no, leave it at that, it was funny;) |
| 07:12 | bairui | :) fair |
| 07:26 | Girvo | hey everyone |
| 07:27 | Girvo | q: is TDD viable in Lisp/Clojure? I'm working in a dialect called Pharen, quite inspired by clojure (compiles to PHP) and am used to TDD using classes. how does it work with just functions? |
| 07:31 | Girvo | any good resources for TDD in clojure? |
| 07:35 | Cheiron | Grivo: check speclj |
| 07:38 | Girvo | cheers @Cheiron |
| 07:39 | Cheiron | Grivo: and of course clojure.test , midje |
| 07:41 | JulioBarros | Hi. I'm coming back to a web app I have not touched in a long time. Had to resolve a couple of dependency issues but now am getting "Could not locate ring/util/serve__init.class" |
| 07:41 | JulioBarros | Any ideas on what could be causing it? |
| 08:01 | josteink | what's the difference between (ns somenamespace) and (in-ns 'somenamespace) ? |
| 08:02 | tomoj | (ns foo.bar) can do more, like (ns foo.bar (:require foo.baz)), and it also refers to clojure.core automatically |
| 08:04 | shachaf | Lenses are "pretty nifty". |
| 08:04 | shachaf | Do they have those in Clojure? |
| 08:04 | josteink | tomoj: ah ok. thanks |
| 08:05 | tomoj | I don't know |
| 08:05 | tomoj | are lenses anything like conal's semantic editor combinators? |
| 08:05 | tomoj | cgrand referenced lenses in a talk |
| 08:05 | josteink | google says "Lenses are the coalgebras for the costate comonad " |
| 08:05 | tomoj | but I only read the slides |
| 08:06 | josteink | lenses are coco |
| 08:06 | tomoj | and I think the conclusion was "that's too complicated for this task" |
| 08:06 | tomoj | http://vimeo.com/45695419 |
| 08:08 | shachaf | tomoj: Yep, they're related. |
| 08:08 | shachaf | A simple version of a lens is a (getter,setter) pair. |
| 08:08 | tomoj | I still don't understand semantic editors, but I feel vaguely like I want them in clojure |
| 08:09 | shachaf | They can be composed, which is the nice part. |
| 08:09 | shachaf | The new "lens" library for Haskell way generalizes them, of course. |
| 08:30 | antoineB | hello, i would like get the "first" element of a concurrent list, and update the list to "rest" |
| 08:30 | antoineB | should i use a ref or atom? |
| 08:32 | antoineB | (first @my-list) (swap! my-list rest) is unsafe between the two sexp |
| 08:32 | josteink | so ... you are creating a queue? :) |
| 08:33 | antoineB | yes |
| 08:33 | antoineB | FIFO |
| 08:34 | _ulises | antoineB: why do you say those two sexps are unsafe? |
| 08:35 | antoineB | the thread can stop at end of first sexp, and another can start at fist sexp |
| 08:36 | antoineB | the two thread will peek the same "first" element |
| 08:36 | _ulises | antoineB: I didn't know you were talking threads :) |
| 08:36 | _ulises | sorry for the silly question |
| 08:40 | josteink | _ulises: when you are talking "concurrent" you are talking about threads ;) |
| 08:40 | _ulises | josteink: I'll blame it on the lack of caffeine |
| 08:40 | josteink | heh |
| 08:40 | josteink | personally I usually blame that I mostly ready the bottom 5 lines, not a 2 page backlog :P |
| 08:41 | _ulises | what backlog? |
| 08:42 | josteink | http://invalid.ed.ntnu.no/~jostein/uploads/irc_backlog.png |
| 08:42 | josteink | whatever has passed out of the screen |
| 08:42 | josteink | :) |
| 08:43 | _ulises | 1) I can see myself 2) I meant "what backlog" in a "I don't read the backlog at all" kind of way |
| 08:44 | _ulises | ;) |
| 08:44 | josteink | ah |
| 08:44 | josteink | heh |
| 08:44 | antoineB | josteink: you can ignore connection/deconnection of user in irssi |
| 08:45 | antoineB | to get it more clear |
| 08:45 | josteink | antoineB: considering it. Im no longer a channel-op in busy, troll-ridden channels |
| 08:46 | josteink | so to quickly be able to spot a bad host is no longer that important ;) |
| 08:50 | josteink | /ignore -channels #clojure,#scheme,#linux * JOINS PARTS QUITS NICKS" |
| 08:51 | josteink | there we go :) |
| 08:51 | AntelopeSalad | i have a question, sort of... i've been reading through the clojure programming book and recently watched a video tutorial from one of the authors |
| 08:51 | antoineB | nobody answer my question |
| 08:51 | AntelopeSalad | he built a url shortener using compojure and ring |
| 08:51 | AntelopeSalad | my question is, everyone claims clojure is great because everything is immutable |
| 08:51 | AntelopeSalad | but right off the bat he setup mutable variables |
| 08:51 | Mr_Bond | wow, your in both clojure and scheme. Isn't that a bit mongamist? :P |
| 08:51 | josteink | antoineB: Im not competent enough to answer it. I would have cheated and just faceded a java concurrentqueue :) |
| 08:52 | Mr_Bond | monogamist.. |
| 08:52 | AntelopeSalad | what's the point in boasting about immutable data structures if you're just doing to use the function that makes things mutable? |
| 08:52 | AntelopeSalad | *doing = going |
| 08:52 | _ulises | antoineB: what operations are you trying to implement on the queue? peek or pop? |
| 08:52 | josteink | AntelopeSalad: well.. you probably need a sequence-number generatator |
| 08:52 | antoineB | pop |
| 08:52 | josteink | AntelopeSalad: that function will probably need some mutable data |
| 08:53 | antoineB | but a concurrent pop |
| 08:53 | AntelopeSalad | josteink: he uses an atom on some counter and also made a mutable map |
| 08:53 | _ulises | antoineB: so pop returns (first...) and updates to (rest...) right? |
| 08:53 | ambrosebs | Can someone please point me to a library that can call private Java methods/access Java fields? |
| 08:53 | josteink | AntelopeSalad: ah well. havent seen the video. cant tell if the guy does stupid things or not :) |
| 08:53 | antoineB | yes |
| 08:53 | cemerick | AntelopeSalad: Using an atom (or other reference type) does not make the data structures it holds mutable; rather, it provides a stable identity that does change over time. |
| 08:53 | ambrosebs | Is it in contrib? |
| 08:53 | antoineB | and i can't do the two in swap! or reset |
| 08:53 | AntelopeSalad | josteink: he's the co-author of the clojure programming book, he can't be that stupid |
| 08:54 | josteink | heh |
| 08:54 | _ulises | antoineB: why not? (please excuse me if it's a silly question) |
| 08:54 | cemerick | AntelopeSalad: We discuss this in chapter 4 |
| 08:54 | AntelopeSalad | i didn't get to chapter 4 yet in the book, i did a lot of reading in the past 2 days and then wanted to watch a video tutorial |
| 08:55 | _ulises | antoineB: I think I get why you can't |
| 08:55 | _ulises | get it* |
| 08:55 | AntelopeSalad | cemerick: you were the video author right? |
| 08:55 | _ulises | not my day today obviously |
| 08:55 | AntelopeSalad | i vaguely remember the name in the slide |
| 08:55 | cemerick | AntelopeSalad: FWIW, yeah |
| 08:56 | AntelopeSalad | your book is really good btw |
| 08:56 | AntelopeSalad | i was just curious if a lot of web oriented clojure apps end up having a ton of mutable data (or things that act like they are mutable) |
| 08:56 | AntelopeSalad | is there no real downside to using atom? it seemed handy in that counter use case |
| 08:57 | cemerick | AntelopeSalad: Having a single identity is hardly a "ton", compared to typical imperative programming environments. |
| 08:57 | cemerick | In the URL shortener example, it's just a convenient stand-in for an external database. |
| 08:57 | antoineB | _ulises: swap! and reset update the atom with the return of the function |
| 08:58 | _ulises | antoineB: yeah, I realised that after I asked you the question :( |
| 08:58 | AntelopeSalad | ah, i see. so normally you would be getting a count of entries from a db |
| 08:59 | tomoj | is it possible that .take on a LinkedBlockingQueue never returns, while the queue fills up with items? |
| 08:59 | AntelopeSalad | cemerick: btw, do you have any other video tutorials floating around? i didn't see anymore in your channel |
| 09:00 | tomoj | hmm |
| 09:00 | tomoj | I switched to openjdk and the problem seemed to go away |
| 09:00 | tomoj | not sure if that was voodoo |
| 09:01 | cemerick | AntelopeSalad: I've done a couple, but they're not on youtube. |
| 09:01 | cemerick | Nothing as comprehensive, though. |
| 09:02 | AntelopeSalad | ok |
| 09:05 | AntelopeSalad | cemerick: can you post the links to them? even if they touch on some subjects in the book it wouldn't hurt to watch them |
| 09:07 | Kototama | Hi, I know about checkouts but is there a way with leiningen to run lein clean / lein deps / lein install for 4 differents projects at once? |
| 09:08 | TimMc | Kototama: With shell scripting, yes. |
| 09:08 | cemerick | AntelopeSalad: old, old, old: http://cemerick.com/2010/11/02/continuous-deployment-of-clojure-web-applications/ http://cemerick.com/2010/03/25/why-using-maven-for-clojure-builds-is-a-no-brainer/ |
| 09:08 | cemerick | The maven one in particular is quite irrelevant at this point. |
| 09:09 | AntelopeSalad | ah, yeah you explained that lein is its successor |
| 09:09 | TimMc | Kototama: for p in repos/foo repos/bar repos/etc ; do (cd -- "$p"; lein clean deps install); done |
| 09:09 | antoineB | _ulises: i used ref |
| 09:10 | _ulises | antoineB: I was going to say that that's what you probably want if you want blocking reads, etc. |
| 09:10 | TimMc | And once I get to work, I'll be able to paste a little modification that makes that for loop stop if any of those repos fails to build. |
| 09:10 | _ulises | antoineB: care to share the code? :) |
| 09:11 | antoineB | is not realy usefull because is not a generic queue |
| 09:11 | antoineB | https://gist.github.com/3958679 |
| 09:11 | Kototama | TimMc: I need something platform independent |
| 09:11 | Kototama | I'm trying to get rid of our shell scripts |
| 09:14 | TimMc | Write it in Python then. |
| 09:15 | TimMc | Python is great for cross-platform automation. |
| 09:15 | Kototama | i don't want windows developpers to have to install python to develop on a clojure project |
| 09:15 | TimMc | Do they have Cygwin? |
| 09:15 | Kototama | nope |
| 09:15 | antoineB | jscript ? |
| 09:16 | Kototama | yeah jscript lol but then I need to main two different set of build script |
| 09:16 | Kototama | maintain |
| 09:16 | TimMc | What's wrong with installing Python? |
| 09:16 | antoineB | never touch jscript |
| 09:16 | antoineB | TimMc: "installing" maybe |
| 09:17 | TimMc | Maven |
| 09:17 | antoineB | Kototama: build a new clojure dsl, one for jscript and one for bash ? :) |
| 09:17 | Kototama | "please install java, leiningen, git" and also python but just two runs two shell commands thanks |
| 09:18 | Kototama | i think i'll create a lein plugin that go up one directory and launch the same commadn in the other if it's possible :p |
| 09:18 | TimMc | Kototama: I think there's a lein plugin to develop multiple projects in the same tree. |
| 09:19 | Kototama | but which one? I found https://github.com/maravillas/lein-multi but it's not what i'm looking for, nor checkouts directory solve the problem |
| 09:19 | TimMc | lein itself uses something... |
| 09:19 | Kototama | i'm not even sure they work on windows, can you create a symlink on windows? |
| 09:19 | TimMc | Not really. |
| 09:20 | TimMc | NTFS has some weird shit that I don't know about, though... |
| 09:20 | TimMc | Maybe just have a "parent" (outer) project with a lein hook that distributes the commands in order to the various "subprojects"... |
| 09:22 | TimMc | Kototama: If you can write the same thing in Windows batch scripting, just have two scripts. |
| 09:22 | TimMc | That's not an uncommon or unreasonable thing to do. |
| 09:22 | Kototama | how do hooks work? |
| 09:23 | TimMc | I don't recall, but I've used one... let me check. |
| 09:23 | josteink | Kototama: you can create symlinks on windows with NTFS. Its just that the OS provides no tools for it ;) |
| 09:23 | Kototama | or I use the lein exec plugin and write a clojure script that do the 4 lein commands :D |
| 09:24 | josteink | the filesystem itself supports it fully |
| 09:24 | josteink | well screw me sideways |
| 09:24 | josteink | http://pastebin.com/N0XDinvC |
| 09:24 | josteink | there you go :) |
| 09:25 | Kototama | ahhhhh maybe https://github.com/kumarshantanu/lein-sub |
| 09:25 | TimMc | josteink: Cool! |
| 09:25 | Kototama | josteink: not so bad :-) |
| 09:25 | Kototama | it does not solve the install problem though |
| 09:26 | TimMc | It doesn't? |
| 09:26 | Kototama | no checkouts is more to augment the classpath than anything else |
| 09:26 | TimMc | Oh, you mean checkouts, not lein-sub. |
| 09:26 | Kototama | yep |
| 09:27 | Kototama | i'm trying lein sub write know... we will see... |
| 09:31 | Kototama | lol the cljsbuild hook get applied to all projects ;-( |
| 09:34 | Kototama | but otherwise it seems to work, this is really great |
| 09:37 | clgv | tools.logging: does not really give me correct line numbers within a namespace although I use the convenience macros. whats wrong there? |
| 09:39 | Kototama | with profiles I can discriminate with project needs to be build a war or not, everything fine. |
| 10:40 | tomoj | crazy to find me asking a question hours ago on the second page of related google results |
| 10:41 | clgv | tomoj: it's a pretty unique question then? |
| 10:42 | tomoj | not really |
| 10:42 | tomoj | "LinkedBlockingQueue clojure seq" oslt |
| 10:42 | clgv | what do you want to know? |
| 10:43 | clgv | happens that I currently have the LinkedBlockingQueue javadoc open ;) |
| 10:44 | tomoj | I just want a seq from it |
| 10:45 | clgv | with or without blocking? |
| 10:45 | tomoj | blocking, of course |
| 10:45 | clgv | just do (repeatedly #(.take lbq)) |
| 10:46 | ejackson | tomoj: I've used cgrand's code for this to great effect: http://clj-me.cgrand.net/2010/04/02/pipe-dreams-are-not-necessarily-made-of-promises/ |
| 10:46 | tomoj | yeah I saw that, and based this on it |
| 10:46 | clgv | ejackson: tomoj: he added a close-fn that put's an EOF in it. |
| 10:46 | tomoj | https://gist.github.com/d5207c5a5074af29b4ac |
| 10:47 | tomoj | rich is producing, not me, so don't need that |
| 10:47 | ejackson | rightio |
| 10:48 | clgv | tomoj: ok then you could just use (repeatedly #(.take lbq)) |
| 10:48 | clgv | tomoj: that gist is only more verbose |
| 10:48 | tomoj | ah! |
| 10:48 | tomoj | I felt there must have been a better way |
| 11:25 | ToBeReplaced | first time using lein midje; when i do lein midje, i show my failures, then Subprocess failed before I get to any lein test summary.... lein test has no issues... anyone have any guesses where to look? Leiningen 2.0.0-preview10 on Java 1.7.0_09-icedtea OpenJDK 64-Bit Server VM |
| 11:25 | leoncamel | what is proper way to execute a external command? I can not find clojure.contrib.duck-streams now. |
| 11:27 | clgv | ~contrib |
| 11:27 | 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 |
| 11:28 | clgv | "clojure.java.shell" or "conch" will help you |
| 11:29 | leoncamel | clgv: OK. thanks. |
| 11:30 | AtKaaZ | anyone using emacs 24.2 can paste their init.el ? |
| 11:31 | antares_ | I have an entire repo for emacs.d :) |
| 11:31 | AtKaaZ | lol that's a lot of lines |
| 11:32 | AtKaaZ | cool I'll check that |
| 11:32 | antares_ | AtKaaZ: http://github.com/michaelklishin/emacsd, although it is by no means an example of an impressive Emacs setup |
| 11:32 | leoncamel | AtKaaZ: what are you looking for? configurations for nREPL+emacs? |
| 11:33 | AtKaaZ | leoncamel: yes exactly (on windows) |
| 11:35 | hyPiRion | AtKaaZ: https://github.com/bodil/emacs.d is a good one to look at. |
| 11:36 | AtKaaZ | thanks I'll check, antares_'s seems to be using .emacs I was expecting init.el |
| 11:36 | hyPiRion | Though it's not for windows. |
| 11:37 | AtKaaZ | understood |
| 11:39 | Bodil | hyPiRion: Thanks, I guess. :) |
| 11:39 | leoncamel | AtKaaZ: My emacs.d become complex and complex, I don't know if it helps. But, I would like recommend this repo : https://github.com/purcell/emacs.d |
| 11:40 | nDuff | AtKaaZ: See https://github.com/overtone/emacs-live -- there are videos showing the features and such. |
| 11:41 | S11001001 | AtKaaZ: my emacs config is top secret, can't share without risking national security |
| 11:41 | AtKaaZ | :)) |
| 11:41 | leoncamel | nDuff: yes. It so dam cool... :) I LOVE that. |
| 11:45 | AtKaaZ | awesome video, I wonder if the text really glows like that |
| 11:46 | adu | which video? |
| 11:46 | AtKaaZ | http://vimeo.com/22798433 |
| 11:47 | adu | doubtful |
| 11:47 | AtKaaZ | yep I just saw the end:) |
| 11:48 | ambrosebs | Just released Typed Clojure 0.1, please try it out https://github.com/frenchy64/typed-clojure |
| 11:48 | adu | OMG |
| 11:48 | adu | typed clojure! |
| 11:48 | nDuff | sweet! |
| 11:48 | adu | is it anything like typed racket? |
| 11:49 | ambrosebs | it's wannabe typed racket, yes :) |
| 11:49 | ambrosebs | nDuff: thanks! |
| 11:49 | nDuff | adu: If you're curious, you should read the paper ambrosebs published. |
| 11:49 | adu | ambrosebs: I think something just happened in my pants |
| 11:49 | adu | which paper? |
| 11:49 | ambrosebs | should be in the readme |
| 11:49 | clgv | ambrosebs: does it work without a modified clojure? |
| 11:50 | adu | "A Practical Optional Type System for Clojure"? |
| 11:50 | ambrosebs | clgv: It only works on 1.5.0-beta1 |
| 11:50 | ambrosebs | clgv: probably |
| 11:50 | ambrosebs | adu: yep |
| 11:51 | clgv | ambrosebs: why i "tc-ignore" not metadata? |
| 11:51 | adu | ambrosebs: did I show you my typed lisp thing? |
| 11:51 | adu | http://andydude.github.com/droscheme/cmd/gos.html |
| 11:52 | adu | it's just an S-expr representation of Go code |
| 11:53 | ambrosebs | clgv: the library "analyze" generates an AST from the Clojure compiler. Sometimes metadata doesn't make it through, so as a rule I don't do any metadata where you might expect. |
| 11:54 | ambrosebs | clgv: It was the quickest thing that works. |
| 11:55 | clgv | ambrosebs: ah ok. then that might be a future feature ;) |
| 11:56 | ambrosebs | clgv: I don't see how (tc-ignore 1) would work with metadata though. |
| 11:57 | clgv | ambrosebs: would `1` be type checked? |
| 11:57 | ambrosebs | I mean, 1 isn't IMeta |
| 11:57 | clgv | I know. but would it make sense to wrap it in tc-ignore? |
| 11:58 | ambrosebs | clgv: probably not. Until we have a new compiler, I'm happy with tc-ignore. |
| 11:59 | ambrosebs | which may be never :) |
| 11:59 | adu | new compiler? |
| 11:59 | clgv | ambrosebs: despite from tc-ignore you could have the "typed clojure" annotations in a different namespace, right? |
| 11:59 | ambrosebs | adu: ie. CLJS |
| 12:00 | adu | I thought CLJS was as good as CLJ |
| 12:00 | ambrosebs | clgv: sure |
| 12:00 | ambrosebs | clgv: these are the sorts of issues I haven't fleshed out yet though. |
| 12:00 | clgv | ambrosebs: that was why tc-ignore disturbed me ;) |
| 12:00 | ambrosebs | clgv: yes, it's a horrible hack of course! |
| 12:01 | ambrosebs | adu: CLJS compiler is much nicer to work with. |
| 12:01 | adu | hmm, maybe I should check it out, I've only used CLJ |
| 12:02 | ambrosebs | adu: check out the compiler namespace, it's just multimethods and maps. |
| 12:02 | ambrosebs | quite remarkable. |
| 12:04 | ambrosebs | I would be grateful if anyone's tried Typed Clojure 0.1 to let me know that it works. |
| 12:05 | ambrosebs | I've been the only user for so long, it's a little nerve wrecking releasing it :) |
| 12:05 | ambrosebs | I probably screwed up something. |
| 12:11 | adu | I'd like to try it |
| 12:12 | ambrosebs | adu: Glad to help if you run into any trouble. |
| 12:17 | adu | ambrosebs: "Could not find artifact typed:typed:jar:0.1 in central (http://repo1.maven.org/maven2)" |
| 12:17 | adu | o wait n/m "Retrieving typed/typed/0.1/typed-0.1.jar (71k)from https://clojars.org/repo/" |
| 12:18 | ambrosebs | I actually just pushed it 1m ago LOL |
| 12:18 | adu | sweet |
| 12:18 | ambrosebs | forgot to release the release |
| 12:19 | wunki | is there a thumbnail library in Clojure? |
| 12:20 | adu | ambrosebs: is there a "defn>"? |
| 12:21 | ambrosebs | adu: nope, I wouldn't encourage one either. |
| 12:21 | nDuff | wunki: If you don't find anything on Clojuresphere, the typical thing is to pick a Java library that looks sane. |
| 12:21 | technomancy | ambrosebs: would it be possible to specify annotations as metadata on vars? |
| 12:21 | ambrosebs | adu: just use (ann var type) |
| 12:22 | adu | ambrosebs: is this important: "CompilerException java.lang.RuntimeException: Unable to find static field: COLUMN_AFTER in class clojure.lang.Compiler, compiling:(analyze/core.clj:825)"? |
| 12:22 | ambrosebs | technomancy: no reason why not. |
| 12:22 | wunki | nDuff: doesn't seem to be. Adding java to the google query :) |
| 12:22 | ambrosebs | adu: ah. |
| 12:22 | technomancy | ambrosebs: seems like the natural place for it provided you're not annotating someone else's code |
| 12:23 | adu | ambrosebs: I got that after "(use 'typed.core)" in "lein repl" |
| 12:23 | ambrosebs | adu: *clojure-version* ? |
| 12:23 | nDuff | wunki: ...by the way, I _do_ recommend clojuresphere (http://www.clojuresphere.com/) as a good place to look for Clojure libraries. |
| 12:23 | adu | ambrosebs: 1.4.0 |
| 12:23 | nDuff | wunki: ...notably, searching there, it _does_ find a thumbnail library. |
| 12:24 | ambrosebs | adu: ok, it only supports 1.5.0-beta1 |
| 12:24 | adu | oic |
| 12:24 | adu | let me change the project |
| 12:24 | ambrosebs | adu: can you run "lein deps :tree" and paste it somewhere? |
| 12:24 | ambrosebs | or just let me know where 1.4.0 is coming from |
| 12:24 | TimMc | adu: http://refheap.com |
| 12:25 | ambrosebs | technomancy: is there a particular reason why you'd prefer metadata? I don't personally see the difference. |
| 12:26 | adu | https://www.refheap.com/paste/6161 |
| 12:26 | technomancy | ambrosebs: just that clojure already has a mechanism for annotating vars; seems odd to make up your own when one already exists |
| 12:26 | gensymv | hello, clojure newbiew here: what is the use case for "lein repl" starting a server? |
| 12:26 | gensymv | *newbie |
| 12:26 | jkkramer | wunki: I use Scalr in a clojure project. I have a ~100 line clj file to make working with loading/saving images a bit easier that I could open source |
| 12:26 | ambrosebs | technomancy: fair enough. Blindly copied Typed Racket there. |
| 12:26 | gensymv | *starting to listen |
| 12:26 | adu | gensymv: I just used lein repl to test stuff |
| 12:26 | ambrosebs | adu: what's your project.clj |
| 12:27 | wunki | nDuff: I didn't know clojuresphere was a site, I though it was a "saying". Thanks |
| 12:27 | gensymv | adu, my question has nothing to do with the code you posted^^ |
| 12:27 | gensymv | i am just curious. |
| 12:27 | technomancy | gensymv: leiningen used to have issues with stdin from within your project, so it had to set up a socket for repl communication |
| 12:27 | technomancy | gensymv: turns out it's a useful property to have for remote debugging anyway |
| 12:28 | gensymv | so if i don't really know what i am doing (which is the case), i might as well continue using clojure with rlwrap. |
| 12:28 | gensymv | technomancy,thanks. |
| 12:28 | technomancy | rlwrap is pretty crappy actually |
| 12:28 | adu | ambrosebs: ok, now that I have 1.5.0-beta1 in the project, leing repl/use now says "WARNING: defrecord already refers to: #'clojure.core/defrecord in namespace: user, being replaced by: #'typed.core/defrecord" |
| 12:29 | gensymv | technomancy, why do you say that? |
| 12:29 | technomancy | gensymv: history support isn't as good; no tab completion |
| 12:29 | ambrosebs | adu: just require it, don't use |
| 12:29 | ambrosebs | (require 'typed.core) |
| 12:29 | wunki | jkkramer: you don't have to do it for me. I'm only using for a side project. If however you wanted to do it anyway. Let me know |
| 12:30 | wunki | jkkramer: pm me if so, gotta go eat |
| 12:30 | adu | I thought it didn't matter |
| 12:30 | jkkramer | wunki: it's short and relative self contained. i'll gist it... |
| 12:30 | gensymv | technomancy, as far as i see leiningen repl doesn't have tab completion either |
| 12:30 | ambrosebs | adu: could you possibly start a new file? |
| 12:30 | technomancy | gensymv: lein1 or lein2? |
| 12:30 | adu | ambrosebs: ok |
| 12:30 | jkkramer | wunki: https://gist.github.com/3959731 |
| 12:30 | gensymv | technomancy, 1.7 |
| 12:31 | technomancy | gensymv: yeah, that's just using rlwrap. lein2 has a much better repl. |
| 12:31 | ambrosebs | adu: (:require [typed.core :refer [check-ns ann]]) |
| 12:32 | TimMc | technomancy: At least it's not jline. |
| 12:33 | adu | I tried "(require [typed.core :refer [check-ns ann]])" in the repl and got a ClassNotFoundException |
| 12:33 | technomancy | TimMc: jline1 is the crappy one; jline2 is sweet |
| 12:33 | TimMc | adu: Put a ' before [typed... |
| 12:33 | TimMc | technomancy: Oh, interesting. |
| 12:34 | adu | YEY |
| 12:34 | adu | that worke |
| 12:34 | TimMc | adu: require is a fn, not a macro, for better or worse -- so it needs to have the libspec quoted. |
| 12:34 | ambrosebs | adu: typed.core/cf checks a form, you might want that to experiment with |
| 12:34 | ambrosebs | adu: try (cf 1) |
| 12:35 | adu | ambrosebs: I get "[(quote 1) {:then tt, :else ff} empty-object]" |
| 12:35 | ambrosebs | great |
| 12:35 | adu | I have no idea what that means |
| 12:36 | ambrosebs | adu: it's a bit complex. (quote 1) is the singleton type containing just one. |
| 12:36 | ambrosebs | adu: the rest is extra stuff. |
| 12:37 | ambrosebs | try (ann-form (fn [a] a) (All [x] [x -> x])) |
| 12:37 | ambrosebs | and import ann-form |
| 12:37 | ambrosebs | it should all be working. |
| 12:38 | ambrosebs | technomancy: what kinds of better inference were you expecting from Typed Clojure? |
| 12:38 | adu | ambrosebs: "(typed.core/cf (Math/sqrt 4))" gives me "AssertionError Assert failed: (class? cls) typed.core/Class->symbol (core.clj:2275)" |
| 12:38 | ambrosebs | adu: that's not right :) |
| 12:39 | adu | do I win a beta testing chocolate cookie? |
| 12:40 | technomancy | ambrosebs: well, trivially in the collatz example, it should be possible to infer the return value, right? |
| 12:40 | ambrosebs | adu: the first bug report :) |
| 12:41 | ambrosebs | technomancy: yes, IMO that's only handy for anonymous functions. I have a convoluted syntax that infers the return: (fn> [[a :- Number]] a) |
| 12:41 | TimMc | technomancy: COuld not reproduce, I was able to get a value other than 1. |
| 12:42 | technomancy | ambrosebs: sure; cool |
| 12:43 | TimMc | (Never mind, my joke fails because his Collatz function doesn't actually check for loops, per se.) |
| 12:44 | technomancy | is it a goal at all to support checking code that's unannotated based on guesses coming from inference? |
| 12:45 | ambrosebs | technomancy: that's for a separate tool. |
| 12:45 | technomancy | ok, I see |
| 12:47 | ambrosebs | technomancy: a tool between those is one that gives a pretty good guess of the types, and allows the user to double check them before being used like normal. |
| 12:48 | edward_123 | anyone used compojure knows how to redirect to a custom 404 page when 404 happens? right now i only have route/not-found "page not found." |
| 12:48 | technomancy | ambrosebs: I expect there's also room for a tool that can avoid reflection that way too |
| 12:49 | ambrosebs | technomancy: yes, just need to figure out how to integrate it into the Compiler. |
| 12:49 | dnolen | ambrosebs: so you see typed clojure as kind of a final pass after an more robust inferencer pass? |
| 12:51 | ambrosebs | dnolen: I meant porting a large amount of untyped code could be pretty annoying, so a decent inferencer would help there. Typed Clojure is fundamentally bidirectional checking only. |
| 12:52 | ambrosebs | adu: fixed it, any more ;) |
| 12:54 | adu | ambrosebs: nice |
| 12:54 | egghead | edward_123: just put the html instead of "page not found." |
| 12:58 | dnolen | ambrosebs: ejackson mentioned S Peyton-Jones was excited about Typed Clojure at FPDays ;) |
| 12:58 | ejackson | indeed ! |
| 12:59 | ejackson | I pointed him at your dissertation - hot off the presses. |
| 12:59 | edward_123 | @egghead, oh it can also be dynamic content if I can corresponding function as long as the function returns string right? |
| 12:59 | egghead | ya edward_123 |
| 13:01 | edward_123 | Thanks! |
| 13:08 | dnolen | ejackson: so did you get any feedback from folks that were familiar w/ constraint solvers? |
| 13:08 | ambrosebs | dnolen: ejackson: no way! |
| 13:09 | ejackson | ambrosebs: yes way. He is working at the moment on optional static typing in Haskell too. |
| 13:10 | dnolen | word on the street is that all the cool kids are doing it |
| 13:10 | ejackson | The idea is that it turns all static errors into warnings at compile time, and throws at runtime instead |
| 13:10 | technomancy | sounds like a hard sell to haskellers |
| 13:10 | dnolen | technomancy: it's already in GHC |
| 13:10 | ejackson | stuff is available and more coming. |
| 13:11 | ejackson | apparently their main use case is refactoring |
| 13:11 | technomancy | sure, haskellers just like to talk about how runtime errors are a thing of the past |
| 13:12 | ambrosebs | Well, we're about to find out if the monads in my dissertation are actually well typed then ;) |
| 13:12 | ejackson | dnolen: feedack - not really. Did have a prologer cut off one of my answers to say how much more expressive core.logic was than prolog in solving the soduku puzzle. |
| 13:12 | ejackson | i certainly wasn't about to disagree. |
| 13:13 | dnolen | ejackson: heh |
| 13:13 | dnolen | technomancy: just like the SMLers & OCamlers before them. |
| 13:14 | technomancy | dnolen: ocaml struck me as a much more chill community |
| 13:14 | technomancy | "Oh, you absolutely need speed? It's cool if you write mutable code then. We won't judge you." |
| 13:15 | technomancy | much less dogmatic |
| 13:15 | dnolen | technomancy: maturity of community perhaps? |
| 13:15 | technomancy | couldn't say for sure. maybe being slightly more industry-leaning than haskell. |
| 13:16 | Iceland_jack | Haskell is too divided between research and usability I feel |
| 13:19 | egghead | Iceland_jack: why do you say that? haskell is certainly useable, just not necessarily accessible :) |
| 13:19 | Iceland_jack | I probably wasn't specific enough |
| 13:20 | Iceland_jack | It is useable but sometimes you need stability of ideas as much as you need stability of libraries or code |
| 13:22 | Iceland_jack | With Haskell there are always new things--arrows, lenses--that mix with people trying to solve problems |
| 13:22 | Iceland_jack | I do love Haskell though |
| 13:23 | gtrak` | I find myself writing this a lot in async code, is there a better way? (let [call #(if % (%))] ... (call some-param)) |
| 13:24 | djcoin | I'm far from being an expert, but my trouble with haskell is functional overengineering maybe and laziness. Ocaml is more pragmatic but for ~20 years it seems it did not evolved as much as it should have (and by the way, not used at much as it should I guess - when I see how Go is getting traction .. it seems to me as a weaker OCaml). Again, i'm far from an expert. |
| 13:25 | Iceland_jack | I think Haskell is definitely on the right track |
| 13:25 | technomancy | yeah, it's a shame Go has so much momentum while OCaml comparatively languishes |
| 13:25 | Iceland_jack | OCaml is an excellent language |
| 13:25 | djcoin | Yeah, it is a total incomprehension for me. You can take OCaml + Lwt, and you get basically Go |
| 13:26 | technomancy | it's the curly braces |
| 13:26 | djcoin | :( |
| 13:26 | gtrak | curly braces make it go fast |
| 13:27 | dnolen | technomancy: I don't think I'll ever use Go myself but I understand the appeal for the mainstream devs. |
| 13:28 | djcoin | dnolen: maybe their were told that it is web scale yet imperative :) |
| 13:29 | djcoin | they * |
| 13:29 | technomancy | maybe it's like the groovy of systems-level code |
| 13:29 | technomancy | the appeal comes from addressing the obvious pain points without requiring you to change the way you think |
| 13:30 | nDuff | ${DEITY} that thing is awful |
| 13:30 | technomancy | yeah that's probably not quite fair to go |
| 13:30 | nDuff | bloody near impossible to tell what a given piece of code does without ridiculous amounts of context |
| 13:31 | technomancy | it's not *bad* (apart from ignoring interactive development, which is unforgivable) it's just unambitious |
| 13:34 | ToBeReplaced | okay i can't get midje to work at all >> has anyone else had any issues? i'm reckoning that i just don't know what i'm doing with java |
| 13:35 | ToBeReplaced | if i do lein new foo; cd foo; lein midje; i get ran 1 test, yadda yadda, then finally "Subprocess failed" |
| 13:37 | egghead | can anyone speak to clj-metrics vs something like reimann ? |
| 13:45 | ambrosebs | adu: Gos is pretty cool! |
| 13:45 | ambrosebs | adu: any macros? |
| 13:46 | ambrosebs | adu: or is that more droscheme's thing? |
| 13:53 | adu | ambrosebs: right |
| 13:53 | adu | ambrosebs: droscheme is the macros, and gos is just a transpiler from S-expr => Go |
| 13:54 | ambrosebs | adu: and the types are just directly from Go? |
| 13:54 | adu | yes |
| 13:54 | ambrosebs | cool |
| 13:54 | adu | I've been meaning to do a release of droscheme |
| 13:54 | adu | but I've been so busy with my new job |
| 13:55 | adu | iirc, the andrew-working branch (https://github.com/andydude/droscheme/tree/andrew-working) is half-way between master branch and what I have now |
| 13:57 | ambrosebs | I should go to bed :) Hearing SPJ knows about Typed Clojure kept me up another hour :P |
| 13:57 | adu | nice |
| 13:58 | ambrosebs | thanks a bunch for being the first known user of Typed Clojure xD |
| 13:58 | ambrosebs | seriously. |
| 13:58 | adu | np :) |
| 13:58 | ambrosebs | cya |
| 13:58 | adu | later |
| 14:07 | mac_ | Hello folks! Anybody up for a short code review (80-odd lines)? I'm getting performance that's surprising me with its slowness, and I thought somebody might see where I've gone wrong. |
| 14:07 | emezeske | ~anyone |
| 14:07 | clojurebot | Just a heads up, you're more likely to get some help if you ask the question you really want the answer to, instead of "does anyone ..." |
| 14:07 | emezeske | mac_: Nothing wrong with pasting the code in question |
| 14:08 | emezeske | mac_: But people might not want to commit to a code review before seeing it :) |
| 14:08 | mac_ | oh, of course. |
| 14:09 | grzm | Just getting started with clojurescript and following along Mark McGranaghan's node.js clojurescript demo at http://mmcgrana.github.com/2011/09/clojurescript-nodejs.html and am getting the following error: |
| 14:09 | grzm | .ObjMap.fromObject(["Content-Type"], {"Content-Type":"text/plain"}).strobj()); |
| 14:09 | grzm | ^ |
| 14:09 | grzm | TypeError: Property 'strobj' of object {"Content-Type" "text/plain"} is not a function |
| 14:09 | mac_ | It's a backtracking sudoku: https://gist.github.com/3960341 |
| 14:09 | dnolen | grzm: it's probably unwise to follow that particular tutorial it's quite old. |
| 14:09 | grzm | This is when running the first http example. |
| 14:09 | grzm | dnolen: that's what I was gathering. |
| 14:09 | dnolen | grzm: it's relies on private implementation details |
| 14:10 | grzm | dnolen: and that too, from here : http://stackoverflow.com/questions/9193705/where-in-clojurescript-is-the-strobj-function-defined |
| 14:10 | grzm | dnolen: any pointers on more modern places to start? In particular, I'm interested in using cljs with node.js |
| 14:12 | emezeske | mac_: Probably not performance-related, but do you know about get-in and assoc-in? |
| 14:12 | grzm | dnolen: btw, I'm incredibly impressed with the level of activity you're able to maintain on the lists, Stackoverflow, and I see it extends to IRC as well :) |
| 14:12 | dnolen | grzm: wild west that. node.js support is still early days. |
| 14:12 | mac_ | emezeske: I see I've reinvented the wheel. |
| 14:12 | dnolen | grzm: ohpauleez is forging some ground there. |
| 14:12 | mac_ | Thought I might have. |
| 14:13 | emezeske | mac_: Only a little bit :) |
| 14:13 | grzm | dnolen: cheers. I'll take a look |
| 14:13 | mac_ | That implementation is slower than a Python implementation that's using (broadly) the same algorithm; Python gets mutable arrays, of course, so there's likely a meaningful win there, but I'm still surprised. |
| 14:14 | mac_ | (Python wins when I have it do many boards, in an attempt to amortize startup costs) |
| 14:14 | ohpauleez | grzm: Let me scroll back a second and catch up |
| 14:15 | ohpauleez | grzm: I'm your man! |
| 14:15 | __zfn__ | Hi all/ |
| 14:15 | __zfn__ | I use lein with clojure 1.2.1 |
| 14:15 | grzm | ohpauleez: good to hear :) |
| 14:16 | __zfn__ | How to update clojure version? |
| 14:16 | dnolen | mac_: you are constructing many transient values tho right? lots of conversions to set, and calls to set/difference. that's not the case in the Python code if I recall |
| 14:16 | technomancy | three remaining blockers on lein2 rc; woo |
| 14:16 | ohpauleez | I have a full app - disk-io, lots of Clojure/edn data, core.logic, interaction with unix utilities - all on node.js |
| 14:16 | mac_ | dnolen: I'm constructing many transient sets in my python version, as well. |
| 14:16 | ohpauleez | as a scripting app |
| 14:16 | technomancy | anyone want to fix https://github.com/technomancy/leiningen/issues/805? |
| 14:16 | dnolen | mac_: by converting to python sets? |
| 14:16 | dnolen | mac_: I'm assuming you're basing this on Norvig's version? |
| 14:17 | mac_ | dnolen: No, from-scratch by me. |
| 14:17 | ohpauleez | technomancy: exciting! |
| 14:17 | ohpauleez | grzm: Are you stuck with anything in particular or just looking for starting points? |
| 14:17 | grzm | ohpauleez: currently googling you and node.js to see what you've got out there, but currently only see links to irc logs. do you have any node.cljs articles/projects out there I might take a gander at? |
| 14:17 | mac_ | dnolen: My python version does the same build-three-sets thing that my clj version does; mutability is likely adventageous there too, though. |
| 14:18 | dnolen | mac_: are you running the JVM w/ -server? |
| 14:18 | mac_ | dnolen: dunno; lemme see. |
| 14:18 | grzm | ohpauleez: just getting started. Haven't done extensive js work, much less node.js, and thought using clojurescript would make it a little less painful |
| 14:18 | dnolen | mac_: if you're using lein you probably are |
| 14:18 | mac_ | dnolen: using the clj wrapper script from homebrew. |
| 14:18 | ohpauleez | grzm: I was going to hold off pushing mine to Github, but let me add that remote and I'll link you |
| 14:18 | mac_ | it's not passing -server. |
| 14:18 | mac_ | Lemme try. |
| 14:18 | grzm | ohpauleez: so I was going to work through Mark's demo |
| 14:19 | grzm | ohpauleez: cheers |
| 14:19 | ohpauleez | grzm: That's a good place to start - the latest Google Closure Lib has promises in it (they're called Resultes) |
| 14:19 | ohpauleez | You need to use them to escape callback hell and program with values |
| 14:19 | technomancy | never mind; I think that issue I linked to is already fixed |
| 14:19 | ohpauleez | I'm going to highlight that in my Conj talk this year |
| 14:20 | mac_ | dnolen: can't tell if that made a difference. |
| 14:20 | mac_ | My "benchmarking" (using the term loosely) isn't good enough to tel. |
| 14:20 | dnolen | mac_: you generally need multiple runs for the JVM to warm up, how long does it take to solve your board? |
| 14:21 | emezeske | mac_: This is probably micro-micro optimization, but it seems like representing the board using numbers instead of strings would be appropriate |
| 14:21 | dnolen | mac_: also if you're doing this at the terminal w/ clj then you're messing JVM+Clojure+compile your script startup time |
| 14:21 | dnolen | you're measuring I mean |
| 14:21 | mac_ | dnolen: yeah, I know I'm paying all the startup time every time. |
| 14:22 | mac_ | But if I have it solve say 20 boards, python still wins. |
| 14:22 | grzm | ohpauleez: I take it https://github.com/ohpauleez/ttt is what I'm looking forward to? |
| 14:22 | ohpauleez | yes |
| 14:22 | ohpauleez | :) |
| 14:22 | dnolen | mac_: how long does it take? |
| 14:22 | mac_ | oh, hang on. |
| 14:23 | mac_ | at ~20 boards, clj takes ~13 seconds wall time, and python takes ~20. |
| 14:23 | mac_ | So it looks like I'm catching up after all. |
| 14:23 | mac_ | (Although that second thread means my CPU time is higher) |
| 14:23 | mac_ | Clearly, I need to examine this more closely. |
| 14:23 | mac_ | (I take it from the other quietness that nobody has seen a drastic performance foulup in that implementation?) |
| 14:24 | dnolen | mac_: it's actually pretty nice looking code, minor things here and there. |
| 14:24 | mac_ | dnolen: thanks! |
| 14:24 | mac_ | It's my first real lisp program. |
| 14:24 | mac_ | Done a fair amount of functional (OCaml, mostly), but never typed this many parentheses in a row before. |
| 14:25 | dnolen | mac_: i was going to say, it seemed like you done some FP before |
| 14:25 | amalloy | yeah, agreed it reads pretty well mac_. that last (if (empty? wins) nil (first wins)) could just be (first wins) |
| 14:25 | Kneferilis | how clojure compares to falcon? |
| 14:25 | mac_ | amalloy: oh, excellent. What I did felt gross. |
| 14:26 | mac_ | Got a meeting to run to. Thanks for the help! |
| 14:26 | amalloy | oh, and (apply str (interleave x y)) is (clojure.string/join x y) |
| 14:28 | hyPiRion | ,(clojure.string/join "," [1 2 3]) |
| 14:28 | clojurebot | "1,2,3" |
| 14:28 | tomoj | it seems clj-http is incompatible with cheshire.custom? :( |
| 14:28 | hyPiRion | ,(apply str (interleave "," [1 2 3])) |
| 14:28 | clojurebot | ",1" |
| 14:29 | amalloy | oh, i see. i was thinking of interpose, because it's such a common pattern |
| 14:29 | amalloy | thanks hyPiRion |
| 14:30 | hyPiRion | I tend to mix them up as well, I feel like I always have to check if I'm using the right one |
| 14:31 | Apage43 | tomoj: you can always ask clj-http for a stream and pass it to decode-stream |
| 14:31 | tomoj | encoding is the problem |
| 14:32 | tomoj | otherwise I could maybe implement a custom response coercion (except clutch won't use it) |
| 14:40 | amalloy | am i totally crazy for wanting to turn an if-let into let+if? i have something like (if-let [x (...)] (f x) (let [x' (...)] (g x))), where f and g are very similar-looking expressions. it seems like it might read better to do (if (x-exists?) (let [x (...)] (f x)) (let [x' (...)] (g x))) |
| 14:43 | dakrone | tomoj: check out https://github.com/dakrone/clj-http/blob/master/src/clj_http/client.clj#L41-51 |
| 14:43 | dakrone | tomoj: you can rebind the fns for it if you want to use whatever you'd like |
| 14:43 | tomoj | ohh |
| 14:43 | tomoj | I didn't notice they were dynamic |
| 14:43 | tomoj | excellent, thanks |
| 14:44 | hiredman | amalloy: we need compiler magic to take let-if-try-let do the right thing |
| 14:44 | Apage43 | oh neat, that means I could pull in clj-http without cheshire. Mind I don't think I've ever actually used one and not the other in any project yet.. |
| 14:44 | hiredman | like other lisps have cdddddr |
| 14:45 | dakrone | Apage43: yes, it's all set up so you can exclude cheshire from the deps if you don't want to use it |
| 14:45 | spligak | could someone explain this idiom to me? I understand you can drop a hash-map into it, but I'm curious as to what's happening in the function arguments. is there some implicit conversion going on? https://github.com/dakrone/clj-http/blob/master/src/clj_http/client.clj#L75 |
| 14:46 | tomoj | destructuring? |
| 14:46 | clojurebot | destructuring is http://clojure.org/special_forms#let |
| 14:46 | amalloy | good idea. if the compiler sees you've mashed the names of six built-ins together into a single symbol, it should figure out what the heck you want that to do |
| 14:46 | hiredman | yes |
| 14:46 | hiredman | dwim |
| 14:46 | dakrone | spligak: the response map is being destructured, the :status key is being pulled out and bound to 'status' |
| 14:47 | tomoj | (g x') I assume? |
| 14:47 | amalloy | i remember having a hell of a time figuring out destructuring from the examples in JoC. might have been the hardest part of the book for me to understand |
| 14:47 | amalloy | tomoj: yep, good catch |
| 14:47 | ohpauleez | grzm: Take a look now: https://github.com/ohpauleez/ttt |
| 14:47 | ohpauleez | shield your eyes from all the hacks |
| 14:47 | ohpauleez | :) |
| 14:48 | tomoj | hmm |
| 14:48 | ohpauleez | it's very much a scratching pad for me |
| 14:48 | dakrone | http://clojure-doc.org/articles/language/functions.html#destructuring_of_function_arguments |
| 14:49 | spligak | tomoj, dakrone interesting. thanks for the direction here - had skimmed a bit on the topic. was jarring to see it in the wild for the first time. |
| 14:49 | spligak | (very new to clojure) |
| 14:50 | Gurragchaa | so Clojure runs anywhere that has a JVM installed, right? And if so, can it call all the functions from the Java API, OpenGL in particular? |
| 14:50 | spligak | dakrone, oh wow. those examples are excellent. thanks. |
| 14:50 | technomancy | Gurragchaa: not really, OpenGL is typically native code |
| 14:50 | egghead | hey sjl are you around? |
| 14:51 | dakrone | spligak: np, good luck! |
| 14:51 | sjl | egghead: yes |
| 14:52 | egghead | sjl: I was playing with your wrapper around codahale's metrics -- by default all my bean metrics are under default.default.metricname -- is there any way to change this? |
| 14:52 | emezeske | Gurragchaa: If OpenGL can be used by Java on a given platform, then yes, Clojure can use OpenGL via the Java APIs. |
| 14:52 | sjl | egghead: http://metrics-clojure.readthedocs.org/en/latest/names.html |
| 14:53 | Gurragchaa | so Clojure could theoretically be useful for cross-platform OpenGL game development? |
| 14:53 | egghead | d'oh, figures I would have missed it, thanks sjl |
| 14:53 | sjl | np |
| 14:53 | emezeske | Gurragchaa: Yes |
| 14:53 | emezeske | Gurragchaa: https://github.com/ztellman/penumbra |
| 14:54 | emezeske | Gurragchaa: Look in the test/ directory for examples of simple games |
| 14:54 | technomancy | Gurragchaa: yeah, but not everywhere Java runs |
| 14:55 | tomoj | dakrone: needs to be bound at middleware time, though? |
| 14:55 | technomancy | just on whatever subset of platforms have lwjgl support |
| 14:55 | tomoj | hmm, that shouldn't be the case, I must have screwed up |
| 14:55 | dakrone | tomoj: I didn't think it did, but I haven't actually tried it with a different library |
| 14:57 | tomoj | oh, looks like clutch calls cheshire.core/generate-string directly |
| 14:58 | dakrone | ahh, can't help there then |
| 15:15 | frawr | Hi, I have some weird behaviour with lein uberjar. When I run the project with lein run it works, but when i java -jar my standalone jar my main can't be found. Any clues? |
| 15:16 | technomancy | frawr: missing a gen-class |
| 15:16 | frawr | Only needed in the main's ns right? |
| 15:17 | dnolen | ohpauleez: so I see ttt is out there. |
| 15:18 | technomancy | frawr: specifically for uberjar, yes |
| 15:18 | antares_ | frawr: for the standalone jar to work, yes, it is unlikely that you are implementing Java classes in Clojure if you are asking this |
| 15:19 | frawr | (ns ap.server.setup (:gen-class)) and in the project definition :main ap.server.setup/quick-start, and quick-start is a fn with only the rest argument in the labdalist |
| 15:19 | TimMc | frawr: You can also use my lein-otf plugin if you don't want to have your code AOT'd (so gen-class would be unnecessary of course). |
| 15:20 | TimMc | Someone has made a fork of it for lein 2 as well. |
| 15:20 | technomancy | frawr: you can also do java -cp my-standalone.jar clojure.main -m my.ns |
| 15:20 | frawr | antares_: I don't think that's what I'm asking |
| 15:20 | technomancy | without any aot |
| 15:20 | antares_ | technomancy: isn't :main supposed to take an ns name? |
| 15:20 | technomancy | antares_: it can take a var name too, but that's not very well-tested |
| 15:20 | technomancy | could be a bug |
| 15:21 | antares_ | technomancy: I am curious how that works for uberjars |
| 15:21 | antares_ | if Main-Class in the jar manifest is a class |
| 15:21 | technomancy | oh yeah, not at all |
| 15:21 | technomancy | it's only for lein run |
| 15:21 | technomancy | frawr: that's your problem |
| 15:21 | technomancy | should probably put a warning around that or something |
| 15:22 | technomancy | not really any way we could support that |
| 15:22 | antares_ | frawr: your main class ns should have a function named -main and in :main you should specify only namespace, not a var/function |
| 15:22 | amalloy | technomancy: whaaaat, of course you could. emit your own gen-classed -main that calls the named var |
| 15:22 | frawr | Aah ok |
| 15:22 | technomancy | amalloy: right, I mean not without violating the prime directive |
| 15:22 | amalloy | $google leiningen prime directive |
| 15:22 | lazybot | [compilation - FileNotFoundException when making a jar file from the ...] http://stackoverflow.com/questions/3246883/filenotfoundexception-when-making-a-jar-file-from-the-clojure-file |
| 15:23 | frawr | didn't know that |
| 15:23 | amalloy | i'm disappointed |
| 15:23 | technomancy | I just made that up |
| 15:23 | clojurebot | I don't understand. |
| 15:23 | technomancy | but it sounds good |
| 15:23 | antares_ | $google what is clojurebot |
| 15:23 | lazybot | [irc log: #clojure on 2012-10-12] http://www.unexpected-vortices.com/clojure/irc-logs/2012/10-12.html |
| 15:23 | amalloy | it sure does. in this context what does it mean? don't make up code in the user's project or something? |
| 15:23 | frawr | and when using java -cp standalone.jar clojure.main -m my.ns, should my.ns be just a ns with a -main too? |
| 15:25 | amalloy | yes |
| 15:25 | antares_ | frawr: basically, you run namespaces. By convention they must have the -main function that takes & args |
| 15:27 | frawr | The error running my jar makes more sense too then, it listed the fn i wanted to use as mai as part of the ns, with a dot instead of a slash |
| 15:29 | frawr | thnx, works! |
| 15:33 | grzm | ohpauleez: thanks! looking forward to it (was pulled away from my desk for a bit) |
| 15:39 | technomancy | frawr: yeah, we should probably warn in uberjar when :main is set to a var |
| 15:39 | technomancy | it's useful for specifying several run targets in aliases but not or uberjars |
| 15:39 | frawr | Didn't really think about it, but that makes sense. |
| 15:42 | Cheiron | clojurebot: besame mucho |
| 15:42 | clojurebot | It's greek to me. |
| 15:49 | frawr | Anyone from the netherlands here? |
| 15:59 | jamii | Fun with parsing - http://scattered-thoughts.net/blog/2012/10/25/strucjure-reading-the-readme/ |
| 16:03 | flying_rhino | hello guys |
| 16:04 | AntelopeSalad | is there anything better than ring/jetty out there for powering a web server? |
| 16:04 | dnolen | jamii: neat stuff, is there some specific you have planned for strucjure? |
| 16:04 | emezeske | AntelopeSalad: Do you have a specific problem with ring/jetty? |
| 16:05 | AntelopeSalad | emezeske: yes, it's getting destroyed under load by artifical benchmarks |
| 16:05 | flying_rhino | I am wondering is it possible to program in clojure in imperative way, like in Java. I am not saying imperative is better, I just want to know is it doable in principle? |
| 16:05 | hiredman | flying_rhino: no |
| 16:05 | emezeske | AntelopeSalad: And you're convinced that this is ring or jetty's fault? |
| 16:05 | nDuff | ...well... |
| 16:05 | ivan | flying_rhino: yes |
| 16:05 | AntelopeSalad | emezeske: no, that's why i asked if there's an alternative to test against |
| 16:05 | nDuff | flying_rhino: _possible_, yes, but very painful. |
| 16:06 | ivan | is it really that painful to use doto and mutable objects? |
| 16:06 | ivan | it's just freakishly ugly |
| 16:06 | AntelopeSalad | i basically put up a node/express server vs clojure/ring (i would have used compojure but the documentation is bad) , and the ring setup was getting beat up, i was hoping there was an alternative |
| 16:06 | nDuff | ivan: When all your language facilities are built to work with immutible objects? Yes. |
| 16:07 | dnolen | AntelopeSalad: ring/jetty and are very fast. |
| 16:07 | emezeske | AntelopeSalad: It's pretty unlikely that the bottleneck is in ring or jetty, as opposed to your application code |
| 16:07 | jamii | dnolen: I'm really excited by http://www.viewpointsresearch.org/html/work/ifnct.htm and http://boom.cs.berkeley.edu/ |
| 16:07 | dnolen | AntelopeSalad: you probably testing w/ a bunch of silly dev route stuff in place. |
| 16:07 | flying_rhino | the thing is, I like some stuff about lisp (like macro system and first class functions), and I even like a lot of things about immutability but there are things I can't use it for. For example, game development (I am thinking of developing a game for JVM), almost screams mutable state. |
| 16:07 | AntelopeSalad | i dunno, the app code came from the ring documentation |
| 16:07 | jamii | dnolen: I want to apply the same kind of thinking to building p2p networks |
| 16:08 | jamii | dnolen: I'm going to start porting bloom to clojure next week |
| 16:08 | dnolen | AntelopeSalad: doesn't mean much. I've done a ton of pointless benchmarking of netty/jetty/node.js in the past. netty can eat Node.js for breakfast. |
| 16:08 | dnolen | AntelopeSalad: jetty is fine for nearly any workload that's not a chat server. |
| 16:08 | AntelopeSalad | all i did for clojure was setup a handler to report back hello world with no templating |
| 16:09 | ohpauleez | dnolen: ttt is in the wild, but shield your eyes - I did it premature so there was an example of some node.js magic people could work from |
| 16:09 | AntelopeSalad | and then i did the same with express |
| 16:09 | AntelopeSalad | then i ran it against ab |
| 16:09 | flying_rhino | so basically what do you do for things that are best done in mutable way (like some things in game development?) |
| 16:09 | tomoj | sounds like a good test if you're going to be serving 100000 'hello world's a second |
| 16:09 | AntelopeSalad | http://pastebin.com/FP5vxyWT |
| 16:09 | ohpauleez | I ripped the logic query out temporarily and restored the working, but extremely naive for-comprehension |
| 16:09 | AntelopeSalad | that is the test setup and results |
| 16:09 | dnolen | AntelopeSalad: do some more homework, look at the Jetty docs, if you seeing less than 4000-5000 req/s you're doing something wrong. if you're building a regular website, who cares anyway. |
| 16:10 | AntelopeSalad | this is on my horrible computer running in a VM so the reqs/s will be low for both |
| 16:10 | dnolen | ohpauleez: still looks like it will be a really sweet resource! |
| 16:11 | tomoj | the req/s differences there look.. unimportant |
| 16:11 | flying_rhino | guys? |
| 16:11 | ohpauleez | dnolen: Here's hoping! :) |
| 16:11 | emezeske | AntelopeSalad: How are you running the clojure code? lein ring? |
| 16:11 | AntelopeSalad | tomoj: look at the -c 150 one, the node server is pumping out 50% more reqs/s |
| 16:12 | AntelopeSalad | that is a non-trivial amount |
| 16:12 | AntelopeSalad | emezeske: i followed the ring's documentation |
| 16:12 | dnolen | jamii: yeah I've been following along - sounds like you've finally find some time to put it together. You're at HackerSchool right? |
| 16:12 | AntelopeSalad | https://github.com/mmcgrana/ring/wiki/Getting-Started |
| 16:12 | AntelopeSalad | i used this exactly, except ring 1.1.6 |
| 16:12 | AntelopeSalad | and clojure 1.4 |
| 16:12 | jamii | dnolen: Yep. I really needed this kind of environment to actually get moving. Far too easily distracted otherwise :) |
| 16:12 | tomoj | yeah, if you're just serving hello worlds |
| 16:13 | dnolen | jamii: been wanting to find some time to really dig into Bloom but I've been busy w/ other things, look forward to seeing the trail you blaze. |
| 16:13 | jamii | dnolen: thanks |
| 16:13 | dnolen | jamii: yeah I love the VPRI/FONC stuff |
| 16:13 | AntelopeSalad | tomoj: what do you propose is a better test, should i return a 5kb string instead? |
| 16:14 | ordnungswidrig | hmm, me has only 500/s for a simple "OK" response with -c 50 |
| 16:14 | ordnungswidrig | osx seems to do sth wrong |
| 16:14 | dnolen | AntelopeSalad: actually those benches look about right, the difference doesn't look large enough to care though. Once you have template, DB, etc I can't imagine there being an interesting diff. |
| 16:14 | ohpauleez | amalloy: Thanks for the typo catches |
| 16:15 | AntelopeSalad | dnolen: 50% isn't enough to care about? |
| 16:15 | AntelopeSalad | what about an api server that doesn't serve templates? |
| 16:15 | AntelopeSalad | or a game backend that's just returning json too with websockets, etc. |
| 16:15 | emezeske | AntelopeSalad: That benchmark is fairly useless with respect to both of those examples |
| 16:15 | ordnungswidrig | AntelopeSalad: is it tuned until no more? Regarding settings, buffer sizes etc? |
| 16:16 | AntelopeSalad | ordnungswidrig: not at all, i have no experience with clojure. i was just bored this afternoon and wanted to setup a comparison between it and node |
| 16:16 | AntelopeSalad | because i'd like to learn something as a general purpose web language |
| 16:16 | dnolen | AntelopeSalad: if you want better than Node.js async perf, I already said use Netty. |
| 16:16 | ordnungswidrig | AntelopeSalad: don't do it :-) |
| 16:17 | AntelopeSalad | ordnungswidrig: don't do what? |
| 16:17 | AntelopeSalad | dnolen: will that still work with ring and compojure? |
| 16:17 | dnolen | AntelopeSalad: w/o seeing a real workload, it's hard to extract any meaning from those numbers. |
| 16:17 | AntelopeSalad | i like the way compojure handles routes a lot |
| 16:17 | emezeske | AntelopeSalad: To answer your question earlier, 50% is definitely not enough to care about, compared to other factors like developer productivity |
| 16:18 | emezeske | AntelopeSalad: Unless you really, really know you're going to be serving tens of thousands of qps or something |
| 16:18 | dnolen | AntelopeSalad: I believe Aleph may have ring compat. |
| 16:18 | ordnungswidrig | AntelopeSalad: such tests, when you don't know how to tweek to max performance |
| 16:18 | AntelopeSalad | yeah, it's just bs tests atm, there's no real world data to run it against |
| 16:19 | ordnungswidrig | I do web development since 15 years and I never had a case where the bottleneck was the http server implementation :) |
| 16:20 | AntelopeSalad | i only asked because cost might be a deciding factor at some point |
| 16:20 | AntelopeSalad | i figured "oh man, 50% wtf... that's going to be 50% more expensive" |
| 16:20 | emezeske | ordnungswidrig: I've run into cases where the HTTP server was the bottleneck, and the answer was _easily_ "throw a couple more servers at it." |
| 16:20 | nDuff | AntelopeSalad: I've never, ever seen the bottleneck be there. |
| 16:21 | nDuff | AntelopeSalad: it's pretty much always datastore, occasionally inefficient app-layer logic... |
| 16:21 | emezeske | AntelopeSalad: Unless you are serving at a massive, massive scale, paying for engineers dominates paying for servers |
| 16:21 | nDuff | AntelopeSalad: "50% more" doesn't matter if that 50% is 0.5% of your runtime. |
| 16:21 | ordnungswidrig | emezeske: sure, there are those cases. But they are special in my experience. and often enough you can change application architecture to reduce the necessary load on servers, conditional requests, caching etc. |
| 16:21 | AntelopeSalad | emezeske: yeah of course, if it gets really big then you're in a great position to hire people who know how to deal with it |
| 16:21 | ordnungswidrig | nDuff: exactly! |
| 16:22 | AntelopeSalad | i was looking at it from a perspective of playing a game |
| 16:22 | ordnungswidrig | AntelopeSalad: it's like having to pay income tax. it's a good sign, saying that you acutally have income |
| 16:22 | AntelopeSalad | it may involve sending back and forth a lot of small size packets |
| 16:22 | emezeske | ordnungswidrig: We agree: 50% means basically nothing. :) |
| 16:23 | ordnungswidrig | AntelopeSalad: your problem will be more likely how many connection can be handled at once. |
| 16:23 | nDuff | AntelopeSalad: ...also, you want to pay attention (lots of attention!) to how things scale on multi-core architectures |
| 16:23 | nDuff | AntelopeSalad: ...which is not really one of node's strengths, but the direction hardware has been heading in for ages. |
| 16:23 | AntelopeSalad | ord: from those tests it looks like the jetty server would eventually crumble with more concurrency |
| 16:23 | dnolen | AntelopeSalad: I ran a Netty+Clojure benchmark on an Amazon Compute Cluster 2 years - I had no idea what I was doing & the hello world benchmark hit >20K req/s. |
| 16:24 | AntelopeSalad | nDuff: my VM is only running off 1 core, and scaling node to use multi-cores is nearly automatic and super easy |
| 16:24 | dnolen | AntelopeSalad: I'm sure Jetty could break 10-15K on the same machine. |
| 16:25 | technomancy | flying_rhino: you can use java arrays and such from clojure |
| 16:25 | AntelopeSalad | dnolen: i'm not sure what that is, some type of server cluster? |
| 16:25 | dnolen | AntelopeSalad: 8 core 23gb box. |
| 16:25 | flying_rhino | technomancy: that's good to know |
| 16:25 | AntelopeSalad | processor concurrency is something clojure gives us for free right? |
| 16:26 | emezeske | AntelopeSalad: Jetty is _not_ going to be your bottleneck for serving http. It just isn't worth worrying about. |
| 16:26 | dnolen | AntelopeSalad: my point is, I'd trust any JVM lib for scaling over Node.js |
| 16:26 | technomancy | flying_rhino: http://meshy.org/2009/12/13/widefinder-2-with-clojure.html <- good example of falling back to java-like code when speed is more important than maintainability |
| 16:26 | AntelopeSalad | i mean, to utilize >1 core there's nothing you have to touch? |
| 16:26 | dnolen | AntelopeSalad: Jetty & Netty autoscale yes. |
| 16:26 | flying_rhino | can I create something like Java struct? (mutable class with no methods) |
| 16:26 | dnolen | AntelopeSalad: of course in a real app you probably need to do a lot of knob twiddling. |
| 16:26 | technomancy | flying_rhino: you can do that with deftype, but usually it's a waste of time |
| 16:27 | technomancy | it's there for those 2% cases when mutability is actually a problem, but it's extremely rare |
| 16:27 | antares_ | AntelopeSalad: there is no such as "concurrency for free". If your server or app does use concurrency in bottleneck areas, with multiple cores you will get close-to-linear throughput increase. |
| 16:27 | flying_rhino | technomancy: well some things about games are inherently mutable, unfortuantely |
| 16:27 | technomancy | that's one opinion |
| 16:27 | AntelopeSalad | antares_: i meant from a writing code perspective |
| 16:27 | antares_ | jetty will make use of extra cores to some extent, given that you have many concurrent requests |
| 16:28 | nDuff | flying_rhino: Remember the ants demo? :) |
| 16:28 | AntelopeSalad | if you setup a few lines of logic to handle spawning child processes in node it'll do its thing automatically give you multi-core usage |
| 16:28 | technomancy | the only thing inherent about mutability is the fact that you're running on a Von Neumann architecture |
| 16:28 | hyPiRion | I've made a lot of different simulators and agents for different bots without mutability |
| 16:28 | flying_rhino | technomancy: you pretty much have to update entire state every tick. In case of RPG I intend to make taht's every 0.25 seconds. |
| 16:28 | AntelopeSalad | antares_: ok, that sounds good |
| 16:28 | hyPiRion | /s/bots/games |
| 16:28 | antares_ | AntelopeSalad: Clojure gives you safe defaults and building blocks. No "concurrency for free" with any language. |
| 16:28 | antares_ | AntelopeSalad: yeah except that spawning a new OS process is dead slow |
| 16:29 | emezeske | flying_rhino: It's perfectly possible to write a Clojure game without using mutable structs |
| 16:29 | flying_rhino | nDuff: I am not aware of any ants demo. Can you provied me a link. |
| 16:29 | antares_ | comparatively to a new thread or Erlang process/Gorouting |
| 16:29 | technomancy | flying_rhino: you're coming at the problem with preconceived biases that aren't based on empirical measurements |
| 16:29 | nDuff | flying_rhino: https://gist.github.com/1093917 |
| 16:29 | amalloy | $google functional retro games |
| 16:29 | lazybot | [Purely Functional Retrogames, Part 1] http://prog21.dadgum.com/23.html |
| 16:30 | AntelopeSalad | btw i didn't intend for this to be any type of flame-y conversation |
| 16:30 | AntelopeSalad | i seriously like clojure a lot |
| 16:30 | AntelopeSalad | (from what i've read so far at least in the "clojure programming" book and fooling around with the repl) |
| 16:30 | nDuff | flying_rhino: ...or, for a newer version: https://www.refheap.com/paste/3099 |
| 16:30 | antares_ | AntelopeSalad: me neither, I find node.js a good choice for Web apps. See http://aphyr.com/posts/244-context-switches-and-serialization-in-node |
| 16:31 | riddochc | Sorry, been busy. |
| 16:32 | emezeske | amalloy: That's a good entry, although some of the problems he runs into are pretty erlang-specific |
| 16:32 | ordnungswidrig | hmm, any idea why stock run-jetty will stop at 50% cpu on both cores? |
| 16:32 | AntelopeSalad | antares_: this looks like a good article but wouldn't you share state in the db most of the time anyways? |
| 16:32 | AntelopeSalad | seems like suicide to have state locked into your app process |
| 16:32 | ordnungswidrig | with stop I mean, limit |
| 16:32 | AntelopeSalad | then you lose any form of scaling out |
| 16:32 | emezeske | amalloy: Like I guess erlang doesn't let you keep shadowing the same local, e.g. (let [a 1 a (+ a 1) a (- a 5)] ...) ? |
| 16:32 | antares_ | AntelopeSalad: this is a typical Web app developer perspective |
| 16:32 | emezeske | amalloy: I could see how that would be annoying |
| 16:32 | ordnungswidrig | AntelopeSalad: you will limit yourself to how fast you can seek a disk. |
| 16:32 | antares_ | AntelopeSalad: google for Wooga and Erlang. They used to share state via data stores. 24 boxes. In-process state with Erlang in the app — 1 box. |
| 16:33 | AntelopeSalad | i mean, if i wanted to store session info on a user. i'd surely put it into redis or some other third party memory storage not the app |
| 16:33 | ordnungswidrig | AntelopeSalad: session does not scale. it's shared state that forces you to synchronization, transactions etc. |
| 16:33 | antares_ | AntelopeSalad: yeah, that's what Wooga did in one of their games |
| 16:34 | AntelopeSalad | this way you could have 1 or 50 app servers reading from the same redis server |
| 16:34 | antares_ | AntelopeSalad: grew up to 24 machines. Shoveled state in and out all the time for no reason. In-process state reduced hardware requirements to 1 machine. |
| 16:34 | amalloy | emezeske: i actually haven't read much of it, but i don't think that matters. it's a series on writing games without state, which must be of interest |
| 16:34 | antares_ | AntelopeSalad: when all you do is Web apps, everything looks like a bunch of stateless servers and shared state in Redis |
| 16:34 | antares_ | a lot of software is not like that or should not be like that |
| 16:35 | AntelopeSalad | antares_: yeah, that is good right? |
| 16:35 | ordnungswidrig | AntelopeSalad: datomic has a nice model: a writer (transaction) multiple reader nodes having local caches for indexes etc. |
| 16:35 | emezeske | amalloy: Oh, it is very much of interest. |
| 16:35 | antares_ | AntelopeSalad: how is that good? |
| 16:35 | AntelopeSalad | if you keep state out of your process, then you can freely scale out without it being a big deal |
| 16:35 | antares_ | AntelopeSalad: having just 1 option you try to apply to everything does not sound good to me |
| 16:35 | AntelopeSalad | *app process |
| 16:35 | emezeske | amalloy: I think I ended up on that blog from that series, and ended up reading every entry exhaustively... O_o |
| 16:35 | amalloy | yeah, i like his blog too |
| 16:36 | antares_ | AntelopeSalad: is a game something you'd do like that? |
| 16:36 | antares_ | AntelopeSalad: with game/player state always being stored in and taken out of Redis? |
| 16:36 | AntelopeSalad | for a game? i'm not sure. i haven't really thought about that fully ever |
| 16:37 | AntelopeSalad | if it's important data i'd probably save it on disk and have a copy in memory for faster access |
| 16:37 | antares_ | AntelopeSalad: see http://www.slideshare.net/wooga/erlang-factory-sanfran |
| 16:37 | ordnungswidrig | AntelopeSalad: btw. think of cutting your state into parts. maybe you can distribute the state on different nodes then. or you can work with eventual consistency. |
| 16:38 | AntelopeSalad | wow this talk looks like it'll be quite interesting |
| 16:40 | AntelopeSalad | antares_: do you happen to know if the video of this is posted anywhere? |
| 16:40 | antares_ | AntelopeSalad: I don't know. Another talk by the same person: http://www.slideshare.net/hungryblank/getting-real-with-erlang, see slide 46 |
| 16:41 | AntelopeSalad | app servers don't need to be monolithic either |
| 16:42 | antares_ | the only reason is why so much software is I/O bound is because a lot of software is written that way: all state is always sholved in and taken out of a data store, even if there is no real reason for doing so |
| 16:42 | antares_ | "we just have always been doing it, right?" |
| 16:43 | AntelopeSalad | right |
| 16:43 | antares_ | that's not at all how things are in many other areas of software |
| 16:43 | AntelopeSalad | i think it's because we can't even trust our web servers |
| 16:43 | AntelopeSalad | they need to be restarted pretty frequently |
| 16:43 | emezeske | antares_: You know... there are some good reasons for how web apps are architected, with databases, etc. Right? |
| 16:44 | AntelopeSalad | also (maybe not in clojure's case tho) if you push a new build that requires restarting the app |
| 16:44 | antares_ | with erlang and to some extent Clojure (or Scala and Java w/ Akka), you can have sane state management and recovery |
| 16:44 | antares_ | so keeping state in-process is not a problem |
| 16:44 | antares_ | emezeske: there are good reasons but Web developers blindly apply the same approach to EVERYTHING |
| 16:45 | AntelopeSalad | i thought one of clojure's main philosophies was to eliminate state and only deal with pure data |
| 16:45 | emezeske | antares_: Well, it turns out that most web apps are kinda similar to one another |
| 16:45 | antares_ | and then spread the gospel of node.js, redis and other stuff that is only necessary if you do things in a particular way |
| 16:45 | hyPiRion | AntelopeSalad: Clojure's main philosophy is to make software development less complex. |
| 16:46 | antares_ | AntelopeSalad: eliminate state? Useful programs always have state. The question is how you change and incapsulate it. |
| 16:47 | AntelopeSalad | antares_: in the first slide show, what are those blue dots on slide 46? |
| 16:47 | AntelopeSalad | are they supposed to be processes? |
| 16:47 | antares_ | presumably processes, Erlang or not |
| 16:47 | antares_ | the point is that in Erlang, distribution is transparent and processes across machines form a single "cluster" |
| 16:48 | ordnungswidrig | why ist there still no OTP for clojure? Seems so natural. |
| 16:49 | AntelopeSalad | what would be contained in each process in this example? |
| 16:49 | antares_ | AntelopeSalad: in their game example, one player's state |
| 16:49 | AntelopeSalad | some piece of the final app and then the "process cluster" is the combination of each sub-app? |
| 16:49 | antares_ | but there are always additional processes that carry out smaller tasks |
| 16:49 | ordnungswidrig | http://www.12factor.net/processes |
| 16:51 | antares_ | ordnungswidrig: keep in mind that that "guide" assumes that what you build is Web apps, on multiple layers. Assets packagers clearly indicate that. |
| 16:52 | ordnungswidrig | absolutely. but the idea of process as an complete processing unit is nice. |
| 16:52 | AntelopeSalad | i'm not sure i understand how their state is stored and gotten back out |
| 16:52 | antares_ | AntelopeSalad: in erlang processes. Do you know anything about Erlang? |
| 16:53 | antares_ | AntelopeSalad: it is NOT stored until a round or the entire game is over |
| 16:53 | AntelopeSalad | i know nothing except a lot of people joke at how cryptic its syntax is |
| 16:53 | antares_ | not stored to a database |
| 16:54 | antares_ | erlang VM can have up to millions of Erlang processes, some of them store state for the duration of a game round |
| 16:54 | antares_ | when the round is over, it is stored to the database |
| 16:55 | antares_ | but all intermediate changes are not stored there, they are kept in the app and propagated to players |
| 16:55 | AntelopeSalad | sounds dangerous |
| 16:55 | antares_ | this cuts number of requests by 99%, as slide 46 indicates |
| 16:55 | AntelopeSalad | what happens if something goes wrong and the process crashes? |
| 16:55 | antares_ | AntelopeSalad: it is not dangerous because Erlang has the concept of supervision trees |
| 16:56 | antares_ | AntelopeSalad: it is restarted by its supervisor. Whole trees of processes can be restarted. |
| 16:56 | AntelopeSalad | and it knows what to put back in? |
| 16:56 | antares_ | AntelopeSalad: that is NOT an OS process, so process crashes means you have issues in your code or something like a network split has happened |
| 16:56 | AntelopeSalad | ah |
| 16:57 | antares_ | AntelopeSalad: it can load something form a database or simply start from scratch |
| 16:57 | antares_ | in an interactive game if a piece of state is gone, it sucks but you cannot make every single change persistent anyway |
| 16:57 | antares_ | there are too many of them |
| 16:57 | AntelopeSalad | i was thinking of it as a worst case scenario like |
| 16:57 | AntelopeSalad | what if you pay for something in the game and then something happens with the process, the round isn't over yet |
| 16:57 | AntelopeSalad | if it crashes and restarts you lose what you paid for |
| 16:57 | antares_ | so they are batched in some shape or form. The difference is that if an OS process goes down, you lose a lot of state + need to reinitialize everything |
| 16:58 | antares_ | in Erlang, a process that goes down is usually monitored by another process and will be restarted |
| 16:58 | antares_ | (or not, it is up to developers) |
| 16:58 | antares_ | AntelopeSalad: changes that you pay for are probably not stored just in process |
| 16:58 | antares_ | AntelopeSalad: but 99% of state changes can be |
| 16:59 | AntelopeSalad | i see an item moving into your inventory as being a state change |
| 16:59 | antares_ | AntelopeSalad: that does not happen that often |
| 16:59 | antares_ | if you care, you can store that |
| 17:00 | antares_ | but movements that happen all the time, it makes no sense to try to store every single one of them |
| 17:00 | antares_ | that's just too wasteful |
| 17:00 | AntelopeSalad | yeah, i agree with that, trying to store every single one would be a bit much |
| 17:00 | antares_ | and if you crash it does not necessarily make sense to recover EVERYTHING |
| 17:00 | AntelopeSalad | it would only be useful if you wanted to make a full on replay of something |
| 17:01 | antares_ | AntelopeSalad: databases have buffers and periodically flush data to disk, nobody seems to be too concerned about that |
| 17:01 | antares_ | one database goes so far its clients do not check for network errors, and Web developers go gaga over its benchmarks |
| 17:01 | Apage43 | .. |
| 17:01 | AntelopeSalad | in most cases that is their job |
| 17:01 | antares_ | AntelopeSalad: but it's the same thing |
| 17:01 | emezeske | /join #erlang |
| 17:01 | antares_ | you cannot persist everything, it will be too time consuming |
| 17:02 | antares_ | so you choose what to store (in case of databases, fsync), apparently in many cases that is a tiny fraction of total state changes |
| 17:02 | AntelopeSalad | you might not need to persist everything, but you'll probably have to handle everything in your app |
| 17:02 | AntelopeSalad | like, player x moved from old-coords to new-coords |
| 17:03 | antares_ | so? |
| 17:03 | Cheiron | A java method requires Class as a parameter, how to pass that in clj? |
| 17:03 | Sgeo | ,(class Object) |
| 17:03 | clojurebot | java.lang.Class |
| 17:03 | AntelopeSalad | i was just getting that in the end you will transfering back and forth a lot of traffic |
| 17:03 | antares_ | Cheiron: (class x) or (Class/forName "String") |
| 17:04 | antares_ | AntelopeSalad: eh? |
| 17:04 | TimMc | Cheiron: Just write the classname. |
| 17:04 | antares_ | AntelopeSalad: no you won't. 99% of your state changes happen in-process. |
| 17:04 | antares_ | or at least they can |
| 17:04 | Cheiron | TimMC: using the class name is throwing classnotfoundexception |
| 17:04 | clojure | ohpauleez: so is ttt pretty zippy on the command line? |
| 17:04 | AntelopeSalad | client moves from old to new -- client sends that to the server -- server says ok, it's a legit movement back to the client -- client continues |
| 17:05 | antares_ | AntelopeSalad: well, if clients cannot talk to each other directly, there is no way around that |
| 17:05 | antares_ | a lot of state can even be stored on the client only (maybe not in multiplayer games, but just software) |
| 17:05 | ohpauleez | For those curious, here's a screencast of me using ttt and how to use it (2 min): http://www.pauldee.org/TTT-Intro.mov |
| 17:05 | dnolen | ohpauleez: oops that was my question, about ttt's on the command line. |
| 17:05 | AntelopeSalad | you might need to check vs a central server to make sure it's within a specific bounds |
| 17:05 | dnolen | ohpauleez: sweet! |
| 17:05 | ohpauleez | dnolen: ^ very zippy |
| 17:05 | antares_ | AntelopeSalad: and how is it different when your server is completely stateless? |
| 17:05 | AntelopeSalad | sort of like having validation code running on your server, of course you need it -- you can't just trust the client (javascript) straight up |
| 17:06 | antares_ | it is not but you send even more data around, for no good reason |
| 17:06 | antares_ | AntelopeSalad: again, why? |
| 17:06 | AntelopeSalad | yeah it's not different in the end |
| 17:06 | antares_ | because Ruby on Rails works that way? |
| 17:06 | dnolen | ohpauleez: are you going to publicize this or waiting to clean it up a bit? |
| 17:06 | AntelopeSalad | i have no idea, i never used rails |
| 17:06 | antares_ | of course you can (again, maybe not in games, but in general you can) |
| 17:06 | Apage43 | multiplayer games do a -lot- client side. The server is there mostly to make sure the things the clients say make sense (aren't cheating), and that they sync up. |
| 17:06 | nDuff | *nod*. |
| 17:06 | antares_ | in games client-side state means cheaters will try to exploit it |
| 17:06 | emezeske | antares_: Are you suggesting that you can leave validation to the client? |
| 17:07 | antares_ | but you sure can store and change a lot of the state in the client |
| 17:07 | ohpauleez | dnolen: I'm ok with people checking it out now, but I'm going to clean it up a little bit before I hit the list with it |
| 17:07 | antares_ | emezeske: absolutely |
| 17:07 | dnolen | ohpauleez: cool |
| 17:07 | nDuff | AntelopeSalad: ...you don't need to make the server validate _every_ move -- those can be batched. |
| 17:07 | antares_ | emezeske: the only case where it won't work is if you also have an API |
| 17:07 | nDuff | No point to making your app unnecessarily latency-sensitive. |
| 17:07 | ohpauleez | dnolen: The best piece of code in there is "blocking-deref" which I think is pretty essential for sane use of Node.js |
| 17:07 | AntelopeSalad | nDuff: yeah, i'm not a game dev -- i'm sure there's all sorts of tweaks you can do to minimize the back and forth traffic |
| 17:07 | AntelopeSalad | but it's something i want to persue in the future |
| 17:07 | dnolen | ohpauleez: is that a macro? |
| 17:08 | TimMc | Cheiron: You'll need to (:import ..) it then. |
| 17:08 | emezeske | antares_: Uh... |
| 17:08 | dnolen | ohpauleez: demo looks cool, and yeah, fun to see command line usage of Clojure that isn't glacial |
| 17:08 | antares_ | AntelopeSalad: on crappy mobile networks, again, a lot of state is kept in the client for at least some time |
| 17:08 | TimMc | Cheiron: or use the pacakge-qualified name. |
| 17:08 | antares_ | emezeske: Uh what? |
| 17:08 | ohpauleez | dnolen: Function - it just ticks Node.js until a promise is fulfilled |
| 17:08 | dnolen | ohpauleez: neat |
| 17:09 | dnolen | ohpauleez: sounds worthy of blog post |
| 17:09 | antares_ | emezeske: are you saying that nobody does that? How about lots-of-state-on-the-client libraries like Ember or even backbone? |
| 17:09 | ohpauleez | dnolen: it's coming :) |
| 17:09 | AntelopeSalad | antares_: handling a lot of state on the client seems worse for mobile dev |
| 17:09 | antares_ | AntelopeSalad: yeah? what will you do when your app detects there is no network connection? |
| 17:09 | AntelopeSalad | if you're talking about stiching up templates with js template libs, that's going to be put serious stress on a mobile device |
| 17:10 | AntelopeSalad | *stitching |
| 17:10 | emezeske | antares_: You made it sound like the server doesn't need to validate input it's receiving. If that's not what you mean, then fine. |
| 17:10 | Sgeo | I'm under the impression that multiplayer games sometimes do store quite a bit of state client-side that server doesn't check, because a bit of cheating is not as bad as having a server that barely runs because it needs to check everything |
| 17:10 | Sgeo | And using a lot of bandwidth and time for every frame that the client needs to display |
| 17:10 | ordnungswidrig | Sgeo: the server can batch-validate later |
| 17:10 | antares_ | AntelopeSalad: what will your super-neat server-based mobile app do when it has no network connection? it has to either keep state in the app for at least some time or drop it on the floor |
| 17:10 | AntelopeSalad | Sgeo: there's probably client side prediction to make it look smooth without crushing the server, but then every x frames or milliseconds it checks back to make sure you're in bounds |
| 17:11 | Sgeo | Can't batch-validate whether client is using semitransparent textures on walls in 3d games |
| 17:11 | emezeske | Sgeo: The server in a multiplayer game should check *all* state that could affect the outcome of the game |
| 17:11 | antares_ | so, it turns out, completely stateless apps is just one historically formed case with "traditional Web apps" |
| 17:11 | AntelopeSalad | antares_: i don't know, i don't develop for mobile devices yet |
| 17:11 | emezeske | Sgeo: Of course graphical state doesn't matter, e.g. in counterstrike source, the ragdoll physics are not synced among clients because they don't really affect the outcome |
| 17:11 | antares_ | with mobile clients, real-time games and data processing, in-process state is an important part of the equation |
| 17:12 | dnolen | ohpauleez: cool to see the datalog query lang, I checked out the core.logic bits seems like a nice and simple use case. |
| 17:12 | emezeske | Sgeo: For things like transparent texture hacking, they do a lot of hashing to check things server side, but obviously that's a cat and mouse game |
| 17:13 | ohpauleez | dnolen: I agree; it's a simple way to say, "Here's a quick way logic makes this easy" |
| 17:13 | Sgeo | But the possibility of cheating is still better than the alternative of having the server compute every bitmap and send it to the client |
| 17:13 | AntelopeSalad | antares_: in the case of losing connection, i have to guess that the server will keep everything in order and keep trying until it eventually either times out or the client comes back from the dead |
| 17:13 | ohpauleez | dnolen: I agree with martin - you can get pretty far with unify, binding-map, set, and filter |
| 17:13 | antares_ | AntelopeSalad: that's not what I am talking about |
| 17:13 | antares_ | AntelopeSalad: my network is down, the user added something in the app |
| 17:13 | antares_ | AntelopeSalad: what do you do if you cannot send a piece of data to your shiny node.js backend? |
| 17:13 | emezeske | Sgeo: Well, onlive did it the latter way (server computes everything), although they did not do well as a business |
| 17:14 | antares_ | AntelopeSalad: drop the change or keep it in the app until network access is back? I think the answer is obvious. |
| 17:14 | AntelopeSalad | antares_: in that case, keep it in the app for sure -- if we're talking about a content oriented web app that isn't really multi-player |
| 17:15 | AntelopeSalad | but "app" in this case would be javascript on the client most likely |
| 17:15 | antares_ | AntelopeSalad: so there you go, you are dealing with more sophisticated state changes. If that happens to include concurrency, bam, it's a lot of fun. Clojure is one of a few languages where state management is much more predictable, even with a lot of concurrency going on. |
| 17:16 | AntelopeSalad | i'm not sure why node would fail with that use case |
| 17:16 | antares_ | AntelopeSalad: javascript or not, the belief that all software is stateless or should be such is wrong |
| 17:16 | dnolen | ohpauleez: yep. lynaghk is working on some cool things it's giving me ideas for things to work on. |
| 17:16 | AntelopeSalad | your state would be partially stored in some client side code that is 100% isolated from the server -- the server choice at this point has no bearing |
| 17:16 | antares_ | AntelopeSalad: node tries to hide concurrent state management from you by only having 1 thread and callback soups everywhere |
| 17:17 | AntelopeSalad | it auto-spawns child processes and manages them internally, i don't know the exact details though |
| 17:17 | dnolen | ohpauleez: I think by making it clear how to build simple rules system maybe be a better entry point for most people than the raw miniKanren itself |
| 17:17 | Apage43 | wait what |
| 17:17 | antares_ | AntelopeSalad: yeah, I guess you never developed anything that's not a Web app and my point will not get across |
| 17:17 | ohpauleez | dnolen: We were just hacking on all that stuff this past weekend - you should have seen the whiteboard - so.much.core.logic. |
| 17:17 | antares_ | AntelopeSalad: it does not autospawn a thing |
| 17:17 | dnolen | ohpauleez: ah right, did you meat up with Kevin in NYC? |
| 17:17 | dnolen | ohpauleez: oh, your in Portland now right? |
| 17:18 | AntelopeSalad | antares_: if you use the cluster module it forks children and then has its own messaging system setup |
| 17:18 | antares_ | AntelopeSalad: maybe some servers do, again, this can be "automatic" only as long as there is no need to share any state and process interactions are trivial |
| 17:18 | ohpauleez | dnolen: I totally agree - more than happy to help with those efforts. Yeah, I'm out in Portland mostly full-time now |
| 17:19 | dnolen | ohpauleez: he's got some neat things he wants to do w/ the grammar of graphics stuff, a lot of it really can be done w/ simple unification + simple constraints (my new idea) |
| 17:19 | AntelopeSalad | antares_: i think that brings us in a full circle haha |
| 17:19 | antares_ | AntelopeSalad: but that's not Node. That's some cluster module. And fork(2) is an expensive operation. |
| 17:20 | AntelopeSalad | it might not be able to handle state in that case which is why people just throw their state in redis |
| 17:20 | AntelopeSalad | cluster is a core module for node |
| 17:20 | AntelopeSalad | just like http is a core module for node |
| 17:21 | ohpauleez | dnolen: For sure. I'd be interested in taking a look at what you cook up for simple constraints- it's one area of core.logic I haven't ventured into yet |
| 17:21 | Apage43 | I remember when it wasn't =P |
| 17:21 | Apage43 | that is, it used to be its own thing |
| 17:22 | Apage43 | it's been pulled into the standard distribution, but it doesn't do anything "special" to make it work well with node |
| 17:22 | Sgeo | Similarly to how lazy-seq exists, something for developers to make their own lazy-seq like things |
| 17:22 | Apage43 | it just sets up a way for you to message the leader, basically |
| 17:22 | AntelopeSalad | Apage43: yeah |
| 17:22 | AntelopeSalad | it works though |
| 17:22 | Sgeo | Such that client code does not have to deal with forcing |
| 17:22 | AntelopeSalad | and it's basically hands free once you set it up |
| 17:23 | Apage43 | right, assuming no shared state |
| 17:23 | AntelopeSalad | yep |
| 17:23 | dnolen | ohpauleez: basically a simple way to take any predicate and attach it to a var, soon as the var becomes ground it will run. This will let people say things like only unify if number, or if this class, etc. |
| 17:23 | AntelopeSalad | that's why everyone keeps their web servers statelesss |
| 17:23 | AntelopeSalad | and all of this stemmed from the TL;DR part of this: http://aphyr.com/posts/244-context-switches-and-serialization-in-node |
| 17:23 | ohpauleez | dnolen: YES!!! |
| 17:24 | Apage43 | because it sucks to write a stateful one in node =P |
| 17:24 | AntelopeSalad | he basically says it's not an issue if you keep state out of the app |
| 17:24 | ohpauleez | It's like you were sitting on my laptop last night |
| 17:24 | ohpauleez | I was in the weeds working on core.contracts+test.generative+Alloy and facing that exact situation |
| 17:24 | AntelopeSalad | Apage43: and in clojure it won't be a problem to run a multi-core/server stateful app? |
| 17:24 | AntelopeSalad | i haven't gotten to managing state and concurrency yet in the book |
| 17:25 | Apage43 | not nearly so much as in node, no |
| 17:25 | Apage43 | multi-server you have the same issues |
| 17:25 | Apage43 | but not with multi-core |
| 17:25 | AntelopeSalad | multi-server seems pretty standard to me |
| 17:25 | ohpauleez | dnolen: ^ (my current approach is a generic "spec" hashmap that gets unified and processed for each any backend. Making it open for extension) |
| 17:25 | antares_ | AntelopeSalad: I am convinced that Web developers run everything stateless because 1) they have never seen a different approach because Web devs only work on Web apps, 2) almost all modern languages suck at error handling and recovery, which is very important for in-app state |
| 17:26 | antares_ | it has nothing to do with "scaling out". Your state is still shared, you just shifted the bottleneck to the database. And once you have a few DB machines, the whole consistency/availability dance begins. |
| 17:26 | AntelopeSalad | no matter what choice you make, a single server is eventually going to crumble with enough pressure |
| 17:26 | ordnungswidrig | antares_: and today's web developers know only database for persistence. |
| 17:26 | nDuff | AntelopeSalad: Nobody is denying the need to scale to multiple servers. |
| 17:27 | antares_ | AntelopeSalad: cool, why again should I keep my app completely stateless? |
| 17:27 | Apage43 | AntelopeSalad: sure, but with the node-cluster approach you couldn't easily do something like distributing users over the works, but then giving the users affinity to a particular worker, and then just manage that state on that worker |
| 17:27 | technomancy | I dunno, I think people spend way too much time thinking "what if we become the next facebook" |
| 17:27 | Apage43 | *workers |
| 17:27 | antares_ | AntelopeSalad: I can keep it mostly stateful and sync when important evens happen |
| 17:27 | antares_ | *events |
| 17:27 | nDuff | ...trying to hard to keep things stateless means your caches aren't close to your requests |
| 17:27 | AntelopeSalad | Apage43: can't you use a load balancer that handles sticky sessions? |
| 17:27 | antares_ | that's what the presentation above basically demonstrates |
| 17:27 | Apage43 | AntelopeSalad: not with node-cluster.. |
| 17:28 | nDuff | so you move things out into memcached or such, but then you're going over a network rather than being able to refer to local memory. |
| 17:28 | AntelopeSalad | Apage43: why not? |
| 17:28 | Apage43 | because once it hits a server you don't get to pick what worker the connection goes to |
| 17:28 | nDuff | Apage43: ...well, that's not quite true; there are techniques for that. |
| 17:28 | Apage43 | since its dispatched before you know who it's from |
| 17:28 | AntelopeSalad | your clustered app is running on 1 port, it doesn't spawn a "real" new process |
| 17:29 | nDuff | Apage43: First person to get a request assigns a cookie. Cookie comes through on all future requests. Load balancer looks at it to pick first-choice handler. |
| 17:29 | AntelopeSalad | as far as your load balancer knows, it's just a single app (i would think, i never tested it full hand) |
| 17:29 | AntelopeSalad | *first |
| 17:29 | ivan | can I query postgres with datalog queries yet? |
| 17:30 | nDuff | ...oh, you're talking about separate-process workers being locally dispatched w/ something not as smart as HAProxy or such? Ugh. |
| 17:30 | antares_ | nDuff: this means now you have a stateful load-balancer ;) won't you want to scale load balancers once you become the next facebook? |
| 17:30 | AntelopeSalad | i don't even care about scaling right now haha |
| 17:30 | AntelopeSalad | i just didn't want to spent 50% more |
| 17:30 | AntelopeSalad | and you guys cleared it up that it won't be a direct 50% cost increase |
| 17:30 | nDuff | antares_: Yes, I have a stateful load balancer. There are damned good ones on the market -- but it doesn't need to be as stateful as you think, if it's just using a hash of the cookie for assignment. |
| 17:30 | wingy | technomancy: or they are just curious about how it works :) |
| 17:31 | antares_ | nDuff: I was kidding. "Smart proxies" definitely can solve some problems well, and there are good off-the-shelf solutions. |
| 17:32 | AntelopeSalad | nDuff: are you running any decently large sites atm with ring serving everything? |
| 17:32 | dnolen | ohpauleez: another thing would be "ghost" values |
| 17:33 | dnolen | ohpauleez: values which can be replaced by other values w/ failing unification |
| 17:33 | nDuff | AntelopeSalad: Nope. My last decently large site was a Django shop. Python's not exactly a high-performance language, not Django a high-performance stack... but it didn't matter, because we did a decent job at horizontal scaling. |
| 17:33 | nDuff | AntelopeSalad: Same thing applies here, except that the JVM is one helluva faster runtime than CPython. |
| 17:34 | dnolen | ohpauleez: w/o I mean |
| 17:34 | AntelopeSalad | can you give me a ballpark on how much traffic you guys had and how much it cost per month for hosting? |
| 17:34 | AntelopeSalad | doesn't need to be exact, just a rough estimate |
| 17:35 | ohpauleez | dnolen: ahh gotcha - would be useful when doing a lot of data-oriented unification |
| 17:37 | nDuff | AntelopeSalad: In PM. |
| 17:37 | wei_ | in clojure, you extend the reader by rebinding *data-readers*. how to do so in clojurescript? looks like *data-readers* is not bound. |
| 17:41 | dnolen | wei_: hasn't been done yet as far as I know. could be wrong |
| 17:42 | wei_ | i see, thanks |
| 17:44 | Cheiron | Hi, any idea what is this ? http://pastie.org/5120925 |
| 17:45 | scriptor | what's the code giving that error, Cheiron |
| 17:45 | Cheiron | trying to test Storm topology with Storm provided macros |
| 17:54 | riddochc1 | that feels like chaos |
| 17:54 | riddochc1 | SOrry. |
| 17:54 | riddochc1 | Wrong channel. |
| 17:55 | Cheiron | it it possible to exclude a namespace from :aot of lein? |
| 18:01 | technomancy | Cheiron: ...yes? |
| 18:02 | Cheiron | I checked the sample.project.clj |
| 18:02 | Cheiron | but didn't find an option to exclude a namespace from :aot |
| 18:02 | technomancy | :aot is a vector |
| 18:03 | technomancy | oh, you mean exclude it from :aot :all? there's nothing for that, no. |
| 18:04 | Cheiron | I see, thanks! |
| 18:05 | technomancy | I think :aot might support a vector of regexes as well though |
| 18:07 | aperiodic | it does |
| 18:10 | Cheiron | it does? so something like com.domain.* will compile the whole name space but not clojure.pprint ? |
| 18:11 | aperiodic | it will compile every namespace that match com.domain.* and any namespaces they use/require |
| 18:12 | aperiodic | as far as i know there's no way around that |
| 18:13 | Cheiron | I see |
| 18:14 | wingy | does aleph work with ring/compojure? |
| 18:14 | technomancy | yeah, that's a long standing clojure bug |
| 18:25 | ivan | wingy: pretty sure it does |
| 18:27 | Apage43 | wingy: you can even use compojure to route async stuff |
| 18:27 | Apage43 | see (wrap-ring-handler) and (wrap-aleph-handler) in the Aleph API |
| 18:28 | wingy | https://github.com/ztellman/aleph/wiki/HTTP |
| 18:28 | wingy | yeah .. nice |
| 18:28 | wingy | now i can choose when to do (a)synchronous handling |
| 18:28 | Apage43 | yup. |
| 18:30 | Apage43 | you can do stuff like use compojure to dispatch to a websocket handler |
| 18:31 | wingy | are there reasons to use jetty instead of aleph? seems like aleph scales better |
| 18:32 | tomoj | :( |
| 18:32 | Apage43 | well if you stick with pure ring, you get the rest of the servlet ecosystem |
| 18:32 | Apage43 | if you're into that kind of thing |
| 18:33 | Apage43 | you can spit out WAR files that you can just drop on any servlet-compatible container and have them go |
| 18:33 | xeqi | wingy: source? |
| 18:33 | wingy | okay .. im not familiar with WAR files and servlets .. have to read up on that |
| 18:34 | Apage43 | it's the sort of thing that's more valuable if you have lots of existing Java infrastructure |
| 18:34 | wingy | xeqi: coming from node.js where we learned async handling = higher performance |
| 18:35 | wingy | Apage43: i see |
| 18:36 | Apage43 | there are places where it's faster to just respond immediately, rather than do the whole async queueing hoopla, especially if its a request that you can fulfill very quickly (don't have to hit network or disk) and without much computation |
| 18:38 | Apage43 | async handling isn't magic, it's just a way of coordinating work that happens to make a lot of sense if you have lots of things that wait on other things |
| 18:40 | wingy | isnt that the case when doing web apps with a database? |
| 18:40 | emezeske | I feel like the disadvantages of async I/O aren't mentioned enough |
| 18:40 | emezeske | It makes things harder to debug, and opens you up to spaghetti callback code |
| 18:41 | emezeske | You can also introduce horrible problems by accidentally doing CPU-intensive work in the worker |
| 18:41 | Apage43 | ++ |
| 18:42 | Apage43 | yeah, there's a lot you have to be careful around |
| 18:42 | wingy | emezeske: what if you don't have to mess with callbacks |
| 18:42 | emezeske | wingy: All the other things still apply |
| 18:42 | technomancy | never thought I'd be so happy to see a proper stack trace after that |
| 18:42 | wingy | if you just wrap your functions with an async handler that will take care of putting your return value to the callback (https://github.com/ztellman/aleph/wiki/HTTP) |
| 18:43 | emezeske | technomancy: Exactly -- async callstacks are so not helpful |
| 18:43 | wingy | so it makes sense to just stick with jetty instead of aleph? |
| 18:43 | emezeske | wingy: Unless you have a very specific workload where jetty is just not working out for you? Yes. (IMHO) |
| 18:44 | wingy | lets just do that then .. jetty .. you are a damn lucky server |
| 18:44 | aperiodic | i get the impression that everybody who uses node.js writes their own idiosyncratic flow control library in order to avoid losing their mind |
| 18:45 | emezeske | aperiodic: Yep! Everyone ultimately tries to create a synchronous-looking API on top of the async :) |
| 18:45 | Apage43 | aperiodic: not everyone, a lot of them have already lost their minds and have become comfortable with it :) |
| 18:45 | wingy | everyone is using async.js |
| 18:46 | emezeske | aperiodic: haha |
| 18:47 | wingy | the fact is that i feel synchronous coding where you don't have to think about server arhictecture is better .. you just focus on the domain problem |
| 18:47 | emezeske | wingy: Synchronous code is undoubtedly easier to read. |
| 18:48 | Apage43 | and reason about |
| 18:48 | wingy | screw scaling .. i want a happy life :) |
| 18:49 | emezeske | wingy: You can scale both ways |
| 18:53 | tomoj | async.js seems way off |
| 18:56 | wingy | tomoj: it's whatever node.js needs it to be |
| 18:59 | dnolen | ohpauleez: LOGIC-63 resolved |
| 18:59 | ohpauleez | dnolen: Excellent, I'll take a look at the ticket now to see the resolution, I'm definitely curious |
| 18:59 | dnolen | ohpauleez: typo :P |
| 19:00 | ohpauleez | :( |
| 19:00 | ohpauleez | dnolen: I apologize |
| 19:00 | dnolen | ohpauleez: from copy and pasting Clojure into ClojureScript, -withMeta -> -with-meta |
| 19:00 | dnolen | ohpauleez: on LCons deftype |
| 19:00 | dnolen | ohpauleez: nah, wasn't obvious |
| 19:00 | Sgeo | Why does tryclj allow def and the bots don't? |
| 19:00 | ohpauleez | Ahh that makes sense |
| 19:01 | dnolen | ohpauleez: thanks for actually trying / using core.logic on CLJS :) |
| 19:01 | ohpauleez | dnolen: Thank you for providing me with something to try! |
| 19:06 | technomancy | Sgeo: probably because everyone in the channel shares a sandbox with lazybot |
| 19:06 | Raynes | Sgeo: Well clojurebot doesn't use clojail, so it has no def sandboxing at all. |
| 19:06 | technomancy | whereas tryclj can build the notion of a session |
| 19:06 | Raynes | Sgeo: On tryclj, everyone gets their own sandbox. In this channel, everybody shares a single sandbox. |
| 19:06 | Raynes | Sgeo: It is entirely possible to make lazybot work like tryclj, I just haven't done it. |
| 19:09 | dnolen | ohpauleez: whenever I work on core.logic on CLJS - I realize, CLJS is pretty freaking awesome. |
| 19:10 | ohpauleez | dnolen: It really is incredible - the reader, protocols, rich data types, and macros - you can pretty much build anything |
| 19:11 | dnolen | ohpauleez: LOGIC-61 resolved |
| 19:11 | dnolen | ohpauleez: I think that's it for your CLJS tickets |
| 19:12 | ohpauleez | dnolen: Thank you so much, definitely very helpful (I needed partial-map for something) |
| 19:12 | dnolen | ohpauleez: partial maps will no longer escape, really meant to be used internally anyway. They always become regular maps when they become a result |
| 19:13 | ohpauleez | excellent, that totally works for me |
| 19:39 | dnolen | core.logic 0.8.0-beta2 going out |
| 19:40 | pandeiro | dnolen: know anything about elm? |
| 19:40 | dnolen | pandeiro: yeah I saw a presentation about it at ELC |
| 19:40 | dnolen | at StrangeLoop |
| 19:41 | pandeiro | just discovered it, some interesting ideas applicable to cljs dev |
| 19:41 | technomancy | which one was presented first? |
| 19:42 | dnolen | technomancy: Elm was I think |
| 19:42 | dnolen | pandeiro: what in particular? |
| 19:42 | pandeiro | dnolen: functional reactive programming |
| 19:43 | technomancy | elm was the more reactive one, yeah |
| 19:43 | technomancy | that was rockin' |
| 19:44 | pandeiro | something like Mouse.position always having the cursor's coords, is that really 'functional'? |
| 19:44 | pandeiro | i am not interested in paradigm purity, just trying to understand things |
| 19:44 | dnolen | pandeiro: it's very interesting I'd like to see much more non-trivial examples though. I also wasn't sold on hiding the details of the platform |
| 19:45 | dnolen | pandeiro: my impression was a FP version of Lively Kernel but much less mature. |
| 19:45 | pandeiro | dnolen: i am torn on that b/c it seems js can be so low level for a high level language |
| 19:45 | pandeiro | the way you have to do things |
| 19:45 | pandeiro | the need for jquery |
| 20:06 | ohpauleez | To those interested in learning more about ClojureScript+Node.js |
| 20:06 | ohpauleez | http://www.pauldee.org/blog/2012/clojurescript-and-node-js-an-experience-report/ |
| 20:15 | wingy | is there a way to add a key/value pair to a map if the key value pair is inside a list or vector? |
| 20:15 | wingy | [key value] |
| 20:16 | black_joe | (keyword) will convert data of another type into a key. |
| 20:16 | Raynes | Not what he wants. |
| 20:16 | wingy | nope |
| 20:17 | Raynes | &(apply assoc {:a :b] [:c :d]) |
| 20:17 | lazybot | java.lang.RuntimeException: Unmatched delimiter: ] |
| 20:17 | Raynes | &(apply assoc {:a :b} [:c :d]) |
| 20:17 | lazybot | ⇒ {:c :d, :a :b} |
| 20:17 | Raynes | wingy: ^ |
| 20:17 | wingy | (some-fn {} [key value]) ;=> {key value} |
| 20:17 | jkkramer | &(conj {:a :b} [:c :d]) |
| 20:17 | lazybot | ⇒ {:c :d, :a :b} |
| 20:18 | Raynes | Huh, cool. |
| 20:18 | wingy | jkkramer: there you go |
| 20:18 | jkkramer | &(conj {:a :b} '(:c :d)) ;but not this |
| 20:18 | lazybot | java.lang.ClassCastException: clojure.lang.Keyword cannot be cast to java.util.Map$Entry |
| 20:19 | wingy | yeah vector only |
| 20:25 | Sgeo | Are there any good libraries for making lazy data types and functions to operate on them? |
| 20:32 | dnolen | ohpauleez: nice post |
| 20:32 | ohpauleez | dnolen: Thanks, I hope people find it useful (and don't mind the bits of passive voice use) |
| 20:34 | ivan | does tools.nrepl support any kind of incremental response? I'd like to write command-line tools that don't want for all of stdout before writing something |
| 20:53 | Sgeo | When is it appropriate to use get? |
| 20:53 | Sgeo | (doc get) |
| 20:53 | clojurebot | "([map key] [map key not-found]); Returns the value mapped to key, not-found or nil if key not present." |
| 20:58 | ohpauleez | Sgeo: When your key is not a keyword |
| 20:58 | ohpauleez | or when your collection can be a number of things (all that support get) |
| 20:58 | Sgeo | ,({1 2 3 4} 1) |
| 20:58 | clojurebot | 2 |
| 20:59 | ohpauleez | ,([1 2 3 4] 1 2) |
| 20:59 | clojurebot | #<ArityException clojure.lang.ArityException: Wrong number of args (2) passed to: PersistentVector> |
| 20:59 | Sgeo | ,(get [1 2 3 4] 1 2) |
| 20:59 | ohpauleez | ,(get [1 2 3 4] 6 2) |
| 20:59 | clojurebot | 2 |
| 20:59 | clojurebot | 2 |
| 21:00 | ohpauleez | ,(get {"a" 1} "a" 2) |
| 21:00 | clojurebot | 1 |
| 21:00 | jamii | I keep getting bitten by this: |
| 21:00 | jamii | secd.core> NIL |
| 21:00 | jamii | #secd.core.NIL-I{} |
| 21:00 | jamii | secd.core> (class NIL) |
| 21:00 | jamii | secd.core.NIL-I |
| 21:00 | jamii | secd.core> (class #secd.core.NIL-I{}) |
| 21:00 | jamii | clojure.lang.PersistentArrayMap |
| 21:00 | ohpauleez | ,(get {"a" 1} "b" 2) |
| 21:00 | clojurebot | 2 |
| 21:00 | ohpauleez | Sgeo: does that help? |
| 21:00 | Sgeo | Yes |
| 21:01 | ohpauleez | excellent |
| 21:01 | ohpauleez | jamii: What is it you're trying to do? |
| 21:01 | technomancy | Sgeo: OTOH calling the map without get will do the same thing |
| 21:01 | technomancy | so get is typically used if the map might be nil |
| 21:01 | ohpauleez | jamii: Ohh, nil is lowercase |
| 21:01 | technomancy | and you're looking up a non-keyword key |
| 21:02 | ohpauleez | yes |
| 21:02 | ohpauleez | I use it most in threading macros |
| 21:02 | ohpauleez | for that reason |
| 21:02 | jamii | ohpauleez: this is a record called NIL. The name is not important. The problem is whenever you use record literals to construct a record that has zero args, the resulting object is a map. |
| 21:02 | jamii | ohpauleez: Which breaks protocol dispatch |
| 21:02 | amalloy | technomancy: get can probably optimize better than calling the map as well |
| 21:03 | gfredericks | what are records that have zero args? |
| 21:03 | ohpauleez | jamii: Definitely sounds like a bug to me. Is there any literature against creating Records of zero args? |
| 21:03 | gfredericks | (defrecord Foo [] ...)? |
| 21:03 | ohpauleez | gfredericks: My thought too |
| 21:03 | gfredericks | the point is to have a mappish thing of a custom type, but not caring about any particular fields? |
| 21:04 | amalloy | on reflection i don't think that's true actually, never mind |
| 21:04 | ohpauleez | jamii: Would you better served with deftype? |
| 21:04 | jamii | ohpauleez: deftypes don't have literals at all, so I can't prn and then read them |
| 21:05 | ohpauleez | jamii: You could define reader-literals (if you're ok using 1.5.0-beta1) |
| 21:05 | ohpauleez | actually - they're in 1.4 too |
| 21:06 | jamii | secd.core> (class `~NIL) |
| 21:06 | jamii | secd.core.NIL-I |
| 21:06 | jamii | secd.core> (class (eval `~NIL)) |
| 21:06 | jamii | clojure.lang.PersistentArrayMap |
| 21:06 | ohpauleez | and if you need the the reader, what's wrong with using nil, which would give you the protocol dispatch |
| 21:07 | amalloy | jamii: `~x is always identical to x |
| 21:07 | jamii | amalloy: ok, so this is the core of the problem |
| 21:07 | jamii | secd.core> NIL |
| 21:07 | jamii | #secd.core.NIL-I{} |
| 21:07 | jamii | secd.core> (eval NIL) |
| 21:07 | jamii | {} |
| 21:08 | jamii | Compared to: |
| 21:08 | jamii | secd.core> (SEL 't 'f) |
| 21:08 | jamii | #secd.core.SEL-I{:then t, :else f} |
| 21:08 | jamii | secd.core> (eval (SEL 't 'f)) |
| 21:08 | jamii | #secd.core.SEL-I{:then t, :else f} |
| 21:08 | jamii | Records with zero args eval to maps, not themselves |
| 21:08 | amalloy | why are you calling eval on a defrecord? like, agreed it probably shouldn't behave this way, but... |
| 21:08 | gfredericks | record literals in the code get eval'd right? |
| 21:09 | jamii | amalloy: I'm splicing a record into a macro. Then trying to figure out why the result has a map in it. |
| 21:10 | jamii | amalloy: https://www.refheap.com/paste/6177 |
| 21:12 | jamii | I think record literals with zero args are broken and splicing in macros is just one of the places it shows up |
| 21:13 | gfredericks | jamii: this isn't actually a blocker for you, right? you could emit a call to the constructor instead? |
| 21:13 | amalloy | well '(run NIL empty-registers) isn't the same as `(run ~NIL ~x), it's the same as `(run ~'NIL ~x) |
| 21:13 | jamii | gfredericks: I'm just playing around anyway so its not blocking anything important. |
| 21:14 | jamii | amalloy: ok, say we do this the other way around |
| 21:15 | jamii | amalloy: huh, thats interesting - this actually works |
| 21:16 | jamii | https://www.refheap.com/paste/6178 |
| 21:17 | jamii | But this doesn't: https://www.refheap.com/paste/6179 |
| 21:17 | Sgeo | I should set up an IRC bot based on .... a UMLbox bot in another channel |
| 21:17 | Sgeo | Would be nice to have a Clojure bot where defmacro works |
| 21:17 | amalloy | of course. in the first, instr is the symbol NIL, and in the other it's the value of NIL in your namespace |
| 21:18 | amalloy | you want the symbol, not the value, so what happens when you eval a record shouldn't be relevant to you |
| 21:18 | jamii | amalloy: Right. Except I am actually using eval at runtime.... :) |
| 21:19 | jamii | amalloy: Ok, so what I'm actually trying to probably do doesn't make much sense and I'm not at all blocked on this. I'm just trying to verify that the eval behaviour is wrong. |
| 21:19 | amalloy | looks wrong to me |
| 21:19 | jamii | amalloy: ok |
| 21:19 | jamii | So I'm sane |
| 21:19 | jamii | Huzzah |
| 21:20 | jamii | amalloy: the code that ran into this was (eval `(fn [registers#] (run ~(vary-meta form assoc :tag (class form)) registers#))) |
| 21:20 | jamii | amalloy: Since I have to run those instructions a couple of thousand times I was wondering if it would be faster to replace them by a clojure where the dispatch was already known |
| 21:21 | jamii | amalloy: But it doesn't work because the zero-arg instructions eval to {} in the above |
| 21:21 | Sgeo | o.O eval is broken? |
| 21:21 | jamii | Sgeo: I think so? Records should probably eval to themselves |
| 21:24 | jamii | Aha - http://dev.clojure.org/jira/browse/CLJ-1093 |
| 21:25 | jamii | Workaround - (eval (assoc NIL :dummy nil)) |
| 21:34 | wingy | is it possible to use clojure to make android apps? |
| 21:35 | Raynes | Yes. |
| 21:36 | Raynes | https://github.com/alexander-yakushev/lein-droid |
| 21:36 | wingy | thx |
| 21:47 | tbaldridge | so, I'm trying to install the clojure-starter-kit for emacs 24.2 on osx (in terminal mode) |
| 21:47 | tbaldridge | for some reason it's not doing anything at all |
| 21:47 | tbaldridge | I'm doing this: https://github.com/technomancy/clojure-mode/blob/master/README.md |
| 21:48 | tbaldridge | but emacs complains that "clojure-mode is not available for install" |
| 21:48 | tbaldridge | any ideas? |
| 21:52 | tbaldridge | so for the logs...aparently it's M-x package-install starter-kit |
| 22:39 | Sgeo | Oh hey, Clojure Conj is in NYC? |
| 22:40 | Sgeo | Oh, it differs every year. Darn. |
| 22:42 | TimMc | Has it ever been in NYC? |
| 22:44 | amalloy | no |
| 22:44 | TimMc | That's what I thought. |
| 22:45 | Sgeo | Hmm, what is http://www.meetup.com/Clojure-NYC/events/16166984/ |
| 22:54 | ToBeReplaced | what does "Core was generated by `java -client -XX:+TieredCompilation -Xbootclasspath/a:/home/ToBeReplaced/.lein/'" mean? |
| 22:55 | TimMc | Sgeo: "NYC Clojure Users Group" - "Clojure Conj 2011 Roundup" |
| 22:55 | TimMc | Deviously misleading title, I'll agree. |
| 22:56 | Sgeo | Oh. |
| 22:56 | Sgeo | Well, hey, at least I learned there's an NYC Clojure users group |
| 22:56 | Sgeo | Wonder if I should try going |