2014-01-10
| 00:05 | amalloy | ## |
| 00:05 | amalloy | or a single & at the start of the message |
| 00:05 | rplaca | amalloy: why not write a macro to flip the let around? I don't think that would be too hard and it would be way more obvious to the reader what you were trying to do |
| 00:05 | amalloy | rplaca: i'm not excited about actually using this where construct, with the ->> trick or with a real macro |
| 00:06 | amalloy | just surprised to note that clojure could easily fake where "out of the box" |
| 00:06 | rplaca | amalloy: there's always that. It does seem nice in Haskell, but I'm not sure it would work (mentally) in Clojure |
| 00:07 | amalloy | rplaca: the problem with a where macro in clojure is that syntactically it can't come in the same place it does in haskell |
| 00:07 | amalloy | you have to write (with-where (+ x y) (where [x 1 y 2])) or something equally horrific |
| 00:07 | Wild_Cat | Haskell's where is a very postfix-ish contruct |
| 00:07 | rplaca | true, since you need a toket in the function position |
| 00:07 | rplaca | *token |
| 00:07 | amalloy | and ->> neatly fills that role |
| 00:07 | arrdem | damnit. Do "we" have any details on Clojure/west yet? |
| 00:08 | Wild_Cat | I think Clojure's standard "let" form is far cleaner. |
| 00:08 | amalloy | of course |
| 00:08 | rplaca | arrdem: last I heard, Alex was finalizing arrangements |
| 00:08 | amalloy | although haskell's works well in haskell |
| 00:08 | rplaca | amalloy: +1 |
| 00:08 | arrdem | rplaca: awesome. we have a place and date. |
| 00:08 | arrdem | (inc rplaca) |
| 00:08 | lazybot | ⇒ 1 |
| 00:08 | Wild_Cat | in Haskell though, where feels more natural than let. |
| 00:09 | rplaca | arrdem: I think it's going to be SF. That's what ALex told me last I asked him about it, but that was back around the conj |
| 00:09 | rplaca | dunno the dates |
| 00:09 | arrdem | rplaca: yep. |
| 00:09 | arrdem | March 24->26 |
| 00:09 | rplaca | ahh, cool |
| 00:10 | arrdem | which means that I can apply to get funding from the Department to come out :D |
| 00:10 | rplaca | I was hoping we'd do Portland again, but I guess I can't complain too much about SF |
| 00:17 | bitemyapp | Wild_Cat: partly because it lets you say upfront what you're going to return, overall, then where lets you describe how that got put together. |
| 00:19 | seancorfield | The Palace Hotel is really nice - MongoSF was there in 2013 |
| 00:22 | logic_prog | dnolen: someone needs to write a core.async cookbook |
| 00:22 | logic_prog | dnolen: of all the pattenrns that (1) are hell with callbacks and (2) have really neat core.async solutions via csp |
| 00:24 | bbloom | amalloy: thanks! that msg is more for dnolen |
| 00:24 | amalloy | bbloom: i sent it to you because you're the one who committed the code |
| 00:24 | amalloy | but hey, if it's for him, let him know |
| 00:24 | bbloom | amalloy: really? i did? |
| 00:25 | amalloy | bbloom: https://github.com/clojure/clojurescript/commit/af4ab91754d30f082b117b40c07ea94d0063c0d6 |
| 00:25 | bbloom | amalloy: oh hey, i did. |
| 00:25 | bbloom | look at that, lol |
| 00:26 | bbloom | amalloy: is there a ticket? |
| 00:26 | amalloy | not as far as i know |
| 00:26 | bbloom | i've been drinking & am gonna wonder away from my desk now, but i don't want your bug report to go missing :-P |
| 00:26 | amalloy | seangrove just pasted a stacktrace of breakage, and i tracked it down to this code for him |
| 00:27 | bbloom | amalloy: thanks |
| 00:27 | bbloom | amalloy: if you or seangrove can open a ticket, that would be awesome. sorry i can't be more help now. thanks! |
| 00:28 | seangrove | bbloom: Enjoy your drinking! |
| 00:55 | ddellacosta | really confused by this exception: Exception in thread "main" java.lang.IllegalAccessError: get-header does not exist, compiling:(not_modified.clj:1:1) <-- seems to be referring to ring.middleware.not-modified, which refers to ring.util.response/get-header. What could be causing this? Full exception: https://www.refheap.com/22750 |
| 00:58 | rplaca | seancorfield: is ClojureWest going to be at the Palace or are you just saying it would be good there? |
| 01:01 | TEttinger | ddellacosta, that's odd https://github.com/ring-clojure/ring/blob/master/ring-core/src/ring/util/response.clj it is defined right? |
| 01:02 | seancorfield | rplaca: look at the clojurewest.org website |
| 01:02 | seancorfield | it lists the hotel and dates |
| 01:02 | ddellacosta | TEttinger: yeah. I'm poking around lein reps now...think it's probably something in a specific profile that's conflicting...older version of ring maybe? |
| 01:02 | seancorfield | oh, actually the website doesn't say... but alex's announcement on the mailing list did |
| 01:02 | TEttinger | https://github.com/ring-clojure/ring/commit/52c11854f6050a2a4a9261c6e77acf265b0b194e#diff-84b6775eb77642c1afe9b5745af47a2f |
| 01:03 | TEttinger | ddellacosta, that commit, 10 months ago, added it |
| 01:03 | ddellacosta | TEttinger: huh, surprised it was even that recent |
| 01:04 | TEttinger | it's present in 1.2.0 |
| 01:05 | TEttinger | (and everything newer) |
| 01:05 | ddellacosta | TEttinger: pooh, I figured it out...include from another private project of ours. Nevermind :-p |
| 01:05 | ddellacosta | pooh -> ooh |
| 01:05 | seancorfield | rplaca: here you go: https://groups.google.com/forum/#!topic/clojure/HaZVWRiDEAM ;; Clojure/West announcement |
| 01:05 | ddellacosta | damn spellcheck |
| 01:06 | rplaca | arrdem: did you see that post from seancorfield - that's the pointer you were looking for |
| 01:07 | rplaca | seancorfield: you're on the bleding edge there - I'm not keeing up with the list that well these days :) |
| 01:07 | rplaca | *bleeding, keeping |
| 01:07 | rplaca | thanks! |
| 01:07 | rplaca | I like that choice, cause I can walk to it from my house. |
| 01:08 | seancorfield | I can walk to BART and ride that to SF :) |
| 01:08 | seancorfield | And it is a *lovely* venue! |
| 01:09 | seancorfield | I'd submit a topic proposal but I'm already committed to creating two new presos for conferences in May / June :( |
| 01:10 | rplaca | seancorfield: I'll have to think about whether I've got something worth submitting |
| 01:12 | xpika | The function read-string reads a single form. Is there a core clojure function that reads multiple forms like those in a .clj file? |
| 01:28 | sm0ke | how does one writes a recursive macro? |
| 01:29 | sm0ke | i am trying to write on with top level form as 1() |
| 01:29 | sm0ke | `() * |
| 01:32 | sm0ke | ,(defmacro weird-macro [&body] `(~@body (weird-macro))) |
| 01:32 | clojurebot | #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: body in this context, compiling:(NO_SOURCE_PATH:0:0)> |
| 01:32 | sm0ke | ,(defmacro weird-macro [& body] `(~@body (weird-macro))) |
| 01:32 | clojurebot | #'sandbox/weird-macro |
| 01:32 | sm0ke | ,(weird-macro (inc 1)) |
| 01:32 | clojurebot | #<CompilerException java.lang.StackOverflowError, compiling:(NO_SOURCE_PATH:0:0)> |
| 01:33 | sm0ke | oh did that worked! |
| 01:46 | arrdem | rplaca: thanks to insomnia I just did :D |
| 02:52 | andyf | bitemyapp: I saw in the logs a mention of a desire for eastwood to complain about :use |
| 02:58 | bitemyapp | andyf: yes |
| 02:59 | andyf | I am guessing no warnings are desired for a use with :only, only for a use that sucks in the whole namespace? |
| 03:06 | arrdem | andyf: personally I would object to any use of (use) over (requrire), but silencing a linter with :only is I suppose reasonable. |
| 03:07 | andyf | arrdem: I'd prefer to warn about the most dangerous uses only, in hopes that people will avoid just turning off those warnings. |
| 03:08 | andyf | arrdem: You don't even do (;use clojure.test) in your test namespaces? |
| 03:08 | arrdem | andyf: nope. I actually sumitted a patch to the lein template which replaces that (use) :P |
| 03:09 | arrdem | only useful patch I've got live anywhere but so be it. |
| 03:09 | andyf | arrdem: So you :require :refer [is] ? |
| 03:09 | arrdem | andyf: yep. |
| 03:09 | arrdem | andyf: occasionally I'll do a :refer :all if I know what I'm doing, but it's something I try to avoid. |
| 03:14 | mark_oz | hey guys, I'm having a bit of a problem with pulling a symbol from a map https://gist.github.com/markgandolfo/5adf492f5ad12d8af322 |
| 03:15 | mark_oz | can anyone lend some experience? |
| 03:16 | arrdem | mark_oz: that's not a map, that's a list containing a map. |
| 03:16 | andyf | Try (:title (first post)) ? Looks like post is a sequence of one map, from the parens around it |
| 03:16 | arrdem | ^^ this |
| 03:17 | mark_oz | thanks guys, that worked |
| 03:58 | bitemyapp | andyf: just suggest rewriting use with :only to require. |
| 03:58 | andyf | because? |
| 03:59 | bitemyapp | andyf: the safe thing is to expect use to get deprecate.d |
| 03:59 | bitemyapp | it's not orthogonal and people should phase it out of their code. |
| 03:59 | bitemyapp | it sets a very bad default. |
| 03:59 | bitemyapp | I'd do the same to Haskell's import if I had my druthers. |
| 03:59 | bitemyapp | sadly, they get away with it because they have an exceptional type system and compiler. |
| 04:01 | andyf | I'll consider it. Just working through the surprisingly-many cases of a use without :only right now. Trying to recognize them all. |
| 04:02 | andyf | Although I should simplify my life by assuming Clojure itself hasn't complained about it. |
| 04:02 | arrdem | bitemyapp: well... all done. ish. http://arrdem.com/2014/01/10/Batbridge.html |
| 04:25 | noncom | when using tools.namespace, i cannot predict its behavior. i have a project in "checkouts" of lein, and tools.namespace seem to fail finding the namespaces of the referred project in an arbitrary manner |
| 04:26 | noncom | if i manually load the ns that cannot be found, it then works |
| 04:27 | noncom | how do i make the tools.namespace/refresh to find all the files? |
| 04:45 | rurumate | ,"hi" |
| 04:45 | clojurebot | "hi" |
| 04:47 | arcatan | "hi" |
| 04:59 | mullr | :salutations |
| 05:06 | ddellacosta | mullr: hello. |
| 05:11 | sveri | hi, i am trying to use the c2 (http://keminglabs.com/c2/) library and like to draw a polyline, however, i have not found an example or something similiar, how would i do that with c2? any ideas? |
| 06:00 | Arafangion | it isn't that hard to learn most languages though. |
| 06:00 | Arafangion | if i needed to work in a project, i would learn the language - might not be elegant at first but it isnt a big deal. |
| 06:24 | AeroNotix | has anyone used Authorize.Net from clojure and/or is there already a library for it? |
| 06:25 | fizruk | hello guys! what's the easiest way (with clj-time) to check whether to dates are separated by midnight (e.g. 31 Dec 2013 23:59:59 and 01 Jan 2014 00:00:01)? |
| 06:29 | augustl | AeroNotix: my first action would be to google for a Java lib for that |
| 06:29 | AeroNotix | augustl: there is. They provide it. |
| 06:29 | augustl | AeroNotix: and possibly just write that part in Java if that for some reason is less work |
| 06:29 | AeroNotix | augustl: no, java is never Less Work |
| 06:29 | augustl | perhaps they have a finished servlet you can just tack on to your exiting servlet, for handling the callbacks and such |
| 06:30 | AeroNotix | I've been looking at the docs. It's just classes which map to their SOAP API |
| 06:30 | AeroNotix | I just wanted to know if there was a better way. |
| 06:31 | augustl | fizruk: as in if they represent different days in a given time zone? |
| 06:31 | augustl | fizruk: or that they are adjacent days in a given time zone? |
| 06:32 | fizruk | augustl: different days in a given time zone, not always adjacent |
| 06:36 | fizruk | augustl: I wish I could truncate datetime to date, can I do that? |
| 07:36 | jtoy | is it possible to do this: from ns A include ns B , then if other namespaces use A, they can use the methods from ns B ? |
| 07:38 | jballanc_ | jtoy: should be able to do that with anything you "use" or ":refer" |
| 07:40 | otfrom | Does anyone have an example of integrating friend and liberator? |
| 07:40 | otfrom | I know sritchie has been working on some stuff |
| 08:00 | sveri | hi, i am trying to use the c2 (http://keminglabs.com/c2/) library and like to draw a polyline, however, i have not found an example or something similiar, how would i do that with c2? any ideas? |
| 08:25 | rurumate | I want to write this with swiss-arrows but it fails: (-<> 2 (+ 4 (inc <>))) |
| 08:25 | rurumate | this works: (-<> 2 (+ 4 <>)) |
| 08:26 | rurumate | Why can only use <> in the top level of expressions? Is there an alternative macro where the diamond can appear in nested forms? |
| 08:26 | fredyr | holy threading batman |
| 08:27 | mdrogalis | Looked at this before I had my coffee. Brain broken. |
| 08:27 | fredyr | haven't seen swiss-arrows before |
| 08:31 | fredyr | the doc string says top-level insertion of x in place of single |
| 08:31 | fredyr | positional '<>' symbol |
| 08:36 | edbond | fizruk, try (to-date) and compare |
| 08:37 | fizruk | edbond: thanks! |
| 08:45 | edbond | fizruk, I was wrong, you need to extract year, month, date and compare them |
| 08:45 | edbond | (year (fmt/parse (fmt/formatter "yyyy-MM-dd HH:mm:ss") "2013-12-31 23:59:59")) ;; 2013 |
| 08:47 | edbond | ((juxt year month day) d1) ;; [2013 12 31] |
| 08:48 | fizruk | fortunately, one of two dates I deal with is (now), so I just used (after? (today-at-midnight) dt) |
| 08:48 | fizruk | nevertheless, it seems that clj-time lacks date truncation functions |
| 08:51 | DerGuteMoritz | ohai edbond :-) |
| 08:51 | edbond | DerGuteMoritz, hello :) |
| 08:52 | DerGuteMoritz | long time no see :-) |
| 09:02 | ro_st | dnolen: what could prevent cljsbuild :none incremental builds? we're getting 10s a build even with a single change to a single ns |
| 09:02 | ro_st | what's the best way to dig into why it's so slow? |
| 09:03 | ro_st | cljs "0.0-2138" / cljsbuild "1.0.1" |
| 09:05 | jcromartie | in Light Table, where can I see errors related to connections? |
| 09:05 | jcromartie | i.e. I am trying to connect to a project but it fails silently |
| 09:08 | CookedGryphon | jcromartie: there's a little red box near the bottom of the screen with a number in it (the number of errors* |
| 09:08 | CookedGryphon | click that to bring up the console |
| 09:12 | john2x | hello. is there a leiningen plugin for colored input/output for the repl? |
| 09:12 | jcromartie | the console doesn't show anything when I add a connection to a project.clj |
| 09:13 | jcromartie | it is just silent, like it isn't even trying |
| 09:13 | jcromartie | does it just not work? |
| 09:13 | jcromartie | or do I misunderstand what "add connection" does? |
| 09:13 | jcromartie | I'd expect it to open a REPL |
| 09:15 | CookedGryphon | jcromartie: try pressing ctrl + enter in a file |
| 09:15 | CookedGryphon | i've not played with it much myself, but i remember being a little confused by that, but evaluating something in a file loaded it automatically |
| 09:15 | jcromartie | hm, so it doesn't connect until you Ctrl + Enter |
| 09:17 | jcromartie | but, yeah, it's working for my app! yay |
| 09:17 | jcromartie | I am still a fan of Emacs with Cider |
| 09:18 | jcromartie | just because it's familiar |
| 09:18 | CookedGryphon | i haven't even taken the time to move from nrepl yet |
| 09:18 | ro_st | i'm happy to wait 6 months for the community to build LT up |
| 09:18 | CookedGryphon | too much work to do to be faffing around with my setu |
| 09:18 | CookedGryphon | setup* |
| 09:18 | ro_st | losing magit is going to be hard to deal with |
| 09:19 | CookedGryphon | LT does look promising though |
| 09:19 | ro_st | very! |
| 09:19 | CookedGryphon | being able to write plugins in clojure rather than elisp opens up a *lot* of avenues |
| 09:19 | jcromartie | :P |
| 09:19 | CookedGryphon | so many things I've wanted my editor to do but got fed up of elisp |
| 09:19 | jcromartie | I see that there's a paredit plugin and commands, but no default keybindings? |
| 09:19 | ro_st | i feel like i've paid my school fees for emacs now |
| 09:20 | ro_st | did the trial-by-fire of learning the paredits binds |
| 09:20 | CookedGryphon | ro_st: you can move those all over to light table! |
| 09:20 | CookedGryphon | in theory, I haven't managed to get the emacs bindings to work yet |
| 09:20 | ro_st | the paredit in LT is not the paredit that's in emacs |
| 09:20 | jcromartie | no |
| 09:21 | ro_st | some stuff is there, but no ways is there all of it |
| 09:21 | CookedGryphon | ro_st: so make them match, the keybinding action stuff is so so easy compared to emacs |
| 09:21 | CookedGryphon | you can just add stuff as you miss it |
| 09:21 | ro_st | like you, i have far too much work to do |
| 09:21 | CookedGryphon | but yeah, I'm going to give it another release or two |
| 09:21 | ro_st | heck, we only just moved to cljsbuild 1.0.1 this week |
| 09:23 | ro_st | i experienced the warm glow that is working cljs sourcemaps today. stepping breakpoints in cljs in the browser. man. so awesome |
| 09:23 | AeroNotix | How do I use -> macros on mutable java objects? |
| 09:23 | AeroNotix | I.e. a (.Method Object) -> nil |
| 09:23 | ro_st | AeroNotix: (.. thing .call .call) |
| 09:23 | AeroNotix | trying |
| 09:23 | hyPiRion | AeroNotix: usually you'd use doto instead |
| 09:23 | AeroNotix | I tried this |
| 09:23 | AeroNotix | oh I will look at doto, as well. |
| 09:23 | ro_st | clojure.org/java_interop |
| 09:23 | AeroNotix | Cheers! |
| 09:23 | hyPiRion | ,(doto (java.util.ArrayList.) (.add 1) (.add 2)) |
| 09:23 | clojurebot | [1 2] |
| 09:24 | rukor | ro_st: i had that when i had local macros. When i moved the macros to a library in checkouts i got back sub second compilation. Not saying it's it but just sharing my experience |
| 09:25 | AeroNotix | ,(doto (Calendar/getInstance) (.add Calendar/DAY_OF_YEAR -10) (.getTime)) |
| 09:25 | clojurebot | #<CompilerException java.lang.RuntimeException: No such namespace: Calendar, compiling:(NO_SOURCE_PATH:0:0)> |
| 09:25 | AeroNotix | dero |
| 09:25 | ro_st | rukor: we only have macros in our checkouts |
| 09:26 | ro_st | pure cljs in the main project |
| 09:26 | rukor | ro_st: interesting then |
| 09:26 | ro_st | weird thing is, on 1.7.0_45 on mac it's fine - 0.5s. i have ubuntu users on 1.7.0_25 getting 10s |
| 09:26 | ro_st | curiouser and curiouser |
| 09:27 | ro_st | they're not getting incremental, basically |
| 09:28 | rukor | would seem so. |
| 09:28 | rukor | clean, then start over? |
| 09:29 | ro_st | that was our first port of call :-) lein clean, lein cljsbuild clean |
| 09:55 | expez | After doing reloading code and running tests with clojure-test-mode the tests starts to get duplicated instead of updated, why does this happen? |
| 10:08 | ro_st | rukor, dnolen: the issue has been found and resolved https://github.com/emezeske/lein-cljsbuild/issues/281 |
| 10:19 | rukor | ro_st: thanks |
| 10:40 | CookedGryphon | I think I'm getting weird bugs trying to combine core.match with core.async |
| 10:40 | gfredericks | expez: did you rename a test? |
| 10:41 | CookedGryphon | if i do a match inside a go block, I always seem to end up with only the first match working and everything else falling through to the else |
| 10:41 | CookedGryphon | take it out of the go block and it works as expected |
| 10:42 | fizruk | is there a map-like function for persistent Maps which returns new persistent Map? e.g. (my-map + {1 2 3 4}) => {1 3 3 7} |
| 10:42 | fizruk | I'd like to map values (but use key when mapping) |
| 10:43 | sw1nn | sritchie: I'm looking at friend + liberator integration and I found your PR on liberator, Where is friend/unauthorized! - is that your function? |
| 10:45 | DerGuteMoritz | fizruk: (into {} (map (fn [[k v]] [k (+ k v)]) {1 2 3 4})) is how you'd usually do it |
| 10:45 | hyPiRion | fizruk: just ##(into {} (for [[k v] {1 2 3 4}] [k (+ k v)])) |
| 10:45 | lazybot | clojure.lang.ArityException: Wrong number of args (3) passed to: core$for |
| 10:45 | sritchie | sw1nn: yeah, I was writing up a post - let me push the example repo I'm making |
| 10:45 | DerGuteMoritz | hmhm, for |
| 10:46 | fizruk | ,(#(zipmap (keys %) (map (partial apply +) %)) {1 2 3 4}) |
| 10:46 | clojurebot | {3 7, 1 3} |
| 10:46 | sw1nn | sritchie: great, thanks |
| 10:46 | DerGuteMoritz | ugh :-) |
| 10:46 | sritchie | https://github.com/sritchie/liberator-friend/blob/master/src/liberator_friend/core.clj |
| 10:47 | sritchie | so, the routes + stuff for hte post aren't in place yet, |
| 10:47 | sritchie | sw1nn: but here's the applied friend middleware with basic auth, |
| 10:47 | sritchie | https://github.com/sritchie/liberator-friend/blob/master/src/liberator_friend/middleware/auth.clj |
| 10:47 | fizruk | DerGuteMoritz: hyPiRion: thanks! |
| 10:47 | sritchie | and here are the resource helpers: |
| 10:47 | sritchie | sw1nn: https://github.com/sritchie/liberator-friend/blob/master/src/liberator_friend/resources.clj |
| 10:47 | DerGuteMoritz | fizruk: yw! |
| 10:47 | DerGuteMoritz | reduce-kv could also be worth trying |
| 10:48 | DerGuteMoritz | ,(reduce-kv (fn [r k v] (assoc r k (+ k v))) {} {1 2 3 4}) |
| 10:48 | clojurebot | {3 7, 1 3} |
| 10:49 | sw1nn | sritchie: Thats fantastic, just what I was looking for, thanks again. |
| 10:49 | sritchie | sw1nn: so making a resource with :base authenticated-base will get you going |
| 10:49 | sritchie | I think there's a bug or two in here with pass the context vs request... |
| 10:49 | sritchie | I have a busted level of unwrapping at one spot |
| 10:50 | sritchie | sw1nn: lmk how it goes! Comments on the proj would be great if you have suggestions |
| 10:50 | sritchie | more coming on that soon |
| 10:54 | zerokarmaleft | sritchie: nice, I'm working on a project with liberator+friend too...I may have some questions/comments for you later |
| 10:55 | sritchie | for sure |
| 10:55 | sritchie | I'm traveling today, so if you guys want to make issues on that project that'd be great |
| 10:55 | sritchie | I'll get that post out sunday or monday, probably |
| 10:56 | gfredericks | is there an option in recent cheshire to turn off the top-level-lazy-seq thing? |
| 10:57 | dakrone | gfredericks: yes, there's a parse-strict option |
| 10:57 | TimMc | gfredericks: something somethign strict |
| 10:57 | jcromartie | so while clojure.tools.namespace is nice, I've just decided to add a call to a custom (unmap-all) at the top of my namespaces |
| 10:57 | jcromartie | yes it breaks defonce |
| 10:58 | gfredericks | dakrone: gotcha looks like 5.3; will upgrade |
| 11:16 | boblarrick | Is there a way to do something like `(map #(apply * 400 %) [1 [2 (/ 9 8)]])` that would return (400 900) ? |
| 11:19 | jcromartie | boblarrick: wat... |
| 11:20 | hyPiRion | ,(map #(apply * 400 (cond-> % (not (sequential? %)) vector)) [1 [2 (/ 9 8)]]) |
| 11:20 | clojurebot | (400 900N) |
| 11:21 | hyPiRion | probably not the best one though |
| 11:21 | justin_smith | ,(map #(apply * 400 %) [[1] [2 (/ 9 8)]]) |
| 11:21 | clojurebot | (400 900N) |
| 11:21 | jcromartie | I see |
| 11:22 | justin_smith | jcromartie: do you really need the input to be sometimes number sometimes sequential? |
| 11:22 | jcromartie | jcromartie: boblarrick was asking |
| 11:23 | justin_smith | oh, oops |
| 11:23 | justin_smith | boblarrick: do you really need the input to sometimes be a number and sometimes sequential? |
| 11:24 | boblarrick1 | justin_smith: Yeah I was hoping for a way that didn't use cond, and that could handle sometimes number, sometimes seq |
| 11:25 | gfredericks | oh I didn't just want strict, I wanted a vector |
| 11:26 | gfredericks | hmm |
| 11:26 | justin_smith | ,(map #(apply * 400 (flatten %&)) [1 [2 (/ 9 8)]]) ; I hate myself for this, but it works |
| 11:26 | clojurebot | (400 900N) |
| 11:27 | justin_smith | that code tastes like sawdust :( |
| 11:27 | clgv | does leiningen's :global-var also work for non clojure.core variables? |
| 11:38 | zerokarmaleft | boblarrick1: I'd take that as a code smell...perhaps whatever is generating the sequence to map over can supply a seq that's uniform |
| 11:39 | zerokarmaleft | i.e. a single number is wrapped in a vector |
| 11:40 | zerokarmaleft | then you get something clean like what justin_smith first suggested |
| 11:40 | zerokarmaleft | ,(map #(apply * 400 %) [[1] [2 (/ 9 8)]]) |
| 11:40 | clojurebot | (400 900N) |
| 11:43 | justin_smith | zerokarmaleft: notice that was exactly my first suggestion |
| 11:43 | justin_smith | and noting flatten makes it do what he wants: ~flatten |
| 11:43 | justin_smith | err |
| 11:43 | justin_smith | ~flatten |
| 11:43 | clojurebot | flatten is rarely the right answer. Suppose you need to use a list as your "base type", for example. Usually you only want to flatten a single level, and in that case you're better off with concat. Or, better still, use mapcat to produce a sequence that's shaped right to begin with. |
| 11:44 | ddima_ | smart bot |
| 11:44 | stuartsierra | ~botsnack |
| 11:44 | clojurebot | Thanks, but I prefer chocolate |
| 11:44 | stuartsierra | :) |
| 11:44 | gfredericks | has anybody seen some nrepl middleware that wraps everything in (time ...)? |
| 11:44 | gfredericks | or know of a similarly structured middleware I could blindly mimick? |
| 11:46 | stuartsierra | xeqi: Pushed fix for DJSON-13, if you want to give it a try. |
| 11:46 | zerokarmaleft | justin_smith: yes, I see that...just wanted to reinforce that "flatten" is usually a bad idea :) |
| 11:48 | boblarrick1 | Thanks al |
| 11:48 | boblarrick1 | *all |
| 11:49 | justin_smith | zerokarmaleft: but that is why I suggested flatten - the root problem is a design problem, the same design problem that leads to using flatten |
| 11:50 | justin_smith | flatten being a symptom of that problem, not solution, mind you |
| 11:52 | boblarrick1 | /shrug. Who knows where data comes from, and how much control one has over it. |
| 12:00 | justin_smith | boblarrick1: would you a) write a version of multiply that checked if args were strings and parsed them as numbers before multiplying, or b) write a preprocessor that validated and coerced input when received? No need to complect handling input with processing it. |
| 12:05 | jcromartie | can anybody help me understand why this works the way it does, and how to avoid it? https://gist.github.com/jcromartie/b63a93e0845603636f9e |
| 12:06 | jcromartie | sorry, updated |
| 12:06 | boblarrick1 | justin_smith: Of course I'd us a preprocessor, unless I was getting data from somewhere else and playing around with overtone in a repl and just wanted a oneliner ;) |
| 12:07 | justin_smith | jcromartie: my hunch is that defn creates a var, or resets it if it exists |
| 12:07 | justin_smith | jcromartie: and g does not get f as a name of a var, but the var f resolves to |
| 12:08 | justin_smith | jcromartie: so if the initial var exists, it picks up the new value, but after the remapping, f is a different var (just happening to have the same name) so it does not affect g when you set its value |
| 12:08 | justin_smith | just guessing though |
| 12:08 | Bronsa | jcromartie: http://sprunge.us/GYMF |
| 12:09 | Bronsa | justin_smith: that's almost right |
| 12:09 | jcromartie | Bronsa, justin_smith, seems to be the case |
| 12:09 | jcromartie | thanks |
| 12:09 | justin_smith | Bronsa: cool, that seems to back up my hunch |
| 12:09 | justin_smith | Bronsa: about the almost, please enlighten me |
| 12:09 | jcromartie | so, is there a way to remove stale vars while avoiding this issue? |
| 12:09 | Bronsa | justin_smith: it's not defn that creates||resets, it's def |
| 12:10 | justin_smith | Bronsa: right, because defn is just a macro over def, right? |
| 12:10 | Bronsa | sure |
| 12:11 | justin_smith | well, clearly not *just*, now that I see the source |
| 12:11 | stuartsierra | data.json 0.2.4 is in the can now. |
| 12:12 | Bronsa | jcromartie: not really, the closest you can get is to unbind the var (.unbindRoot #'the-var) instead of ns-unmapping it |
| 12:12 | jcromartie | so if I do this: (doseq [sym (keys (ns-interns *ns*))] (ns-unmap *ns* sym)) |
| 12:13 | jcromartie | I want to specifically avoid the issues where renaming a function during interactive development leads to floating references hanging around |
| 12:13 | jcromartie | and I'd love to use clojure.tools.namespace but it blows up on my with my AOT needs |
| 12:13 | jcromartie | I guess the answer is "be careful" |
| 12:14 | justin_smith | jcromartie: I wonder about maybe a function that parses a namespace file as edn, and also looks at the ns-publics of the same namespace, and returns the ns-publics not reflected by the forms in said edn? |
| 12:15 | stuartsierra | jcromartie: Don't know if this is an option for your use case, but if you can separate your AOT-compiled code into another project, tools.namespace will work. |
| 12:15 | justin_smith | which more or less would give you the floating stuff (unless you were using higher level trickery to create vars) |
| 12:16 | jcromartie | maybe I could redefine def :) |
| 12:16 | jcromartie | to update a counter |
| 12:16 | jcromartie | oh god what have I done |
| 12:17 | technomancy | gen-class inside a fedonce |
| 12:17 | technomancy | defonce |
| 12:18 | pandeiro | where does stdout end up going when using lein repl :headless ...? |
| 12:19 | technomancy | pandeiro: "stdout" is ambigious |
| 12:19 | pandeiro | technomancy: i'm using pedestal and when i do `lein run`, services log requests to the terminal's stdout; when i do `lein repl :headless` etc, they don't |
| 12:19 | technomancy | System/out will go wherever the process is started |
| 12:19 | justin_smith | technomancy: yeah, I have been tempted to use defonce for side effects like that, maybe it calls for a "do-once" macro |
| 12:20 | technomancy | the root binding of *out* will be the same |
| 12:20 | technomancy | out of th ebox at least |
| 12:20 | stuartsierra | `gen-class` has no effect when not AOT-compiling. |
| 12:20 | technomancy | pedestal might change it |
| 12:20 | technomancy | the thread-local binding of *out* could be anything the client wants it to be |
| 12:20 | pandeiro | technomancy: i am using foreman to start a bunch of services in one terminal, maybe that is at play... but when i use foreman with lein run, i see output |
| 12:21 | technomancy | remove variables until the problem can be isolated |
| 12:21 | pandeiro | yeah ok |
| 12:24 | hansel-han | any library name that includes a substring of "clojure" is an instant classic imo. can't really go wrong with that. |
| 12:25 | hansel-han | i'm lovin "Cloact", React for Clojurescript |
| 12:25 | michaniskin | clojacked |
| 12:25 | michaniskin | disregard that came out wrong :) |
| 12:25 | michaniskin | i mean clojact |
| 12:25 | hansel-han | oh, nice |
| 12:26 | hansel-han | the impromptu brilliance of this community keeps me coming back |
| 12:26 | michaniskin | i guess probably not good to have "jacked" in the name, at least in the US |
| 12:26 | hansel-han | nah, dude. i always tell people at the gym how jacked i am |
| 12:27 | michaniskin | my barber shaves jacks every day |
| 12:27 | michaniskin | dude is a hacker extraordinaire |
| 12:27 | andyf | Bronsa: Any thoughts on alpha releases of tools.analyzer(.jvm) libs? :-) |
| 12:28 | tbaldridge | Bronsa: I'll also be asking for this sometime in the next few months, I'm re-writing core.async to use tools.analyzer as we speak |
| 12:29 | Bronsa | ok, I guess a 0.1.0-alpha1 is in the way then |
| 12:30 | hyPiRion | yay |
| 12:30 | stuartsierra | java.classpath 0.2.2 is on the way. |
| 12:30 | hyPiRion | I need to use tools.analyzer for some project of mine, but really want a stable release. So this is good |
| 12:31 | andyf | Bronsa: excellent. Eastwood still has some sharp edges, and I'm sure there are problems I don't know about yet, but it seems about ready to have a few more people besides us run it through the grinder |
| 12:32 | jcromartie | woah… Chrome's view-source gives some serious nondeterministic results |
| 12:32 | jcromartie | weird |
| 12:32 | Bronsa | right, I guess having people actually use it will probably help us find/fix more bugs :) |
| 12:32 | bbloom | Bronsa: i apologize in advance for asking this question, but ... how hard would it be to add XML literals to the reader? |
| 12:33 | bbloom | Bronsa: b/c apparently "looks like HTML" is an important requirement for some people, lol |
| 12:33 | Bronsa | stuartsierra: t.a.j depends on t.a, does hudson automatically update the t.a version in t.a.j pom.xml or sohuld I do it manually myself? |
| 12:33 | jonasen | bbloom: :) |
| 12:33 | stuartsierra | Bronsa: No, dependency version numbers are not updated automatically. |
| 12:33 | Bronsa | bbloom: ugh. there's the issue of < > and friends being clojure.core functions |
| 12:33 | Bronsa | stuartsierra: ok, thanks |
| 12:34 | stuartsierra | Bronsa: you're welcome |
| 12:34 | Bronsa | bbloom: I can try and give you a patch if you're *really* sure you mean it |
| 12:35 | bbloom | Bronsa: lol i don't want it |
| 12:35 | jonasen | bbloom: you could do a JSX transformation and translate <foo></foo> into (foo) or [:foo] |
| 12:35 | bbloom | Bronsa: i'm not personally interested in such silliness, since HTML is an abomination for UI components anyway |
| 12:35 | Bronsa | *phew* |
| 12:35 | bbloom | jonasen: yeah, that's basically the idea |
| 12:35 | bbloom | if it was just hilariously easy, i'd want it for the sake of a joke tho :-P |
| 12:36 | bbloom | if it was like "i can hack that out in ~20 min w/ low quality w/ some shitty regexes" i'd enjoy that, but that's the extent of my request |
| 12:39 | andyf | Bronsa: Oh, one question on top level do forms. Does Clojure treat a do *inside* of a top level do the same as the top level do, i.e. analyze and evaluate its forms one at a time? |
| 12:40 | technomancy | pretty sure it's just one level |
| 12:40 | Bronsa | andyf: I'm not really sure about that, let me check |
| 12:40 | S11001001 | I think it's recursive |
| 12:41 | Bronsa | it *is* one level, but I think clojure transforms (do (do foo bar)) into (do foo bar) somewhere |
| 12:41 | apetresc | What's the most mature parser-generator for Clojure? Like, to generate a parser for some CFG/PEG? |
| 12:42 | tbaldridge | apetresc: I've heard instaparse is good |
| 12:42 | apetresc | I'm aware of fnparse but it doesn't look like it's seen any activity for ~3 years |
| 12:42 | apetresc | tbaldridge, instaparse, thanks, I'll look into it :) |
| 12:43 | apetresc | Oh neat, it looks perfect. Thanks again, tbaldridge! |
| 12:43 | jcromartie | "Can't change/establish root binding of: *print-length* with set" ??? like hell I can't |
| 12:43 | hyPiRion | apetresc: yeah, instaparse is the best |
| 12:43 | justin_smith | jcromartie: maybe you need binding or alter-var-root ? |
| 12:44 | jcromartie | ,(set! *print-length* 100) |
| 12:44 | clojurebot | 100 |
| 12:44 | jcromartie | I can have this in a file when I recompile it with C-k, but not when it's loaded when starting up the project |
| 12:44 | tbaldridge | jcromartie: the var doesn't have a root. set it with alter-var-root |
| 12:45 | jcromartie | why does it work after the facT? |
| 12:45 | jcromartie | after the REPL starts up, that is |
| 12:45 | technomancy | the repl binds it |
| 12:45 | tbaldridge | jcromartie: stuart just talked me through that one the other day. You can't do set! on a var that is unbound. The REPL goes and sets roots for a ton of stuff. That doesn't happen when you app is run outside of the repl. |
| 12:46 | jcromartie | ah ha |
| 12:46 | tbaldridge | I dug into Var.java for awhile at it does make sense, but yeah, it's a pain. |
| 12:46 | jcromartie | is there any kind of hook for after the REPL starts up, particularly in a user.clj namespace? |
| 12:46 | tbaldridge | *and it |
| 12:47 | amalloy | $google lein sample project.clj |
| 12:47 | lazybot | [Leiningen's sample project.clj - GitHub] https://github.com/technomancy/leiningen/blob/master/sample.project.clj |
| 12:47 | amalloy | jcromartie: iirc it's called something like :repl-init |
| 12:47 | tbaldridge | I'd just wrap your app entry point in a (binding[]) |
| 12:48 | jcromartie | thanks amalloy |
| 12:49 | Bronsa | bbloom: http://sprunge.us/GbOX?diff |
| 12:49 | bbloom | Bronsa: ha! awesome. does that really work? |
| 12:50 | Bronsa | wait, it has a bug. |
| 12:50 | bbloom | Bronsa: too bad the #< dispatch macro is already used for "unreadable" |
| 12:50 | bbloom | which i guess is accurate, since XML is unreadable... ZING! |
| 12:50 | andyf | Bronsa: I test eval form seems to confirm that a do inside of a top level do somehow causes its subforms to be analyzed and evaluated before the next subform |
| 12:51 | Bronsa | bbloom: http://sprunge.us/HIKX?clj here |
| 12:51 | Bronsa | s/clj/diff |
| 12:53 | Bronsa | andyf: yeah, looks like so (line 5733 of Compiler.java) |
| 12:54 | Bronsa | so it does (do (do 1 2) 3 4) => (do 1 2 3 4) |
| 12:59 | amalloy | andyf: a top-level (do a b) is treated as if it were the two top-level forms a and b. naturally if a or b is a do, the same thing happens "recursively" |
| 12:59 | andyf | Bronsa: amalloy: technomany: I can't navigate Clojure compiler source as fast as Bronsa, but this REPL interaction confirms his findings https://gist.github.com/jafingerhut/8359201 |
| 13:01 | amalloy | andyf: you've doubtless already written code many times that would break if things didn't work this way |
| 13:02 | andyf | amalloy: If I did, I wasn't aware of it :-) |
| 13:02 | amalloy | well, i was thinking of stuff that macroexpands to (do (do (do (defn ...)))) or whatever, but i guess if there aren't any "backreferences" in there it would work either way |
| 13:03 | bbloom | Bronsa: ok now dnolen needs to write a blog post to be like "what? you want HTML? fine. you bastards" |
| 13:03 | andyf | OK, well now I know. Looks like I need to go remove the max-1-deep limitation I coded into the part of Eastwood that handles this case. |
| 13:03 | bacon1989 | Hi, I was wondering how easy it would be to jump into clojure with clojurescript? I have very little lisp experience other than emacslisp |
| 13:05 | dnolen | bbloom: Bronsa: heh that is pretty cool, but I really am glad to remain clear of such trivial decisions |
| 13:05 | justin_smith | bacon1989: the toolchain with clojurescript is still a little janky in my experience - it works but the dev environment / workflow is weird (to me at least) |
| 13:05 | justin_smith | that said, clojurescript is great once you have it compiling / running in the browser |
| 13:06 | seancribbs | dnolen: ohai, you going to stick around? |
| 13:06 | dnolen | seancribbs: yep |
| 13:06 | justin_smith | bacon1989: the jvm version is much easier to fire up and experiment with and learn in |
| 13:06 | seancribbs | dnolen: cool, midday meetings and things then I'll ask you about Om stuff |
| 13:07 | S11001001 | bacon1989: there's a little more setup than emacs lisp, unless you're non-FP and are going to hold onto anti-FP biases. I can't say about clojurescript, though. First tip: ignore clojure install, go to https://github.com/technomancy/leiningen#installation and https://github.com/clojure-emacs/cider#installation , that's what you need to start. |
| 13:07 | S11001001 | bacon1989: as you mentioned elisp I assume your editor of choice is emacs. |
| 13:08 | dnolen | bacon1989: I think worth learning Clojure first, ClojureScript is not significantly different and the tooling is admittedly not as nice. |
| 13:08 | dnolen | bacon1989: doing ClojureScript in Light Table is the best experience I've seen so far |
| 13:11 | rasmusto | bacon1989: doing clojure in lighttable is easy too |
| 13:12 | bacon1989 | that's a lot of info, thanks a lot |
| 13:12 | bacon1989 | I already have clojure running cider on emacs with leinigen |
| 13:12 | bacon1989 | The only web development i've done though, is PHP and Python |
| 13:13 | bacon1989 | i'm kind of wondering how long it could take for someone like myself to pick up clojure and write meaningful application? |
| 13:13 | bacon1989 | I guess it would also depend on my dedication, maybe I shouldn't jump into it and use it in my next project 'just yet' |
| 13:13 | rasmusto | depends on your definition of "meaningful" |
| 13:14 | rasmusto | bacon1989: I'd definitely recommend playing around with 4clojure and project euler before you try to build something with it, just to get language familiarity |
| 13:15 | rasmusto | also, clojure programming (o'reilly) and the joy of clojure are good references |
| 13:26 | justin_smith | bacon1989: yeah, seconding rasmusto, common mistake for people coming from an algol-family language is to just jump in not really understanding clojure syntax/semantics, and 4clojure / clojure koans / euler will help prevent the tiny newbie mistakes from turning into a frustrating mess in a real project |
| 13:26 | Bronsa | andyf: hiredman tbaldridge t.a/t.a.j 0.1.0-alpha1 on their way to maven |
| 13:26 | hiredman | neato |
| 13:27 | andyf | Bronsa: If you are at Clojure/West, I owe you a beer :-) |
| 13:28 | Bronsa | andyf: eh, I could only wish I was. Italy is somewhat far :) |
| 13:29 | Bronsa | duh. s/hiredman/hyPiRion |
| 13:30 | hiredman | hey, I care |
| 13:31 | hyPiRion | Bronsa: yay |
| 13:32 | muhoo | why is alter not alter!, or why isn't swap! swap ? |
| 13:32 | technomancy | muhoo: ! kind of half-heartedly means "unsafe in a transaction" |
| 13:33 | justin_smith | and alter only works in a transaction |
| 13:36 | muhoo | makes sense, thanks |
| 13:38 | TimMc | technomancy: I'm going to start referring to Java! instead of Java |
| 13:38 | technomancy | hehe |
| 13:38 | TimMc | Downside: People will think I am excited about Java. |
| 13:38 | technomancy | or a yahoo! employee? |
| 13:38 | TimMc | ha |
| 13:39 | amalloy | dangit technomancy, too fast for me |
| 13:40 | TimMc | technomancy: Wait, is that that keyboard you have to solder together? |
| 13:40 | technomancy | yeah |
| 13:41 | technomancy | it is The Best |
| 13:41 | technomancy | https://secure.flickr.com/photos/technomancy/11437911574/ |
| 13:41 | amalloy | TimMc: technomancy's POV is that every keyboard is the one you have to solder together, but people just aren't as aware of it |
| 13:42 | technomancy | I'm not hard-core like thisg uy though: https://secure.flickr.com/photos/obra/8197649629/ |
| 13:43 | TimMc | amalloy: Yeah, yeah. :-P |
| 13:43 | TimMc | I meant "you", not "you". |
| 13:43 | technomancy | he couldn't even wait for the circuit board |
| 13:44 | TimMc | technomancy: That first picture is one of the most hipster things I have ever seen. (Note: "Hipster" not used in a derogatory fashion here.) |
| 13:45 | rasmusto | I think its the scarf that really brings the picture together |
| 13:45 | hiredman | I dunno, technomancy often wears a scarf, that is pretty hipster |
| 13:45 | rasmusto | (inc hiredman) |
| 13:45 | lazybot | ⇒ 33 |
| 13:46 | bacon1989 | thank you rasmusto and justin_smith, I got lost in some code |
| 13:46 | bacon1989 | I think I might pick up the oreilly book and just practise with it at first |
| 13:46 | rasmusto | bacon1989: http://www.4clojure.com/ until you have the book :) |
| 13:47 | justin_smith | bacon1989: try some of 4clojure in the browser too - but note that numeric order is not difficulty/knowledge order |
| 13:47 | justin_smith | jynx |
| 13:47 | technomancy | TimMc: someone referred to it as "fashioning my very own majestic hand chariots" which is maybe my new favourite phrase |
| 13:47 | TEttinger | hey I had a beard before it was hip. I'm a neckbeard grognard, not a hipster! |
| 13:48 | seubert | is there a way to reset my 4clojure account |
| 13:48 | seubert | i did a bunch of exercises a year or so ago and was just going to restart |
| 13:48 | TEttinger | seubert, did you submit a password as an answer? haha |
| 13:48 | seubert | no haha |
| 13:48 | justin_smith | you could just make a new one? |
| 13:49 | hansel-han | if you started a website today, would yall use example.com or www.example.com? |
| 13:49 | seubert | justin_smith: gotta dig up an email to use then i guess :V |
| 13:49 | seubert | haha both of my usual emails are already used |
| 13:49 | seubert | i must have gone through this process before |
| 13:49 | technomancy | hansel-han: www-less looks nicer, but it's a lot less flexible if you need to make changes due to a ddos |
| 13:50 | hansel-han | every once in a while, i read a discussion where `www` provides benefits, but i can't tell how esoteric or useful the benefits are |
| 13:50 | technomancy | hansel-han: https://devcenter.heroku.com/articles/apex-domains |
| 13:50 | hansel-han | technomancy: if the extent of my response to handling a ddos was to utilize cloudflare, would i care? |
| 13:50 | hansel-han | i'll read that, thanks |
| 13:51 | justin_smith | hansel-han: if you own foo.com, you also control www.foo.com automatically |
| 13:52 | hansel-han | justin_smith: right. half the sites i own redirect www->naked, the other half naked->www. i'm launching a fresh website and trying to be deliberate about it for once |
| 13:59 | nDuff | ...there are some fairly common practices that violate the letter of the RFC when done with naked domains |
| 13:59 | nDuff | though why we're having this discussion in #clojure... |
| 14:00 | stompyj | does anyone have any experience with deploying clojure apps to vagrant? |
| 14:03 | jcromartie | stompyj: a little |
| 14:03 | jcromartie | generally with "lein run" |
| 14:03 | jcromartie | and a good main |
| 14:04 | stompyj | jcromartie: but the step before that, do you just check out master from git? etc? |
| 14:04 | TimMc | technomancy: That is a fantastic phrase. |
| 14:05 | stompyj | currently I'm using chef+capistrano |
| 14:05 | stompyj | wondering if I should just move to ansible |
| 14:07 | jcromartie | … why would ansible beat chef + capistrano |
| 14:07 | jcromartie | when you can just push an uberjar and run it? |
| 14:08 | jcromartie | either check out source and lein run, or package the uberjar and push that |
| 14:08 | jcromartie | actually I prefer the uberjar for most cases |
| 14:08 | stompyj | hmmmm, actually, pushing the uberjar is extremely interesting |
| 14:08 | stompyj | I just don't want to use capistrano, and ansible (supposedly) can handle deploys |
| 14:09 | stompyj | deploying to production is so easy with beanstalk or heroku |
| 14:09 | stompyj | when I went to deploy to vagrant I wasn't sure what the idiomatic-esque solution was |
| 14:09 | technomancy | are you talking about vagrant in production or what? |
| 14:11 | stompyj | no, we use vagrant as a staging like environment |
| 14:12 | stompyj | that was any developer can just "vagrant up" a service |
| 14:12 | stompyj | instead of having to worry about dependencies on their local box |
| 14:12 | technomancy | yeah, the uberjar is a great way to do that |
| 14:12 | stompyj | yeah |
| 14:12 | stompyj | that sounds like the move |
| 14:13 | stompyj | I keep forgetting that its all java under the hood, so .jar and .war files are in play |
| 14:13 | mdrogalis | Stu Halloway is on the Youtube's live right now |
| 14:13 | tbaldridge | https://www.youtube.com/watch?v=VD9UCfQohQE |
| 14:13 | technomancy | you'll need to figure out $JVM_OPTS yourself from wherever the rest of your config is coming from |
| 14:14 | stompyj | technomancy: makes sense, thanks! |
| 14:14 | stompyj | I saw Rich give a talk on datomic here in NY a couple of months ago, itching to use it in a project |
| 14:15 | randomenduser | I'm having troubles getting https://github.com/cemerick/austin up and running. Is that the recommended way to get a browser repl these days? |
| 14:16 | TimMc | stompyj: So if you have a bunch of services you need to develop against, do you load the vagrant instances locally, or on a remote machine? |
| 14:16 | seancribbs | dnolen: ping |
| 14:17 | stompyj | TimMc: right now, locally. as I'm sure you're thinking, this is problematic if you have a ton of services. this project I'm doing now only has 3 |
| 14:17 | stompyj | so it's not so bad |
| 14:17 | cemerick | randomenduser: I certainly believe so. If you follow the readme and/or the browser-connected application sample that it links to, you should be good. If not, file an issue. |
| 14:18 | randomenduser | cemerick, I'll close everything and go slow then report back :) |
| 14:19 | stompyj | TimMc: so far the upside has been well worth the downside for us. and eventually, I"m sure we'll be able to use docker to spin up a single vm instance, and use docker slices to add services on top |
| 14:19 | dnolen | seancribbs: pong |
| 14:23 | jcromartie | is it bad practice to use assertions for business logic checks? |
| 14:24 | mdrogalis | jcromartie: It depends :P |
| 14:24 | mdrogalis | I think it depends mostly on how you want to react to failure. |
| 14:24 | randomenduser | cemerick, my fault! (cemerick.piggieback/cljs-repl :repl-env (cemerick.austin/exec-env)) was exactly what I was looking for. Very slick |
| 14:25 | cemerick | randomenduser: (cemerick.austin.repls/exec) is even shorter if you really just want a REPL w/o any ceremony :-) |
| 14:25 | randomenduser | cheers :) |
| 14:25 | jcromartie | comparing (assert x "Invalid x") to (when-not x (throw (IllegalArgumentException. "Invalid x"))) |
| 14:25 | jcromartie | I certainly prefer to write the former |
| 14:26 | mdrogalis | jcromartie: There's a little more to consider than that. Where do the assertions go? Complected with the business logic? Where does the failure reaction go? |
| 14:27 | jcromartie | unfortunately it's in a messy routine that executes a bunch of outside API calls |
| 14:28 | mdrogalis | tbaldridge: Hector sounds sleepy lol |
| 14:29 | jcromartie | it's a command pattern, and performing the command returns events that are then applied to the read model and stored, or else an exception is thrown and the whole thing is abandoned |
| 14:29 | seancribbs | dnolen: wow, my RTT sucks :D |
| 14:29 | seancribbs | hahah |
| 14:30 | jcromartie | if I thought I could provide some useful feedback then I'd use ex-info |
| 14:30 | seancribbs | dnolen: i think what I'm struggling right now is app structure/organization, and what 'owner' is in the functions in your todomvc example. |
| 14:30 | mdrogalis | jcromartie: Maybe this might work? https://github.com/MichaelDrogalis/dire#preconditions |
| 14:30 | dnolen | seancribbs: it's the backing React component |
| 14:30 | seancribbs | ok, so like the "parent" in the DOM sense? |
| 14:31 | seancribbs | oh wait, i see now |
| 14:31 | seancribbs | n/m |
| 14:31 | dnolen | seancribbs: I wanted to remove the React-isms and make it a bit more Clojure-like, in React you would typically define a new React class per component, with React.createClass |
| 14:31 | jcromartie | interesting |
| 14:32 | dnolen | seancribbs: in Om we have a single component which allows to present a much more functional and immutable value oriented API |
| 14:33 | TimMc | stompyj: Good to hear, because I'm currently running like 10 other services on my laptop and not thrilled about it. :-P |
| 14:33 | dnolen | a single React component I mean, called Pure |
| 14:34 | Jarda | dnolen: how does http://holmsand.github.io/cloact/ compare to OM? |
| 14:34 | dnolen | Jarda: it doesn't enforce a component design which makes app-state snapshottable |
| 14:34 | stompyj | TimMc: yeah, for us, half our team is osx, and the other half is linux, and we had issues with people struggling to install dependencies, etc |
| 14:34 | stompyj | and the vagrant environment cleaned all that up |
| 14:35 | TimMc | Jarda: "cloact" sounds like a part of bird anatomy :-( |
| 14:35 | dnolen | Jarda: Om does, and I have some things planned around that |
| 14:35 | Jarda | TimMc: also cloact seems to be a drug of some kind (according to google results) |
| 14:35 | Jarda | dnolen: ok |
| 14:36 | TimMc | Jarda: Probably something for constipated chickens. |
| 14:37 | hyPiRion | I think calling it "Cloak'd" would've fixed some naming issues |
| 14:37 | Jarda | it's not my project |
| 14:37 | Jarda | something I catched up on the internets |
| 14:37 | TimMc | stompyj: My dream: Press a button to spin up all the dependencies of a service, configured to point to each other, built from the branches I specify. |
| 14:38 | TimMc | Yes, it would be server-expensive and possibly slow, but imagine how much less frustrating it could be. |
| 14:38 | stompyj | TimMc: yeah, so if you have a box that can handle multiple vms, then vagrant can do that for you today (this is how we're doing things) |
| 14:39 | stompyj | TimMc: Once docker integration happens, then you should be able to do all that from one vm, so it would be even more lightweight |
| 14:39 | TimMc | stompyj: This would require projects to know/report their dependencies in a way that a VM manager could use. |
| 14:40 | noonian | i tried something like that using pallet but i didn't finish it |
| 14:41 | hiredman | pallet is such a yak shave |
| 14:42 | mercwithamouth | what's the best way to start up a compojure app from lighttables instarepl? |
| 14:42 | mercwithamouth | in emacs i can just jump right into the project.repl namespace and start server...not so with light table. |
| 14:42 | mikerod | Are there any certain things to look out for that would hurt compilation performance in Clojure on JVM? |
| 14:43 | tbaldridge | mikerod: don't query a server on the moon from inside a macro? |
| 14:43 | mikerod | Such as, does compilation slow down when there are a lot of reflection warnings/lack of type hints vs many type hints |
| 14:43 | hyPiRion | I would avoid doing (while true) outside defns and defmacros |
| 14:43 | mikerod | tbaldridge: well, that is certainly one good piece of advice :P |
| 14:43 | stompyj | TimMc: did you mean with docker? or just with vagrant? with pure vagrant we just use chef to configure each box as needed. it's the same chef scripts we use to build production boxes on ec2 |
| 14:43 | seancribbs | dnolen: but i can still create components that have their own state, right? like, for instance i need a dropdown in this one place that will have some local/transient state |
| 14:44 | mikerod | ok, so slow macros |
| 14:44 | mikerod | and infinite looping top-level forms |
| 14:44 | dnolen | seancribbs: yes, om/get-state om/set-state! take the owner and allow this. |
| 14:44 | tbaldridge | mikerod: seriously though, I've only seen slower compilation when doing really heavy code transformations. The core compiler is super fast |
| 14:45 | seancribbs | ok, maybe I'm more confused now than before, hah. i just need to poke at it |
| 14:45 | mikerod | tbaldridge: I see. The reason I ask, is currently we have an jar artifact being distributed over a MapReduce cluster that is not compiled. |
| 14:45 | dnolen | seancribbs: the Om separates app-state (kind of like your DB/model in traditional design) from component local state (transient stuff) |
| 14:45 | hiredman | our big app at work takes a minute or two to load and compile |
| 14:45 | mikerod | so this will be compiled dynamically on each of the nodes. we are probably goign to move to AOT compiling it |
| 14:46 | seancribbs | so om/set-state! changes the props on the local component |
| 14:46 | seancribbs | ? |
| 14:46 | mikerod | I've experienced a few minute build times by changing a project to AOT-compiled |
| 14:46 | dnolen | seancribbs: no the component local state |
| 14:46 | mikerod | few minute build-time increases |
| 14:46 | dnolen | seancribbs: props come from the app state, only way to change that is via transact! |
| 14:47 | seancribbs | so, if i want to say "show this dropdown", i have to put something in the app state |
| 14:47 | TimMc | stompyj: Yeah, first we'll have to get a uniform build system for all these services. |
| 14:47 | seancribbs | that seems like mixing concerns |
| 14:47 | TimMc | build/deployment |
| 14:47 | dnolen | seancribbs: no, you can do that with component local state |
| 14:47 | dnolen | seancribbs: they are intentional separated for this reason |
| 14:47 | seancribbs | ok, then we're on the same page |
| 14:47 | seancribbs | i think |
| 14:48 | stompyj | Yeah, that's definitely the trick. Getting buy in can be hard, because it's hard to quantity this stuff. But once you get it working, you wonder what the hell you were thinking beforehand |
| 14:48 | dnolen | seancribbs: we actually don't venture too far from the high level React model |
| 14:48 | stompyj | Just like working with mutable data structures :) |
| 14:48 | dnolen | seancribbs: components get their basic data (props) from app state, just like reading that stuff of out of a DB |
| 14:48 | dnolen | seancribbs: if you a component needs to change something in the app state (DB) you need to transact! |
| 14:49 | seancribbs | sure, like the items i want to put in that dropdown will be app state |
| 14:49 | dnolen | seancribbs: for transient stuff, local component state is enough, om/set-state! |
| 14:49 | dnolen | seancribbs: exactly |
| 14:49 | seancribbs | cool, now i think i have the separation |
| 14:50 | seancribbs | i like the idea of the UI being a set of functions over the app state |
| 14:50 | seancribbs | so much easier to reason about |
| 14:50 | seancribbs | just hard to break myself out of the MVC junk |
| 14:50 | bbloom | ibdknox: you there? |
| 14:51 | dnolen | seancribbs: yes I much prefer this. Not yet set on the names for the functions so I haven't committed to documenting what's there yet in a more visible fashion. |
| 14:51 | dnolen | seancribbs: also as people use it getting a clearer picture of what's needed |
| 14:51 | seancribbs | cool. hopefully this experiment of mine can result in some feedback |
| 14:51 | TimMc | dnolen: So this is like data state vs. ui state? |
| 14:52 | dnolen | TimMc: precisely |
| 14:52 | TimMc | Sweet! |
| 14:52 | TimMc | I have to take a look at this, that problem has been bothering me for a while. |
| 14:52 | dnolen | TimMc: and the separation is even more important in Om because we render on request animation frame. So in transact! you need to be careful. |
| 14:52 | dnolen | TimMc: you need to check your assumptions |
| 14:53 | TimMc | boy do I ever |
| 14:53 | dnolen | TimMc: but even om/set-state! is better than what you normally get |
| 14:53 | dnolen | TimMc: every component can see it's current local state and what it will become |
| 14:53 | dnolen | mutation that doesn't suck |
| 14:54 | dnolen | same as React here |
| 14:54 | TimMc | like the Kwisatz Haderach |
| 14:54 | seancribbs | lol |
| 14:56 | seancribbs | the nice thing about the app I'm doing is that all data that is loaded from the server is immutable anyway. you can only add new things |
| 14:57 | seancribbs | by "you" i mean some external process |
| 14:57 | dnolen | seancribbs: fwiw, the main advantage in the Om model over React is faster defaults and simple model for access to app state history - if you don't really need/want this then plain React works great. |
| 14:58 | seancribbs | dnolen: well, redraws are a real problem in this app, mostly because of medium-sized (read thousands) of data items |
| 14:58 | dnolen | seancribbs: like 10,000? is this in a giant list? |
| 14:59 | seancribbs | it's somewhat tree-like |
| 14:59 | seancribbs | the main drag is taking ~1000 items, slicing it into a N-level index and then displaying that as a table |
| 15:00 | dnolen | seancribbs: tree-like will be better, React does not yet provide the hooks required for truly fast rendering of very large lists |
| 15:00 | dnolen | and thus nor do we |
| 15:00 | dnolen | "truly fast re-rendering" |
| 15:00 | seancribbs | yeah, well i need to compute the matrix, heh |
| 15:00 | seancribbs | but Ember drags with that many bindings |
| 15:00 | seancribbs | where it's really not necessary |
| 15:02 | dnolen | seancribbs: so does the server give the client a delta or something? |
| 15:02 | seancribbs | eventually we'll probably hook up EventSource |
| 15:02 | seancribbs | but that is turned off for right now |
| 15:02 | seancribbs | so yeah, potentially new information can be added |
| 15:03 | dnolen | seancribbs: then what exactly are you re-rendering? Are you just sending down all the new data? |
| 15:03 | seancribbs | different subsets of the data |
| 15:03 | dnolen | seancribbs: and you just mutate the part of the data that changed? |
| 15:03 | seancribbs | err, sub-"trees" |
| 15:04 | seancribbs | better if i just show you, hah |
| 15:04 | seancribbs | http://giddyup.basho.com (click riak_ee, then one of the dropdowns under 2.0.0) |
| 15:06 | dnolen | seancribbs: wow ouch, locked up my browser had to restart |
| 15:07 | seancribbs | yep |
| 15:07 | seancribbs | ETOOMANYBINDINGS |
| 15:07 | seancribbs | Safari is quite snappy on it actually |
| 15:08 | dnolen | seancribbs: yeah Safari seems significantly faster when it comes to DOM ops than Chrome it seems. |
| 15:09 | seancribbs | so my guess is, tell me if i'm off base here... Ember is delaying those DOM updates to the end of the run loop, but not doing them in one batch |
| 15:09 | seancribbs | and it's a complicated tree of templates there |
| 15:12 | dnolen | seancribbs: hrm I really can't say, I don't know Ember, but the UI doesn't seem very complicated to me and that seems crazy slow. |
| 15:12 | seancribbs | yeah |
| 15:12 | seancribbs | easy vs. simple |
| 15:12 | seancribbs | Ember was easy, but is complex |
| 15:13 | seancribbs | and honestly its latest incarnation is grating me, as much as I like Tom and Yehuda it's just too hard to debug |
| 15:14 | dnolen | seancribbs: I suspect you could solve most of your issues w/ just React, nothing here much warrants Om unless you really want to use ClojureScript :) |
| 15:15 | seancribbs | cool, I might just start with that, but perhaps come back for the core.async |
| 15:15 | seancribbs | :D |
| 15:24 | bitemyapp | seancribbs: Ember wasn't even easy anyway. |
| 15:25 | bitemyapp | unless you'd spent a fair amount of time immersed in it. |
| 15:25 | seancribbs | bitemyapp: fair. "easy" if you're used to railsy things |
| 15:27 | seancribbs | never said "easy" was good |
| 15:27 | seancribbs | :-p |
| 15:27 | bitemyapp | seancribbs: I mostly went CL -> Python -> Clojure -> hs, not much interest in Rails/Ruby except when I was forced to dive into it periodically. |
| 15:28 | seancribbs | yeah it was more like, we knew some Ember already when we did this app, it was quick to get going |
| 15:28 | seancribbs | we were on a deadline |
| 15:28 | seancribbs | now it's just tech debt |
| 15:28 | seancribbs | and it's not our core thing, just a tool we use |
| 15:28 | seancribbs | so it doesn't get updated that often |
| 15:34 | bitemyapp | always regrettable. |
| 15:34 | bitemyapp | seancribbs: the only times I've been happy with that sort of stuff in recent memory has been when I was using cljs or fay with the vanilla DOM API, or Angular. |
| 15:35 | seancribbs | bitemyapp: *shrug*. going to try plain react.js and see if i can't speed this sucker up |
| 15:36 | bitemyapp | seancribbs: sure, I haven't tried React myself yet. |
| 15:40 | arrdem | $mail ambrosebs thinking about giving a c.c.t talk at c/w? |
| 15:40 | lazybot | Message saved. |
| 15:41 | bitemyapp | arrdem: that would incentivize me to go to c/w. |
| 15:41 | arrdem | bitemyapp: if I can prove that either ambrose or bronsa will be at c/w I can get the department to pay for flying me out :P |
| 15:42 | arrdem | bitemyapp: so I'm not entirely unbiased. |
| 15:43 | bitemyapp | Makes sense. |
| 15:48 | bitemyapp | arrdem: having looked at LightTable's code, beyond the fact that c.c.t isn't really JS ready, I can see why it isn't likely to be used. |
| 15:48 | bitemyapp | a lot of the editor is uni-typed objects stored globally with some metadata tags and the like. |
| 15:49 | bitemyapp | primary irritation is non-hackability at runtime. |
| 15:51 | saint_cypher | I have a friend question https://gist.github.com/rjspotter/8362283 |
| 16:05 | noonian | saint_cypher: for one thing, ::users/user should just be :users/user |
| 16:06 | bitemyapp | ,::user |
| 16:06 | clojurebot | :sandbox/user |
| 16:06 | noonian | using two colons with a keyword expands out to the namespace qualified one, so ::user (in the users ns) would expand to :users/user |
| 16:06 | bitemyapp | ,:user |
| 16:06 | clojurebot | :user |
| 16:07 | noonian | ,::sandbox/user |
| 16:07 | clojurebot | :sandbox/user |
| 16:07 | noonian | ,::users/user |
| 16:07 | clojurebot | #<RuntimeException java.lang.RuntimeException: Invalid token: ::users/user> |
| 16:10 | kristof | Here's a heretical question. |
| 16:10 | kristof | Is the STM system an actor? |
| 16:10 | kristof | Or rather, would it be useful to think of it as one? |
| 16:11 | tbaldridge | kristof: no, it's more like a managed lock system |
| 16:12 | kristof | tbaldridge: Oh, you're the core.async guy. I've watched all the videos I can (that you've released), and I think it's all great stuff :) |
| 16:12 | tbaldridge | kristof: thanks! |
| 16:12 | kristof | Goroutines in general seem like magic, ha |
| 16:12 | stuartsierra | [org.clojure/data.json "0.2.4"] and [org.clojure/java.classpath "0.2.2"] are in the Maven Central repo now. |
| 16:13 | kristof | I'm just mostly impressed with the way the go macro deep walks a bunch of code and sets up a state machine accordingly |
| 16:13 | kristof | tbaldridge: Question, is there only one STM per running clojure process? |
| 16:13 | stompyj | bitemyapp: you're saying you think light table isn't likely to be used? (sorry, only read half the convo) |
| 16:15 | tbaldridge | kristof: not really. The way STM works is a lot like locks are used in any Java program. But in STM threads can "barge" locks. So one thread locks the refs it needs, does its work, and then only commits if someone else hasn't barged the locks. If there's a barge then the thread drops all its work and retries. |
| 16:17 | saint_cypher | noonian: thanks. |
| 16:18 | noonian | saint_cypher: np, other than that i'm not shure whats going on, you might need to make sure you are calling authenticate in your middleware |
| 16:18 | kristof | tbaldridge: Oh, I think I understand now. So you can concurrently access two refs and commit to both of those at the same time if they're not the same ref, right? |
| 16:18 | tbaldridge | kristof: *if they're not in the same transaction |
| 16:20 | kristof | Ok, that makes sense. |
| 16:20 | tbaldridge | kristof: but yes, that's the general idea. Although I was surprised to find how little I need STM. Actually I can't think of a single time I've used it and didn't refactor it out later |
| 16:20 | tbaldridge | kristof: it's often much easier to put a hashmap in a single atom, or something like that. |
| 16:20 | mrhanky | i need some hints, i have a clojure script which calls (read-line) to read user input (the script realises a repl). i know want to port this to clojurescriot, so i defined a read-line myself. i use a javascript terminal (jq-console) to handle input/output. my (read-line) starts a new input prompt of jq-console, but my read-line returns a nil immediately and the script failes. how can i "block" the execution of my ported script until a |
| 16:20 | mrhanky | input is made? |
| 16:20 | kristof | tbaldridge: Under what circumstances do you find that you really need to coordinate and synchronize state changes? |
| 16:21 | kristof | I mean, I suppose you just answered that, but can you think of anything? |
| 16:23 | tbaldridge | that's the problem, I don't really use it much at all. And have rarely (never?) seen it in production code. Normally things are either async, and so core.async or agents are used. Or people just an atom with a hashmap. I think you might want refs if you have a number of refs, and enough threads that they are tripping over themselves during swap! |
| 16:23 | technomancy | I feel like refs would be a lot more useful outside the server-side context |
| 16:23 | tbaldridge | Although even then I'd be tempted to throw all the updates into a core.async channel and serialize them. So yeah, I wonder sometimes if refs aren't superseded by core.async. |
| 16:24 | technomancy | because you're more likely to be able to fit everything in one process |
| 16:24 | arohner | tbaldridge: I find refs are superseded by my DB more than core.async |
| 16:24 | arohner | I almost never want to transact on something that I don't want written to disk |
| 16:25 | amalloy | mrhanky: javascript is single-threaded, so a blocking approach won't work. you have to switch to a callback mechanism, either by hand or using core.async |
| 16:25 | tbaldridge | arohner: yeah, that too. Esp if you use Datomic. |
| 16:25 | arohner | yup |
| 16:25 | mrhanky | amackera, yeah, i just came accross core.async |
| 16:25 | mrhanky | * amalloy |
| 16:25 | kristof | arohner: the point of datomic was to really run in memory and only commit to disk occasionally, wasn't it? |
| 16:25 | stcredzero | What would be the best way to do server push from clojure to a clojurescript client? (Could also be js client) |
| 16:25 | arohner | kristof: I don't think I'm qualified to comment on that, given other people in the channel, but IMO no |
| 16:25 | tbaldridge | kristof: no in server mode all data is always written to disk. |
| 16:26 | kristof | ok. |
| 16:26 | tbaldridge | kristof: there is a memory only mode for Datomic however. |
| 16:26 | hansel-han | is there any reason to use a default location like /var/www/example.com/public_html instead of just ~/public_html? |
| 16:26 | kristof | tbaldridge: Hand-wavey question. Is Cognitect an exciting place to be at? :) |
| 16:27 | ToBeReplaced | stcredzero: you have a ton of options... i would decide which web technology you want first (SSE, websockets, other) |
| 16:28 | tbaldridge | kristof: no. it's horrible. They make us work on open source projects sometimes, and I have to program in Clojure all day. |
| 16:28 | arohner | :-) |
| 16:28 | stcredzero | ToBeReplaced: I'm writing a game with as thin a client as possible, but still needs to be responsive. It's a roguelike, so all it does is pass keypresses to the server and displays a 80x24 ascii grid. |
| 16:28 | tbaldridge | kristof: ofcourse! I love it. |
| 16:29 | kristof | :) |
| 16:29 | wink | > Chinese spy manages to steal last 50MB of Lisp program governing U.S. missile launches. Fortunately, it was all closing parentheses. |
| 16:29 | wink | best lisp joke I heard in months :D |
| 16:29 | stcredzero | ToBeReplaced: I also would de-prioritize browser compatibility. |
| 16:30 | ToBeReplaced | tbaldridge: core.async eliminated the clojure concurrency primitives altogether for us -- we store application states in "system" variables with control channels and go loops -- feels great |
| 16:30 | bitemyapp | tbaldridge: I'm with arohner on refs/core.async/dbs |
| 16:31 | bitemyapp | tbaldridge: refs are superseded by Datomic :) |
| 16:31 | locks | has anyone implemented a card game? I only got to https://github.com/locks/sueca/blob/master/src/sueca/core.clj before getting coder’s block. my brain has a hard time thinking clojure still |
| 16:31 | bitemyapp | arohner: how have you been? |
| 16:31 | arohner | good. busy |
| 16:31 | bbloom | locks: stuartsierra has a good talk about a poker game in clj |
| 16:31 | arohner | still not on datomic yet |
| 16:31 | arohner | :-P |
| 16:31 | bbloom | locks: well, it's more about working with data, but he uses a poker example |
| 16:31 | ToBeReplaced | stcredzero: since you have back and forth, i would consider something like https://github.com/lynaghk/jetty7-websockets-async |
| 16:32 | tbaldridge | ToBeReplaced: bud don't you loose instant deref with that? |
| 16:32 | arohner | it's amazing how many things there are to do, that aren't the things you want to work on |
| 16:32 | bbloom | locks: http://www.infoq.com/presentations/Thinking-in-Data |
| 16:32 | bitemyapp | arohner: I didn't figure you were. I've assumed that when you were ready to test a migration, you'd do something with berossus first. |
| 16:32 | bitemyapp | arohner: sorry, brambling. |
| 16:32 | tbaldridge | *but |
| 16:32 | bitemyapp | I keep naming all my projects with the letter b and it's causing me to scramble them a bit. |
| 16:32 | ToBeReplaced | tbaldridge: explain? |
| 16:32 | arohner | bitemyapp: is the story on datomic migrations any better yet? |
| 16:32 | locks | bbloom: yeah, I even tweeted at him thanking, but it’s pretty thin on the main “run loop” and code |
| 16:33 | bitemyapp | arohner: I'm still the only show in town. |
| 16:33 | arohner | might be a good post to the newsgroup |
| 16:33 | locks | bbloom: I did learn some useful things from his talk |
| 16:33 | bitemyapp | arohner: and I'm still open to incremental/differential migrations. |
| 16:33 | bitemyapp | arohner: but, my workplace hasn't needed it yet, so I haven't implemented it yet because my at-home projects are Haskell right now. |
| 16:33 | tbaldridge | ToBeReplaced: you said you're storing app state as locals inside gos. How does one go get access to the data inside another go? |
| 16:33 | arrdem | bitemyapp: I think that the lack of cljx support is important, but I think that there are major usability concerns that need to come first. |
| 16:33 | arohner | bitemyapp: Circle has never had planned downtime, so I don't plan on starting now :-) |
| 16:34 | bbloom | locks: just takes some practice. start by trying to figure out what operations you need & what the data structures need to look like to support those operations |
| 16:34 | bitemyapp | arohner: part of the reason I am holding off on incremental migrations is that I want a second pair of eyes on Brambling. |
| 16:34 | ToBeReplaced | tbaldridge: control channels -- the go loops alt and look for requests of "where am i at?" |
| 16:34 | arrdem | bitemyapp: and yes. writing programs in top type isn't condusive to using a more restrictive system. |
| 16:34 | ToBeReplaced | tbaldridge: might be a bit clunky... first forays into CSP |
| 16:35 | bitemyapp | arrdem: but it was a clever way to defeat static analysis. |
| 16:35 | bitemyapp | arrdem: if that was ibdknox's intent :) |
| 16:35 | locks | bbloom: I’ll keep at it, thanks |
| 16:35 | arrdem | bitemyapp: :/ on an open project? doubtful, but possible. |
| 16:35 | bitemyapp | arohner: I don't want to implement incremental migrations myself and then tell startups/businesses, "ya sure, trust this with your data" unless at least one other reasonably competent person has given it a look over. |
| 16:35 | bitemyapp | arohner: I was being facetious. |
| 16:35 | bitemyapp | errr |
| 16:35 | bitemyapp | arrdem: I was being facetious. |
| 16:36 | bitemyapp | arohner: if the ROI on switching to Datomic isn't worth poking at a migration tool then it's probably not yet time to make the switch anyway. |
| 16:37 | stcredzero | ToBeReplaced: Thanks! That looks just beautiful! |
| 16:37 | arohner | bitemyapp: it's time, but I haven't heard a strategy, even in theory, to get schema migrations yet |
| 16:37 | arohner | also, it's been time for a while, but we can never find the bandwidth |
| 16:38 | bitemyapp | arohner: there already is a way to do arbitrary schema migrations with Brambling, do you mean in-place |
| 16:39 | bitemyapp | add a ? to the end of that. |
| 16:39 | arohner | in-place isn't a strict requirement, but zero downtime and no races is |
| 16:39 | arohner | so migrate into a second DB, but then you need to handle the switchover |
| 16:39 | bitemyapp | I'm not sure where a data race with Brambling would happen. |
| 16:40 | bitemyapp | arohner: the only Datomic support schema changes that are likely to be supported in the near future are the adding (removal?) of indexes and possibly uni-directional cardinality promotion. |
| 16:40 | arohner | (I don't mean brambling needs to handle this, I mean I need to understand how my code would work) |
| 16:40 | bitemyapp | zero downtime depends on how abstracted your applications are from Datomic. |
| 16:40 | arohner | bitemyapp: at time t1, all peers are on database d1. you migrate to d2. Then you need to switch all peers over to d2, and make sure all in-flight writes appear on d2 |
| 16:40 | bitemyapp | it goes back to whether or not you can down a clean hand-off with a query queue. |
| 16:41 | bitemyapp | that's how you avoid races and downtime, at least as a first pass. |
| 16:41 | bitemyapp | can do* |
| 16:41 | arohner | also, duplicating the data size just to do a migration :-( |
| 16:42 | bitemyapp | arohner: if your applications are calling your database directly, that's not good. You need a middleware layer / queue like larger services. |
| 16:42 | bitemyapp | the middleware layer / queue makes the hand-off safe and prevents any lost transactions. |
| 16:42 | arohner | it still sounds like there's a race there |
| 16:42 | ToBeReplaced | tbaldridge: i'd also appreciate critique if there's something clearly funky with that approach -- it's true that we don't get instant deref b/c you have to wait for the go block to alt again. It might make more sense to just have each block update an atom to deref against. however, we need (or think we need) the control channels anyway so it didn't seem awful |
| 16:42 | bitemyapp | arohner: I don't think so, the queue/middleware layer is pausing for the length of the final migration. |
| 16:43 | bitemyapp | arohner: but the reason for incremental migrations is to make that final migration VERY short |
| 16:43 | bitemyapp | like, not detectable by your users. |
| 16:43 | bitemyapp | I thought I'd explained all this before. |
| 16:43 | arohner | sorry, it's been a while |
| 16:43 | arohner | where the final migration is incremental, over the time since the 'full' migration finished? |
| 16:43 | bitemyapp | the only real source of delay would be long running transactions/queries. |
| 16:44 | bitemyapp | arohner: it's zeno's paradox type thing. |
| 16:44 | tbaldridge | ToBeReplaced: yeah, it depends on the app. But as a whole that's one of the issues with actor systems. The actor can get backed up, and then it can't be deref'd. But YMMV. |
| 16:44 | bitemyapp | arohner: you're incrementally catching up the destination to the origin over and over until the differential is so small that a final migration should take no time at all. |
| 16:44 | arohner | right |
| 16:44 | bitemyapp | arohner: then for that final migration, you bring the hammer down in your middleware/queue to hold the boat, let things wrap up, then flip over. |
| 16:45 | bitemyapp | my only real complaint is the data duplication, but I don't think it's expensive at your scale, especially if you're using EC2. |
| 16:46 | ToBeReplaced | tbaldridge: was your comment earlier that you're finding that you're not shipping refs anymore, only atoms (and agents?) |
| 16:46 | arohner | tbaldridge: any hope on this stuff (zero downtime schema migrations w/ datomic) getting easier? :-) |
| 16:46 | bitemyapp | from there you can do a differential archive of the contents of the origin/old database against some archival instance and then kill 'em off. |
| 16:46 | arohner | bitemyapp: I worry more about the pain-in-the-ass factor than the cost |
| 16:46 | arohner | (though cost does matter some) |
| 16:46 | bitemyapp | arohner: I've been bugging Cognitect about it, what I mentioned earlier is the only thing they've explicitly said they'd be comfortable doing. |
| 16:47 | bitemyapp | arohner: I don't worry about the cost arising from the data duplication, just the operational ick. |
| 16:47 | tbaldridge | arohner: I'd ask bobby or stuart in #datomic. They are more qualified (and authorized) to speak to that. |
| 16:48 | arohner | tbaldridge: thanks. Which stuart? :-) |
| 16:48 | bitemyapp | arohner: probably the dude with the rock star hair. |
| 16:48 | tbaldridge | arohner: stuart h works full time on Datomic. Bobby specializes in customer relations for datomic. |
| 16:49 | bitemyapp | Bobby's almost always the one answering my questions. |
| 16:49 | bitemyapp | Halloway's accidentally responded once I think. |
| 16:49 | bitemyapp | tbaldridge: neither seem to be in the channel though. |
| 16:50 | bitemyapp | and I'm loathe to file a ticket for something I'd already asked them about in the past. |
| 16:57 | logic_prog | why are nested #( ... % ... ) 's not allowed? |
| 16:57 | logic_prog | why not have % bound to the nearest # ? |
| 16:57 | tbaldridge | logic_prog: that would be super easy to get wrong |
| 16:58 | tbaldridge | and #(%) is just gross anyways (imo) |
| 16:58 | ucb | bitemyapp: ! |
| 16:59 | amalloy | (map #(map #(map #(+ % %) %) %) xs) doesn't read super-well |
| 16:59 | TimMc | tbaldridge: Nonsense, where would swearjure even be without it? |
| 17:00 | bitemyapp | ucb: I sent you a lot of music. |
| 17:00 | ucb | bitemyapp: I saw my name highlighted but lost the backlog :'( |
| 17:00 | bitemyapp | muh lord. |
| 17:01 | bitemyapp | ucb: http://kasperrosa.bandcamp.com/track/coronal-mass-ejection http://dumbsaint.bandcamp.com/album/something-that-you-feel-will-find-its-own-form |
| 17:01 | ucb | muh limechat. |
| 17:01 | bitemyapp | this is why I am civilized and use a persistent IRC session. |
| 17:02 | ucb | thanks! |
| 17:02 | bitemyapp | ucb: and https://soundcloud.com/you-are-not-cat/tangled-up-in-clouds https://www.youtube.com/watch?v=YQ1wsf7tAE0 |
| 17:02 | ucb | me too, but limechat is a piece of gunk |
| 17:02 | bitemyapp | ucb: last one comes by way of akurilin. post-punk'ish hardcorey stuff. good. |
| 17:02 | ucb | cool! |
| 17:03 | TimMc | bitemyapp: Do you have somethign set up that collects all your highlights in another file? |
| 17:03 | TimMc | If I forget to /away, it's really annoying to figure out where a highlight came from when I get back. |
| 17:03 | rasmusto | hilite for irssi is kewl |
| 17:03 | bitemyapp | TimMc: I just have logs. |
| 17:03 | bitemyapp | TimMc: and /lastlog |
| 17:03 | TimMc | Fair. |
| 17:04 | bitemyapp | TimMc: arrdem's setup is even better, he gets a phone jingle. |
| 17:04 | TimMc | I highlight on more than just my nick, though. |
| 17:04 | bitemyapp | TimMc: be sure to use this knowledge for evil liek I do. |
| 17:04 | bitemyapp | like* |
| 17:04 | bitemyapp | I don't highlight on anything but my name. Nobody talks about my libraries. |
| 17:04 | bitemyapp | except occasionally on the mailing lists. |
| 17:04 | bitemyapp | s/occasionally/rarely/g |
| 17:05 | bitemyapp | ucb: https://www.youtube.com/watch?v=hzMeU8tuvNE |
| 17:05 | mikerod | Why is the type hierarchy of Clojure functions so... big? |
| 17:06 | bitemyapp | mikerod: I mean, it's not Spring Framework. |
| 17:06 | mikerod | AFunction, AFn, IFn, Fn |
| 17:06 | mikerod | wat |
| 17:06 | bitemyapp | mikerod: have you ever tried to make something nice in Java? |
| 17:07 | mikerod | bitemyapp: haha, ok I guess that is a fair enough explanation |
| 17:07 | bitemyapp | mikerod: Clojure's implementation is pretty solid at the ground floor, IMHO. |
| 17:08 | locks | what about clojure on CLR :P |
| 17:08 | bbloom | mikerod: IFn is for things that can be called like functions. AFn is used internally to deal with some ugly java crap about variadics via implementation inheritence, Fn is a marker interface for saying "this is a real function", and AFunction is the implementation of Fn |
| 17:08 | bitemyapp | mikerod: you don't want to roll all this stuff into a single class. |
| 17:10 | rasmusto | everything is a class, a class is everything |
| 17:10 | mikerod | bbloom: that is a good explanation of these things that I certainly haven't heard befor |
| 17:11 | mikerod | before* |
| 17:11 | bbloom | mikerod: all you really need to know as a user is that there is clojure.core/ifn? and clojure.core/fn? |
| 17:11 | mikerod | bitemyapp: I know that smaller, composable interfaces (abstractions) are favorable to monolithic ones; especially in the Clojure core |
| 17:11 | bbloom | mikerod: implementation wise, you've also overlooked RestFn and a few other things |
| 17:12 | bbloom | that's the point of AFn and Fn. AFn lets all the concrete impls share stuff and Fn lets you do fast testing against an interface for clojure.core/fn? |
| 17:12 | bbloom | but maps and vectors and things are not functions, they can only be called LIKE functions, hence ifn? |
| 17:15 | bitemyapp | ucb: https://www.youtube.com/watch?v=efsUakRY2IQ |
| 17:16 | ucb | bitemyapp: http://www.youtube.com/watch?v=_G3UsM0D6aA |
| 17:16 | bitemyapp | bbloom: do you listen to music while coding? |
| 17:17 | Raynes | Who doesn't? |
| 17:18 | ucb | +1 |
| 17:18 | Raynes | bbloom jams out to Grimes while he codes. |
| 17:18 | Raynes | Not the band, podcasts featuring me. |
| 17:18 | bitemyapp | ucb: surf doom? |
| 17:18 | bitemyapp | Raynes: that chick is spooky yo/ |
| 17:18 | ucb | bitemyapp: never heard of it |
| 17:18 | egghead | lol |
| 17:18 | egghead | grimes while devvin |
| 17:18 | bitemyapp | ucb: that's how I'm describing what you sent me. |
| 17:18 | egghead | I've been listening to lee bannons new album while devvin |
| 17:18 | ucb | bitemyapp: oh! heh. Never had somebody refer to The Coral as surf doom :) |
| 17:19 | bitemyapp | ucb: s'what it sounds like. |
| 17:19 | bitemyapp | I should write a thesis on genre bucketing. |
| 17:19 | Raynes | I listen to recordings of bitemyapp played at 0.5x speed |
| 17:19 | egghead | is anthony grimes a member of the band grimes??? |
| 17:19 | lazybot | egghead: Yes, 100% for sure. |
| 17:19 | egghead | ty lazybot |
| 17:19 | Raynes | egghead: I wish :( |
| 17:19 | bitemyapp | that would be hella cool if it was true. |
| 17:19 | Raynes | Screw programming, music is my passion. |
| 17:19 | Raynes | That's not true, but I am a wannabe singer. <3 |
| 17:20 | egghead | we can start a band Raynes |
| 17:20 | egghead | we'll use overtone and livecode |
| 17:20 | Raynes | I'm down. |
| 17:20 | bitemyapp | I need to learn to play keyboard. |
| 17:21 | egghead | oh nice do you play keyboard? nah I play emacs |
| 17:21 | egghead | i'm sure we could get a gig at the echoplex those guys let anyone |
| 17:23 | mikerod | Looks like I lost my connection, thanks for the IFn and Fn family explanations |
| 17:23 | mikerod | I feel a little more at ease on it now |
| 17:26 | stuartsierra | mikerod: I made a little utility to help visualize those class hierarchies https://github.com/stuartsierra/class-diagram |
| 17:26 | stuartsierra | And somewhere on the web is a giant diagram of all the Clojure classes/interfaces. |
| 17:27 | mikerod | stuartsierra: Oh, I forgot I came across this I think a while back. This is definitely useful. |
| 17:27 | dnolen | https://raw2.github.com/Chouser/clojure-classes/master/graph-w-legend.png |
| 17:28 | stuartsierra | that's it |
| 17:28 | mikerod | awesome to both |
| 17:33 | locks | wait, Clojure has classes? |
| 17:33 | locks | I’ve been lied to |
| 17:33 | locks | :P |
| 17:37 | hyPiRion | :gen-class man |
| 17:37 | logic_prog | in core.async, is there a way to say : create a new channel by (1) taking everything from chan1, then (2) take everything from chan2? |
| 17:37 | logic_prog | basically, I want a way to concat two chans |
| 17:46 | AeroNotix | is there anything like `doto' which returns the value of the last form? |
| 17:47 | bbloom | AeroNotix: not precisely, but there is .. which is for chaining style, like if you have a "fluent" builder or something from java land |
| 17:47 | bbloom | (doc ..) |
| 17:47 | clojurebot | "([x form] [x form & more]); form => fieldName-symbol or (instanceMethodName-symbol args*) Expands into a member access (.) of the first member on the first argument, followed by the next member on the result, etc. For instance: (.. System (getProperties) (get \"os.name\")) expands to: (. (. System (getProperties)) (get \"os.name\")) but is easier to write, read, and understand." |
| 17:48 | AeroNotix | bbloom: that's different |
| 17:48 | bbloom | AeroNotix: i'm aware. hence i said "not precisely" |
| 17:48 | AeroNotix | oke doke |
| 17:49 | bbloom | was just guessing, since that's a popular thing in java libs for functions that always return "this" |
| 17:49 | AeroNotix | I can write a macro for this (most likely just copying the majority of doto) |
| 17:49 | AeroNotix | any reasoning why doto returns the original value? |
| 17:49 | AeroNotix | (doc doto) |
| 17:49 | clojurebot | "([x & forms]); Evaluates x then calls all of the methods and functions with the value of x supplied at the front of the given arguments. The forms are evaluated in order. Returns x. (doto (new java.util.HashMap) (.put \"a\" 1) (.put \"b\" 2))" |
| 17:49 | AeroNotix | returns x |
| 17:49 | AeroNotix | L |
| 17:50 | bbloom | AeroNotix: it returns the original b/c you're presumably mutating it and then want it |
| 17:50 | bbloom | AeroNotix: i wouldn't copy doto, i'd delegate to it |
| 17:50 | AeroNotix | hmm, indeed. Could be a reason |
| 17:50 | justin_smith | if you want the last result, you can use -> or ->> instead of doto, which assume functinoal rather than mutational chaining |
| 17:50 | AeroNotix | justin_smith: but it doesn't work if the functions are mutating a java object, instead of returning values |
| 17:50 | noonian | just make sure your calls return compatible values |
| 17:51 | AeroNotix | It's not my Java code |
| 17:51 | nhjk | noob question, but is it worth it to learn some java because clojure is based on the jvm? |
| 17:51 | AeroNotix | nhjk: somewhat, I've found |
| 17:51 | stuartsierra | logic_prog: maybe something like this (totally untested) https://gist.github.com/stuartsierra/8364220 |
| 17:51 | AeroNotix | you'll be exposed to it. Namely things like how java organizes code |
| 17:51 | AeroNotix | and a lot of useful stuff is in the java stdlib |
| 17:51 | technomancy | nhjk: you need to learn to read it eventually, but learning to write it is a waste of time |
| 17:52 | justin_smith | learning java is meh I think, but knowing enough so you can read javadoc and do interop? definitely |
| 17:52 | AeroNotix | exactly |
| 17:52 | logic_prog | staurtsierra: noted, thanks! |
| 17:52 | AeroNotix | Just enough so you can read function signatures would be nice. |
| 17:52 | stuartsierra | logic_prog: just fixed to return `out` |
| 17:53 | AeroNotix | haha, I love going away from Clojure to Go, and then coming back to Clojuer |
| 17:53 | AeroNotix | Clojure* |
| 17:53 | justin_smith | the three java skills needed in clojure: jvm config / tuning / classpath; reading javadoc; reading stack traces |
| 17:53 | AeroNotix | Clojure stack traces are fugly, jus' sayin' |
| 17:54 | justin_smith | they are, but knowing how to read them is a must, for now |
| 17:54 | rasmusto | IFugly |
| 17:54 | stuartsierra | Whenever I hear that, I think "Compared to what?" |
| 17:54 | noonian | lol |
| 17:54 | AeroNotix | stuartsierra: some languages which don't include internal machinary |
| 17:54 | AeroNotix | in their stack traces |
| 17:54 | nhjk | alright thanks, I'm already familiar with the syntax because of an algorithms class, but I'll dive a little deeper! |
| 17:54 | stuartsierra | What language does that? |
| 17:54 | AeroNotix | There's references to things like `apply' interspersed with all my stuff. |
| 17:54 | nDuff | AeroNotix: ...and you can use available tools and libraries in Clojure to strip them out here. |
| 17:54 | technomancy | compared to nearly everything |
| 17:54 | nDuff | AeroNotix: ...if you're so inclined. |
| 17:54 | AeroNotix | nDuff: such as? |
| 17:55 | AeroNotix | I use emacs, probably cannot switch at this point. |
| 17:55 | nDuff | AeroNotix: clj-stracktrace, f'rinstance |
| 17:55 | technomancy | racket actually has different stack trace styles for its beginner languages vs its expert ones, which is brilliant |
| 17:55 | AeroNotix | stack traces to 11 |
| 17:55 | mikerod | I don't really care if the stacktrace shows the Clojure internal functions being called. I don't see what is hard about finding the relevant code that causes the issue in that. |
| 17:55 | mikerod | The harder things are when it is a compiler-time error |
| 17:55 | technomancy | nDuff: clj-stacktrace doesn't actually remove any gunk |
| 17:55 | hiredman | what a pain it must be to debug things when the runtime is actively trying to hide things from you |
| 17:55 | nDuff | Ahh. I've seen stuff that did, but not paid much attention. |
| 17:56 | AeroNotix | nDuff: clj-stacktrace still includes crap in the trace |
| 17:56 | mikerod | The worst is when it is no-source-file eval-fns |
| 17:56 | nDuff | AeroNotix: As I said above, I've not paid much attention to those tools. |
| 17:56 | stuartsierra | ^ What hiredman said. |
| 17:56 | AeroNotix | clojure.lang.RestFn.invoke, like what the hell does that need to be in the stack trace for |
| 17:56 | technomancy | hiredman: actively hiding stuff from you is what abstraction is all about |
| 17:56 | mikerod | ^ to not hiding details of the stack |
| 17:56 | stuartsierra | I dunno, maybe because it was on the stack? |
| 17:57 | nDuff | AeroNotix: ...ahh, https://github.com/AvisoNovate/pretty was the more recent one |
| 17:57 | AeroNotix | stuartsierra: sure, but it's not anything that's to do with me, really. If you need that, it should be configurable |
| 17:57 | AeroNotix | stuartsierra: as in, some variable which you can set for stack trace verboseness |
| 17:57 | dnolen | AeroNotix: *sigh* it is configurable today, no one uses it |
| 17:57 | stuartsierra | What's next, configurable core dumps? Configurable segfaults? |
| 17:57 | stuartsierra | Configurable BSOD? |
| 17:58 | nDuff | AeroNotix: ...it's not filtering things, but it is using highlighting to distinguish |
| 17:58 | locks | I’d configure segfaults to —never |
| 17:58 | AeroNotix | nDuff: it's better |
| 17:58 | AeroNotix | dnolen: any docs? |
| 17:58 | dnolen | AeroNotix: you can get pretty stack traces since 1.3 |
| 17:58 | AeroNotix | > any docs? |
| 17:58 | dnolen | AeroNotix: it the default behaior of clojure.repl/pst |
| 17:58 | dnolen | AeroNotix: pst has been doc forever |
| 17:59 | dnolen | doc'ed |
| 17:59 | technomancy | that's a pretty low bar for "pretty" |
| 17:59 | dnolen | technomancy: we've already discussed this like a million times :) |
| 17:59 | dnolen | clj-stacktrace is an abomination |
| 17:59 | stuartsierra | `psh` also conveniently hides the cause chain, breaking any attempt by a library designer to provide a useful error message. |
| 17:59 | stuartsierra | `pst` |
| 17:59 | dnolen | stuartsierra: I'm not condoning it by any means |
| 17:59 | technomancy | dnolen: everything is terrible; I agree there |
| 18:00 | bitemyapp | the complaining is partly why I stopped trying to improve clj-stacktrace. |
| 18:00 | stuartsierra | Just this week I had to hunt for an exception that clj-stacktrace swallowed. |
| 18:00 | bitemyapp | I went back to banging rocks together. |
| 18:00 | dnolen | but if people want to find out about stuff they'll eventually abandon, who am I to get in the way :D |
| 18:00 | technomancy | "Everything is great the way it is" just means we've lowered our standards |
| 18:01 | mikerod | what is clj-stacktrace, never heard of this one |
| 18:01 | AeroNotix | I guess eventually I'll just tune out the noise |
| 18:01 | stuartsierra | a pretty stacktrace is like a pretty autopsy. |
| 18:01 | mikerod | ohhh, yes I have |
| 18:01 | bitemyapp | mikerod: you are...so lucky I've sworn off lgtfy. |
| 18:01 | AeroNotix | stuartsierra: that's a terrible opinion :) |
| 18:01 | kristof | Especially with java stacktraces, hah. |
| 18:01 | kzar | dnolen: Going to have a look at om hopefully this weekend, is it ready for production stuff in your opinion? |
| 18:01 | stuartsierra | i.e. if it's pretty you're going to hide lots of important details |
| 18:01 | bitemyapp | stuartsierra: I think stacktraces can get cleaned up and bracketed without dropping information. |
| 18:01 | AeroNotix | stuartsierra: it's a post mortem on a sometimes critical part of your system. You need that information to contain what you need exactly. |
| 18:01 | bitemyapp | stacktraces wouldn't be so damn critical if we had sensible types. |
| 18:01 | stuartsierra | Yes, which is why it shouldn't hide anything. |
| 18:01 | mikerod | bitemyapp: hah I looked it up, stupid question |
| 18:02 | dnolen | technomancy: I think anyone who has done CLJ long enough likes verbose stack traces, as long as it's not deep in the compiler or the reader |
| 18:02 | kristof | bitemyapp: Oh? Why? |
| 18:02 | bitemyapp | logging/tracing is usually more valuable and semantically relevant than stacktraces. |
| 18:02 | technomancy | stuartsierra: so do you turn on GC logging too? |
| 18:02 | mikerod | I was thinking the discussion was of clojure.stacktrace |
| 18:02 | bitemyapp | kristof: source/sink distance on errors. |
| 18:02 | technomancy | wouldn't want to miss anything important |
| 18:02 | bitemyapp | kristof: if the compiler is catching 90% or more of the common-case stuff, then it's less often that you need to pick through a stacktrace. |
| 18:02 | dnolen | kzar: it's pre-alpha, things are going to change |
| 18:03 | dnolen | kzar: it's worth assessing, not building critical stuff on. Though that doesn't appear to be stopping anyone. |
| 18:03 | hyPiRion | There are some pretty good ideas and concepts in Racket, CLisp and Erlang on how to read stack traces and issues in programs. |
| 18:03 | technomancy | dnolen: so anyone who doesn't like it just hasn't been using clojure long enough? interesting. |
| 18:03 | bitemyapp | kristof: in the rare occasion when I need to look at a stacktrace in, say, Haskell it's because I had an unintentionally non-total pattern match. |
| 18:03 | hyPiRion | Even gdb/lldb would be good/valuable. |
| 18:03 | bitemyapp | kristof: it then tells me what value I failed to match, then I add the match. |
| 18:03 | dnolen | technomancy: I don't think that's all that weird |
| 18:03 | bitemyapp | kristof: source->sink distance: 0 |
| 18:03 | kzar | OK good to know, still am intrigued enough to want to spend my weekend looking at it. Curious if it could replace AngularJS |
| 18:03 | technomancy | how many years does it take? |
| 18:04 | dnolen | technomancy: I once thought not being able to set locals was stupid |
| 18:04 | bitemyapp | kristof: source->sink distance of my average Clojure stacktrace? ohgod.jpg |
| 18:04 | technomancy | maybe two or three more years and the beauty will sink in |
| 18:04 | technomancy | and I'll stop being such a noob |
| 18:04 | bitemyapp | kristof: I would be willing to bet OCaml users have a similar experience. |
| 18:04 | stuartsierra | No one ever said they were beautiful. |
| 18:04 | dnolen | technomancy: it's not about pretty / not pretty |
| 18:04 | bitemyapp | there are ways to make stacktraces more readable/usable without dropping info. |
| 18:04 | mrcheeks | dnolen: 'completeness' of the stacktrace then? |
| 18:05 | dnolen | mrcheeks: not missing critical information |
| 18:05 | bitemyapp | If everybody agrees on that point then we can just discuss what those improvements could be. |
| 18:06 | bitemyapp | I'm pretty sure everybody understands stack-trace elision is a bad idea. |
| 18:06 | mikerod | mrcheeks: we want them the stacktrace to be both complete and sound |
| 18:06 | dnolen | what makes me laugh about all of this is that the main reason that CLJ stack traces are so noisy are precisely the same reasons that CLJS stack traces aren't |
| 18:06 | mikerod | :P |
| 18:06 | dnolen | decomplected compile/runtime |
| 18:06 | stuartsierra | I believe .printStackTrace is good enough, and every attempt I have seen to "improve" it ends up having subtle bugs that lose the original exception. |
| 18:07 | stuartsierra | s/subtle/edge case/ |
| 18:07 | technomancy | stuartsierra: the only lib that's even attempted is a 3-year-old abandoned hack |
| 18:07 | technomancy | whose author ran off to write Google go code |
| 18:08 | justin_smith | locks: I once wrote a c program for win98, no segfaults is not a bonus |
| 18:08 | technomancy | hardly compelling |
| 18:08 | stuartsierra | There are 2 stack-trace printers in Clojure alone, `pst` and clojure.test. |
| 18:08 | justin_smith | the alternative to segfault is worse |
| 18:08 | bitemyapp | justin_smith: mmmm data corruption |
| 18:08 | stuartsierra | Regrettably I wrote one of them. I've learned my lesson. |
| 18:08 | technomancy | part of the reason no one tried picking that up is that chouser said he was going to do it |
| 18:08 | stuartsierra | And then decided it wasn't worth it. |
| 18:10 | technomancy | clojurebot: usability is not a big deal |
| 18:10 | clojurebot | You don't have to tell me twice. |
| 18:10 | Bronsa | arrdem: I'm afraid there's no way I'll be at clojure/west, San Francisco is a long way from Italy |
| 18:13 | supersym | facebook does their whole operation in mysql? ... those nr's kinda blow my mind |
| 18:14 | bitemyapp | supersym: no. It's not that simple. |
| 18:14 | arrdem | Bronsa: this doesn't especially surprise me :P |
| 18:14 | supersym | well they partition the whole thing ofc but still |
| 18:14 | arrdem | Bronsa: wish you could make it tho |
| 18:14 | bitemyapp | supersym: the messaging backend persistence layer is HBase (they hired a ton of ex-Yahoo! people). Some of their core persistence layer is MySQL. |
| 18:14 | supersym | yeah |
| 18:14 | bitemyapp | supersym: it's an inaccurate statement, there are many data stores at Facebook. |
| 18:14 | supersym | ok... I read that 90% doesn't scratch the db layer |
| 18:15 | supersym | caching mostly |
| 18:15 | bitemyapp | MySQL is their "primary" one in some sense, but sharded MySQL as facebook is a completely different animal than you might be thinking of. |
| 18:15 | bitemyapp | supersym: some of that is TAO, some of that is other things. |
| 18:15 | supersym | true in that sense, I must be my wording ;) |
| 18:15 | bitemyapp | supersym: they have an aggressive cache dependency graph built in TAO on top of memcached. |
| 18:15 | bitemyapp | if B depends on A, and A gets busted, B must be busted too. |
| 18:16 | supersym | I never heard of TAO... going to read up some on that |
| 18:16 | bitemyapp | supersym: their whole OLAP stack is Hadoop. |
| 18:16 | bitemyapp | only the core OLTP is the sharded MySQL, and realistically, most read requests are served by TAO/memcached if things are going well. |
| 18:16 | supersym | Its that I got involved with this magento shop now (they use this pretty advanced EAV setup) that I got to work with mysql again |
| 18:17 | supersym | but it really wants to make me stab my eyes out the whole PHP/HTML soup |
| 18:17 | bitemyapp | supersym: you do not want to model your backend stack based on anything Facebook does. |
| 18:17 | bitemyapp | Seriously. Don't. |
| 18:18 | supersym | bitemyapp: nah... purely noticed for the fact of it, and what can be done as 'nice to know' |
| 18:18 | bitemyapp | making your own EAV for an ecommerce site seems terribly unwise. |
| 18:18 | bitemyapp | if you really need EAV, there's always Datomic though. |
| 18:18 | supersym | nothing planned on that front, I was actually wondering if I couldn't do better clean slate with clojure and datomic :P |
| 18:18 | bitemyapp | clean slates are pretty risky. |
| 18:19 | bitemyapp | incremental migrations are better. |
| 18:19 | bitemyapp | pick off pieces of your stack and port a single component at a time. |
| 18:19 | supersym | my idea |
| 18:19 | supersym | yeah |
| 18:19 | bitemyapp | supersym: there are books on how to deal with legacy code-bases. Divide and conquer. |
| 18:20 | supersym | bitemyapp: thanks, I really do feel there is a case here but indeed, I should approach this from certain angle |
| 18:20 | supersym | got this experienced magento people to bring me up to speed so nice time to pick their brains on some stuff as well |
| 18:22 | supersym | luckily it isn't a huge site in terms of catalog size but still the amount of customization makes every upgrade a huge pain in the ass and those guys are running way way behind in production version already |
| 18:22 | supersym | takes about 50 hours after 1 or 2 trial runs, according to teh googles |
| 18:22 | bitemyapp | supersym: do you have any questions about Clojure? |
| 18:24 | supersym | well besides that I wonder in terms of components, my obvious picks would be hiccup, datomic, jetty or probably http-kit but then also styling using garden, compojure ofc, ring, friend probably would be a good one esp. since you've got online payments |
| 18:25 | bitemyapp | I use http-kit, Ring/Compojure, datomic, and selmer (instead of hiccup). |
| 18:25 | supersym | all in all a lot of dependencies... chopping it up would seperate those, yet since its still web based, I wonder if pedestal would be a option |
| 18:25 | bitemyapp | I avoid hiccup and friend. Garden depends on your frontend people. |
| 18:25 | supersym | its really single page apps I think |
| 18:25 | AeroNotix | What're people using for syntax checking in Emacs? |
| 18:26 | amalloy | syntax...checking? what would it check? |
| 18:27 | supersym | bitemyapp: ok I don't think I've used selmer (or have it register for that matter). Any particular reason for picking it over hiccup? |
| 18:27 | bitemyapp | Raynes: in Geidi Primes there are moments where she almost sounds like Kate Bush |
| 18:27 | technomancy | supersym: oh man, prepare for a rant |
| 18:27 | AeroNotix | amalloy: it would check if the syntax is valid clojure, what else? |
| 18:27 | AeroNotix | surely you understand this concept? |
| 18:27 | supersym | technomancy: lol |
| 18:27 | Raynes | bitemyapp: I've actually never even listened to Grimes before. |
| 18:27 | bitemyapp | Raynes: ZOMG |
| 18:27 | Raynes | I just knew the name because... we share it. |
| 18:28 | technomancy | this used to be like a weekly thing where bitemyapp would complain how terrible web dev in clojure was because he couldn't use hiccup for some reason |
| 18:28 | amalloy | AeroNotix: the only syntax that exists is (stuff), [stuff], {stuff}. write code with paredit, and it's impossible to write incorrect syntax |
| 18:28 | bitemyapp | technomancy: hiccup is awful. |
| 18:28 | AeroNotix | amalloy: sure. Sure. SURE! |
| 18:28 | technomancy | lies |
| 18:28 | hyPiRion | oh, here we go again |
| 18:28 | AeroNotix | amalloy: I'll get RIIIIGGGHt on that |
| 18:28 | bitemyapp | hyPiRion: don't fear the reaper. |
| 18:28 | bitemyapp | supersym: just use Selmer. The library speaks for itself. |
| 18:28 | AeroNotix | amalloy: and we both know that there are more invalid pieces of syntax, but whatevs. |
| 18:28 | AeroNotix | e.g. |
| 18:29 | bitemyapp | (invalid lel :lol |
| 18:29 | supersym | lol ok |
| 18:29 | bitemyapp | I think the compiler catches that. |
| 18:29 | technomancy | supersym: if you have a team of designers and folks that don't know clojure touching the views, hiccup is not a good fit |
| 18:29 | bitemyapp | supersym: that's not the only reason to use Selmer. |
| 18:29 | bitemyapp | supersym: it also narrows down the origin of template context to a single bottleneck |
| 18:29 | bitemyapp | supersym: makes it super easy to log template context and what caused this or that output |
| 18:29 | AeroNotix | ,(let [m {:k :v}] (defn foo [{:keys [k] m}] k)) |
| 18:29 | clojurebot | #<RuntimeException java.lang.RuntimeException: Map literal must contain an even number of forms> |
| 18:30 | hyPiRion | AeroNotix: I just attempt to compile the file through cider/nrepl through C-c C-k. If it fails somewhere, there will be error lines explaining what failed |
| 18:30 | AeroNotix | amalloy: very simple error |
| 18:30 | bitemyapp | supersym: you can have m * n "connection points" between templates and your application in Hiccup. It's awful. |
| 18:30 | supersym | technomancy: no I guess I should use enlive for that |
| 18:30 | amalloy | yes, i should have written {stuff stuff}, not {stuff} |
| 18:30 | technomancy | supersym: ehrm... you can try that. it can be ... difficult. |
| 18:31 | bitemyapp | supersym: enlive is worse than hiccup. |
| 18:31 | bitemyapp | it's also horrifically slow. |
| 18:31 | technomancy | enlive code reads beautifully but when you go to modify it sometimes it can be difficult to know what to do |
| 18:31 | technomancy | it's not slow anymore |
| 18:31 | amalloy | seriously, clojure's syntax is so simple (it really is just lists vectors and maps), and its semantics so flexible (you can define macros that make anything syntactically valid be semantically meaningful), there's nothing for a syntax checker to do |
| 18:31 | supersym | right...well that really makes sense, it's the idea that it would be a more generic concept of e-commerce appliance in clojure but I guess once you venture into Clojure development, you are faced with tons of people who aren't |
| 18:31 | bitemyapp | technomancy: time to rerun my benchmark suite then. |
| 18:32 | bitemyapp | supersym: so use Selmer. |
| 18:32 | supersym | any freelance work I'd do in clojure and bet my ass people would come back cause it's hard to find developers >< |
| 18:32 | bitemyapp | there are a 1,001 reasons to use Selmer over Hiccup and you just named one of the better ones. |
| 18:32 | S11001001 | &(-> (java.text.SimpleDateFormat. "MMM-dd-yyyy") (.format (java.util.Date.))) |
| 18:32 | lazybot | ⇒ "Jan-10-2014" |
| 18:32 | amalloy | aside from run the compiler, as hyPiRion suggested, and then let you know if it broke |
| 18:32 | bitemyapp | S11001001: non-ISO format? Pagan. |
| 18:33 | bitemyapp | amalloy: I said that earlier :( |
| 18:33 | S11001001 | bitemyapp: working specifically with UI-side |
| 18:33 | noonian | yeah, the biggest problem with Clojure is that most people hate lisps |
| 18:33 | bitemyapp | S11001001: ignore the mewling cries of weak humans and use the standard format. |
| 18:34 | hyPiRion | Someone sayin enlive is the best thing ever would bring so much joy into this channel. |
| 18:34 | locks | noonian: lisps are hard to understand (yes, I made that pun) |
| 18:34 | noonian | lol |
| 18:34 | bitemyapp | hyPiRion: why? |
| 18:34 | hyPiRion | bitemyapp: That was attempted irony. |
| 18:36 | bitemyapp | hyPiRion: Enlive just reinforces my hypothesis that francophones are from outer space. |
| 18:36 | supersym | haha...I'll give you that ;) |
| 18:38 | hyPiRion | bitemyapp: That's no problem, Clojure is my alien spacecraft anyway. |
| 18:39 | technomancy | http://www.lisperati.com/logo.html |
| 18:41 | bitemyapp | technomancy: almost seems quaint these days. |
| 18:41 | technomancy | it was quaint when it came out iirc |
| 18:46 | mikerod | lisp is only for *real* programmers, obviously |
| 18:47 | dnolen | noonian: considering how many people are in this channel these days, I don't know if any of the old complaints about Lisp really hold up. |
| 18:49 | noonian | i've just found it hard to get other people past it's syntax, i think it being a lisp is a strength for sure but many people don't want to invest the time to become comfortable with it |
| 18:50 | mikerod | noonian: it's "syntax" is one of the best part, is the irony |
| 18:51 | noonian | yep |
| 18:51 | mikerod | I can't type; is one of the best parts, that's the irony* |
| 18:51 | bitemyapp | noonian: really? I haven't had any trouble teaching it to Python programmers. |
| 18:51 | mikerod | Python people understand first-class functions |
| 18:51 | Tolstoy | People where I'm at (extremely traditional Java types) become interested as a result of a few of us writing "cool" apps with a simple build system and hardly any code (seemingly). |
| 18:51 | bitemyapp | noonian: on the rare occasion any of them say anything about syntax I give them a withering look that lets them know how shallow they are being and they clam right up. |
| 18:51 | Tolstoy | Trying to talk it up never works. |
| 18:53 | noonian | bitemyapp: my withering look must not be as effective as yours :P |
| 18:53 | bitemyapp | noonian: I am feared in three continents. |
| 18:53 | bitemyapp | noonian: the bamboo stick helps. |
| 18:53 | AeroNotix | At the moment I'm using Clojure because our Erlang application needs to interface with authorize.net and they provide only a SOAP interface. They also provide a Java SDK, so naturally, I'm leveraging that. Using my functional programming experience from Erlang to hopefully help with Clojure. |
| 18:54 | technomancy | AeroNotix: how are you finding that transition? |
| 18:54 | technomancy | my guess would be the language itself would be easy compared to the runtime |
| 18:55 | bitemyapp | Raynes: but seriously, listen to Grimes. |
| 18:55 | hiredman | if only erjang |
| 18:55 | AeroNotix | technomancy: fine. I "wrote" clojure a few years ago back when it first came out. I've also written Common Lisp for years |
| 18:55 | AeroNotix | hiredman: no |
| 18:55 | technomancy | but from what I can tell erlang doesn't have a lot of HOF usage going on, so that's pretty different |
| 18:55 | bitemyapp | hiredman: pls no |
| 18:55 | alew | bitemyapp: what do you think of crystal castles? |
| 18:55 | bitemyapp | technomancy: you can't "scale up" Erlang. |
| 18:55 | AeroNotix | bitemyapp: uhhh what? |
| 18:55 | Raynes | bitemyapp: Okay |
| 18:55 | AeroNotix | erlang scales incredibly well, it's kind of the point |
| 18:55 | bitemyapp | AeroNotix: I'm talking about FP, not distributed systems. |
| 18:56 | bitemyapp | AeroNotix: you can't really grow into high level FP in Erlang. |
| 18:56 | AeroNotix | Not sure what you mean there. |
| 18:56 | technomancy | bitemyapp: you mean build out new abstractions? |
| 18:56 | Raynes | bitemyapp: Apparently Gerard Way listens to Grimes :3 |
| 18:56 | bitemyapp | technomancy: it's very difficult, yes. |
| 18:56 | AeroNotix | there are behaviours |
| 18:56 | bitemyapp | alew: not a fan. I think they're hacks. :( |
| 18:56 | technomancy | interesting word choice, but I see where you're coming from |
| 18:56 | AeroNotix | behaviours are kind of like Interfaces |
| 18:56 | bitemyapp | technomancy: Erlang code is generally 0 degrees removed, Clojure 1, Haskell...a lot more. |
| 18:56 | alew | bitemyapp: similar style to grimes imo |
| 18:57 | AeroNotix | and if you couple them with Dialyzer you get semi-static checking |
| 18:57 | bitemyapp | alew: I know who they are, I just avoid them. |
| 18:57 | bitemyapp | lol. semi-static checking. No. |
| 18:57 | AeroNotix | So yeah, you can write higher level abstractions like that |
| 18:57 | AeroNotix | bitemyapp: dialyzer is shit, but it helps |
| 18:57 | bitemyapp | AeroNotix: dialyzer is a linter on steroids, it doesn't make anything static and truly safe or sound. |
| 18:57 | AeroNotix | it's better than nothing |
| 18:57 | bitemyapp | AeroNotix: the point of a type system in FP is to help you scale your abstractions safely, Dialyzer cannot help you with that. |
| 18:58 | AeroNotix | Sure, it's no silver bullet. Dialyzer is shit, like I already said. |
| 18:58 | bitemyapp | AeroNotix: case in point, if you have a stack of monads Haskell can help you keep your code straight and correct. A comparable pattern in Erlang would be incomprehensible to Dialyzer. |
| 18:58 | AeroNotix | > Dialyzer is shit |
| 18:58 | AeroNotix | I already said this |
| 18:58 | bitemyapp | AeroNotix: stop. I'm making a broader point than Dialyzer. |
| 18:58 | alew | so enlive isn't a good choice when working with designers? |
| 18:59 | bitemyapp | AeroNotix: that's why you can't really extend yourself beyond simple HOFs in dynamic languages. |
| 18:59 | alew | seems better than selmer would be for that |
| 18:59 | bitemyapp | alew: it complects the functionality of your templates with your HTML and CSS. That's insane. |
| 18:59 | arrdem | bitemyapp: hiccup? |
| 18:59 | bitemyapp | If you don't have a type system to keep things clear and correct you can't really abstract your FP very much without making it very hard to write correct code. |
| 19:00 | dnolen | noonian: people will ignore syntax if you show them you write better/faster software |
| 19:00 | AeroNotix | You present a false dichotomy |
| 19:00 | bitemyapp | the point of the types isn't just correctness, it's leverage. |
| 19:00 | bitemyapp | arrdem: shush you. |
| 19:00 | AeroNotix | You can write perfectly correct code in dynamic languages, it's just harder to prove. |
| 19:00 | arrdem | bitemyapp: to that, nevar. |
| 19:00 | dnolen | noonian: you can't convince everyone, but for people who don't want to reason, can't do much for them anyway |
| 19:01 | AeroNotix | What *is* the comparable thing for Clojure, anyway? (re: dialyzer) |
| 19:01 | bitemyapp | AeroNotix: you're not disagreeing with what I just said. |
| 19:01 | alew | selmer builds in the template into the html and css, isn't that coupling them? |
| 19:01 | AeroNotix | bitemyapp: I'm just augmenting it to allow a wider definition |
| 19:01 | bitemyapp | AeroNotix: you're misunderstanding what I'm saying because you don't know the approaches I'm referring to. |
| 19:01 | dnolen | AeroNotix: nothing like dializyer, but you've got Typed Clojure |
| 19:01 | hyPiRion | AeroNotix: core.typed I guess |
| 19:01 | technomancy | AeroNotix: there's core.typed, but it doesn't have any of the inference functionality dialyzer has unfortunately |
| 19:01 | noonian | dnolen: right, people have to be willing to try something different |
| 19:01 | AeroNotix | dnolen: how well does that integrate with regular clojure? |
| 19:02 | bitemyapp | AeroNotix: the point is that things like map, filter, and reduce are nice, but you can do a lot better and further decomplect your implementations from your interfaces. |
| 19:02 | dnolen | AeroNotix: it designed to integrate with regular clojure |
| 19:02 | bitemyapp | core.typed is pretty ugly and won't really enable the patterns I'm talking about. |
| 19:02 | AeroNotix | dnolen: cool |
| 19:02 | dnolen | AeroNotix: some people already use it in production and seem to like it quite a bit |
| 19:02 | bitemyapp | AeroNotix: I think CircleCI uses c.c.t |
| 19:02 | dnolen | AeroNotix: ambrosebs is very reponsive and cranks on it |
| 19:02 | arrdem | AeroNotix: core.typed can be a pain, but it's a nice toolkit. |
| 19:02 | technomancy | AeroNotix: you still have to spec everything top-level, so it's a lot of work |
| 19:02 | AeroNotix | Haskell does provide some very interesting methods of providing really high level abstractions |
| 19:03 | AeroNotix | functors, applicative functors are some really light and easy abstractions that make so much sense it's untrue |
| 19:03 | bitemyapp | AeroNotix: it's not just about being high-level, it's about keeping things simple and separate in a way that makes sense. |
| 19:03 | AeroNotix | and they really make sense when creating your own types |
| 19:04 | bitemyapp | The point is that map and filter aren't the essence of FP. Nor are 1-degree-removed HOFs. |
| 19:04 | technomancy | AeroNotix: stop saying good things about haskell; he's trying to argue with you =) |
| 19:05 | AeroNotix | technomancy: oh I have plenty of disagreements with Haskell |
| 19:05 | AeroNotix | it's community being #1 |
| 19:05 | kristof | There's no limit on the order you can write a higher order function in clojure |
| 19:05 | kristof | And map, filter, and first class functions are in fact the essence of some value of FP |
| 19:05 | technomancy | kristof: I've wondered what's the highest order of HOF ever seen in real-world code |
| 19:05 | technomancy | we should have a high-score board |
| 19:06 | kristof | technomancy: Doesn't matter, any good abstraction works for any degree-order |
| 19:06 | hyPiRion | technomancy: just apply some Y-combinators and get going? |
| 19:06 | bitemyapp | kristof: it turns into a tarpit pretty quickly. |
| 19:06 | bitemyapp | becomes hard to debug, hard to write correct code. |
| 19:06 | technomancy | swap!+update-in+conj+fnil seems like a good starting point |
| 19:06 | kristof | bitemyapp: I'd appreciate some actual examples. I'm not being combative, I'm really interested in what you're saying. |
| 19:07 | AeroNotix | Is there nothing out there (or even if this is a sane approach) which uses type annotations in Clojure to deduce (some value of) correctness? |
| 19:07 | bitemyapp | kristof: just learn Haskell. You'll figure it out in a hurry. |
| 19:07 | technomancy | I guess you still need one more as an arg to fnil |
| 19:07 | bitemyapp | there's no better way to understand my point. |
| 19:07 | bitemyapp | kristof: then try to take what you were doing in Haskell with functors/applicatives/monads and do them in Clojure. |
| 19:07 | kristof | bitemyapp: came to Clojure from some newbie use of Haskell |
| 19:07 | bitemyapp | kristof: then you'll realize you were standing on a sand castle. |
| 19:07 | technomancy | bitemyapp: are you seriously arguing that combo I refered to above is difficult to debug? |
| 19:07 | technomancy | or are you talking about something else entirely |
| 19:08 | kristof | bitemyapp: The "sand castle" has not yet been discovered. |
| 19:08 | bitemyapp | technomancy: something else. |
| 19:08 | bitemyapp | kristof: learn more Haskell. |
| 19:08 | bitemyapp | kristof: the epiphany probably didn't hit yet. It takes awhile. |
| 19:08 | AeroNotix | bitemyapp: you could easily write an applicative monad in Clojure, you just cannot prove it's correct. |
| 19:08 | AeroNotix | or at least typesafe |
| 19:08 | bitemyapp | AeroNotix: what exactly is an applicative monad? |
| 19:08 | bitemyapp | AeroNotix: do you mean an applicative functor? |
| 19:08 | AeroNotix | sorry yes |
| 19:08 | kristof | bitemyapp: I certainly plan on it but like I said, I'd really like an example of what you're talking about. The coolest example I can think of is the maybe monad. |
| 19:09 | bitemyapp | AeroNotix: and how easy do you think it's going to be to write correct code in terms of those abstract interfaces without chewing through a bunch of type errors? |
| 19:09 | AeroNotix | bitemyapp: quite. The abstraction is still 'there' though, right? At least I still see the value in writing code like that. |
| 19:09 | bitemyapp | kristof: that's not a great way to explain monads. |
| 19:09 | bitemyapp | kristof: Maybe/Some/Option is as much about algebraic data types as anything else. |
| 19:09 | kristof | bitemyapp: Hrm. |
| 19:09 | bitemyapp | kristof: you don't need monads for maybe. You can rely on ADT pattern matching or functors entirely. |
| 19:09 | AeroNotix | ADTs are wonderful, though |
| 19:10 | dnolen | AeroNotix: you cannot prove monad laws in Haskell either, so there's no proof of correctness there either. |
| 19:10 | bitemyapp | `fmap (+1) $ Just 1` returns Just 2 |
| 19:10 | AeroNotix | dnolen: true |
| 19:10 | dnolen | word to the wise it's best to ignore bitemyapp on this channel |
| 19:10 | bitemyapp | AeroNotix: no, it's NOT |
| 19:10 | bitemyapp | AeroNotix: you use quickcheck to verify monad laws in Haskell. |
| 19:10 | noonian | lol |
| 19:10 | dnolen | on anything to do w/ Haskell |
| 19:10 | bitemyapp | people do it all the time. |
| 19:10 | AeroNotix | bitemyapp: not by the compiler, though |
| 19:10 | bitemyapp | oh ffs. |
| 19:10 | bitemyapp | so because the spaceship has one toilet instead of two you want to stay in a mud-hut? |
| 19:10 | bitemyapp | for real? |
| 19:11 | AeroNotix | c'mon |
| 19:11 | AeroNotix | so caremad |
| 19:11 | kristof | bitemyapp: You'll have to be more specific than "you're all living in a mudhut!" |
| 19:11 | bitemyapp | kristof: so fmap is from the Functor typeclass, you can do anything you want with a Maybe wrapped value just with that. |
| 19:11 | bitemyapp | kristof: monads are overkill for that. |
| 19:12 | bitemyapp | kristof: better examples would be State in Haskell, Async in OCaml. |
| 19:12 | kristof | Async in ocaml? Did you mean occam? |
| 19:12 | bitemyapp | kristof: I can't really drop an easy to digest explanation in IRC if you don't understand the math or Haskell behind it. You're better off just getting the epiphany yourself. |
| 19:12 | bitemyapp | kristof: I mean Async in OCaml. It's a library. |
| 19:12 | AeroNotix | Do you really need to understand math to understand fmap? |
| 19:12 | bitemyapp | kristof: look at grenchman's source code. |
| 19:12 | AeroNotix | unless there was something else you wanted him to understand |
| 19:13 | bitemyapp | AeroNotix: no. |
| 19:13 | bitemyapp | fmap is pretty straight-forward. |
| 19:13 | AeroNotix | sure |
| 19:13 | bitemyapp | it has the same type signature as map, it's just abstract instead of concrete, and specifically for Functors. |
| 19:14 | bitemyapp | the best way I can bake it down is in terms of typeclasses and type deduction for method dispatch. |
| 19:14 | bitemyapp | Fluokitten's use of protocols might demonstrate some of it. |
| 19:14 | AeroNotix | hm |
| 19:14 | bitemyapp | kristof: AeroNotix - https://github.com/uncomplicate/fluokitten |
| 19:14 | bitemyapp | so, they're basically using protocols to solve the type deduction and dispatch thing |
| 19:14 | kristof | Type inference is cool, I'll give static typing that. |
| 19:14 | bitemyapp | but it's not really composable or type-checked the way typeclasses are. |
| 19:15 | AeroNotix | next up: Go's type system |
| 19:15 | bitemyapp | it also can't really help with the composition of multiple protocols and help you stay sane. |
| 19:15 | bitemyapp | Go's type system is pointless. Why even bother? |
| 19:15 | kristof | ^ |
| 19:15 | AeroNotix | was a joke |
| 19:15 | bitemyapp | so the point is that in Haskell, you can (safely) write code in terms of composing things from different typeclasses |
| 19:16 | kristof | bitemyapp: So what you're saying is that protocol dispatch on type is flimsy without typeclasses and some form of single/multiple inheritance. |
| 19:16 | bitemyapp | kristof: you don't need inheritance, but yes. |
| 19:16 | bitemyapp | kristof: you can compose without inheritance. |
| 19:16 | kristof | Well, that's what typeclasses are kind of for, aren't they? |
| 19:16 | kristof | This is a that |
| 19:16 | kristof | This is an Ord |
| 19:16 | kristof | and a Num |
| 19:16 | kristof | etc. |
| 19:16 | bitemyapp | yeah but they're independent. |
| 19:16 | bitemyapp | those specific ones are. |
| 19:16 | kristof | So? |
| 19:17 | kristof | Classes can be independent |
| 19:17 | bitemyapp | Superclassing is a thing - people have been trying to turn Monad into a superclass of Applicative for awhile |
| 19:17 | bitemyapp | so that the relationships are more clear and match the category theory more directly. |
| 19:17 | bitemyapp | but it doesn't harm anything. |
| 19:17 | kristof | bitemyapp: I'm really think about generic functions and multiple inheritance in Common Lisp |
| 19:17 | bitemyapp | kristof: ick, you can do better than that by far. |
| 19:17 | kristof | Oh, probably, but it's certainly a step above Clojure protocols |
| 19:17 | bitemyapp | Rust traits, Scala traits, and Haskell typeclasses are a better way to do it. |
| 19:18 | kristof | bitemyapp: when's rust 0.9 out? |
| 19:18 | bitemyapp | kristof: yeah, I think I'd agree with that, but I was an AOP'er in CL. |
| 19:18 | bitemyapp | kristof: now. |
| 19:18 | kristof | Woah! Hold the phone! :P |
| 19:18 | kristof | bitemyapp: AOP? |
| 19:18 | locks | aspect-oriented programming |
| 19:18 | seangrove | ~aop |
| 19:18 | clojurebot | I don't understand. |
| 19:18 | locks | ? |
| 19:18 | kristof | Oh, I see |
| 19:19 | seangrove | clojurebot: aop is Aspect-oriented Programming http://en.wikipedia.org/wiki/Aspect-oriented_programming |
| 19:19 | clojurebot | Ok. |
| 19:19 | seangrove | ~aop |
| 19:19 | bitemyapp | kristof: metaobject protocol stuff. |
| 19:19 | clojurebot | aop is Aspect-oriented Programming http://en.wikipedia.org/wiki/Aspect-oriented_programming |
| 19:19 | bitemyapp | kristof: I do the same in Clojure occasionally with dire/robert.hooke |
| 19:19 | locks | is this channel always this caremad? |
| 19:19 | bitemyapp | I don't think bringing 4chan jargon into this channel improves anything - can we drop that word? |
| 19:20 | kristof | locks: I coerced bitemyapp into having cordial discussion, no harm in that |
| 19:20 | bitemyapp | it implies that you should be detached from everything you say and that seems a poor way to communicate with others. |
| 19:20 | bitemyapp | insincerity ain't a good thing. |
| 19:20 | kristof | The internet is at stake, after all |
| 19:20 | kristof | :P But yes, discussion is important and I think it's healthy for any language community |
| 19:21 | locks | what I’ve seen isn’t discussion |
| 19:21 | bitemyapp | it's also how a lot of knowledge gets propagated in programming language communities. |
| 19:21 | locks | it’s “everything sucks" |
| 19:21 | bitemyapp | locks: well, I don't think you're obligated to be here. |
| 19:21 | locks | literally even, a couple pages up |
| 19:21 | kristof | locks: Everything does suck! |
| 19:21 | bitemyapp | you could go make a sandwich. |
| 19:21 | kristof | I'm about to fix myself a sandwich, actually. |
| 19:22 | locks | bitemyapp: oh, nice |
| 19:22 | bitemyapp | locks: if you're satisfied, you're not looking hard enough. |
| 19:22 | locks | yes I will leave because I won’t put up with your passive aggressiveness |
| 19:22 | bitemyapp | good way to blub it up. |
| 19:22 | alew | when writing clojure macros that involve functions included from other namespaces, should you unquote them? |
| 19:22 | technomancy | alew: just look at the macroexpansion |
| 19:22 | bitemyapp | alew: you mean fully qualify them? |
| 19:23 | justin_smith | alew: quasiquote already does the full neamespace expansion |
| 19:23 | kristof | bitemyapp: if you're on haskell or here regularly, I'll pester you sometime, thank you for piquing my interest again with opinionated combative behavior |
| 19:23 | hyPiRion | ,`(+ 1 2) ;; alew |
| 19:23 | clojurebot | (clojure.core/+ 1 2) |
| 19:23 | bitemyapp | kristof: no problem. I give Haskell tutorials periodically in person and over the internet so if you need any help with anything please ping me. |
| 19:23 | bitemyapp | kristof: I'm always online but not necessarily at my terminal. I see my logs. |
| 19:24 | kristof | bitemyapp: I will. My biggest problem with Haskell was the bondage and discipline, but it's not without justification. |
| 19:24 | alew | right, it namespace expands them, but if that macro is used in another namespace, there won't be any issues? |
| 19:24 | bitemyapp | kristof: hum. Usually if it feels BDSM-y you might be going about things the hard way. |
| 19:25 | justin_smith | alew: if the defining namespace requires the ns in question, it is available if fully ns qualified, it all just works |
| 19:25 | bitemyapp | kristof: one of the better ways to break out of that when you want to "say less than things actually are" is Lens. |
| 19:25 | bitemyapp | especially to handle non-deterministically structured data. |
| 19:26 | justin_smith | alew: it would break if the macro uses an ns that its own file does not require, but then again that would break down at ns qualification time when compiling |
| 19:26 | noonian | alew: syntax quote namespace expands things in the namespace that the macro is written in which will have required the relevant namespaces so it's all good |
| 19:26 | bitemyapp | kristof: I prefer the BDSM compiler errors to the long tail of unnecessary type errors/stack-traces. That's subjective I s'pose, but I am legitimately more productive over a given period of time that way, not just preferentially. |
| 19:26 | kristof | Oh, no, I wasn't talking about static typing |
| 19:26 | kristof | It was with regard to state in general |
| 19:27 | alew | what about with java imports? those don't seem to be qualified |
| 19:28 | bitemyapp | kristof: I think that comes with grokking the typeclassopedia really. |
| 19:29 | bitemyapp | kristof: having pure/impure functions decomplected is pretty nice and monads let your side effects and state be introspectable, typed values instead of magic aetheria. |
| 19:29 | bitemyapp | kristof: I don't recall having any trouble firing off side effects at will. |
| 19:29 | bitemyapp | kristof: that might be awkwardness around not knowing how to write valid monadic code. |
| 19:29 | bitemyapp | I had the same problem earlier on. |
| 19:30 | bitemyapp | but again, I'd rather get smacked on the nose called a bad puppy for writing incorrect code. |
| 19:33 | Raynes | bitemyapp: I listened to the entirety of Visions and only realized it because I noticed the music stopped. |
| 19:34 | Raynes | Me not realizing I'm listening to music for 45 minutes isn't a good sign |
| 19:35 | bitemyapp | Raynes: a good sign for the music or your dehydration? |
| 19:35 | Raynes | For the music :p |
| 19:35 | bitemyapp | Raynes: you're used to really rambunctious stuff. |
| 19:36 | bitemyapp | with clear, loud, proud vocals. |
| 19:36 | bitemyapp | Raynes: Grimes is this spooky chick with a tape recorder from the 80s and a garage sale keyboard. |
| 19:36 | Raynes | Indeed. |
| 19:39 | arrdem | if I notice that the music is there, it's doing its job wrong. |
| 19:39 | arrdem | white noise ftw. |
| 19:39 | noonian | dnolen: is this an appropriate way to nest components in om or is this not a good idea to do? For example (om/build my-c app {:opts {:content (om/build my-c2 app {})}}) |
| 19:40 | lsdafjklsd | noonian: why not |
| 19:41 | noonian | /shrug, it just doesn't feel intuitive |
| 19:42 | lsdafjklsd | noonian: yea, it doesn't look great just looking at it, but there is no context |
| 19:42 | Tolstoy | noonian: That doesn't seem right at all. Aren't ops for passing in small "configuration" settings for the my-c component? |
| 19:42 | stcredzero | In Rich Hickey's ant simulation, I keep seeing things like (send-off *agent* #'animation) in timing loops. What is with *agent*? Do those asterisks mean something, or is it just a different method name? |
| 19:42 | lsdafjklsd | tolstoy: well you can pass dynamic view in the ops |
| 19:42 | lsdafjklsd | tolstoy: he does that in an example |
| 19:43 | hyPiRion | stcredzero: That's old examples, but *name* means that the variable is dynamic |
| 19:43 | technomancy | stcredzero: it means the agent running the current code |
| 19:43 | Tolstoy | lsdafjklsd: Ah, okay. |
| 19:43 | justin_smith | strax: method? - *agent* is just a name for a var |
| 19:43 | noonian | lsdafjklsd: which example? |
| 19:43 | alandipert | stcredzero: the 'earmuffs' indicate in lisp a dynamic or mutable variable |
| 19:44 | justin_smith | naming dynamic bindings with *name* is a convention, but is not enforced at all |
| 19:44 | hyPiRion | and technomancy beat me to the second part |
| 19:44 | stcredzero | So it's just a convention, not some kind of sigil? |
| 19:44 | noonian | Tolstoy: its either in the ops or in the cursor for the app state right? |
| 19:44 | hyPiRion | stcredzero: yeah, just convention, but you'll get warnings by default if you don't follow it |
| 19:44 | justin_smith | right, a naming convention |
| 19:45 | Tolstoy | noonian: Alas, I always tend to try to keep things simple. I'd rather pass in an option, then use a "cond" or whatever to decide what to do. |
| 19:45 | hyPiRion | ,(def *foo* nil) ;; e.g. |
| 19:45 | clojurebot | #<CompilerException java.lang.SecurityException: denied, compiling:(NO_SOURCE_PATH:0:0)> |
| 19:45 | lsdafjklsd | noonian: the sortable example |
| 19:46 | justin_smith | ,(do (def *thing* 1) (def *what* 2) (+ *thing* *what*)) |
| 19:46 | clojurebot | #<CompilerException java.lang.SecurityException: denied, compiling:(NO_SOURCE_PATH:0:0)> |
| 19:46 | noonian | lsdafjklsd: thanks |
| 19:46 | lsdafjklsd | noonian: (om/build sortable app {:opts {:view item}})))) |
| 19:46 | justin_smith | &(do (def *thing* 1) (def *what* 2) (+ *thing* *what*)) |
| 19:46 | lazybot | java.lang.SecurityException: You tripped the alarm! def is bad! |
| 19:46 | justin_smith | hmm |
| 19:46 | lsdafjklsd | noonian: item is an om/component |
| 19:46 | noonian | Tolstoy: it'd be nice to be able to write reusable component libraries though so you couldn't know ahead of time what to do in the different cases |
| 19:47 | robonerd | in the context of web app dev (+ client/mobile/etc would only be a bonus), does anyone happen to know of a language similar to ruby, but perhaps slightly tightened up? (eg, [opt-in] static typing, of which so far i've found erlang and racket) |
| 19:48 | alew | clojure has opt-in static typing |
| 19:48 | alew | sort of |
| 19:48 | robonerd | please explain? |
| 19:48 | noonian | lsdafjklsd: but there he builds it in the component he passes it to, which then needs to know about the interface for the item right? |
| 19:49 | alew | https://github.com/clojure/core.typed |
| 19:50 | lsdafjklsd | noonian: yea, it just get's wrapped in the functionality of sortable so not exactly as decouple as what you're trying to do |
| 19:50 | robonerd | in the context of web app dev (+ client/mobile/etc would only be a bonus), does anyone happen to know of a language similar to ruby, but perhaps slightly tightened up? (eg, [opt-in] static typing, of which so far i've found erlang and racket) ideally, on the topic of opt in typing i want to not only be able to say some property is an array, but say it's an array with only string elements. |
| 19:50 | robonerd | there, updated |
| 19:51 | alandipert | noonian: have you given hoplon.io a peep? our goal is modularity and to do it we separate the app state machine from the rendering via 'cell' ref type |
| 19:51 | hiredman | core.typed is based in some part on typed racket |
| 19:51 | alandipert | noonian: a similar approach might be possible using om but i haven't tried |
| 19:52 | lsdafjklsd | in react cant you render into components through mounting? |
| 19:52 | arrdem | hiredman: in large part... |
| 19:52 | lsdafjklsd | i've been meaning to look into that |
| 19:52 | dyreshark | robonerd: if you can deal with full static typing, F# is pleasant, runs on Windows/WP and OS X (with Mono, which is decent). Also, it has Xamarin for porting directly to iOS/Android. (Xamarin website advertises C#, but they have plugins for F# dev IIRC) |
| 19:52 | hiredman | and it can type collections just fine |
| 19:52 | dyreshark | s/OS X/Anything supported by mono/ |
| 19:52 | noonian | alandipert: thanks for the link, i'll check it out |
| 19:53 | robonerd | in the context of web app dev (+ client/mobile/etc would only be a bonus), does anyone happen to know of a language with [opt-in] static gradual typing? ideally, i want to not only be able to say some property is an array, but say it's an array with only string elements. |
| 19:53 | robonerd | (updated) |
| 19:53 | dyreshark | ok :p |
| 19:53 | technomancy | robonerd: this isn't a forum, geez |
| 19:53 | hiredman | stop updating please |
| 19:53 | robonerd | oh sorry |
| 19:53 | Tolstoy | robonerd: Groovy? ;) |
| 19:54 | xuser | robonerd: Dart |
| 19:54 | hiredman | anyway, you've gotten plenty of responses |
| 19:56 | robonerd | loaded them up, will reearch now, ty |
| 19:56 | robonerd | btw does clojure have this feature? |
| 19:56 | robonerd | ah, loading core.typed now |
| 19:57 | hiredman | he must irc via email |
| 20:00 | bitemyapp | robonerd: if you want full static typing with FP give Haskell a shot! |
| 20:01 | bitemyapp | robonerd: the types are organized around typeclasses, and the functions are abstract/polymorphic by default rather than concrete by default. |
| 20:01 | bitemyapp | robonerd: so a relatively common function signature would be things like a -> b or a -> a with some relevant typeclass qualifier than having to go to extra trouble to make your functions reusable. |
| 20:03 | bitemyapp | Makes doing things the right way lower friction. |
| 20:04 | arrdem | $google haskell javascript compiler |
| 20:04 | lazybot | [The JavaScript Problem - HaskellWiki] http://www.haskell.org/haskellwiki/The_JavaScript_Problem |
| 20:05 | bitemyapp | arrdem: Fay, GHCJS, Haste. |
| 20:05 | dyreshark | ^ Also, as much as it's considered good practice to add explicit type information in Haskell for functions, most types can be inferred for you by the compiler if you're feeling lazy ;) |
| 20:05 | arrdem | bitemyapp: yep. |
| 20:05 | bitemyapp | dyreshark: I use the inference to "query" what my code is doing. Very informative. |
| 20:05 | bitemyapp | arrdem: things that aren't Haskell but are similar that compile to JS include: PureScript and Roy. |
| 20:06 | bitemyapp | the most practical option right now is Fay. |
| 20:06 | bitemyapp | and that's what I use. |
| 20:06 | bitemyapp | FPComplete has about 10k+ LOC of Fay in their frontend at the moment. |
| 20:06 | bitemyapp | Types are shared directly with the backend. |
| 20:06 | arrdem | Javascript: not an acceptable PL, acceptable compile target. wat. |
| 20:07 | technomancy | * if you don't need integers |
| 20:07 | bitemyapp | technomancy: uh, mostly. |0 is guarantee to return an integer. |
| 20:08 | bitemyapp | technomancy: so if you annotate the results of all numeric operations with that, it's integers all the way down modulo precision loss. |
| 20:08 | bitemyapp | asm.js understands it. |
| 20:08 | technomancy | bitemyapp: precision loss is what I mean |
| 20:08 | bitemyapp | technomancy: oh yeah, that part sucks but that's what asm.js is for. |
| 20:10 | bitemyapp | technomancy: asm.js compatible VMs will turn the operations into integers specifically. |
| 20:10 | alew | is there a good way to avoid increasingly nested conditionals for handling complex validation? specifically in web handlers |
| 20:10 | technomancy | sure, nice if you can assume it's there |
| 20:12 | alew | s/avoid/refactor/ |
| 20:12 | arrdem | alew: dire's postconditions/preconditions could be useful... |
| 20:12 | bitemyapp | alew: Monoids! |
| 20:13 | arrdem | bitemyapp: quiet you. |
| 20:13 | bitemyapp | I'm serious :( |
| 20:14 | alew | I'm not super familiar with dire, but from what I gathered it doesn't give much benefit for one off conditionals? |
| 20:14 | alew | I'm probably off here |
| 20:15 | bitemyapp | alew: dire's fine if it's a match for what you want. Monoid Validator + Writer/Error is one way to do it "scalably" with sensible error messages. |
| 20:15 | arrdem | I mean if you are truly faced with a raft of disjoint, once-off conditionals there's nothing that can really help you. Any refactoring approach or tool will rely on commonalities or common sub-conditions. |
| 20:16 | alew | I guess I should just break them out into internal helper functions |
| 20:18 | bitemyapp | arrdem: if they're separated by space and time then you can use Monads... |
| 20:18 | arrdem | bitemyapp: I suppose -> [ a:Value, b:Err ] with short curcuiting would be a monoid... |
| 20:18 | bitemyapp | alew: Monoids let you aggregate a super-conditional, monads let you sequence functions against the value with sensible validation/error output as needed after/before the operations without repeating yourself. |
| 20:18 | bitemyapp | there are many options here! |
| 20:19 | alew | Well I'm using clojure, so monoids might not be the most idomatic approach here |
| 20:20 | ehabs | After profiling some code, I found out that walking lazy seqs is a big performance bottleneck in one of my functions. The problem is that running doall on it causes a stack overflow. Whats the best way for me to handle this? |
| 20:20 | steerio | why do you need the doall? |
| 20:21 | ehabs | because i don't want to re-walk the seq over and over again. or am i misunderstanding something? |
| 20:21 | steerio | re-walk as in? |
| 20:21 | arrdem | ehabs: need code to comment. refheap please. |
| 20:21 | steerio | the seq gets realized the first time you walk over it. whether the head gets retained depends on your code. |
| 20:22 | steerio | if the sequence is too large for your memory, however, it's your heap that gets blown, not your stack |
| 20:22 | alew | maybe your lazy seq is infinite, that would blow the stack |
| 20:23 | alew | or actually no |
| 20:23 | steerio | it wouldn't, that'd be the heap |
| 20:23 | ehabs | just a minute. i'll post the code for you to check out. i'm sure it isn't infinite because it evaluates as expected when its lazy. its just extremely slow |
| 20:24 | steerio | can you paste the actual output when that overflow happens? |
| 20:24 | steerio | (along with the code) |
| 20:25 | ehabs | here is the code: http://pastebin.com/45aweM15 |
| 20:26 | arrdem | (dec pastebin) |
| 20:26 | lazybot | ⇒ -1 |
| 20:26 | arrdem | ~pastebin |
| 20:26 | clojurebot | Titim gan éirí ort. |
| 20:26 | arrdem | clojurebot: you have failed me for the last time commander |
| 20:26 | clojurebot | Huh? |
| 20:27 | ehabs | sorry, i haven't used refheap before. i'll try to use it next time |
| 20:28 | ehabs | http://pastebin.com/gpuEa652 |
| 20:28 | steerio | can you see the repeating pattern in the stack trace? |
| 20:29 | steerio | in fact your problem has nothing to do with the fact that you deal with lazy seqs |
| 20:30 | steerio | there's simply endless recursion somewhere in there |
| 20:30 | arrdem | steerio: it may be bounded, just bigger than stack size. |
| 20:30 | ehabs | let me see what i changed. it definitely ran for me a minute ago |
| 20:31 | steerio | that's true, just unlikely |
| 20:33 | ehabs | this code runs without a stack overflow: https://www.refheap.com/22773 |
| 20:35 | steerio | i'm a bit too tired to diff them now |
| 20:35 | steerio | also, they contain quite some references to functions that you define but are not included |
| 20:37 | steerio | any of them could easily be the culprit |
| 20:37 | ehabs | do you have any advice on what i should look for? |
| 20:37 | steerio | anything that ends up in a circular call |
| 20:38 | shep-home | ehabs: are you running all of that code in the REPL? |
| 20:38 | ehabs | yes |
| 20:39 | shep-home | you might want to put some of it into a different namespace - that would help the stacktraces identify your code |
| 20:42 | steerio | in fact there's nothing in the visible stack trace that's not from core |
| 20:42 | shep-home | steerio: good point, I was just scanning for something different.. |
| 20:43 | shep-home | Is it possible to have created a circular structure of some type? |
| 20:43 | shep-home | s/to have/that ehabs has/ |
| 20:44 | ehabs | i don't think i do. the code works exactly as expected if i use a subset of the data |
| 20:44 | ehabs | the problem is when its using 12,000 data points |
| 20:45 | steerio | which is weird. |
| 20:45 | shep-home | ehabs: the only difference in the code is adding `vec` to the apply? |
| 20:45 | steerio | if it was a head retention problem, you'd blow the heap, not the stack |
| 20:46 | steerio | as far as lazy sequences go, they don't care how many items you end up having in them |
| 20:46 | shep-home | I wonder if you are just realizing something now that you weren't before |
| 20:46 | ehabs | yes that is correct. taking vex out causes it to blow the stack |
| 20:46 | shep-home | oh, taking it out... |
| 20:46 | ehabs | *vec |
| 20:50 | steerio | so what does seq-without-nth look like? |
| 20:50 | steerio | i think i'm starting to see what's going on here |
| 20:51 | steerio | you're basically creating lazy seqs of lazy seqs of lazy seqs... |
| 20:51 | steerio | so you're doing operations on sequences that yield lazy seqs in a depth proportional to your data size |
| 20:51 | steerio | which is all fine until you realize it |
| 20:51 | steerio | and then you blow the stack because it's so deep |
| 20:52 | steerio | imagine (map #(map #(map .... |
| 20:52 | steerio | in a 12k level depth |
| 20:52 | steerio | your call on vec is a way out of it because it realizes the given depth and frees you from one level of calls whenever you do it |
| 20:53 | ehabs | here are the other two helpers used in the let: https://www.refheap.com/22774 |
| 20:54 | ehabs | the data is shaped like: X= [{1 float 2 float 3 float 4 float 5 float}...] and Y=[zeros-and-ones] |
| 20:55 | steerio | let me just illustrate you what i'm talking about |
| 20:55 | shep-home | steerio: so it could be "fixed" by only realizing a bit at a time, but there's still a timebomb waiting...? |
| 20:55 | steerio | ,(reduce (fn [s _] (map identity s)) (range 12000)) |
| 20:55 | clojurebot | #<StackOverflowError java.lang.StackOverflowError> |
| 20:56 | steerio | in fact the buildup of lazy sequences should be identified and eliminated |
| 20:56 | steerio | perhaps by a different algorythm, perhaps by realizing every step |
| 20:57 | ehabs | can you see where the buildup is happening? |
| 20:57 | steerio | your code is way more complex than what would allow me to see that at 3am |
| 20:57 | steerio | :D |
| 20:59 | steerio | in such situations what happens is that you repeatedly do some operation over elements of a collection |
| 20:59 | steerio | which in most cases can be refactored into one operation |
| 21:00 | steerio | like: (map inc (map inc (map inc coll))) is equivalent to (map #(+ 3 %) coll) |
| 21:00 | steerio | in this case you are thousands of level deep in the "(map inc (..." |
| 21:00 | steerio | granted, it's more complex than this example |
| 21:01 | ehabs | yeah, that makes sense. too bad it isn't that obvious in this case |
| 21:01 | steerio | start taking apart this huge functions into smaller ones |
| 21:02 | kristof | If it has over 5 levels of nesting... |
| 21:02 | steerio | and testing and comprehending what they do one by one, and you'll probably end up finding it |
| 21:02 | kristof | Ah, how does that joke go again... |
| 21:02 | kristof | "How do you know when a function or method gets too big?" "When it's bigger than my head." "You mean when it's too conceptually large?" "No, I LITERALLY put my head against the monitor." |
| 21:04 | ehabs | haha yeah, i definitely need to do that. the top part of the cross validation function is seems to be where the problem is and that can easily be broken out into small pieces. |
| 21:06 | steerio | ehabs, check this |
| 21:06 | steerio | ,(class (flatten [1 [2 3] 4])) |
| 21:06 | clojurebot | clojure.lang.LazySeq |
| 21:06 | steerio | flatten yields a lazy seq. now, you're storing these as values in a hash |
| 21:06 | steerio | then you probably at some point repeat this operation and nest lazy seqs at a huge level |
| 21:07 | steerio | as you merge hashes and whatnot |
| 21:08 | steerio | every merge-with just nests those lazy seqs even more |
| 21:08 | steerio | without actually doing any flattening |
| 21:08 | steerio | the (vec) call realizes them at each level to create that vector out of them |
| 21:09 | steerio | thereby saving you from this nesting |
| 21:09 | steerio | in fact probably everything goes fine and dandy until your REPL tries to _print_ the insanely nested lazy seq |
| 21:12 | ehabs | yeah, that makes sense. thats definitely what its doing. i just don't see how it would get deep enough to matter in this case. i'm running it with only 10 groups, so it would at most be 9 levels deep. |
| 21:12 | steerio | remember that pretty much every operation you do on a collections yields a lazy seq |
| 21:13 | ehabs | yeah, thats true. i'm starting to visualize it now. is the solution to just start running doall on them or convert them to vectors? or is there a better way? |
| 21:14 | steerio | and in your case, if you merge two hashes with the same keys, all the values have just become at least one more level deeper nested |
| 21:14 | xuser | d |
| 21:14 | steerio | and all those hashes have the same keys, :training and :testing |
| 21:15 | steerio | (which begs the question of why you don't use a two-element vector for this) |
| 21:15 | steerio | also, partitioning data can be done more efficiently too |
| 21:16 | steerio | same goes for the :x/:y map, use a vector |
| 21:16 | steerio | so your data becomes [x y] instead of that (map #(hash-map ... thing |
| 21:17 | gtrak | I've missed it when other folks have talked about it, is 'austin' the most full-featured cljs repl? I'm hoping for some autocomplete love. |
| 21:17 | steerio | (get-in [:training :x] foo) becomes (first (second foo)) |
| 21:18 | ehabs | yeah, that makes sense. but that still doesn't solve the issue with most of the clojure functions returning lazy seqs. whats the best way for me to avoid that? |
| 21:19 | steerio | a better algorythm :) |
| 21:19 | steerio | this normally isn't a problem |
| 21:19 | steerio | while in a non-lazy lisp this would not blow your stack, it'd be really ineffective |
| 21:20 | steerio | as you'd traverse collections 12k times, instead of writing less functions that do it in one step |
| 21:23 | bitemyapp | arrdem: doters? |
| 21:25 | ehabs | ok, i'll make the changes that you mentioned. thanks for the help steerio |
| 21:25 | steerio | np |
| 21:26 | steerio | in fact even using vector tuples instead of the hashes eases up on this |
| 21:27 | steerio | well, maybe even solves it |
| 21:29 | ehabs | ok, thats the first change i'll make |
| 21:31 | hiredman | /win 26 |
| 21:46 | logic_prog | in clojure, is it possible to construct an object where (1) it supports all operations of map and (2) can only be constructed by a certain function |
| 21:47 | logic_prog | i.e. I want "(my-magic-foo ...)" to be the only way to construct a special map |
| 21:48 | alandipert | logic_prog: check out def-map-type in potemkin, https://github.com/ztellman/potemkin |
| 21:49 | logic_prog | alandipert: this is interesting, let me look into this |
| 21:50 | noonian | logic_prog: sounds like records might be what you want |
| 21:50 | sritchie | noonian: I think logic_prog wants to hide the constructors |
| 21:50 | noonian | ah |
| 21:50 | logic_prog | yeah, I want guarantee that a function was only created via (my-magic-foo ...) |
| 21:51 | logic_prog | s/function/map |
| 22:04 | logic_prog | how can I check if something is a core.async.chan ? |
| 22:04 | logic_prog | err, clojure.core.async/chan |
| 22:06 | gtrak | seems like they all may extend clojure.core.async.impl.protocols/Channel |
| 22:06 | gtrak | satisfy, rather |
| 22:07 | gtrak | but.. one way to know is to try to use it as a channel :-) |
| 22:07 | gtrak | surely that'll fail. |
| 22:07 | logic_prog | I'm surprised there's no (chan? ...) function |
| 22:08 | noonian | me too |
| 22:08 | logic_prog | great wizards of clojure, |
| 22:08 | logic_prog | fix the above please |
| 22:08 | logic_prog | add a (chan? ..._) to clojure.core.async |
| 22:09 | gtrak | seems harmless enough |
| 22:10 | gtrak | I'm trying to get a dump of the cljs analyzer state, massive rabbit hole |
| 22:11 | gtrak | from hacking cljsbuild |
| 22:20 | abp | logic_prog: There was a ticket for it: http://dev.clojure.org/jira/browse/ASYNC-12 |
| 22:21 | logic_prog | (defn chan? [c] #+clj (= (type c) clojure.core.async.impl.channels.ManyToManyChannel) ) |
| 22:21 | logic_prog | looks sorta ugly |
| 22:24 | arrdem | bitemyapp: just got back from a barbeque outing. hopping on. |
| 22:27 | bobajett | hi folks, Im wondering why in Perl/Ruby split("foo", "") -> ["f","o","o"] and in clojure (str/split "foo" #"") -> ["","f","o","o"]? |
| 22:29 | andyf | bobajett: Clojure's split is based on Java String class split, and that is the way Java String split works. |
| 22:29 | bobajett | andyf: gotcha. Thanks! |
| 22:30 | amalloy | bobajett: i can't speak for ruby, but clojure of course just delegates this to java. and java asks "where is the first match of #"" in this string? okay, it's before all the characters. i'll return a match there. now where's the next? after f, all right, return a match there..." |
| 22:30 | TEttinger | bobajett, there's also ##(vec "fpp") |
| 22:30 | lazybot | ⇒ [\f \p \p] |
| 22:30 | TEttinger | but that returns chars |
| 22:30 | amalloy | that's as sensible an interpretation of "split on [nothing]" as ruby's |
| 22:30 | TEttinger | or ##(mapv str "foo") |
| 22:30 | lazybot | ⇒ ["f" "o" "o"] |
| 22:31 | noonian | is there an empty string on either end of "foo"? |
| 22:31 | bobajett | amalloy: :-) cool thanks for the detailed explanation |
| 22:31 | amalloy | TEttinger: (seq "foo") seems nicer than vec |
| 22:31 | noonian | seems like theres actually any number of them |
| 22:31 | bobajett | noonian: yeah thats what I was wondering too |
| 22:31 | TEttinger | amalloy, yeah, that too |
| 22:31 | hiredman | ,(.charAt "foo" 0) |
| 22:31 | clojurebot | \f |
| 22:32 | bobajett | TEttinger: sorry Im only very early in my learning clojure career what do the two ## mean in ##(mapv str "foo")? |
| 22:32 | lazybot | ⇒ ["f" "o" "o"] |
| 22:32 | TEttinger | just a command to execute the bot's eval |
| 22:32 | amalloy | noonian: http://docs.oracle.com/javase/6/docs/api/java/lang/String.html#split(java.lang.String,%20int) says some things about "trailing empty matches", but the sentence is hard for me to follow |
| 22:32 | TEttinger | same as starting a line in IRC with , |
| 22:32 | bobajett | ah got it thanks. |
| 22:33 | andyf | noonian: If you want to get all splits, including the trailing ones, give a negative integer as a 3rd arg |
| 22:33 | amalloy | &(.split "foo" "" -1) |
| 22:33 | lazybot | ⇒ #<String[] [Ljava.lang.String;@9ffba4> |
| 22:33 | amalloy | &(seq (.split "foo" "" -1)) |
| 22:33 | lazybot | ⇒ ("" "f" "o" "o" "") |
| 22:33 | logic_prog | in cljs, how can I check if an object is an atom, a string, or a cljs.core.async ? |
| 22:34 | andyf | Several examples available here that might be more instructive to read through than to try to give general rules: http://clojuredocs.org/clojure_core/clojure.string/split |
| 22:34 | TEttinger | so (mapv str "foo") will take "foo", and for each element (a character), return the result of calling str on it "f" "o" "o", and then make it a vector (not a lazy seq as for map, which may be preferable or not) |
| 22:36 | bobajett | TEttinger: got it thanks. I could guess what (mapv str "foo") did, but didn't know what the two ## were for. |
| 22:37 | bobajett | ##(class "foo") |
| 22:37 | lazybot | ⇒ java.lang.String |
| 22:37 | TEttinger | bobajett, heh it's an odd shortcut for the bot to use, since #(* %1 %1) is an anon fn that will multiply an argument by itself |
| 22:38 | TEttinger | same as (fn [n] (* n n)) |
| 22:39 | bobajett | TEttinger: isn't the reader macro for creating a set also start with a "#" ? |
| 22:39 | TEttinger | yes |
| 22:39 | TEttinger | # is a dispatch char |
| 22:39 | TEttinger | it changes what comes after it |
| 22:40 | TEttinger | #() is a fn, #{} is a set, there are a few others |
| 22:40 | TEttinger | I believe one causes a form to be ignored, can't remember what it is |
| 22:40 | bobajett | logic_prog: I shouldn't be answering this, since my clojure knowledge only some days old, but maybe (class yourObject) ? and compare it with java.lang.String or java.lang.Long or some such? |
| 22:41 | logic_prog | bobajett: good try, but I need it to work in cljs |
| 22:41 | TEttinger | bobajett, that would definitely work on JVM, but maybe it doesn't on CLJS aaaagh |
| 22:42 | bobajett | TEttinger: '("foo" #_(elide this stuff) "bar") |
| 22:43 | TEttinger | bobajett, seems like that's one of them. I believe #> also gets elided, it came up earlier |
| 22:44 | amalloy | wat |
| 22:44 | bobajett | TEttinger: ah did not know about that one. don't see it on the cheatsheet. |
| 22:44 | amalloy | ,'(x #> y) |
| 22:44 | clojurebot | #<RuntimeException java.lang.RuntimeException: No reader function for tag >> |
| 22:44 | amalloy | that doesn't work in any version of clojure |
| 22:45 | bobajett | ,'(x #_y z) |
| 22:45 | amalloy | as far as i know |
| 22:45 | clojurebot | (x z) |
| 22:45 | TEttinger | it was one of the reader macros on that one thing earlier today |
| 22:47 | bobajett | thanks folks, I was trying to do regex splitting and noticed Perl/Ruby behaved differently and Python behaved differently and Clojure behaved differently. #clojure is where I found the most helpful people :-) |
| 22:51 | logic_prog | given an object |
| 22:51 | TEttinger | http://sprunge.us/GbOX?diff |
| 22:51 | logic_prog | is there a easy way to list all protocols it satsifies/implements? |
| 22:52 | tbaldridge | no, but you can list all objects that extend a protocol |
| 22:57 | bja_ | logic_prog, maybe something involving #(.keys js/Object %)? |
| 22:57 | bja_ | err, maybe not. |
| 22:57 | bja_ | cljs$lang$protocol_mask$partition0$ doesn't look super helpful |
| 23:03 | gtrak | cemerick: would you balk at an autodoc sort of thing in lein-cljsbuild? I managed to make it dump the analyzer output, now I want to see if I can grab what I need to build something like that. |
| 23:05 | gtrak | I'm also thinking auto-complete eventually, not sure if that's the right approach, but just trying stuff :-). |
| 23:05 | cemerick | gtrak: Not sure. Open an issue when you're closer. :-) |
| 23:05 | gtrak | cool |
| 23:13 | logic_prog | what are the names of the protocols that string, number, atom implement ? |
| 23:19 | gtrak | logic_prog: huh? |
| 23:19 | logic_prog | in clojure, everything implements some protocol right? |
| 23:19 | logic_prog | what protocols do string, number, and atom objects implement? |
| 23:20 | gtrak | not necessarily, plus some of those are java interfaces |
| 23:20 | gtrak | like IDeref |
| 23:20 | tbaldridge | clojure or clojurescript? |
| 23:21 | tbaldridge | in clojure, most things are backed by java interfaces |
| 23:22 | gtrak | holy jesus, the serialized output of the cljs compiler is massive |
| 23:22 | gtrak | I mean the state |
| 23:23 | tbaldridge | yeah....it will be |
| 23:23 | tbaldridge | there's a ton of structural sharing |
| 23:24 | tbaldridge | so the same hashmap will extist on almost every ast node |
| 23:24 | gtrak | in general are there libs that walk it? trying to simply extract 'vars' and metadata and such. |
| 23:24 | gtrak | I could do it in-process, but was hoping to just dump it :-) |
| 23:25 | tbaldridge | yeah, it's not really dump-able. You want to do it in process |
| 23:26 | tbaldridge | although you might be able to strip the :env nodes before export. That's where 99% of the bulk is, and it's not really needed |
| 23:30 | gtrak | I might resort to inspector.clj :-) |
| 23:30 | gtrak | I've used that like once. |
| 23:30 | andyf | gtrak: I've used the inspector quite a bit for looking at output data from tools.analyzer(.jvm) |
| 23:30 | tbaldridge | just use prewalk and post walk |
| 23:31 | andyf | gtrak: It does not show metadata, unfortunately |
| 23:31 | gtrak | ah |
| 23:31 | tbaldridge | and metadata isn't really used by the cljs compiler |
| 23:31 | gtrak | yea, metadata seems silly, the whole thing is metadata |
| 23:32 | logic_prog | https://github.com/clojure/clojurescript/search?p=2&q=swap%21&type=Code <-- where is swap! defined ? |
| 23:32 | tbaldridge | https://github.com/clojure/clojurescript/blob/master/src/cljs/cljs/core.cljs#L7081 |
| 23:32 | tbaldridge | That's swap! ^^ |
| 23:32 | andyf | gtrak: I wouldn't use it for looking at analysis results of large source files, but worked OK for me for small to medium source files. |
| 23:35 | logic_prog | tbaldridge: https://github.com/clojure/clojurescript/search?q=defn+swap%21&type=Code <-- how should I be searching for taht instead? |
| 23:36 | tbaldridge | most stuff is in that single file, I' |
| 23:37 | tbaldridge | I've never really used github search |
| 23:37 | amalloy | logic_prog: just look in the file that it "should" be in - the cljs source is organized pretty predictably. i have no experience with github code search, but it sounds like it's not that useful |
| 23:37 | logic_prog | amalloy: I'm getting started, "should" means nothing to a newb with no intuition |
| 23:37 | logic_prog | however, grep seems to work |
| 23:38 | amalloy | like tbaldridge says, most functions from cljs.core are in that one file |
| 23:38 | amalloy | macros are all in another file somewhere |
| 23:38 | Raynes | Yay for shoving everything in a giant file! |
| 23:39 | tbaldridge | at least it's easier to find. |
| 23:39 | tbaldridge | I really don't have a problem with putting it all in one file |
| 23:43 | KeithPM | Good day. I am having a few problems with a function to generate permutations. I created a gist here https://gist.github.com/kpmaynard/8367053. I have some commentary at the top but I am currently running in to two errors in LightTable (permx '(1 2 3)) is generating the following errors |
| 23:43 | KeithPM | at recursion$permx.invoke(/Users/kpm/dev/clojure/recursion/src/recursion.clj:262) |
| 23:43 | KeithPM | in the status window |
| 23:43 | KeithPM | and |
| 23:43 | KeithPM | clojure.lang.ArityException: Wrong number of args (0) passed to: recursion$permx |
| 23:43 | KeithPM | AFn.java:437 clojure.lang.AFn.throwArity |
| 23:43 | KeithPM | AFn.java:35 clojure.lang.AFn.invoke |
| 23:43 | KeithPM | |
| 23:43 | KeithPM | In the REPL |
| 23:44 | gtrak | eek, don't paste multi-lines like that |
| 23:45 | KeithPM | Would you prefer that to be on one line? |
| 23:45 | gtrak | well, here's the relevant single line: clojure.lang.ArityException: Wrong number of args (0) passed to: recursion$permx |
| 23:46 | KeithPM | gtrak: I am calling the function (perms '(1 2 3)) That looks like one argument to me right? |
| 23:47 | gtrak | permx is the breaking one |
| 23:47 | KeithPM | OK… Maybe in the recursive calls? |
| 23:48 | gtrak | seems like you didn't evaluate something before running it |
| 23:48 | gtrak | so, it's running an old version of the function or something like that |
| 23:48 | KeithPM | I think I know why… Looks like when the seq is a singleton, rest is nil... |
| 23:48 | KeithPM | Let me take a look at that |
| 23:48 | gtrak | nil is still an arg |
| 23:48 | KeithPM | OK |
| 23:48 | KeithPM | Hmmm |
| 23:48 | gtrak | so.. it's whatever's calling that in the first place most likely |
| 23:49 | TEttinger | KeithPM, are you sure your parens line up? |
| 23:50 | KeithPM | TEttinger Hmmm… I think so, I have pretty much cleared out the repo and the file compiles OK |
| 23:51 | TEttinger | yeah, it's just the indents were at different levels in the gist |
| 23:51 | TEttinger | nvm just checked |
| 23:54 | KeithPM | TEttinger: OK. |
| 23:55 | KeithPM | gtrak: The first call is being made in the instarepl |
| 23:55 | TEttinger | also I think you may be using nil incorrectly: ##(nil? []) |
| 23:55 | lazybot | ⇒ false |
| 23:55 | hansel-han | What could I use to get a set where values have a TTL? |
| 23:55 | TEttinger | hansel-han, like an expiration date? |
| 23:56 | hansel-han | TEttinger: it's for a Who's Online box on a forum. yeah. users get conj'd when they do click around on the forum but fall off when inactive for 5 minutes. |
| 23:58 | amalloy | hansel-han: i've used a sorted-map of {timestamp, value} |
| 23:58 | TEttinger | I'd use something like overtone/at-at and schedule an event to delete users who have are inactive for 5 minutes, resetting on action |
| 23:58 | KeithPM | TEttinger: Do you mean in permx? RH says when there is nothing left in a sequence clojure returns nil not ()… I therefore test for nil? not empty? Is that a problem? |
| 23:58 | hansel-han | I've never used core.cache but I see it has a "TTLCache". Perhaps that's an option? |
| 23:59 | amalloy | with such a sorted map, you can easily say "remove all entries whose keys are less than x", and updating someone's timestamp is just dissocing them and re-associng to the current timestamp |
| 23:59 | TEttinger | KeithPM, kinda. the preferred idiom is using seq to test for non-emptiness, which returns nil on an empty seq and the seq otherwise. |
| 23:59 | TEttinger | ,(seq [1 2 3]) |
| 23:59 | clojurebot | (1 2 3) |
| 23:59 | TEttinger | ,(seq []) |
| 23:59 | clojurebot | nil |
| 23:59 | amalloy | using scheduling or a cache sounds like a lot of work, and less predictable (timing-wise) than doing it yourself |