#clojure logs

2014-04-14

00:01martinklepschanother question on futures... creating a future for reading, parsing, deleting a file for a few thousand files and return a list of futures — does that sound something what you'd do with futures?
00:04amalloymartinklepsch: you don't really want to create a thousand futures at once - that's a lot of scheduler contention
00:05martinklepschamalloy, whats something I should look into then to read/parse/delete files paralelly
00:06maxthoursiesounds like a task for a queue
00:07awalkerhaving a hard time wrapping my head around this destructuring behavior: https://www.refheap.com/75845
00:08awalkerI'm expecting the 2nd example to work, but it fails.
00:08turbofailmartinklepsch: take a look at the claypoole library, it's pretty sweet
00:10martinklepschturbofail looks interesting thanks!
00:11Raynesawalker: (apply (fn [& {:as more}] more) (mapcat identity {:a 1}))
00:12RaynesIdeally, if you have control over this function you'd just make it take a map instead.
00:12RaynesGenerally if you find yourself unrolling arguments for the sake of keyword destructuring, it's better to just pass a map.
00:15awalkerthank you, but why does the 2nd ex fail? feels like it should work but is it intentionally not supported?
00:17[Neurotic]Anyone else noticed that clojars latest-version.svg is being aggressively cached by github? It doesn't seem to be updating in my README.md
00:19amalloyawalker: because when you seq {:a 1}, you get ([:a 1]), not (:a 1)
00:20amalloyso when you apply f to ([:a 1]), it sees a single arg, [:a 1], rather than the two args :a and 1 you wanted to pass
00:20bob2pretty sure github doesn't touch it at all, and just tells your browser to load it
00:21awalkerah, thank you
00:21[Neurotic]bob2: was that to me?
00:31bob2[Neurotic], yes
00:32[Neurotic]bob2: I wish ;) nope, they now cache it on fastly cdn - it's no longer pass through
00:32[Neurotic]https://github.com/github/markup/issues/224
00:37bob2interesting
00:44[Neurotic]there is a Cache-Control: max-age=0 in the header, but doesn't look like it's respecting it
02:07dissipatehow do you set up selectors with clojure.test? for instance, i want to tag a particular test as an 'integration' test, and only have it run when i want to select integration tests to be run
02:11dissipatenevermind, looks like this is supported by lein
03:57sm0kecan macros be made private?
03:57amalloyyes, but there's not much point (as with functions, really). like, you prevent the user from...expanding into code they could have written themselves? what's the point?
03:58sm0kepoint being hiding them from documentation
03:59amalloymmm. well, you could see if your doc-generator supports some annotation other than ^:private, or you could put them into an "internal" namespace and ask it not to document that namespace
03:59amalloyor document it as "bro, don't use this. you'll regret it"
03:59sm0ke:P
03:59sm0kewhat if the bro is adventurous
04:00amalloythen...so what?
04:00sm0kelet me try attaching meta
04:00amalloythey used a function you told them not to, and it made them happy. if a future version of your software removes it, they only have themselves to blame
04:00sm0kei am using codox
04:01amalloyhttps://github.com/weavejester/codox#skipping-individual-functions
04:01sm0ke,(doc defmacro)
04:01clojurebot"([name doc-string? attr-map? [params*] body] [name doc-string? attr-map? ([params*] body) + ...]); Like defn, but the resulting function name is declared as a macro and will be used as a macro by the compiler when it is called."
04:01sm0kewhere is the meta-map here?
04:07sm0keoh its called attr-map?
04:08sm0ke^:private works with codox
04:09amalloyas does ^:no-doc, sm0ke, which i linked to
04:12sm0keyes yes
04:12sm0ke(inc amalloy)
04:12lazybot⇒ 94
04:12sm0kewhoa!
04:12sm0kethats a lot
04:16kaw_LSD ls -ltra
04:16kaw_Oops, sorry
04:32derek_cdoes anyone know how to give ring a callback on exit?
04:32derek_cso I want some code to be run when the web application terminate
04:32derek_c*terminates(
04:34beamsohttps://github.com/weavejester/lein-ring#general-options (:destroy)
04:38derek_cbeamso: thanks!
04:58sveriHi, I am using datomic and I wonder if its common do use some uniqe id's for datoms like you do in relational databases? I have not seen an example for this so far
05:30oskarthWhat's a good pattern to remove the mental overhead of remembering if a resource should be called as function or not? For example (def users-url "foobar.url") and (defn user-url [id] (str "users-url" id)) I could do (defn users-url [] ...) but that feels silly, and putting (str "users-url" id) everywhere seems prone to mistakes. What does a _simple_ solution
05:30oskarthlook like?
05:31oskarth*(str users-url "/" id)
05:41oskarthSlighly silly question but it feels like must be a simple solution which doesn't involve overly long names like "make-user-url"
05:43ucboskarth: if you're taking votes, I'd +1 (defn user-url [id] ...)
05:43ucb(without knowing anything else about your problem)
05:43oskarthucb: what would you do with users-url then? def or defn?
05:44oskarthcause it "should" be a def, but if it is at least I make the mistake of calling it as (user-url) since it has the same shape as (users-url id)
05:45oskarthnot a hard problem but feels like one that shouldn't exist at all if you are doing it right
05:46oskarth(cause someone else might be doing a (let [user-url (str users-url "/" id)]...)
05:47ucbsure
05:47ucbso, is users-url a constant or could that change?
05:47oskarthconstant
05:47ucbif the latter, it's common practise to name it *users-url*
05:47ucbwhich already gives it meaning
05:47ucbright
05:47oskarthyeah definitely
05:47ucbwhat'll be the most common usage?
05:48ucbwouldn't (defn user-url [id] ...) mas users-url anyway?
05:48ucbmask*
05:48oskarthnope
05:48oskarthin the case of an API both would be used
05:48ucbsorry, not mask, but rather use users-url internally, implying users-url is private anyway
05:49ucbin danger of sounding silly, if you want consistency, then make (defn users-url [] "...")
05:49oskarthyeah I agree that's one one solution to enforce consistency, but as you say it's a bit silly to write (users-url) for a string
05:50ucbagain, I don't have a good answer, but is users-url is bound via config
05:50ucbthen an alternative is to have (defn users-url [config] ...)
05:50ucbwhere config could be a map, etc.
05:51oskarthin this case it would just be the same string all the time
05:51oskarthI guess it could be hidden away in one or two functions with (get-user [...]) since that's the actual resource, and then let it be a bit ugly there
05:52ucbsure
05:52ucbsounds like users-url is an internal detail anyway
05:52oskarthbikeshedding problem perhaps, but feels like it should be a solved problem with good patterns, not something you spend mental cycles on
05:52oskarthjust tired of getting those types of errors
06:18ssqqIn a function call, when I use let create a lexical binding, how to redefine its value?
06:19nightflyuse a reference type
06:24ssqqnightfly: you means? (defn f [] (let [v (ref "s")] (dosync (ref-set v "v")))
06:25llasramssqq: More typically, you just don't do that, or use e.g. recursion to get the effect of rebinding w/o actual mutability
06:25llasramssqq: What in particular are you trying to achieve?
06:25nightflyor that :p
06:27ssqqllasram: I want a char cache in a function call. I use perl before.
06:27llasramWhat is a "char cache"?
06:28ssqqllasram: In a loop of char-list, push char to a vector one by one.
06:29llasramYeah, you want the pattern of updating by recursion
06:30llasramWhich is the essential nature of `reduce`: ##(reduce conj [] "string")
06:30lazybot⇒ [\s \t \r \i \n \g]
06:31llasramOr manually: ##(loop [v [], s (seq "string")] (if-not s v (recur (conj v (first s)) (next s))))
06:31lazybot⇒ [\s \t \r \i \n \g]
06:32ssqqllasrm: but have many branch when met a char. I want write a reader of clojure.
06:32llasramLike https://github.com/clojure/tools.reader ?
06:34ssqqllasram: yes, I need learn this project. thanks very much.
06:34llasramnp
06:40sverihi, i have a datomic schema with an instant attribute, now, when I initialize my database I load some data from an edn file, how would I add a valid datetime for that instant attribute? I cannot find an example for this
06:49sm0kewhats is the simplest way to have a f applied to a initial value, then again apply to the result, and return a lazy seq
06:56gfredericks,(doc iterate)
06:56clojurebot"([f x]); Returns a lazy sequence of x, (f x), (f (f x)) etc. f must be free of side-effects"
06:58perseshello
06:58perseswhat is the best way to create a graph and then serialize it to a binary?
06:58noidi12:44] < ucb> if the latter, it's common practise to name it *users-url*
06:58persesis there a native support for a graph in clojure?
06:58noidiI'm sorry but that's just wrong
06:59noidithe "earmuffs", as they're called, signify that the var is dynamically bound
06:59ucbnoidi: isn't it the case that is a var is dynamically ... yeah
06:59noidiit has nothing to do with constancy
06:59ucbsure, apologies, words don't come out easy early in the morning :)
07:02noidiand apparently reading doesn't come easily to me either, I misread you and thought you suggested using the earmuffs for constants, so apologies to you as well :)
07:03ucboh, heh, no :)
07:04sm0kegfredericks: thanks
07:04sm0ke(inc gfredericks)
07:04lazybot⇒ 52
07:06noidioskarth, I think the right way to solve that problem is with a type system. In core.typed, your examples would have the types String and [String -> String].
07:07oskarthnoidi: I think you might be right. I'm actually looking into it right now :)
07:07oskarth(not for that specific problem, just in general)
07:10noidiI don't think it's quite polished enough to be recommended for general use (yet!), but it's already usable and useful if you don't mind reporting bugs and working around them :)
07:12jonathanjdoes it bother anyone else that (inc foo) shouldn't actually do anything permanent? poetic license? :P
07:12vijaykiranperses: Graph as in graph image ?
07:13jonathanj(i guess (swap! foo (inc foo))) is a bit of a mouthful?)
07:13persesvijaykiran: Graph: set of nodes + set of edges
07:13noidiambrosebs keeps improving core.typed an impressive rate, so I'm sure it's only a matter of time until I'll feel comfortable recommending it without any disclaimers
07:14noidi(given the enormous size of the task that might take a couple of years, though)
07:15gfredericksjonathanj: it'd be (swap! foo inc)
07:16jonathanjgfredericks: err, right!
07:17jonathanjuser=> (def foo 0)
07:17jonathanjuser=> (swap! foo inc)
07:17jonathanjClassCastException java.lang.Long cannot be cast to clojure.lang.Atom clojure.core/swap! (core.clj:2160)
07:17Bronsajonathanj: foo needs to be an atom (def foo (atom 0))
07:17pjstadigjonathanj: you'd have to either (def foo (atom 0)) or (alter-var-root #'foo inc)
07:17gfredericks,(def next-num (partial swap! (atom 0) inc))
07:17clojurebot#'sandbox/next-num
07:18gfredericks,(next-num)
07:18clojurebot1
07:18gfredericks,[(next-num) (next-num) (next-num)]
07:18clojurebot[2 3 4]
07:18jonathanjah
07:18pjstadig,(take 50 (repeatedly next-num))
07:18clojurebot(5 6 7 8 9 ...)
07:18persesis there anybody here have used loom graph lib?
07:19gfredericks,(next-num)
07:19clojurebot12
07:19gfrederickspjstadig: ^ ha
07:19jonathanjhaha
07:19pjstadiggrr
07:19gfredericks,(->> (repeatedly 10000 next-num) (reduce +))
07:19clojurebot50125000
07:19gfredericks,(next-num)
07:19clojurebot10013
07:20jonathanjso i guess next-num is like Python's itertools.count, is this not defined in clojure somewhere already?
07:22jonathanj("count" is a different thing and i'm out of names to try searching for)
07:27ambrosebsBronsa: FYI you might have missed Aaron's latest comment on your GSoC proposal
07:27Bronsauh, I sure did. I'm going to check now, thanks
07:35gfredericksjonathanj: only similar thing is gensym I think
07:35gfredericks,(gensym)
07:35clojurebotG__27
07:35gfredericks,(last (repeatedly 930848 gensym))
07:35clojurebotG__930899
07:35gfredericks,(gensym)
07:35clojurebotG__930924
07:35llasramWell, or `range`
07:36jonathanjrange, duh. i forgot to look for that one
07:36llasramModulo the fact that Clojure doesn't do the stateful-iterator thing
07:36jonathanjllasram: yeah, obviously it doesn't map quite the same way
07:36jonathanji was just curious
07:51gfredericksoh I thought statefulness was the essense of the question
07:51gfredericksglobal statefulness in particular
08:01wunkiI found out that a multimethod is only found if I require the namespace where it is defined in my main. Is this correct?
08:03gfrederickswunki: it's the same as for any var
08:03gfredericksthe multimethod lives wherever the `defmulti` is
08:04wunkigfredericks: I'm defining a multimethod in a namespace which is never referenced from the `:main`, so it's also not found
08:05wunkigfredericks: the defmulti is defined in an external library
08:05gfredericksright; requiring things is important, not just for multimethods
08:06wunkigfredericks: is there a way to require a multimethod?
08:06wunkigfredericks: or should I just use `:refer :all`
08:10llasramFor the multimethod itself just `require` the namespace and refer to it like any other var.
08:10llasramFor implementations, you just need to `require` the implementing namespace(s)
08:10llasram(no special details on the `require`, that is -- any `require`ing will do)
08:11llasramwunki: Rule of thumb: if you need to `:refer :all`, you've done something wrong
08:11wunkillasram: thanks, will keep it in mind
08:11wunkillasram: currently only using `:refer :all` in my tests
08:12llasramCool. That's perfectly reasonable
08:30ambrosebsBronsa: is it a good idea to assume tools.analyzer will preserve arguments to `do`, especially constants?
08:33Bronsaambrosebs: hm, at the moment it does. In the future it will have a pass to remove no-ops like constants in statement position but that's going to be in a pass
08:33Bronsaso you can always remove that pass if you need that guarantee
08:34ambrosebsBronsa: ok. `do` statements seem like a good place to jam annotations since we can preserve tag inference
08:34ambrosebs(tc-ignore foo) => (do ::tc-ignore foo)
08:35BronsaI see. Yeah, you should have no problems with that right now
08:36Bronsaambrosebs: I'll let you know if/when this might change, but again, you'll always have the option to preserve the original behaviour
08:36ambrosebsBronsa: thanks. Also folding nested `do`s would break my approach.
08:36Bronsaambrosebs: uhm that might be a problem I think
08:36dottedmagAre there alternatives to Datomic? That is, other "accretion-based" DBs.
08:37Bronsaambrosebs: nested top level `do`s need to be folded to address the Gilardi Scenario
08:38Bronsaambrosebs: nevermind, that's not done in the analyzer
08:38tbaldridgedottedmag: not that I'm aware of, at least not any that have immutability + datom based storage + datalog + data locality
08:39ambrosebsBronsa: I can deal with that possibility, good to know.
08:39Bronsaambrosebs: you should be good to go on that. IIRC the only place where t.a removes some forms is (try foo) => foo which I believe Compiler.java does too
08:39dottedmagtbaldridge: Thanks, that's what I expected as well.
08:51mdrogalisdottedmag: My experience has been that you have to treat the data store as accretion-only yourself.
08:51mdrogalisNathan Marz's book that's coming out covers it pretty well, IMO
09:02arrdemambrosebs: +1 for supporting symbol aliases
09:10ambrosebsarrdem: was it you talking about the > suffix a few days ago?
09:35jonathanjhow would i write (re-find #"[^0-9]+" "ZAR123.45") without regexes?
09:36jonathanj(apply str (take-while-not digit? s)) is what i had in mind
09:37jonathanjbut i'm guessing a bunch of these don't exist
09:40`szx,(defn digit? [c] (Character/isDigit c))
09:40clojurebot#'sandbox/digit?
09:41`szx,(apply str (take-while digit? "123abc"))
09:41clojurebot"123"
09:41`szxoh wait you want the other way around
09:43`szx,(apply str (take-while (complement digit?) "ZAR123.45"))
09:43clojurebot"ZAR"
09:45jonathanjcomplement
09:45jonathanji can never remember that damn name
09:45jonathanj`szx: thank you
09:46jonathanjhrm
09:46jonathanjCharacter/isDigit is not defined in my environment
09:48TimMc&(apply str (remove #(Character/isDigit %) "४२123"))
09:48lazybot⇒ ""
09:49jonathanjuser=> Character/isDigit
09:49jonathanjCompilerException java.lang.RuntimeException: Unable to find static field: isDigit in class java.lang.Character, compiling:(NO_SOURCE_PATH:0:0)
09:49jonathanj:/
09:49TimMcjonathanj: It's a static method, not a function.
09:49TimMcYou can call it, but you can't evaluate it.
09:50TimMcs/static // more generally
09:50jonathanjuser=> (Character/isDigit "a")
09:50jonathanjIllegalArgumentException No matching method found: isDigit clojure.lang.Reflector.invokeMatchingMethod (Reflector.java:80)
09:50TimMcOh, how old is your Java?
09:51jonathanji have no idea how to find that out
09:51jonathanjjava version "1.7.0_45"
09:51jonathanjJava(TM) SE Runtime Environment (build 1.7.0_45-b18)
09:51jonathanjJava HotSpot(TM) 64-Bit Server VM (build 24.45-b08, mixed mode)
09:51TimMcOh, type issue.
09:51TimMc&(Character/isDigit \a)
09:51lazybot⇒ false
09:51TimMcPass it a character, not a string. :-)
09:52jonathanjhur
09:52jonathanjTimMc: so what's going on with your example there? an empty result seems broken
10:11arrdemambrosebs: neg
10:12ambrosebsarrdem: np
10:12TimMcjonathanj: Those ara Devanagari digits. :-)
10:12TimMchttp://www.fileformat.info/info/unicode/char/96e/index.htm
10:12ambrosebsarrdem: cheers for the input
10:12arrdemambrosebs: usability++
10:12jonathanjTimMc: aha!
10:13TimMc&(.getPort (.toURL (java.net.URI. "http://google.com:६/&quot;)))
10:13lazybot⇒ 6
10:14TimMc^ Java mistakenly uses a broad definition of "digit" for some parsers.
10:14ambrosebsarrdem: just one of those things I played it safe on
10:15arrdemambrosebs: I really appreciate the desire to make sure you get it correct, but I think there's a very reasonable element of "you'd expect it to work" at play with :require :as annotations.
10:16arrdemhence my support therefor... the compiler should already be issuing warnings if you have an :as conflict.
10:17ambrosebsarrdem: yes I'll implement it. My reasoning for the decision didn't make sense in hindsight.
10:17arrdemambrosebs: <3
10:17ambrosebsglad I'm adding alias support (non-breaking) than removing it :)
10:24afgdfin the /bin/repl (datomic) i cannot use the arrow keys, i get '^[[A'. D left, C right, , A up, B down. Anyone knows how i solve that?
10:34btcNeverSleepsI've got an issue and can't really produce a minimal test case so I'm asking for help here in case anyone had the same problem... I've got one test .clj file (using clojure.test) which fails when I try "cider-eval-buffer".
10:34btcNeverSleepsHowever that same test .clj file works fine from "lein test"
10:34ToBeReplacedbtcNeverSleeps: persists after you restart cider?
10:34btcNeverSleepsToBeReplaced: yup
10:35btcNeverSleepsToBeReplaced: persists after I restart Emacs
10:35btcNeverSleepshowever...
10:35btcNeverSleepsIf I switch to the other .clj file (which I :require / :refer all from the test file) and do cider-eval-buffer, then back to the test .clj file then cider-eval-buffer now works from Emacs too
10:36ToBeReplacedbtcNeverSleeps: sounds like a source path problem; are you using multiple profiles with leiningen?
10:37btcNeverSleepsI don't think so... No too sure what multiple profiles are. It's a regular lein project. I mostly call "lein test" and, once in a while, "lein run". The project directories were created using lein.
10:37btcNeverSleepscould it be some _ / - issue?
10:39btcNeverSleepserf...
10:40btcNeverSleepscannot easily do more testing because I'm under Emacs and I'm using erc to do IRC (silly me)
10:40arrdemdamnit... I shoulda parsed lazybot's logs..
10:41btcNeverSleepsoh well, I take it I'll just cider-eval-buffer the other buffer(s) manually as of now. And then update everything (lein, cider, etc.) to the latest versions.
10:42ToBeReplacedbtcNeverSleeps: absolutely could be a _/- issue... not sure what should be done to better document that; seems a lot of people stumble on it
10:43btcNeverSleepsI renamed the file, I'll restart Emacs and come back in the channel to tell if it works or not
10:43justin_smithload failure should check for - in the name and then add an extra output about munging
10:43justin_smithwhy would that require an emacs restart?
10:46btcNeverSleepshmm still not working: it's still saying "Unable to resolve symbol: ... in this context" when I try to cider-eval-buffer that test .clj file even though the require is there and even though from "lein test" things work fine. Even though I removed the "-" from my test .clj filename / namespace. Not that much of a big deal: it's just a minor annoyance.
10:47justin_smithwhat about lein check?
10:48sverihi, I am getting this instant type back from datomic: #inst "2014-12-01T00:00:00.000-00:00" and want to parse that in clojure script, how would I do that?
10:48justin_smithcan't clojurescript just read that? it should
10:49arrdemyou shouldn't have to read that... and besides #inst is a standard EDN reader form.
10:49justin_smithright, if you can read at all, that should be parsed no problem
10:49guest234235any advice on best way to grab (or examples) of Om (or vanilla cljs) fetching remote JSON data?
10:49btcNeverSleepsI just tried "lein check": throws an Exception for that one .clj file that my test doesn't want to :require : "java.lang.ClassNotFoundException: clojure.stacktrace"
10:50sveriarrdem: so I should have to convert it to a string before passing it to cljs?
10:50justin_smithbtcNeverSleeps: that's a namespace, are you referring to it in some odd way?
10:51btcNeverSleepsjustin_smith: let me check ^ ^
10:51justin_smithyou should be able to require it no trouble, but if you accidentally referred to it unquoted you may see that error
10:51btcNeverSleepsit's on this line in my source file: (clojure.stacktrace/print-stack-trace t)
10:51btcNeverSleeps
10:52justin_smithdo you require the ns? that's probably the issue
10:52btcNeverSleepsoh I see
10:52btcNeverSleepsbut why is it an issue? And why is "lein test" not chocking on it?
10:52sveriguest234235: as far as I can tell OM uses an app-state cljs variable, so all you have to do is replace that app-state contents with your JSON returned data
10:52justin_smithlein test runs tests, if you define them and put them under a test/ dir
10:53justin_smithlein check, on the other hand, loads every clojure file it finds, and reports any errors it sees
10:53justin_smithso lein test will never try to load an ns that is not required by a test ns
10:53btcNeverSleepsgotcha
10:54btcNeverSleepsI didn't know about "lein test" btw: thanks for the (great) info : )
10:54guest234235sveri: yep. was looking at using cljs-http to do a standard GET request; though that returns an async channel ... still learning ..
10:54sveriguest234235: I guess we all are :-)
10:55guest234235wondering if there's any example apps or repos that have already 'solved' this seemingly common thing: "get remote data; update display accordingly"
10:55guest234235in elegant, succint cljs, of course ;-)
10:56justin_smithguest234235: bird's eye view: do an ajax call, the callback provided to the ajax call should update the data structure that om renders when it gets its result
10:56justin_smiththis will make om re-render, et voila
10:57justin_smithhttp://stackoverflow.com/questions/8567114/how-to-make-an-ajax-call-without-jquery
10:58`szxguest234235: have you read the advanced tutorial? https://github.com/swannodette/om/wiki/Intermediate-Tutorial
10:58`szxerr, intermediate
11:01guest234235yeah. think https://github.com/yogthos/cljs-ajax is going to make things easier.
11:17teI am using clojure.data.csv. I have tuples like: ["foo", 1, "baz"]. I want to /append/ to a CSV file and not just write it wholesale.
11:17teSuggestions?
11:18justin_smithte: appending is a fiction, you write the previous contents, followed by new ones
11:19seangrove justin_smith offers new-comers no choice between red and blue pills
11:19arrdemjustin_smith: really?
11:19tejustin_smith: heh, seriously?
11:19arrdemjustin_smith sits on a throne of lies...
11:19justin_smitharrdem: well some operating systems fake it :)
11:19seangroveclojurebot: justin_smith sits on a throne of lies
11:19clojurebotI don't understand.
11:19arrdemjustin_smith: some operating systems aren't completely retarded :D
11:19seangroveclojurebot: justin_smith is sits on a throne of lies
11:19clojurebotAck. Ack.
11:20seangrove~justin_smith
11:20clojurebotjustin_smith is sits on a throne of lies
11:20arrdemseangrove: lemme
11:20seangroveGrammar challenges aside, I like it
11:20arrdemclojurebot: justin_smith is <reply> justin_smith sits on a throne of lies
11:20arrdem~justin_smith
11:20arrdemgoddamnit clojurebot.
11:20seangroveHahaha
11:20teso, assuming that's true justin_smith -- still, help me out here
11:20arrdemseangrove: would you do the honors?
11:20arrdemsince the bots hate me..
11:20seangrove~justin_smith
11:20clojurebotjustin_smith is sits on a throne of lies
11:21teI'm assuming I need something like (io/writer "foobar.csv" :append true)
11:21tebut i dont know if I can use csv/write-csv if that's the case
11:21seangroveclojurebot: justin_smith is <reply> justin_smith sits on a throne of lies
11:21clojurebotAlles klar
11:21seangrove~justin_smith
11:21clojurebotjustin_smith sits on a throne of lies
11:21cowinfantrythere we go
11:21seangrovejustin_smith: That was a lot of work, hope you appreciate it
11:21seangrovearrdem: How'd you upset the bots?
11:21arrdemseangrove: I have no idea...
11:22teso, anyway -- anyone want to offer help on this or just configure bots? ;)
11:22arrdemte: we're just here to play with the bots man :P
11:22teheh, fair enough
11:22seangrovete: Haven't used data.csv, but it seems straightforward enough
11:22arrdemte: you could probably use Java interop to open the file in append mode and then write the str of what you want to append...
11:22seangrovete: Presumably you have an atomic lock on the file, no one else is reading/writing?
11:23seangrovete: It looks like you just use csv/write-file and give it whatever you've previously read from the file appended with whatever you want to add
11:24justin_smithseangrove: which is exactly my throne of lies
11:24teseangrove: i was thinking about using agents
11:24seangrovejustin_smith: That's where I got my explanation form
11:28arrdemBronsa: ping
11:28Bronsaarrdem: pong
11:29arrdemBronsa: know of any projects do to test coverage analysis on the basis of t.a trees?
11:29Bronsanope
11:29justin_smithit looks like you can in fact create the io/writer you pass to clojure.data.csv/write-csv with the args :append true
11:29arrdemgood. I have a first project then :D
11:29justin_smith(what the OS does with that is another question of course)
11:29tehmm okay
11:29telet me give this a try
11:30Bronsaarrdem: afaik currently the only projects that are using t.a in releases are core.typed and eastwood
11:30Bronsaarrdem: huh cool!
11:30tethanks justin_smith
11:30teand company
11:30arrdema merry band...
11:39guest234235does cheshire compile to cljs ? or can it only be required in a clj namespace?
11:39gtrakguest234235: cheshire is a wrapper over jackson
11:39gtrakwhich is a java lib
11:39dakroneguest234235: no, cheshire uses Jackson which is a java library
11:39Jabberzthe 'for' macro, is that idiomatic for doing transformation on lists, i.e. putting functions in :let, or are doing say, separate doseq's perferred?
11:40justin_smithJabberz: for when you care about the result, doseq when you want to do something and return nil
11:40Jabberzjustin_smith: cool, thanks
11:40justin_smithdoseq has the some cartesian elaboration that for does
11:40guest234235dakrone: figured that was the case. best way to 'digest' and work with json in cljs namespace?
11:40justin_smithJabberz: so it need not be nested
11:41dakroneguest234235: probably data.json then?
11:41justin_smithwhat about just using interop to turn the json into vanilla js data?
11:41`szxguest234235: you can just convert it to clojure data
11:41justin_smithand then do what `szx suggests next
11:43guest234235want to keep things simple. am a sucker for wrapper libraries that make anything easier, more terse.
11:43justin_smithguest234235: turning json into javascript data is very terse
11:43stuartsierraUse the G.Closure JSON parser; data.json doesn't have a ClojureScript version.
11:44justin_smithwhy not JSON.parse? that is part of the ecma standard
11:44justin_smithhttp://stackoverflow.com/questions/4935632/how-to-parse-json-in-javascript
11:44stuartsierraOr that. I don't know.
11:45mpenetJSON.parse is the way to go, and there are shims for when it's missing
11:45justin_smithJSON.parse("{foo : bar}")
11:45`szxi would assume closure's JSON parser delegates to JSON.parse
11:45justin_smithit's that simple
11:45guest234235do GET request; returns JSON; need to parse and present.
11:45gtraklove that we can grab everything in closure piecemeal. It's massive.
11:45dnolen_guest234235: go w/ stuartsierra's suggestion if you need to target <= IE7
11:46guest234235targeting mobile.
11:47justin_smithie <= 7 will not run on mobile (that you care about at least)
11:47justin_smithcorrecting myself: JSON.parse('{"foo" : "bar"}')
11:47justin_smith(the previous was invalid json)
11:54guest234235stuartsierra: really? no clojurescript version to parse json
11:54stuartsierraguest234235: It's not needed. Some browsers have it built in and G.Closure libs handle the rest.
11:54justin_smithguest234235: JSON is a javascript serialization format, it's silly to write your own javascript json parser
11:57justin_smith(js->clj (JSON/parse "{\"foo\" : \"bar\"}")) <- this gives you native clojure data
11:57justin_smithit's pretty succinct
11:58gtrakguest234235: a fully-clojure impl provides no benefits for most use-cases.
11:58gtrakI wonder the same about any lib that reimplements things that already exist..
11:59guest234235reimplements in a way that makes a given lib easier to work with.
11:59gtrakmaybe once we get a fancy compiler, optimization might change things.
11:59justin_smithguest234235: explain to me what part of what I posted above is not easy?
11:59guest234235but yes, argument then is immediately, just improve that lib
12:00justin_smithit's a function call and a javascript method
12:00gtrakguest234235: or we can do idiomatic wrappers, but that's still dubious a lot of the time.
12:00gtrakdepending on the complexity of the wrapped project
12:01guest234235true. I'm not here advocating crafting dubious, redundant libraries.
12:01gtrakIf it's not a trivial interface, like the JSON parser, often I'll end up learning more than I would've to use java interop.
12:01AimHereYou don't need to; those libraries will happen, regardless
12:01guest234235just need to grab some remote JSON data, serve it up on a page ;-)
12:02gtrakfor instance, clj-http and related projects can get really hairy when you do something like client-auth.
12:02gtrakyou end up learning more levels of abstraction b/c you're already committed to the idiomatic wrapper.
12:02gtrakso it kind of just pushes the cost around
12:03gtrakbut clj-time I think is pretty nice to use, because it's more about surface area than depth.
12:03guest234235gtrak: yep. if the use-case is that "it just works" , then fine. costs offloaded.
12:03AimHereMost json is parsed by (read-string (replace foo #":" "")) anyways...
12:04justin_smithhah, fair enough
12:04gtrakAimHere: you're joking? haha.
12:04justin_smithin practice yeah that would mostly work I guess
12:04AimHereI might not be entirely serious, true ;)
12:05gtrakreally, if we had better tooling, interop would be even easier.
12:06gtrakand wrappers kind of fill the gap for now
12:15VfeHow can I get an entire vector as an argument? for example. (defn func [ [my-vec] ] {:key [my-vec]}) (func [“item1” “item2” “item3”]) gives my-vec a vector of just “item1”.
12:16VfeIs there some trick to the behavior I want?
12:16rasmusto,(let [[a b :as all] [1 2]] [a b all])
12:16clojurebot[1 2 [1 2]]
12:17`szxVfe: you're destructuring the vector, is that what you wanted to do?
12:17rasmustoVfe: hm, maybe I didn't fully understand the question. Do you want the vector destructuring?
12:17`szxotherwise (defn func [my-vec]] {:key my-vec}) will work just fine
12:17`szxugh
12:17`szx(defn func [my-vec] {:key my-vec})
12:18VfeNo, I just want to take a vector in that will add that vector to a map
12:18VfeIf it’s destructing it that’s maybe where I’m confusing myself XD
12:18`szx,((fn [v] {:k v}) [1 2 3 4])
12:18clojurebot{:k [1 2 3 4]}
12:18rasmustoVfe: ah, then do as `szx suggested, don't bother with the destructuring bit
12:18justin_smiththe extra [] pair introduces destructuring
12:19VfeGah, you’re right. Thanks for the help. I blame lack of sleep, I should know this, hah
12:19VfeAppreciate it guys :)
12:20justin_smithwell, in some c-like language v[] may mean "v, which is a vector", so I could imagine guessing (wrongly) that [v] in an arg vector means the same thing.
12:20justin_smithI am probably overthinking that
12:21`szxprobably :)
12:23rasmusto,(clojure.set/intersection) ; why not #{} ?
12:23clojurebot#<ClassNotFoundException java.lang.ClassNotFoundException: clojure.set>
12:24justin_smiththe intersection of nothing :) sounds pretty zen
12:24rasmustojustin_smith: union has a 0-arity case
12:25justin_smithrasmusto: if we are basing this on mathematics, I think "everything in null" and "intersection of null" are very different questions
12:26justin_smithif on intuition, yeah, generalize all the things to zero args
12:27rasmustojustin_smith: I'm doing an (apply intersection some-seq-of-sets), where some-seq-of-sets might be empty, I guess I can just wrap the thing in a cond
12:27justin_smithyeah, that makes sense, we really should have zero argument arities of everything defined for that kind of thing
12:28justin_smith((fnil f #{}) sets) maybe?
12:28rasmustojustin_smith: yep, was just writing that :)
12:28justin_smith((fnil println "default") nil)
12:28justin_smith,((fnil println "default") nil)
12:28clojurebotdefault\n
12:29justin_smith,((fnil println "default") "provided")
12:29clojurebotprovided\n
12:29rasmusto,((fnil count 'baz) ())
12:29clojurebot0
12:30rasmusto,((fnil count 'baz) nil)
12:30clojurebot#<UnsupportedOperationException java.lang.UnsupportedOperationException: count not supported on this type: Symbol>
12:30justin_smithok, you should call seq
12:30justin_smith,((fnil count "baz") (seq ()))
12:30clojurebot3
12:30justin_smithunless there is an fempty
12:31jonathanji'm trying to remember what term Clojure uses to describe the structures it uses for efficiently handling things like subvectors
12:31rasmustojustin_smith: I was assuming that nil? would work on '(), probably good that it doesn't
12:31justin_smithsomehow fempty sounds like something lewis carrol would invent
12:31jonathanj(efficiently in terms of memory use)
12:31technomancystructural sharing?
12:32justin_smithpersistent data structures?
12:32gtrakjonathanj: persistent array-mapped hash tries
12:32tim__jonathanj: trie
12:33jonathanjthanks, all of those were helpful
12:33rasmustojustin_smith: oh, how should I get 'apply and (fnil intersection #{}) to behave, I won't have a nil argument if I apply that fn to nil :p
12:33justin_smithoh wait
12:34justin_smith(fnil (partial apply intersection))
12:34justin_smith(fnil (partial apply intersection) #{}) that is
12:34rasmustojustin_smith: hah, gotcha!
12:34rasmustothanks :)
12:34justin_smith(fnil (partial apply intersection) [#{}]) final answer
12:36justin_smith(defn intersect' ([] #{}) ([& args] (apply set/intersection args))) ; simpler
12:37te/whois te
12:37AimHereYouis te!
12:37te:D
12:37justin_smithoh, I just found out who te is
12:37te<-devn on a different client
12:39justin_smith"*** lazybot is logged in as Raynes" I should use whois more often
12:39tejustin_smith: im going to bug you again about visiting. have you gotten a chance to talk to anyone?
12:40justin_smithI'll bring it up again
12:42martinklepschany clever suggestion beside threadpools to write/read tens of thousands of small files?
12:42tejust read? any processing?
12:43justin_smithmartinklepsch: if they are on one disk, doing it in parallel threads will be slower than reading them one at a time
12:43justin_smiththread per disk
12:44justin_smithbecause seek time
12:44martinklepschte, read = xml parsing in that context
12:44martinklepschjustin_smith,ah thats interesting, also true for SSDs?
12:44justin_smithSSD has non-zero seek time
12:44martinklepschI guess yes?
12:45justin_smithand reading files in parallel will not be faster than sequentially
12:45justin_smithand parsing xml is much faster than getting data from the disk
12:45teclojurebot: justin_smith?
12:45clojurebotjustin_smith is sits on a throne of lies
12:45justin_smithhah
12:45te:)
12:45rasmustoheh
12:48justin_smitheven ignoring seek time, most OS's will pre-cache, so things are faster if you go sequentially through files rather than in parallel
12:48justin_smithunless you are doing something CPU heavy, xml parsing is not CPU heavy
12:52Jabberzis there a way to get the index of the entry inside a for/:let ?
12:53llasram,(for [[i x] (map-indexed vector [:a :b :c])] {:value x, :index i})
12:53clojurebot({:value :a, :index 0} {:value :b, :index 1} {:value :c, :index 2})
12:53amalloyJabberz: no; sometimes that notion isn't even well-defined, eg for a nested-loop. but you can use map-indexed at the level you're interested in
12:53rasmustoJabberz: ##(for [[i x] (map-indexed vector [:a :b :c])] [i x])
12:53lazybot⇒ ([0 :a] [1 :b] [2 :c])
12:54llasram(inc amalloy)
12:54lazybot⇒ 95
12:54justin_smithman, and I was *this close* to saying map-indexed too :)
12:54Jabberzah, thanks
12:54llasramAlways thinking about the problem slightly deeper than the rest of us
12:54amalloyjustin_smith: too slow, bro
12:54justin_smithheh
12:55rasmustoah, thoughts too deep for me o;
12:56martinklepschjustin_smith, I'm essentially splitting a large file into smaller string chunks, save them, parse them, delete them
12:56martinklepschjustin_smith it's a workaround for not being able to hand strings with paths to DTDs to xml/parse
12:56justin_smithmartinklepsch: if it is all one file system, I don't think multiple threads will gain you much, given the linearity of storage devices
12:57justin_smithwhich is why I suggested a thread per disk
12:58martinklepschjustin_smith, I got that... I just wonder if there are any other ways I could do it. But again this is probably more related to xml parsing
12:58Bronsaambrosebs: ping
12:58ambrosebsBronsa: hi
12:59amalloyjustin_smith: you could use threads a bit. like, read sequentially from the disk in one thread, putting jobs onto a queue, and have a threadpool to process items from the queue. only matters if processing is slower than disk read, of course, but that's the only case when anything at all matters
12:59justin_smithmartinklepsch: you don't need to write them if you were going to delete anyway
12:59justin_smithmartinklepsch: just make an in-memory reading source (ByteArrayInputStream)
13:00justin_smiththe disk bounce is pointless
13:00justin_smithamalloy: yeah, I tried to say that above, but probably much less clearly (when I mentioned the issue of CPU bound processes)
13:01justin_smithmartinklepsch: see first example here http://clojuredocs.org/clojure_core/clojure.xml/parse
13:01martinklepschjustin_smith, theoretically, but xml/parse takes either File, InputStream or a String naming a URI.
13:01Bronsaambrosebs: I think I mentioned this to you some time ago, but I've been thinking about putting Symbols rather than Classes on the nodes, would this be a problem for core.typed?
13:01amalloymartinklepsch: that's why he said a ByteArrayInputStream
13:01technomancybbloom: were you the one bugging me about tail calls in my forth instead of loops?
13:01bbloomtechnomancy: yup
13:01justin_smithmartinklepsch: right, you can make an input stream out of a string, as shown there
13:01bbloomtechnomancy: did you make the switch? :-)
13:01amalloytechnomancy: who else, eh?
13:02Bronsaambrosebs: not going to do it anytime soon b/c it's a bit tricky to handle reify/deftype but if I figure out an easy way to do it it *should* be a performance win
13:02technomancybbloom: no, but I just read an interview with moore about how he regrets loops in forth and how he got rid of them in his new dialect in favour of recur
13:02technomancyhttp://www.ultratechnology.com/1xforth.htm
13:02bbloomtechnomancy: yup. it's not really recur tho. it's basically just "rewrite the previous word from a call in to a jump"
13:02martinklepschjustin_smith, amalloy, the issue is that the xml to parse contains <xml version ... > a few thousand times and this obviously breaks xml/[arse
13:03bbloomtechnomancy: operating at the machine level, of course
13:03ambrosebsBronsa: which nodes?
13:03justin_smithmartinklepsch: requesting permission to use xml/arse in future jocularity
13:03justin_smithmartinklepsch: that's why you split the string, make streams of the parts, then parse those, right?
13:03Bronsaambrosebs: everywhere I now store a Class, that would be replaced by a Symbol. e.g the :class field on :static-call etc
13:03technomancymy loop implementation is pretty terrible; it requires a bunch of nasty primitive stuff
13:04technomancyI should probably get rid of it
13:04amalloyaside: am i the only one who thinks it's silly that clojure.java.io/reader interprets a string as a url, instead of creating a StringReader? like, we have java.net.URI and java.io.File to disambiguate, but if you want to treat the string as a source itself you just can't use c.j.io/reader at all
13:04justin_smith(inc amalloy)
13:04lazybot⇒ 96
13:04justin_smithyeah, that has bugged me too
13:04technomancyhaha "It would of course not be convenient to nest loops but nested loops are a very dicey concept anyway."
13:04ambrosebsBronsa: ok, it'll probably blow up some preconditions.
13:04bbloomtechnomancy: heh, indeed. he's a crazy man
13:04technomancyamalloy: oinc
13:05ambrosebsBronsa: which is fine.
13:05amalloyi just had an idea: i'll catch up to technomancy's karma by expression non-controversial opinions as if they were novel
13:05justin_smithhah
13:05bbloomtechnomancy: the other nice thing about implement ; as jump means you can do early exits of words & transfer of control
13:05arrdemamalloy: good luck with that...
13:06Bronsaambrosebs: cool. I'll let you know if/when I make that change. Not anytime soon btw
13:06llasram(inc amalloy)
13:06lazybot⇒ 97
13:06martinklepschjustin_smith, I think I've tried that before and then the parsing failed because xml/parse couldn't find the DTDs etc, maybe I need to try again ;)
13:06technomancybbloom: I'm kinda biased against early exits because of FP, but this stuff is unapologetically imperative, so ...
13:06technomancyI should probably get over that
13:06bbloomtechnomancy: yeah, you're writing the exact opposite of FP right now
13:06justin_smithmartinklepsch: you may need to do more elaborate massaging before the arsing stage
13:06bbloomtechnomancy: which is a good thing in such a context
13:06technomancybbloom: but ; as anything other than "definition over" seems to be specific to colorforth afaict?
13:06bbloomtechnomancy: turns out that a lot of the things you thought were no-nos from your C days turn out to be pretty damn reasonable in forth
13:06ambrosebsBronsa: great
13:07technomancybbloom: I didn't have C days
13:07bbloomtechnomancy: it's basically any "machine forth" which is just moore & friend's idea for a very simple minimal forth
13:07martinklepschjustin_smith, yeah, potentially prepending directory names before files and that type of stuff
13:07justin_smithmartinklepsch: I just realized how inappropriate that sounded, no harrassment intended
13:07amalloytechnomancy: apologetically imperative would be like..."look i'm really sorry, but i need you to increment the variable i. yes, i know you liked it as five, but we really need six right now, and you need to work with the team"
13:07bbloomtechnomancy: ok fine, your emacs lisp days
13:07technomancywell, more like my C days are happening now, solely in order to let me write forth
13:07bbloomamalloy: nice.
13:07martinklepschjustin_smith, all good
13:07arrdem(inc justin_smith)
13:07lazybot⇒ 33
13:07bbloomtechnomancy: haha
13:08technomancyamalloy: hehe; totally
13:08bbloomtechnomancy: it's fun when you have such a small simple core. it's almost hard to resist tweaking it endlessly
13:08ambrosebsBronsa: you should be able to edit your proposal
13:08arrdemtechnomancy: yeah... this penultimate yak shave of yours is seeming more and more like a decent into madnes.s..
13:08bbloomtechnomancy: like w/ eclj now, the semantics of clojure are expressed so sussinctly that i can clearly see every flaw b/c it's wherever an 'if occurs lol
13:08technomancyamalloy: "don't be all X is five, if five is what you mean. If five is on your mind then baby just come clean"
13:09technomancyhttp://achewood.com/index.php?date=05052003
13:09technomancyarrdem: I am not ruling it out
13:09Bronsaambrosebs: oh, huh, didn't notice that. I guess I'll just copy paste the comment in a "Milestones" section of the proposal, for consistency, then
13:10ambrosebsBronsa: Aaron unlocked it but forgot to tell you
13:10arrdemtechnomancy: it's ok tho, you can alway blame it on the atreus curse
13:10technomancyarrdem: hopefully this time no blood is spilled
13:11arrdemtechnomancy: lets hope so... I'd like to see you live to use that keyboard :P
13:12Bronsaambrosebs: ah ok, done
13:12ambrosebsBronsa: thanks
13:18acinigliois there a way to memoize a multimethod?
13:18amalloyaciniglio: wrap it in a function?
13:18arrdem*memoized function
13:18aciniglioamalloy: just the defmethod? or the whole block?
13:19amalloyif you want to memoize every implementation, then create a function that calls the multimethod, and memoize that
13:19arrdemand be sure to recur through it.
13:19amalloyif you want to memoize just one implementation, then define its method to call a function, and memoize that function
13:19amalloyarrdem: meh. you might or might not want to memoize recursive calls
13:20aciniglioyeah, that makes sense
13:20acinigliothanks
13:20justin_smitharrdem: so you mean use explicit self calls instead of recur?
13:20arrdemjustin_smith: use explicit calls to the memoizing wrapper rather than recur
13:20arrdemhalves your effective stack size tho :c
13:20justin_smitharrdem: cool, I can see how that would make sense for some reducing algorithms
13:21technomancyamalloy: can't you alter-var-root with a defmulti?
13:21amalloyuhhhh
13:21amalloyi would be super-worried about doing that. maybe
13:21justin_smitharrdem: maybe memoizing some trampolined functions would be cleaner?
13:21amalloyprobably not though, i would think
13:21technomancyI don't think you need an in-between function
13:22justin_smithtechnomancy: so you are saying you would replace the multi with its memoization with alter-var-root
13:23BronsaI recently discovered that multimethods heavy code is a pain in the ass to profile
13:23amalloytechnomancy: yeah, as i expected, you can alter-var-root it, but if you do you can't add new defmethods
13:23BronsaIt really doesn't help to know that you spend 88% on MultiFn.invoke
13:24arrdemew...
13:24amalloyBronsa: what profiler are you using? surely you can check self-time instead of total-time, or tell it to ignore time spent in MultiFn.invoke
13:24technomancyamalloy: true
13:24tbaldridgeamalloy: yeah don't redef, instead define a multimethod called -foo and then name the memoized version foo. That way you can call the right one depending on what you want.
13:24amalloytbaldridge: yes, that was my advice, though i didn't weigh in on naming
13:25tbaldridgeamalloy: I don't think each method gets named sanely though either.
13:25justin_smithamalloy: but then the situation where you want to find out where your bottleneck is, and it may or may not be the multimethod
13:25tbaldridgeThe compiler doesn't emit (foo-bar...) when you (defmethod foo :bar)
13:26amalloyi'd call it foo and foom, because how often do you get to write source code as onomatopoeic explosions?
13:27amalloythat's a good point, tbaldridge. i guess you'd have to do something pretty gross make the profiler aware of what methods are taking the time. like, have each just delegate to a function, or something. yuck
13:28tbaldridgeyeah, but I sonder if cursive integrates enough with intelij that YourKit would give good insight into this.
13:28tbaldridge*wonder
13:31hiredmanamalloy: we have this thing in our code at work call the spock-tock-lock, and sometimes things block on the spock-tock-lock, it makes for greating standups
13:32justin_smithhah
13:32rasmustohm, if I bind some stuff with :or, it doesn't get put into the :as binding thing?
13:33amalloyrasmusto: no. :as refers to exactly the incoming object
13:33rasmustoamalloy: okay, thanks.
13:34justin_smith,((fn [{a :a :or {a 0} :as m}] [m a]) {})
13:34clojurebot[{} 0]
13:34rasmustomy code is getting a bit dangerous with these optional arguments + defaults :s
13:34justin_smithrasmusto: instead of :or you can do a merge on the input, and then destructure
13:35justin_smith(fn [m] (let [m (merge default m) {a :a} m] ...))
13:35rasmustojustin_smith: I like that approach, thanks again
13:35justin_smithnp!
13:35S3thc0nI stumbled over Haskell and noticed it is 'missing' Lisp's macros. After some pondering I wonder: For which constructs are they actually >needed< (whose functionality is not already built into a hypothetical rather extensive language)? Most examples I have seen are pretty basic, and everything I tried to come up with ends being just a function. (Not that I doubt it, but I wish to know.)
13:36amalloyor provide a more spartan API, and make your clients pass the optional arguments anyway. if they don't, you can (throw (IllegalArgumentException. "This is SPARTA!"))
13:36TEttingerhaskell calls its metaprogramming "templates" IIRC
13:36technomancyS3thc0n: using macros to delay evaluation isn't necessary in a lazy language
13:36amalloyTEttinger: like lispers, i think haskellers call their metaprogramming "programming"
13:36rasmustoamalloy: make them be explicit, I think I like that
13:36TEttingerheh fair enough
13:37justin_smithrasmusto: if nothing else, you can have a strict layer with no implicit arguments or coercions, then a separate coercing layer
13:37justin_smithif nothing else that makes understanding ones own code much simpler
13:38amalloytemplate haskell exists, but it's way more heavyweight than macros. and, as technomancy says, less necessary in a lazy language
13:38rasmustoall the pieces are coming together now :)
13:39S3thc0nThat's my point: Would a lazy Lisp (just hypothetical) with the basic constructs (let, pattern matching etc) still need macros (except for when the designers abandon it and newly appeared basic features should be implemented)?
13:39amalloythe primary feature of macros is controlling the evaluation of arguments, by putting them in a different lexical/dynamic context, or by evaluating them multiple times or whatever
13:40justin_smiththat makes me think of another possible framing "macros are for doctor who's business, if you don't need to deal with alternate flows of time, or universes where things are parsed differently, you may not need them"
13:40amalloyin a lazy language, a lot of that wouldn't be necessary, but it's still nice, both for bootstrapping the language from a small set of primitives, and for letting users customize things
13:41technomancyS3thc0n: oh I see; interesting. probably the main one would be evaluating things in a different lexical context, like how the for macro's :while or :let stuff works.
13:41llasramAnd for locally reducing boilerplate
13:41bbloomamalloy: evaluating multiple times is the one that gets forgotten by lazy advocates
13:41technomancybut that's not strictly necessary; it's just map sugar
13:42llasramI think my most frequent use of macros is when I'm defining <n> of the same thing in the same place, and create a private, local macro to capture the pattern
13:42amalloybbloom: well, of course in a truly lazy side-effect-free language that doesn't matter anyway
13:43technomancyprobably heavy code-walking things like core.async couldn't be done in userspace, but I'm not very familiar with that
13:43technomancyand that's not the kind of macro mere mortals should be writing anyway, so not having that capability built-in to the language isn't a big deal IMO
13:43amalloysince evaluating an expression multiple times always produces the same result, and has no other effects
13:44bbloomamalloy: except that's not really true, hence Control.Monad.Loops
13:44S3thc0ntechnomancy: That is exactly what I was thinking of.
13:44amalloyto meaningfully evaluate something multiple times in a pure, lazy language, you need it to be a function, and pass it different args; this is roughly the same as evaluating multiple times in a modified lexical environment
13:45amalloybbloom: but those don't evalaute the same thing multiple times!
13:45bbloomamalloy: sure, they thread a state variable you can't get at through
13:45amalloyright. which means they don't need to be macros
13:46bbloomamalloy: right, but laziness is orthogonal to purity. it's just that laziness is practically impossible to reason about without purity
13:47bbloomamalloy: and you can't implement loops with laziness alone, you also need a trampoline of sorts, which in the case of haskell is provided by the runtime for monads
13:47technomancyS3thc0n: I can't think of any cases of macros you'd write in application code anyway
13:47amalloydefinitely. i guess i didn't say soon enough that i was talking about a pure language as well as a lazy one
13:48bbloomamalloy: our discussion was more for the sake of S3thc0n than either of us anyway :-P
13:48justin_smithin impure lazy lang would be kind of a fun INTERCAL style esolang actually
13:48amalloybbloom: you sound so noble! you know we were just arguing because it's fun
13:48bbloomamalloy: sshhh
13:49S3thc0nbbloom: You may very well continue, I'm extracting knowledge through that. o.o
13:49amalloybbloom: i don't understand what you mean by being unable to implement loops with just laziness
13:49justin_smithyou could have like a "supervisor" construct, that forces the default lazy functions to grudgingly process some of their inputs at a semi-nondeterministic rate...
13:49amalloyobviously tail recursion is enough to implement loops, so you must mean something i don't understand
13:49winkhm, is there an easier way for foo-bar -> "Foo Bar" than this monstrosity? (let [p (string/split (:class c) #"-")] (apply str (map (fn [x] (str (string/upper-case (first x)) (apply str (rest x)) " " )) p)))
13:50amalloywink: ##(doc clojure.string/join)
13:50lazybot⇒ "([coll] [separator coll]); Returns a string of all elements in coll, as returned by (seq coll), separated by an optional separator."
13:50justin_smithwink: camel-snake-kebab may help you?
13:50justin_smithhttps://github.com/qerub/camel-snake-kebab
13:50winkthanks both, checkin
13:51bbloomamalloy: tail recursion isn't lazy
13:52bbloomamalloy: well... i guess i can be
13:52amalloymonads certainly don't enter into it. you can write a lazy looping function without any monads
13:52justin_smithwink: oh, you would need to fork c-s-k and add a [capitolize capitolize " "] rule here for it to help you https://github.com/qerub/camel-snake-kebab/blob/stable/src/camel_snake_kebab.clj#L27
13:53justin_smithso probably never mind that - though c-s-k *should* provide that, as far as I am concerned
13:53winkhehe
13:53amalloylet f 0 = []; f x = x:(f (x - 1))
13:53justin_smiths/capitolize/capitalize/g
13:53amalloyit's the automatic thunking that makes lazily looping possible, not monads
13:55bbloomamalloy: i think you're making sense, but i'm not going to think about it too hard b/c my brain is still exhausted from yesterday
13:55amalloygoodness. what did i miss yesterday?
13:55bbloomamalloy: https://twitter.com/BrandonBloom/status/455452491304685568
13:56justin_smithyou are in a twisty maze of stack-frames, all alike
13:56bbloomGO EAST
13:56yedi_does anyone have example ansible scripts for deploying clojure webapps
13:56technomancyoh man
13:56justin_smithyour inspector has not been implemented yet, you are likely to be eaten by a Grue
13:56technomancyI started playing zork with my kids last week
13:57enquoraanyone here using clara-rules?
13:57technomancythat damn maze is like ... an object lesson in life's unfairness
13:57llasramtechnomancy: The one you solve by leaving a trail of your most precious belongings?
13:58technomancy"I went east and then west and I should be back where I started but I'm not; what is the deal" / "listen buddy, what is this 'should'? the world doesn't owe you anything."
13:58technomancy(not actually how I talk to my kids but you get the idea)
13:58justin_smithI once solved a non-euclidean self-modifying maze in a MUD by marking each room in a binary system devised of presence or absence of multiple easily found objects that could be left on the floor
13:58amalloyjustin_smith: maybe it makes sense for c.j.io/reader to interpret a string as a url, for symmetry with c.j.io/writer, which clearly can't interpret a string as anything but a place to write to
13:58technomancyllasram: right; and then sometimes the thief steals your landmarks for kicks.
13:58llasramOH RIGHT
13:58llasramI forgot that part
13:59justin_smith{:mushroom 1 :magic-light 2 :dried-meat 4} and thus mark rooms...
13:59llasramUnless you kill him first? But maybe you can't do that until later
13:59justin_smithamalloy: I can see the logic, but not the usefullness
13:59llasramamalloy: Of course, io/copy with a source string copies the string content. Fun times
14:03mikerodso, are there no functions exposed in clojure.core that would allow me to test if a Symbol resolves to a class name or not?
14:03mikerodwithout throwing an exception
14:04S3thc0nllasram: Good idea killing him, you can mark the floor with his blood and guts :3
14:04mikerodI think I see this idea @ Compiler$HostExpr#maybeClass() but it is a private method :)
14:04llasrammikerod: Why do you need this?
14:05mikerodllasram: DSL stuff
14:05mikerodllasram: fairly long story
14:05mikerodllasram: I want to fully-qualify symbols without compiling things.
14:06justin_smith,(try (resolve 'java.io.Files) (catch ClassNotFoundException e false))
14:06clojurebotjustin_smith: No entiendo
14:06mikerodllasram: dealing with the static member access via interop macros
14:06mikerod(Instant/now)
14:06ambrosebs,(resolve 'java.io.Files)
14:06clojurebot#<ClassNotFoundException java.lang.ClassNotFoundException: java.io.Files>
14:07ambrosebs,(resolve 'java.io/Files)
14:07clojurebotnil
14:07ambrosebsof course.
14:07justin_smithahh
14:08ambrosebspretty sure this is abug
14:08llasrammikerod: I think you'll probably just want to Class/forName and catch the exception
14:08justin_smithambrosebs: which behavior being a bug? the one where the class is not there?
14:08ambrosebsjustin_smith: (resolve 'java.io.Typo) should return nil I think
14:08ambrosebsresolve returns (U nil Var)
14:08ambrosebsresolve returns (U nil Var Class)
14:08llasrammikerod: Although it honestly seems like a bad idea to do a different thing w/ a symbol based simply on whether or not a class named by it exists
14:09justin_smithllasram: yeah, good point/ Class/forName is more direct than turning the string into a symbol and resolving
14:09tobani, (resolve 'java.io/Typo)
14:09clojurebotnil
14:09llasramI think it's because the symbol has a namespace, and thus cannot be a class
14:09justin_smithtobani: but that is not a class, it is a function in a nonexistent ns
14:11tobaniYeah that was me thinking "is there a Files class in java8 or...."
14:11justin_smithI should have used a more obvious typo
14:12Bronsaambrosebs: yeah it looks like a bug
14:13Bronsa,(doc ns-resolve)
14:13clojurebot"([ns sym] [ns env sym]); Returns the var or Class to which a symbol will be resolved in the namespace (unless found in the environment), else nil. Note that if the symbol is fully qualified, the var/Class to which it resolves need not be present in the namespace."
14:13Bronsashould definitely return nil
14:14bbloom,(def ^{:xx (prn 1)} f) ; whoa
14:14clojurebot1\n1\n#'sandbox/f
14:14bbloomapparently def evals the metadata!?
14:14Bronsabbloom: yeah, it's by design
14:15bbloomBronsa: interesting. why?
14:15Bronsabbloom: however it's a bug that it evals the metadata twice
14:15bbloomheh
14:15Bronsathere should already be a ticket in JIRA for that
14:15Bronsabbloom: don't talk to me about :arglists
14:16bbloomlol
14:16tpopeoh bbloom 90% of the clojure.core's in fireplace are gone now
14:16bbloomtpope: that's both great news AND bad news b/c it means i need to port my changes :-)
14:16S3thc0nWow - I just realized that with runtime macros, one could implement functions as a macro which replaces the variables in the function body's AST. And macros are special functions. Macroception?
14:16tpopeusing tricks like "eval in the user namespace"
14:17bbloomtpope: what's that mean exactly?
14:17tpopeand tricks like "who the fuck would shadow macroexpand-1 I mean seriously"
14:17bbloomlol shit. b/c i might do that lol
14:17bbloomhell, doesn't clojure.walk do that?
14:17Bronsabbloom: I don't know *why* it's evalauted though, I just know that it's explicitely stated in http://clojure.org/special_forms#Special%20Forms--(def%20symbol%20init?) that it will be
14:17tpopejesus man you're the reason I got defensive about clojure.core in the first place
14:17bbloomS3thc0n: if you're interested in "runtime macros" i highly recommend checking out a language called "Kernel" & fexprs
14:18bbloomBronsa: weird. *shrug* ok
14:18S3thc0nbbloom: Thanks for the hint :)
14:18S3thc0nI've never liked the differentation between runtime and compile time anyway :b
14:18Bronsabbloom: I guess it's convenient for :inline/:inline-arities though
14:18bbloomBronsa: i split def in to two primitive effects: :declare and :define
14:18technomancycompile time is just a subset of runtime
14:19tpopeby "eval in the user namespace" I just mean I'm assuming that you'd have to be a pretty big asshole to shadow something in user
14:19Bronsabbloom: huh? what are the benefits?
14:19ambrosebstpope: if relevant: clojure.tools.analyzer/macroexpand-1, clojure.tools.analyzer.jvm/macroexpand-1
14:20bbloomtpope: so if i evaluate an individual form, you somehow evaluate that in user? what if i'm evaluating it in a ns that has extra stuff in scope?
14:20bbloomBronsa: https://github.com/brandonbloom/eclj/blob/master/src/eclj/env.clj#L64-L73
14:21bbloomBronsa: b/c i implement it in terms of intern and intern doesn't have a way to differentiate nil from unbound
14:21Bronsalol I didn't even know intern took a val argument
14:22Bronsabbloom: makes sense
14:22tpopebbloom: individual forms get evaled with no extra wrapping
14:22bbloomtpope: they get evaluated in the current namespace tho, right?
14:22tpopethat (try (eval ...)) nonsense is long gone
14:22tpopeyeah the current namespace
14:22bbloomtpope: ok, so what if the current namespace defines macroexpand-1 ?
14:22tpopethen what the fuck is wrong with you
14:23bbloomtpope: Bronsa, ambrosebs, and i have all done that :-P
14:23amalloy,(def macroexpand-1 (partial list 'macro!))
14:23clojurebot#<CompilerException java.lang.SecurityException: denied, compiling:(NO_SOURCE_PATH:0:0)>
14:24amalloy:(
14:24bbloomfor eclj, i have to patch up eval, case, defprotocol, deftype, ns, and reify b/c all of those are basically compiler primitives in disguise
14:25rasmustoread edn from a resource (edn/read-string (slurp (resource filename))) ?
14:25justin_smithI love case for providing such a straightforward performant low level functionality, I hate it for making a special case exception for what (...) means
14:25tpopemacroexpand-1 feels like a pretty frivolous extra to worry about anyways
14:26gtrakas far as I can tell, this discussion is about fireplace eval'ing stuff. Is it an option to implement this in an nrepl middleware? We shouldn't be writing new tooling code that gets eval'd except as a stopgap.
14:26gtrakat least in theory
14:26justin_smithrasmusto: (edn/read (resource filename)) maybe?
14:26rasmustojustin_smith: edn/read wnats a pushback reader
14:26tpopelol don't talk to me about middleware mr. my middleware sends map data as lists because that makes the elisp easier
14:26justin_smithor do we need to turn resource into a reader first to make that work?
14:27justin_smith(-> filename resource reader edn/read) ?
14:27Bronsajustin_smith: reader doesn't return a PBR
14:27justin_smithnever mind then :)
14:27rasmustojustin_smith: its a bufferedReader
14:28justin_smiththere should totally be a clojure.java.io/hipster function that returns a PBR
14:28tpopeseriously the fact there's generic ops like "info" that send data hand tailored for elisp makes the whole notion a bit of a joke
14:28rasmustojustin_smith: cloblue/ribbon
14:28bbloomtpope: here's my hacks btw: https://github.com/brandonbloom/vim-fireplace/compare/master...eclj
14:28gtraktpope: I have a ticket out there to fix that :-), just backwards compatible for now b/c whatever..
14:28gtrakI haven't heard any complaints.
14:29gtrakdon't point at me! tpope: https://github.com/clojure-emacs/cider-nrepl/issues/27
14:29rasmustojustin_smith: I'll use string-pushback-reader I guess
14:29rasmustostring-push-back-reader*
14:30tpopegtrak: whew at least we're on the same page there
14:30justin_smithrasmusto: what ns is that in?
14:30gtrakI had to debug the elisp bencode implementation to get this to work at all.
14:30gtrakbelieve me, I have zero preference for elisp
14:30rasmustojustin_smith: clojure.tools.reader.reader-types
14:32rasmustojustin_smith: I might be on the wrong track here though, since slurp + memoize seemed to work OK
14:32gtraktpope: if there's any other blockers for you, you should let me know.
14:32gtrakkinda working in a vacuum here.
14:32tpopegtrak: my other piece of feedback is that you're sending absolute paths, whereas I already have classpath searching locally and would prefer to use that, because it will even work in cases like drawbridge on a remote server
14:33tpopegtrak: I get sending absolute, but could we also send classpath relative if available?
14:33justin_smithrasmusto: extra credit, have the internal function take two args, file path and timestamp, and top level function passes in the file you ask for, and its modification time
14:33justin_smiththen memoize the internal, of course
14:33gtraktpope: in that case I'd probably add an extra attribute to the response.
14:33tpopegtrak: yeah exactly
14:33gtrakI'll make an issue for it
14:34rasmustojustin_smith: hm, clojure.tools.reader.reader_types.PushbackReader isn't a java.io.PushbackReader I guess
14:34justin_smithouch
14:34tpopegtrak: I already hooked up the stracktrace and complete ops
14:34gtraktpope: I'll call it 'resource', I think.
14:35gtrakfile-classpath doesn't quite make sense
14:35justin_smith,(java.io.PushbackReader. (io/reader (io/resource "project.clj")))
14:35clojurebot#<CompilerException java.lang.RuntimeException: No such namespace: io, compiling:(NO_SOURCE_PATH:0:0)>
14:35tpopeyeah resource sounds much better than anything I can think of
14:35TimMcIs it some kind of sick joke that lein-voom is at 0.1.0-SNAPSHOT instead of a stable release?
14:35llasramnice
14:36dbellAnyone know what might cause a dirty take/put in core.async? #omproblems
14:36mikerodllasram: sorry, had a meeting...
14:36justin_smith(defn pbr [location] (java.io.PushbackReader. (io/reader (io/resource location))))
14:36justin_smithrasmusto: that function should make it easy?
14:37llasrammikerod: How dare you walk in the way of the channel dispensing sage advice?
14:37mikerodllasram: so I tried to catch up with what all was said. and the consensus is I have to try-catch a Class#forName ? booo
14:37mikerodllasram: I know, I'm sorry :(
14:37rasmustojustin_smith: yep, shaves off about 1s from the slurp + read-string version
14:37llasrammikerod: haha. I don't know about consensus -- that's just my suggestion
14:37justin_smithrasmusto: oh, nice
14:37mikerodI was surprised that `resolve` throws exceptions on me for classes
14:38gtraktpope: I think the map/list thing will be pretty easy. It's just at the top-level. I'll let you know when it's ready to go, I have to implement it in cider itself first.
14:38justin_smithmikerod: consensus is that is a bug that should be fixed I think
14:38llasrammikerod: What's so bad about catching exceptions?
14:38gtrakmake it work both ways, then pull the rug out
14:38tpopegtrak: any concerns about making the op backwards incompatible?
14:38mikerodjustin_smith: ah I see
14:38tpopeah ok
14:38llasrammikerod: If you're concerned about the class-load-initialize behavior, you can always use the form which inhibits initialization
14:38tpopeyeah I'll just hold out for the map implementation I guess
14:39gtraktpope: cider hasn't had a real release since I started on this, and the plugin remains at SNAPSHOT, too.
14:39mikerodllasram: no initialize concerns for me. try-catch control flow just always looks a bit shady to me.
14:39llasrammikerod: *shrug* When the Java standard library gives you exceptions, you make exception-ade
14:40mikerodllasram: haha, +1 putting it that way
14:40bbloomtpope: gtrak: sorry, i'm not really following this conversation right now, but i just want to add that sometimes nrepl returns errors that fireplace can't parse
14:40mikerodfor putting*
14:40bbloomi'm not sure when that happens or why
14:40bbloomtpope: it happens at .value[0] in the nrepl.vim code
14:40bbloombasically, value isn't a vector sometimes... *shrug*
14:40gtrakbbloom: yea, I'd need more detail, like a printout of the nrepl response.
14:41bbloomgtrak: i can get that, 1 sec
14:42bbloomgtrak: i get:
14:42bbloomException not caught: nREPL: namespace not found
14:42bbloomwhich is probably a mix of clojure & vim errors
14:42bbloomalso, i have a patched nrepl, so it could be me being an idiot somehow
14:43bbloomgtrak: my patch is here: http://dev.clojure.org/jira/browse/NREPL-50?page=com.atlassian.streams.streams-jira-plugin:activity-stream-issue-tab
14:44gtrakah, yea we don't do anything at all to handle top-level exceptions, emacs will just freeze when that's the case :-). Barring a general fix for that, if you have specific inputs that cause it, we can add a testcase and fix for the specific op.
14:44bbloomgtrak: seriously? sheesh.
14:45tpopethere are definitely errors that fireplace can't handle either
14:45gtrakOnce I understand the ramifications, I'll figure it out, but I'm still pretty new to nrepl and elisp :-)
14:45tpopein particular when nrepl craps out midway through serializing a response
14:45gtrakI just _really_ wanted the cljs thing to work.
14:45tpopebbloom: I don't have time to dig in now but feel free to make issues
14:46gtrakI'll add an issue for the general exception handling, I don't think there is one yet, but I've been aware of it.
14:46bbloomtpope: i only didn't file an issue b/c i don't have enough info to make a sensible bug report
14:46gtrakbbloom: should still get me the bad inputs, we should handle them if they make any sense.
14:47gtrakor often, returning nil is fine.
14:47gtrakbetter than an exception
14:47bbloomgtrak: i think it has to do w/ stack overflows in eval. basically if there is no stacktrace available, then tpope's code will do pst and gets no result to parse
14:47bbloomgtrak: returning nil is NOT FINE. that's super confusing lol
14:48gtrakbbloom: depends :-). I think it's sensible if you're asking for a var that doesn't exist?
14:48tpopebbloom: skimming your changes, it's a mixture of happily moot and merge confict
14:48gtrakor we could just implement http ;-)
14:49bbloomtpope: which parts are which? / how can i help?
14:49bbloomit's working good enough for me right now, so i probably won't bother attempting to reconcile your changes until after i get a little bit more stuff working in my own code
14:49tpopebbloom: the stacktrace stuff is hopefully moot. that's where I just evaled in the user ns
14:49tpopebbloom: one off runner definitely moot
14:50tpopebbloom: oh and for stacktrace you can just provide a stacktrace nrepl op
14:50tpopematching the cider nrepl one
14:51bbloomtpope: i can?
14:51bbloomtpope: honestly, most of this stuff is only your problem b/c nrepl is not as general purpose as promised
14:51tpopewell if you provide one fireplace will use it
14:52tpopecan't really speak to your abilities
14:52bbloomi didn't write nrepl :-P
14:52gtraktpope: bbloom: I've had similar problems recently with collisions between our own stacktrace stuff and the CLJS setup. still thinking about it.
14:52gtraklike.. somehow the browser JS engine ends up evaling clojure pst code :-).
14:52gtrakand totally screws up the repl.
14:53bbloomgtrak: yeah, clj + cljs + eclj = enough differences to design sensible enhancements
14:53gtrakI'm guessing that's because it's trying to eval it on the actual repl session instead of the tooling session to take advantage of dynamic vars *e.
14:53gtrakthe answer is, don't eval.
14:53gtrakhence why I jumped into this :-)
14:53bbloomgtrak: for stack traces?
14:54bbloomthe whole damn point is that i wrote a fucking eval function! :-P
14:54gtrakah, well, that might be interesting.
14:55gtrakYou're saying you want eclj eval with nrepl?
14:55tpopemy use of eval is way down and once the info op is stable it'll basically just be frivolities
14:55gtrakmaybe you should look at how piggieback implements it for cljs: https://github.com/cemerick/piggieback/blob/master/src/cemerick/piggieback.clj#L126
14:56gtrakwell, it's somewhere in there
14:56bbloomgtrak: i shouldn't need to write a plugin to swap out a single function. that's just silly
14:56tpopeeval for macroexpansion seems pretty benign for example. it's basically just a shortcut to type out (macroexpand-1 ...) for you
14:56tpopewe're not evaling to query, just helping the user to interactively eval
14:57bbloomtpope: i know that fireplace does macroexpand, but for some reason i never use it... probably should
14:57tpopeI don't really use it either
14:57bbloomhere i am, typing out macroexpand like a sucker
14:57gtrakbbloom: 'eval' is an op in nrepl, it's more complicated than that, but yea I guess you could use whatever to call a function.
14:57gtrakthe nrepl eval supports interruption and some other stuff
14:57bbloomgtrak: clojure.main/repl has an eval argument, so i supply it :-P
14:57bbloomseems to work for me
14:59gtrakI'm not sure I understand the use-case, but that won't be first-class in nrepl terms.
15:00gtraki mean, you wouldn't want to replace clojure's eval for the whole process.
15:00gtrakunless you do, but that sounds bad
15:01bbloomgtrak: i changed fireplace to look at the file extension. if it's clj, it does nothing different. if the ext is eclj, then it passes :eval 'eclj.core/eval
15:01bbloomthat's all
15:02Bronsajustin_smith: mikerod btw I opened a ticket for the ns-resolve bug
15:02mikerodBronsa: awesome, I'll watch that one
15:03sverihi, I am trying to parse some datomic data, especially the instant type, which comes as a standard date string. From the server I get some edn back, but when I try to display the date I see nothing, not even an error, however, it works with different attributes: this is the code: http://pastebin.com/VP1yQjRZ
15:04gtrakbbloom: ah, ok. weird :-). does fireplace use that for something?
15:04bbloomgtrak: no. i'm writing a clojure interpreter
15:04bbloomgtrak: and i wanted it to work in vim
15:04bbloomand now it does w/ my various patches/hacks
15:05amalloysveri: i mean, you're trying to embed a time/date object into your dom. presumably you want to format it as a string of some kind
15:05sveriamalloy: are there helper functions in cljs available for this?
15:06amalloyalso you seem to not be passing enough args to map? like, your paste is missing stuff. you have (apply dom/div nil (map #(...)))
15:07sveriamalloy: i left out the calls around that are not needed for the paste, however, calling a different keyword on the map it works as expected
15:08gtraktpope: is the map thing only an issue in the response, or the request, too?
15:09bbloomBronsa: ok eclj now evaluates var metadata... ONCE :-)
15:09tpopegtrak: I would much prefer to send a map for associative data, yes. I don't remember noticing any ops that forced me to send lists
15:10gtraktpope: yea, I just haven't traced the request code yet, somehow it magically ends up as a map once it hits my middlewares :-).
15:10gtrakbut I'm not sure what it starts out as
15:11tpopeso the top level structure seems to always be a map. I don't think any cider-nrepl ops take a nested structure?
15:11gtrakyea, I don't think there's a reason for it yet
15:12gtrakbut arglists at least is an example of some nested data
15:12gtrakin the response
15:12tpopeoh yeah that. I'm wondering if that might be better sent as a string?
15:13tpopeI mean it depends what you want to use it for, but the only use case I have is display
15:13gtrakI'm back and forth on that. elisp ends up reading it, but it's a bit weird, since [] encodes as nil. I was thinking of adding an arglists-str attribute too.
15:13tpopeyeah maybe both is the safe bet
15:13whodidthisany idea how to add index to maps in a vector like [{:t :a} {:t :c}] -> [{:t :a :index 0} {:t :c :index 1}]
15:14amalloy&(doc map-indexed)
15:14lazybot⇒ "([f coll]); Returns a lazy sequence consisting of the result of applying f to 0 and the first item of coll, followed by applying f to 1 and the second item in coll, etc, until coll is exhausted. Thus function f should accept 2 arguments, index and item."
15:15whodidthiswhoa, clojur has everything, thanks
15:16tpopegtrak: how are you formatting docs over in emacs? just stitching togethr the symbol, arglists, and doc string by hand?
15:16tpopewith an arglists str that's pretty straightforward
15:17btcNeverSleepswhen using clojure.test, is there an easy way to shortcut out of a deftest as soon as on test fails? e.g. I'd like (deftest test-ff (is false) (is false)) to report only one failure, not two.
15:17btcNeverSleepss/as on/as one/
15:18gtraktpope: it actually uses the data.
15:18gtrakit used to 'read' the string.
15:18gtrakbut that's an elisp read on clojure data (eww..)
15:19tpopeyeah sounds treacherous
15:20gtrakso, we got rid of the 'read' just a couple days ago, now I'm going to add the string representation back for you :-)
15:20gtrakthere's still some work to be done, the cljs arglists end up looking weird, I have to figure that out.
15:21gtraklike '([113 117 111 116 101] [(coll k v) (coll k v & kvs)])'
15:21gtrakfor assoc
15:21gtrakum.. come to think of it, pretty sure that first one is quote
15:22gtrak(map int "quote")
15:22gtrak,(map int "quote")
15:22clojurebot(113 117 111 116 101)
15:22gtrakhaha
15:22tpopebrilliant
15:27hyPiRiongtrak: I know how you just knew by looking at the decimal representation
15:27hyPiRion/s/know/love/
15:28gtrakhehe, tbh I'd seen it quoted before a couple months ago, just made the connection (five of them).
15:37gfrederickspeople who like non-namespaced maven artifacts: my build just broke and you're all individually responsible
15:38llasramgfredericks: I apologize for the mistakes of my past selves
15:39gfredericks(inc llasram)
15:39lazybot⇒ 21
15:43hyPiRiongfredericks: like, unnamed packages?
15:43gfrederickshyPiRion: no like [foo "0.1.0"]
15:44hyPiRiongfredericks: oh, you're welcome then
15:57xeqigfredericks: I'm interested to hear more
15:58gfredericksxeqi: somebody internally made a clojure library named [foo "0.1.1"] and put it on our internal maven repo
15:58justin_smithlol
15:58gfredericks6 months later an OSS organization decides they like that name too
15:58gfredericksso they put [foo "0.1.1"] on clojars
15:59xeqihaha
15:59justin_smithI hope the package was actually called foo
15:59justin_smithlike literally
15:59technomancysolution: never use libraries that aren't oss
16:00bbloomjustin_smith: the new version of the package is foo.bar version 3.1.4
16:00gfredericksjustin_smith: it wasn't
16:01gfredericks$latest foo
16:01lazybotNo project by this name exists on clojars.
16:01xeqigfredericks: becareful, the foo on clojars might of had secret compiled code that uploaded everything on your hardrive to some hackerz server
16:02technomancyseriously, with all the hassle around private repositories it's really a wonder that anyone bothers writing libs that aren't OSS in the first place
16:03pjstadiggfredericks: maybe you shouldn't have had an internal library named foo, and instead one called namespace/foo :-p
16:03xeqinot that namespacing the internal one prevents someone from using the same group/artifact combo in a public server
16:04pjstadigif namespace == [YOUR COMPANY'S DOMAIN NAME] probably not likely
16:04gfrederickspjstadig: yes I agree and that's how I fixed the issue
16:04gfredericksI didn't decide to name it that in the first place
16:04pjstadigbut naming things in a global namespace is hard
16:07justin_smith(defproject `(symbol (str (java.util.UUID/randomUUID) / "project-name")) ...)
16:08gfrederickstechnomancy: I think we have some people that use the private repo for app deployment
16:08pjstadigYES!
16:08turbofailshouldn't that be a ~?
16:08justin_smithturbofail: yeah, also / should have been "/" or \/
16:09technomancygfredericks: I've seen people do that but do not understand the motivation at all
16:09technomancyI guess if you have regulatory concerns about S3 or something?
16:10justin_smithturbofail: also, the unquoting does not kick in until after the version number, it was a mock suggestion so whatevs
16:10gfredericksor availability? I dunno
16:10gfrederickstechnomancy: some companies might consider amazon to be a competitor :P
16:11technomancyit takes a lot of hubris to think you can do better than S3 though
16:11justin_smithbecause we need to keep all the client's private credentials in a clojure library as plaintext
16:11turbofaillol
16:11justin_smithand a private repo keeps that safe, right? /s
16:11gtraktechnomancy: I don't think that's what he's saying..
16:11arrdemin registers, everything is plaintext
16:11pjstadigjustin_smith: they use https, so by definition they are safe
16:11gtrakit doesn't take hubris to not give a competitor control over stuff you care about :-)
16:11justin_smithoh, yeah, I forgot
16:12technomancygtrak: meant re: availability specifically
16:12justin_smithcarry on then
16:12arrdempjstadig: low blow
16:13gfrederickstechnomancy: the more datacenters it takes to deploy your app...
16:13technomancygfredericks: still though, why not just scp or something?
16:14technomancyall the repository-specific logic isn't being used for single uberjars
16:14gfredericksno idea
16:14gfrederickssetting up a private repo is still good for redundancy though
16:14technomancysure, as a cache
16:14gfredericksright
16:15technomancyI guess if you already have it up as a cache, it's not much additional extra complexity
16:15technomancybut it's complecting caching and publishing zomg
16:15justin_smiththat's been traditional for analog publishing
16:15technomancy(protip: easy way to convince clojure users something is a bad idea: accuse it of complecting)
16:16justin_smithtechnomancy: that's complecting good programming advice with social engineering advice
16:16technomancyoh noes
16:16TEttingertechnomancy: I've linked people to the keyboard pants concept after they said they'd paid $200 for a keyboard
16:17technomancyTEttinger: hehe; nice
16:17technomancyFWIW I haven't been doing that recently, but maybe there is more research to explore in that field
16:18TEttingerI wonder if you could use similar technology to those laser keyboards and track finger movement directly
16:18TEttingerkeygloves
16:19technomancynah, typing without tactile feedback is a nightmare
16:19TEttingerwho said no tactile feedback?
16:19TEttingeryou could have a pad at the fingertip
16:19justin_smithtechnomancy: easily fixed the way cellphones do it: install a vibrator in the pants
16:19rasmustoI want haptic gloves
16:19justin_smithtechnomancy: bonus, secondary market :)
16:20technomancyTEttinger: maybe if you cloud vary the strength of the feedback based on hew far from the center of the "key" you struck
16:21amalloyi wonder what cyborglovesystems.com would be like
16:22justin_smithdepends where you break the words
16:22justin_smithcyborg love systems
16:22rasmustohaha
16:23amalloythat's really the only sensible place to break the words, which is why i thought it was funny
16:23rasmusto(inc amalloy)
16:23lazybot⇒ 98
16:38TimMchagelborglovesystems
16:39rasmustoha! gel borglo vesys tems
16:40Bronsalol
17:02blake__Is there a preferred way to indicate a function parameter when the function has a specific, known task (as opposed to being highly abstract). Like, if I need a function that foos bars, should I code the formal parameter as "bar-fooer-fn" or "bar-the-foo" or...is there a "best practice" here?
17:03justin_smithblake__: I typically just call it f
17:03justin_smithand make sure my comment and code are clear as air
17:03blake__'k.
17:04justin_smithactually - maybe "half the time" - if there is an extremely straightforward name, I just go for that
17:04justin_smithlike if it describes something that stores data, I call it "save"
17:04justin_smithI like to name it the verb, and not "doer of the verb"
17:05blake__but also not "verb-the-noun"...
17:05justin_smithno
17:05justin_smithbut that is style of course, I am sure there are many good ways to do it
17:06bbloomblah-fn is common when you want to differentiate from blah the macro
17:06blake__Sure. I'm not gonna marry it, I just don't want to bring over some other language-style, like nounReceiveVerbWhenDesired.
17:07devthtwi
17:07blake__bbloom: Good tip, thx.
17:07devthmt
17:07TimMcdevth: Are you a cat?
17:07mdrogalisHahah.
17:07mdrogalisThat took me a sec. :P
17:08amalloyone example of a bad way would be to name it after the type signature it would have in haskell. (defn frobnicate [data lparen_a->b->a_rparen->a->lsquare_a_rsquare->a] ...)
17:08devthTimMc: nope, alfred user trying to switch to twitter window :)
17:09blake__amalloy: I can't even.
17:09amalloyhey, where does the "mt" acronym for like "oops, wrong channel/window/person" come from?
17:09devthmistell
17:09TimMchuh
17:09amalloyokay. that's what i guessed, because i'd only seen it in games before. but then you brought it here
17:09rasmustowtb a better irc client, pst
17:10devthi figured it was appropriate in irc
17:10technomancyhttp://nedroid.com/2012/07/b-r-webcoms/
17:10TimMcI wonder if I could set up irssi to require me to type /say in front of messages.
17:10justin_smith(inc rasmusto)
17:10lazybot⇒ 7
17:10BronsaTimMc: that would be horrible to use.
17:11justin_smithcast fireball TimMc
17:11justin_smith:( didn't work
17:12amalloyBronsa: he would add a keyboard macro to automatically prefix with /say
17:12TimMcprolly
17:13blake__Ultimately, probably ending up defeating the purpose...
17:13oskarthWhat's a good example of simple error handling in a Clojure library interacting with an API? Looking for good patterns I should adopt
17:14gtraksimple: happy-paths-only programming :-)
17:14llambdaare there any best practices around testing om apps? (even cljs in general, for that matter)
17:15justin_smithoskarth: this may seem like a non-sequitor, but always name anonymous functions
17:15justin_smith(fn name-you-see-in-the-stacktrace [& args] ...)
17:15oskarthgtrak: definitely
17:15justin_smithmakes figuring out what you broke so much easier....
17:16oskarthFor example if I call a GET I might get three types of errors. The request might be malformed, I might lack access, the resource might not exist etc. How to uniformly report and propogate this in a sane manner?
17:16oskarthtrue, good one
17:16justin_smithif only I could "name" comp - how hard would it be to make comp produce an anon fn with a name derived from the names of its args? is that totally absurd?
17:16gtrakoskarth: in our compojure api, I just slingshot throw an exception with the status code as part of the map, can pattern match on that if I feel like it.
17:17oskarthRight now I'm doing a cond for the different "levels" of error and returning a heterogenous map with an error key with optional details
17:17justin_smithslingshot rich exceptions are pretty cool, yeah
17:17oskarthwhat does slingshot throw an exception mean?
17:17gtrakI've got a middleware to catch and modify them, too
17:18gtrakoskarth: well, actually you can use ex-info instead of slingshot for the throw side.
17:18justin_smithoskarth: slingshot lets you attach arbitrary clojure data to exceptions, that the one catching it can use
17:18oskarthoh, it's a library?
17:18justin_smithyeah
17:18gtrakslingshot can pattern-match the data on catch, yea.
17:18gtrakex-info's built into clojure
17:18gtrak,(ex-info {:a :b})
17:18clojurebot#<ArityException clojure.lang.ArityException: Wrong number of args (1) passed to: core/ex-info>
17:19gtraksee? it exists ;-p
17:19devnwhoa. i hadn't seen the "Promote" button on clojars.
17:19justin_smithit's not a great way to do general purpose programming since exceptions are expensive and in the jvm truly are designed only for exceptional conditions, but it definitely beats switching on the type of the exception or something
17:19gtrak,(ex-info "Message" {:a :b})
17:19clojurebot#<ExceptionInfo clojure.lang.ExceptionInfo: Message {:a :b}>
17:19oskarthwhat about "sane" errors, ie external ones? sometimes they are in a json body, and sometimes they are just in a "not authorized" response, any getting around cond-handling that?
17:20justin_smithoskarth: design the api to always return a map including error code and optional message, with a convenience function for the common "barf on it if it is weird" option
17:20oskarthslingshot looks interesting though
17:21oskarthjustin_smith: it's not necessarily my API ;) but yeah, something like that is what I'm doing right now
17:21oskarthbut manually constructing the map when it doesn't exist
17:22gtrakif you're just throwing stuff, I don't think slingshot actually helps you
17:22oskarthit seems like a lot of special case analysis though, with all the cond, and then higher up dealing with it in different ways
17:22oskarthnot sure what the shape of something better would look like
17:22gtrakin the impl of the lib, you don't need it, might be convenient for clients to use it
17:23oskarthsome kind of rules system?
17:24gtrakas a lib user, in practice, I don't handle every error case, just the ones I'm interested in.
17:24justin_smithoskarth: maybe a multimethod or protocol for the returned data, and the client defines the implementation that is called in each error state?
17:24oskarththats true
17:24oskarthjustin_smith: do you have any examples of code using such a pattern?
17:24justin_smithwith sane defaults provided of course
17:24justin_smithhmm...
17:25gtrakjustin_smith: how is that better than just wrapping the call? a little more obvious, imo.
17:25justin_smithI don't know that I've seen it, it was just an idea of how it could be done?
17:25oskarthseems reasonably, if I want to get a user and the thing I get back does not satisfy being a user, it might satisfy being a malformed request or something, and then it can be dealt with on a differnet level
17:25justin_smithgtrak: in a try block you mean?
17:25gtrakyea
17:26gtrakor just funnel stuff into a common function
17:26gtraknot necessarily a try-catch every time you use it
17:27gtrakI guess, why worry about being clever here? I don't get it. if the data's available in a convenient way, that's enough.
17:27oskarthright now I have a handle-error function which creates a map for various cases
17:28justin_smithgtrak: I guess my motivation with the multimethod / protocol defining was that this way the client does not have to worry about the control flow (which is a common source of bugs, and could easily be defined once by the lib), and instead just implement each of the known possible cases
17:28justin_smithwhich could be a win for clarity overal
17:28oskarthhaving a protocol for the returned data is something I'll look into
17:29gtrakbut that's global.. I'd probably just do a default impl that throws an exception :-)
17:29justin_smithoskarth: I didn't mean a protocol for the returned data, but a protocol defining the handlers that would be used on that data
17:29gtrakthen you've got the issue of defining what exactly the protocol handles and doesn't handle. I'd want to see everything I could.
17:29justin_smithahh
17:29oskarthhm
17:30gtrakie, don't define spurious abstraction boundaries.
17:30oskarthI think a code example of something which has nice error handling/flow would be most useful at this point, if anyone knows of any
17:30oskarthyeah I see that point
17:33gtraknice is when I can easily see everything I want to see, clj-http is pretty good at that. https://github.com/dakrone/clj-http/blob/master/src/clj_http/client.clj#L143
17:33dakrone\o/
17:33justin_smithgtrak: I think you are right, I was trying to overengineer it
17:34gtrakdakrone: but I wonder if slingshot is necessary anymore :-)
17:34justin_smithalso agreed, once i figured out how it worked, clj-http was nice
17:34dakronegtrak: hmm.. when was ex-info added again?
17:34gtrak1.4 I think?
17:35gtrakya
17:35dakronehmm... wonder if it's time to drop 1.3 support
17:36gtraki guess it's not hurting anything
17:37technomancyit'd be cool to see "how long did you take to upgrade" numbers for various clojure versions in the State of Clojure survey
17:37technomancyI suspect 1.3 would score pretty low
17:37gtrakjustin_smith: I guess my biggest criticism of multi-method/prot is simply action-at-a-distance
17:38gtrakyou end up splaying the dependency across your codebase, without the normal benefits of those things (extending existing/closed types)
17:49blake__How does one rename a lein project? Do I just manually go through and change all the directory and filenames?
17:50hiredmanblake__: depends what you mean by rename
17:50hiredmanblake__: if you just want to change the artifact name in maven, just make the change to project.clj
17:50hiredmanif you want to keep the artifact name but change the namespace names, move the files and change the ns forms
17:50hiredmanand of course you can have various mixes of the two
17:50blake__I did a "lein new aproject" when I should've done "lein new bproject".
17:52hiredmanif it is a brand new project you may as well just delete the typo and lein new again with the corrected version
17:52devthblake__: i like ack -l 'pattern' | xargs perl -pi -E 's/pattern/replacement/g'
17:52blake__So I have to go into project.clj, change "def project aproject" to "def project bproject" and ":main aproject.core" with ":main bproject.core".
17:52blake__hiredman: Yeah, not new.
17:52blake__(I've done that a lot =P)
17:52hiredmanblake__: it realyl depends
17:53blake__devth: Thanks, I'll try.
17:53hiredmanwhat are you trying to achieve
17:53hiredmanthere are lots of orthogonal names that lein new generates
17:53blake__hiredman: Well, exactly the same thing I would've gotten had I done it right. I think it's just the project.clj and the core.clj?
17:53blake__hiredman: But I take your point; probably why there isn't a "lein rename".
17:54justin_smithin emacs you can do M-x rgrep to get hyperlinks to every usage of a regex within some directory subtree
17:54hiredmanblake__: so you want to change the artifact id and all the namespaces
17:54justin_smith(then follow and edit, followed by renaming applicable files)
17:55blake__hiredman: yeah, I think so. I'm not sure what an "artifact" is.
17:55hiredmanyou might try using https://github.com/clojure/tools.namespace/blob/master/src/main/clojure/clojure/tools/namespace/move.clj to automate renaming namespaces
17:55hiredmanblake__: the artifact id is the name of the artifact in a maven repo
17:55blake__justin_smith: Fie upon your emacs!!! (I'm getting there. Slowly. Right now I'm doing a combination of "edln" and smoke signals.)
17:56amalloyi just found https://github.com/dakrone/cheshire/blob/master/src/cheshire/generate.clj#L67-L69 - can anyone think of a reason it might have been done this way, before i send a pull request to use (name k#)?
17:56justin_smithblake__: I am pretty sure sublimetext has a similar feature, vim may also
17:56blake__justin_smith: "edln" does not. =P
17:57hiredmanamalloy: it may be for backwards compat
17:57justin_smithamalloy: also wanting the namespace part?
17:57hiredmanamalloy: name used to throw on strings
17:57justin_smith,(name :foo/bar)
17:57clojurebot"bar"
17:57amalloyhiredman: wow, really? that must have been before 1.2, which is when i showed up
17:57rasmusto,(str :foo/bar)
17:57clojurebot":foo/bar"
17:57justin_smith,(.substring (string :foo/bar) 1)
17:57clojurebot#<CompilerException java.lang.RuntimeException: Unable to resolve symbol: string in this context, compiling:(NO_SOURCE_PATH:0:0)>
17:57amalloyi'm pretty sure cheshire isn't that old anyway
17:57hiredmanamalloy: I could be mistaken
17:57justin_smith,(.substring (str :foo/bar) 1)
17:57clojurebot"foo/bar"
17:58justin_smithI don't know if the different behavior with namespaced keywords is intented, but that would definitely change
17:59amalloyyeah, the a/b stuff looks like the only difference, and probably an important one
18:11amalloyhm, i'm having trouble following the locals-clearing here. it seems like https://www.refheap.com/347dfa4f9706149b049631c34 should be able to run in constant memory, but if i actually run it that's not what happens. i think this is because when it seqs over my map, each k/v entry holds a reference to the whole map
18:11amalloyis there a clever way i can use cheshire to do something like this, or do i have to do it by hand, like manually write "{x: 100, xs: " and then ask cheshire to write the object, and then write "}"?
18:13dnolen_amalloy: I don't see how that could work, there's no local to clear since the root of sequence is in the map and the map needs to be written.
18:13dakroneamalloy: see my experiments with doing that for a string field here: https://github.com/dakrone/cheshire/blob/master/src/cheshire/experimental.clj
18:14amalloydnolen_: if the large object (here, xs) were the very last thing in the map, you could un-reference the map before you start writing xs
18:14amalloyor even, perhaps, dissoc :xs from the map before you start writing it? that seems like it should work even ignoring field ordering
18:15dnolen_amalloy: yeah dissoc'ing would work, wasn't clear you could do this in your case.
18:16amalloydnolen_: well, i mean cheshire could do that. in order to write m, first dissoc x, then write the value of x; then dissoc xs and write the value of xs; then discover that the remaining map is empty
18:16amalloythat is, instead of seqing over the map, you recurse on it until it's empty
18:17justin_smithmaybe a reduce?
18:17justin_smithno, never mind
18:19dnolen_amalloy: hmm, yeah seems like that would work? though honestly I'm surprised it doesn't just work if they seq the map first
18:20amalloydnolen_: if you seq the map first, every entry in the map has a reference back to the root, right? and even if your "large" field is last, there's a thunk after it, which discovers that the map is actually nil so there's no work left to do
18:20amalloyi'll put together a prototype and see if it improves behavior for my test case
18:21justin_smithwhat about (map vec {...}) ?
18:21amalloydakrone: still holds onto it all, in the seq produced by map
18:21amalloybecause the first thing map does is seq it
18:23justin_smith,(into [] {:a 0 :b 1})
18:23clojurebot[[:b 1] [:a 0]]
18:23justin_smithmaybe not
18:25dnolen_amalloy: ok yeah I don't dissoc'ing is enough, you have to know that the original map is going to get collected.
18:25amalloydnolen_: sure, whoever's above you has to not be holding onto the map as well
18:26dnolen_yeah
18:26dnolen_seems brittle
18:26amalloydissoc is necessary but not sufficient
18:27amalloybrittle seems a bit strong. cheshire should hold onto the object as weakly as it can (which should be enough to permit streaming output, i think); then it's your fault if you hold on too tightly as a user of cheshire, and you can fix it
18:27dnolen_amalloy: interesting, you could avoid this by cloning the value before printing it
18:27amalloycloning, huh? how does that help?
18:28amalloyoh, in the user/client code
18:28amalloymaybe. i don't think it's actually necessary, but i'll finish my little proof of concept and see
18:28dnolen_amalloy: when you encounter a value if it's a lazy sequence / range you copy all the fields into a new thing first
18:28dakroneamalloy: interested in the results, lemme know how it goes
18:29dnolen_amalloy: you don't have clone in CLJ, but with-meta nil serves the same purpose
19:45rhg135hello everyone, is it just me or is the :nodejs target broken? keeps on saying cljs.nodejs being provided twice, i've tried 0.0-2202 and 0.0-2197 thanks
19:46dnolen_rhg135: gist of your project.clj
19:46rhg135k
19:48rhg135dnolen_, https://gist.github.com/rhg/10690590
19:49dnolen_rhg135: that doesn't include any :build settings
19:49rhg135i'm building at the repl, dnolen_
19:50dnolen_rhg135: you still need to supply build settings
19:50rhg135(cljs.closure/build "server.cljs" {:optimizations :simple :target :nodejs :output-to "server.js"})
19:51dnolen_rhg135: in server.js do you see the nodejs ns provided twice?
19:53rhg135it won't output anything but the shebang with :target
19:55dnolen_rhg135: k, I can't look into this at the moment, I suggest bringing it up on the ClojureScript ML asking if someone else has encountered this with exact steps to repro.
19:56rhg135ok, dnolen_ wasnt sure if it was just me
19:58dnolen_rhg135: you might want to try :optimizations :whitespace to check if the offending namespace is actually provided twice
19:59amalloyso dakrone, i wrote https://github.com/amalloy/cheshire/commit/ee81c68986a55c06a43753e423c42596fe0b66d4, which has a few issues. (1) it doesn't work for java.util.HashMap, since it uses dissoc. you'd need a special case there. (2) i can't actually tell if it worked. in all my trials i don't see objects being held onto by cheshire, but they're still being held onto by swank somehow(???)
20:03dnolen_rhg135: fwiw can't repro w/ cljsbuild, helpful if you create a minimal repo with the problem that I can look at, thanks.
20:05rhg135hmm interesting ok
20:10amalloydakrone: i see that you have some stuff in cheshire.generate that takes a JsonGenerator, which i imagined that i could use: create a generator, write some stuff to it, then write some more - so that i can try managing the gc reachability of my own objects
20:10amalloybut you don't expose a way to actually get a jsongenerator
20:11hiredmanamalloy: I wonder if it would be behave differently if it was a hash-map instead of an array map?
20:12amalloyhiredman: probably not. i think seqing over either of those maintains a pointer to the top-level map
20:12amalloybut my patch makes it not keep a handle on the seq anyway, so it shouldn't really matter
20:15seangrovebbloom: Was it you talking about a debugger visualizing events traveling up the component tree?
20:15seangroveSome time ago
20:16persesif i have empty graph G, and i want to do this, and want to add 1, 2, 3 one by one to g, my technique is: add-nodes (add-nodes (add-nodes G 1) 2) 3, add-nodes G node will return a new graph with nodes, how can i implement this?
20:18arrdem,(doc alter)
20:18clojurebot"([ref fun & args]); Must be called in a transaction. Sets the in-transaction-value of ref to: (apply fun in-transaction-value-of-ref args) and returns the in-transaction-value of ref."
20:19arrdem,(doc dosync)
20:19clojurebot"([& exprs]); Runs the exprs (in an implicit do) in a transaction that encompasses exprs and any nested calls. Starts a transaction if none is already running on this thread. Any uncaught exception will abort the transaction and flow out of dosync. The exprs may be run more than once, but any effects on Refs will be atomic."
20:20arrdemsmelly code smells
20:22rhg135dnolen_, this is WEIRD, https://github.com/rhg/htmlscript actuall compiles now
20:25persescan anybody help?
20:26crocketCan clojure be used as a systems programming language yet?
20:26cespareIf I find myself using update-in with a length-1 vector is there some other function I should be using instead?
20:27gfrederickscespare: not in clojure.core; various util libraries define update
20:27gfredericksI use prismatic/plumbing
20:27cesparegfredericks: ok thanks
20:29bob2crocket, no
20:29arrdemcrocket: define "
20:29arrdemsystems"...
20:30crocketA language in which to write linux utilities and OSes.
20:30rhg135no
20:30arrdemand it may never be...
20:30rhg135the jvm isnt even a dep
20:30dbaschI have a rest API built using compojure. What’s the easiest/standard way to type-check the parameters on the server and create standard error messages (e.g “parameter X must be [type])?
20:31technomancycrocket: you'd be better off with racket or ocaml
20:31crocketracket?
20:31arrdem$google racketlang
20:31lazybot[The Racket Language] http://racket-lang.org/
20:31technomancyassuming your goal is "FP systems"
20:31rhg135or c
20:31technomancy...
20:31arrdemrhg135: please... no...
20:31rhg135assuming you like pain
20:31crocketIt seems rust will replace C if it is lucky.
20:31arrdemrhg135: we point people at Rust. Not at C. C needs to die.
20:32gfredericks~C |needs| to die
20:32clojurebotc'est bon!
20:32rhg135agreed, but c will always be great self-harm
20:32technomancyC is perfectly cromulent...
20:32technomancyfor people writing code that needs to run on microcontrollers
20:32technomancy...assuming those people are allergic to forth
20:32arrdemrhg135: I mean if you want a sufficiently large shotgun with which to remove that pesky leg of yours...
20:33arrdemor landmine...
20:33rhg135exactly arrdem !
20:33arrdemor artilery piece..
20:33crocketNo
20:33crocketWe need artificial general intelligence that writes programs instead of languages.
20:33arrdemcrocket: but you could remove it so elegantly with a 155mm shell...
20:33arrdemareyoufuckingkiddingme.jpg
20:33crocketWhy do we toil on writing programs ourselves?
20:34arrdembecause for four generations of researchers we haven't built an AGI
20:34arrdemso this I say to you
20:34arrdemcrocket: http://arrdem.com/i/shoo.gif
20:34crocketarrdem, Fortunately, this time around, hardwares are about to emulate human brain.
20:34crocketMoore's law caught up with us.
20:34arrdemcrocket: you believe that, if it gives you comfort.
20:35rhg135arrdem, i worked on https://bitbucket.org/rhg135/nice for a friend once, i havent recovered
20:35arrdem^ Mr. Bennit, Pride and Predudice, Jane Austin.
20:35crocketarrdem, Humans will probably emulate human brains around 2030.
20:35crocketWith super computers.
20:36arrdemcrocket: great. call me in 14 years when you still can't build a sufficiently high resolution scanner to fulfull Ray's grand vision.
20:36arrdems/14/16/g
20:36crocketarrdem, destructive brain scanning might be there around that time.
20:36crocketIt means slicing a dead brain into sheets and scanning it.
20:37arrdemcrocket: thank you, I'm sure everyone else in this channel has read The Singularity Is Near as well.
20:37crocketarrdem, Just a probable timeline.
20:37crocketmight happen or might not.
20:38timsganyone know offhand where the logic for clojure’s basic repl lives?
20:38arrdemunfortunately, this means that we have another 16 years of using handtools as master craftsmen before we can build an "A"GI to do the job better.
20:38arrdemtimsg: clojure.repl?
20:38crocketarrdem, yes at least 16 years.
20:38crocketlong enough for my career.
20:38hiredmanclojure.main and clojure.repl
20:39arrdemcrocket: did you have a question or are you just being offtopic.
20:39crocketarrdem, I was just off topic.
20:40crocketarrdem, I just want to be lazy.
20:42dbaschTo rephrase my question: I have a json api, so I get my parameters from the json-params map, and they are typed. I’d like to have a wrapper that type-checks them according to the spec for each call, and returns a 400 error if the types are not right. Does such a thing exist, or do I need to build it?
20:42seangrovedbasch: Check out prismatic's stuff. I don't know how it works with the compojure routing system though.
20:43dbaschseangrove: you mean fnhouse?
20:43seangroveYeah, that and Schema
20:44bob2you could use it with liberator
20:44bob2if you have the patience
20:46dbaschseangrove: this guy is doing it with schema https://github.com/metosin/compojure-api/
20:46dbaschthere should be one preferred way to do these things though
20:47crocketarrdem, How good is clojure compared to other general purpose languages?
20:47seangrovecrocket: ~7ish
20:47crocket7ish?
20:47seangrovecrocket: Often times blue though
20:47timsgarrdem, hiredman: thanks
20:47dbaschbob2: liberator seems like overkill for this
20:48crocketMy company is a java/javascript shop, which is depressing.
20:49crocketseangrove, Your analogies don't really sink in my mind.
20:50crocketSo how good is clojure?
20:50arrdemwell, fellow lurkers, it seems that we warranted an upgrade! someone saw fit to send us a technically competent troll rather than a help vampire!
20:52nightflycrocket: Give it a try
20:52nightflyMade a judgement about it on your own
20:52nightflyIf you've never worked with a lisp before it will probably be a very interesting experience for you
20:57gtuckerkelloggclojure+emacs+cider is awesome, but I could really use an Explain It Like I’m Six explanation of integrating clojurescript
20:58gtuckerkelloggor is it Explain it Like I'm Five? Anyway, the point stands
21:00`szxgtuckerkellogg: how about one of these? https://github.com/magomimmo/modern-cljs https://github.com/swannodette/lt-cljs-tutorial http://swannodette.github.io/2013/11/07/clojurescript-101/
21:03gtuckerkelloggooh, i hadn't seen the port of the lighttable tutorial
21:03bob2arrdem, clojure is moving up in the world!
21:03gtuckerkellogg@thanks `szx
21:03`szxnp
21:06technomancygtuckerkellogg: I wrote the original code behind cider and I'm still confused by all the stuff that comes up when people try to debug their cljs repls
21:07gtuckerkelloggthat's reassuring :)
21:25arrdembob2: :D
21:33RosnecI just had a pretty cool idea for a function, which may or may not exist already
21:34Rosnecit would be a modified ->, where along the way you can somehow prefix with a keyword
21:34Rosnecand it returns a mapping of all of those keywords, to the evaluated form that comes after it
21:35Rosnecso something like this...
21:36Rosnec(->' x f :first g :second h) => {:first (g (f x)), :second (h (g (f x)))}
21:36Rosnecit would let you use threading, but store intermediate values along the way
21:36Rosnecthe only problem I see would be the fact that keywords are functions
21:37Rosnecso that would conflict with how threading works
21:37Rosnecbut perhaps there's some way to get around that
21:37arrdemRosnec: I think that zipmap and juxt are right up your alley...
21:37RosnecI've actually never really looked too much into those two, so I don't really know how they work
21:38RosnecI should probably learn, though
21:39arrdem,(doc fnmap
21:39clojurebot#<RuntimeException java.lang.RuntimeException: EOF while reading>
21:39arrdem,(doc fnmap)
21:39clojurebotNo entiendo
21:39arrdem,(doc fmap)
21:39clojurebotNo entiendo
21:40arrdem,(defn -:> [v & pairs] (let [pairs (partition 2 pairs) keys (map first pairs) fns (map second pairs)] (zipmap ((apply juxt fns) v) keys)))
21:40clojurebot#'sandbox/-:>
21:40arrdem,(-:> 3 :+ inc :- dec)
21:40clojurebot{2 :-, 4 :+}
21:41arrdemI got it backwards but that's the idea :P
21:41arrdem,(defn -:> [v & pairs] (let [pairs (partition 2 pairs) keys (map first pairs) fns (map second pairs)] (zipmap keys ((apply juxt fns) v))))
21:41clojurebot#'sandbox/-:>
21:41arrdem,(-:> 3 :+ inc :- dec)
21:41clojurebot{:- 2, :+ 4}
21:41arrdemHAH
21:41arrdemaaaand that's my first use of juxt in anger :D
21:42Rosnecawesome, arrdem
21:43Rosnecwhat happens if I do this:
21:43Rosnec,(-:> 3 inc :+ inc :- dec)
21:43clojurebot{#<core$inc clojure.core$inc@1a955d8> nil}
21:43arrdemit breaks just like you'd expect...
21:43Rosnecyeah
21:44Rosnecyou could always do what you do in lets anyway
21:44Rosnec,(-:> 3 :_ inc :_ inc :+ inc :- dec)
21:44clojurebot{:- 2, :+ 4, :_ 4}
21:44Rosnectreat _ as trash
21:44RosnecI thought this might be useful in lets anyway
21:45Rosnecyou could thread through a bunch of functions, and destructure it in the let binding
21:45Rosnecor I guess any binding
21:46Rosnecwell, I'm saving that function
21:46RosnecI might as well use it in the piece of code that made me think of that
21:48arrdemhum... got a better name for it than -:>
21:49arrdemjuxt->
21:51Rosnecwell thank you for that, arrdem
21:51Rosnecand actually, now I'm thinking I shouldn't use it in that snippet of code
21:51Rosnecbut I'll definitely save it for later
21:51arrdemT_T
21:51arrdem:P
21:52RosnecI would basically need it to be able to fork into multiple ->'s
21:52Rosnecbecause I need to call two different functions on the first form
21:53Rosnecso it'd actually be simpler to just write them out one-by-one
21:53Rosnecat least in this case
21:56Rosnecif there isn't, there should really be a way to destructure & [key val]*
21:56Rosnecwhich would basically use partition 2 in that case on the & pairs
21:56Rosnecor to put that better
21:57Rosnecinstead of doing (fn [& pairs] (partition 2 pairs))
21:57Rosnecyou could do (fn [& [key val]*] ... crap what would you even refer to it by?
21:58Rosnecmaybe this won't work
21:58RosnecI just think it would make the documentation more readable
21:59Rosnecalthough I guess you could just modify the arg list it shows in the doc
22:24TravisDOr you could, like, pass in a map
22:26TravisDHeh, unnecessary and delayed sarcasm is the greatest
22:31cbpI have a bunch of .class files in a jar how do I go about putting them on clojars?
22:33seangrove"Right?"
22:35technomancycbp: you can scp a jar up
22:35technomancyactually wait no
22:35technomancyyou can use `lein deploy` on any random old jar
22:35technomancyjar+pom that is
22:38cbpOk well I'm not entirely sure how to make a pom for a bunch of protobuffers but ill try
22:38cbpthanks :-P
22:46cbpjava.lang.NullPointerException
22:46cbpfor a second I thought it would be easy
23:12cbpI'm getting an error when I scp to clojars https://www.refheap.com/76236
23:13cbpMy pom is this https://www.refheap.com/76233
23:13cbpAny pointers?
23:16beamsois there an issue in that the artifact id has no capital letters but the .jar does?
23:17cbpIf I remove the capital letter from the .jar it then complains that it expected a jar with a capital letter
23:17beamsoouch
23:23dbaschcbp: I used a pom based on this and it worked https://github.com/ato/clojars-web/wiki/POM
23:33cbp....
23:35cbpI've been modifying a copy of the pom which im not actually using in the scp and wondering why my changes do nothing haha
23:35cbpdbasch: thanks
23:35cbpIt worked finally
23:36dbaschhaha
23:37derek_cnewbie question: I'm trying to write a macro that takes an arbitrary number of expressions, and then just put those expressions in a list and return the list
23:37derek_cso something like: (mymacro 1 2 3) => [:some_other_stuff 1 2 3]
23:37derek_chow do I do that?
23:37cddrwhy must it be a macro?
23:38derek_ccddr: it doesn't have to
23:39cddrIn that case, I think you just need a variadic fn. For example (fn [& args] (concat [:some-other-stuff] args))
23:42cddrIf you get to choose datomic for persistence, and clojurescript for the client, would you just propagate the datomic info model all the way down to the app?
23:43derek_ccddr: thanks
23:44cddrOr is there still benefits to be had in building a conventional "REST" API
23:44derek_cwhen a macro and a function do the exact some thing, does it make sense to choose the macro because it saves you a function call?
23:45beamsocddr: i'd still build the REST API.
23:45beamsoderek_c: it is seen as better form to only use macros when necessary
23:45cddrderek_c: I'd always prefer a function because they are more composable
23:46derek_cbeamso: I see, thanks
23:46derek_ccddr: why?
23:50bbloomseangrove: still there?
23:50cddrderek_c: Paul Graham has a chapter on it in "On Lisp": http://dunsmor.com/lisp/onlisp/onlisp_12.html
23:51seangrovebbloom: Yeah, finishing up some stuff, but a bit burnt out. Might have some visual stuff you might enjoy soon though from some ideas that I've been able to pull off
23:52bbloomseangrove: heh ok awesome, well let me know tomorrow or something
23:52bbloomseangrove: i'm beat now
23:52derek_cis there a function that can sort of take things out of a list? I mean, instead of doing (concat [1 2 3] [4 5 6]), I want to do [1 2 3 (something [4 5 6])]. is that possible?
23:54cddrWhat is "something" a function that you indent to pass [4 5 6] to?
23:55seangrovebbloom: Sounds good, will do
23:55seangrovebbloom: As a hint, it's another "oh, he's crazy, that'd take a ton of work" => "oh, that's possible, and kind of handy"
23:55derek_ccddr: yeah
23:55derek_cso [1 2 3 (something [4 5 6])] would return [1 2 3 4 5 6]
23:56bbloomseangrove: yeah that's not a hint
23:56Jaood,(into [1 2 3] [4 5 6])
23:56clojurebot[1 2 3 4 5 ...]