#clojure logs

2014-11-15

00:56nonubyif I have a map with deep nested maps etc. and I want to perform a mutation of specific values (mainly convert those of a particular type to str) would clojure.walk/walk be the best place to start?
00:58justin_smithnonuby: do you want to do it based on type, or based on where they are in a map?
00:58justin_smithalso, maps aren't mutable, you would be making a modified copy regardless
00:58nonubypurely based on type, disregard of where/depth they are in the map
00:59justin_smiththan yeah, walk/postwalk is usually the right thing
01:00justin_smith,(walk/postwalk (fn [e] (if (string? e) (keyword e) e)) {"hello" ["world" {:foo '(bar "baz")}]})
01:00clojurebot#<CompilerException java.lang.RuntimeException: No such namespace: walk, compiling:(NO_SOURCE_PATH:0:0)>
01:00justin_smith,(require '[clojure.walk :as walk])
01:00clojurebot#<SecurityException java.lang.SecurityException: denied>
01:00justin_smith&(require '[clojure.walk :as walk])
01:00lazybot⇒ nil
01:00justin_smith&(walk/postwalk (fn [e] (if (string? e) (keyword e) e)) {"hello" ["world" {:foo '(bar "baz")}]})
01:00lazybot⇒ {:hello [:world {:foo (bar :baz)}]}
01:03nonubythanks
01:04justin_smith&(walk/keywordize-keys {"foo" :bar "baz" ["quux"]}) ; related but different
01:04lazybot⇒ {:foo :bar, :baz ["quux"]}
01:48liathitWhat is "?" in clojure? Example: (defn foo? [])
01:49justin_smithliathit: it is a part of a name like any other character
01:49justin_smith,(defn foo? [] 1)
01:49clojurebot#'sandbox/foo?
01:49justin_smith,(foo?)
01:49clojurebot1
01:49justin_smithusually it means a function that returns true or false, but that's just a convention
01:50justin_smithliathit: there are a few special symbols that modify words in clojure, but that's at the beginning 'quote #reader-macro :keyword etc.
01:50justin_smith@deref
01:51justin_smith&(->> 'clojure.core ns-publics keys (map name) (filter #(.endsWith % "?")))
01:51lazybotjava.lang.SecurityException: You tripped the alarm! ns-publics is bad!
01:52justin_smithoh yeah, lazybot doesn't like that
01:52justin_smith&(->> 'clojure.core ns-publics keys (map name) (filter #(.endsWith % "?")) (clojure.string/join " "))
01:52lazybotjava.lang.SecurityException: You tripped the alarm! ns-publics is bad!
01:52justin_smith,(->> 'clojure.core ns-publics keys (map name) (filter #(.endsWith % "?")) (clojure.string/join " "))
01:52clojurebot"decimal? contains? every? satisfies? seq? fn? vector? thread-bound? isa? char? some? future-done? pos? sequential? neg? reduced? float? set? reversible? bound? map? volatile? var? empty? string? associative? keyword? even? extends? counted? future? zero? not-every? class? future-cancelled? sorted? nil? instance? record? identical? true? integer? special-symbol? ratio? delay? ifn? chunked-seq? dis...
01:56liathitThank you for the help
01:59liathitlazybot: (+ 1 1)
02:01amalloy&(+ 1 1)
02:01lazybot⇒ 2
02:01liathit&(+ 1 1)
02:01lazybot⇒ 2
02:01liathitamalloy: :)
03:06zerkmsHey there. Guys, what would be an idiomatic here instead of ugly `if`? https://www.refheap.com/93405
03:06zerkmswhat I don't like is that "offset" there is repeated 4 times
03:12kenrestivois there a good way to represent a circular data structure in clojure? i.e. 1->2->3->4->1 ?
03:14TEttinger(doto rac (.seek (if (>= (.length rac) offset) offset 0))) ;there, now it's only repeated 3 times
03:16kenrestivohmm, maybe i just just use CircularArrayList or similar in java
03:16zerkmskenrestivo: http://clojuredocs.org/clojure.core/cycle may be
03:16zerkmsTEttinger: would you do it like that? Now it's hard to read
03:17kenrestivocycle is cool if i want to turn a circle into a line (sequence). i'm looking to take points and place them on a circle, and be able to determine if they are left or right of each other
03:18TEttingerI mean, maybe the simplest thing to do would be to not reuse names for different immutable values
03:18kenrestivokind of thing i'd do with linked lists in c, i guess
03:18TEttingerlet [offset-revised (if (>= (.length rac) offset) offset 0)] ...
03:18TEttingerthat might make it a bit more clear
03:19zerkms"that might make it a bit more clear" --- that's very true indeed
03:20TEttingerI don't think if is a terrible thing to use in clojure
03:35kenrestivoah, nevermind, i just used maps and immutability. https://www.refheap.com/93408
03:37zerkmskenrestivo: learnt about "condp
03:37zerkms" from it
03:53olivierrr(= (repeat 100 :foo) (take 100 (iterate ___ :foo))))
03:53olivierrri'm stuck on that koan, any hint would be appreciated :)
03:54kenrestivohaha
03:54godd2olivierrr what function returns the argument passed to it?
03:55olivierrr(if true :foo) ?
03:55olivierrror (map) perhaps?
03:55kenrestivosimpler than that
03:56kenrestivomore boring.
03:57kenrestivoit's a function that, looking at it, you'd think "why would anyone ever want to use that?"
03:58olivierrr(fn :foo) ?
03:58olivierrri have no idea
03:59kenrestivoi'd have a look through the list of functions here: http://clojuredocs.org/quickref/Clojure%20Core
04:00godd2olivierrr consider the math function f(x) = x
04:00godd2what is f(3) ?
04:01olivierrr3
04:02olivierrrreturn args[0]
04:02godd2alright so you agree that f(x) = x returns whatever was given to it, correct?
04:02olivierrrright
04:02godd2well in math, this is called the "identity" function
04:03godd2in other words, the input and output are identical
04:04godd2in clojure, there is a function of the same name
04:04kenrestivoand you can write your own by translating godd2's math into clojure, i.e. f(x)=x
04:04godd2https://clojuredocs.org/clojure.core/identity
04:04olivierrrgot it, thanks godd2
04:04olivierrrthanks kenrestivo
04:04kenrestivobasically, (fn [x] x)
04:06olivierrrvery cool, thanks again :)
04:32GlenjaminI just thought of a great plugin name, but I don't have a plugin to use it
04:32GlenjaminSo I'm throwing it out there; lein-backer
04:57zerkmsGuys, would you say that (do (async/close! stop) (async/close! out)) works the same as (map async/close! [stop out]) (apart of returning result, which I don't care)
04:57zerkms?
05:02kungizerkms: it might create a problem with map being lazy
05:03zerkmskungi: I see, it makes sense
05:03kungizerkms: I think the if you want to shorten this you should use doseq instead of map
05:03kungizerkms: doseq is used for the sideeffects
05:03zerkmsyep, it explains everything, thanks
05:04kungizerkms: did the channels not close properly with the map solution
05:04kungi?
05:04zerkmsthat's correct
05:04zerkmsthey didn't
05:04kungiI've seen this in my code when I used for
05:07zerkmsImplemented it as (doall (map async/close! [stop out])) which looks slightly better whan doseq in this case
05:07zerkmskungi: ^ ^
05:11kungi(doseq [c [stop out]] (async/close! c))
05:12kungiEither way seems nice :-)
05:12zerkmsseems like it's very personal :-) may be I'm map-liker
05:16justin_smithzerkms: when you don't care about the result, use dorun instead of doall
05:17zerkmsbecause... ?
05:17justin_smithbecause doall holds onto the result data structure, and dorun throws away the results
05:17justin_smithbetter memory performance
05:17zerkmsyep, checked docs
05:17zerkmsthanks
05:18justin_smithfor two items it doesn't matter much
05:18justin_smithbut it's good to get in the habbit of using the right one
05:18zerkmsyep, it makes sense as well
05:19justin_smithalso, if the input is the classic Soul get The Crystals, one should use the-do-ron-ron
05:20zerkms:-S
05:20zerkmsthe last phrase is over my english-fu
05:20justin_smithsorry - it's a joke
05:20zerkmsyep, I got it's a joke, just didn't get it :-)
05:21justin_smithThe Crystals are known for the song https://www.youtube.com/watch?v=cSpwxz8s0NU
05:21zerkmsbtw, https://www.refheap.com/93411 --- my precious
05:21zerkms1 day of crafting it. 2 days of programming in clojure in total
05:24justin_smithzerkms: for two days of clojure experience, that's damn good
05:25zerkmsI've been reading a lot for a long
05:25zerkmsIt probably was a year of lazy-reading without a single line written :-D
05:52cflemingI agree, looks very good. Nice work zerkms!
05:54zerkmsIt actually now looks even better with moving an alts!! duplicate to its own function: https://www.refheap.com/93412
05:54zerkmsbtw, thanks :-)
05:58zerkmswhat you guys use for clojure? trying la clojure with idea, but it seems like it's missing some useful features
05:59justin_smithzerkms: funny you should ask about idea.. cfleming writes cursive, which is very popular, probably the best integration right now
05:59justin_smithI use emacs, because I have always used emacs
05:59zerkmsjustin_smith: several weeks ago it was a local meetup with a guy who develops Cursive
06:00zerkmsI couldn't get there :-(
06:00cflemingzerkms: I'm biased, but I think you should definitely use Cursive over La Clojure - LC is basically deprecated now in favour of Cursive
06:00cflemingzerkms: Are you in Wellington?
06:00zerkmsyep
06:00cflemingzerkms: Nice, I'm just across the water in Nelson
06:00zerkmshow was it? :-)
06:00zerkmsoh, lol
06:01cflemingIt was cool, it was the second meetup and got a lot more people than the first, so hopefully there's a community forming there.
06:01zerkmsI rsvp'd for next with hope that I will be able to do it
06:02cflemingMostly Scala programmers but there's one company doing only Clojure/ClojureScript, and one company just putting Datomic into prod
06:02zerkmscurious how long it will take for seek/trademe jobs for the first clojure position in NZ
06:02zerkmsreally? that's surprising to hear
06:02cflemingThere are a few companies using it here now.
06:03cflemingBut a lot more Scala
06:03cflemingjustin_smith: Where are you based? I'm starting to wonder if you ever sleep.
06:03justin_smithcfleming: having some insomnia tonight
06:03justin_smithwest coast US
06:04cflemingjustin_smith: Ah, ok.
06:04justin_smithI usually wake up pretty early, (like 5 am or so) but if I do anything social I end up staying up late...
06:04justin_smithso there are few hours I am never up :)
06:04cflemingHehe, yeah, I'll just never see them from here :)
06:07justin_smiththis is compounded by heavy caffiene usage interspersed with caffeine withdrawal (to reduce the dependency which limits the effectiveness of caffeine) so some days I rarely sleep, others I am rarely awake..
06:08cflemingjustin_smith: I gave up coffee a couple of years back when I was having a pretty stressful time and it was making me anxious. I was amazed how much better I slept, I never thought it affected me.
06:09justin_smithcfleming: yeah, I am dependent on that chemical control of productivity - though I would like to rely on self-discipline instead, working on that
06:29TEttingerjustin_smith: long-acting stimulants like vyvanse can do the same thing caffeine does with a lower risk of dependency or tolerance and no crash
06:29TEttingervyvanse is a controlled prescription med here in the US
06:30TEttingerrelative of adderall, just longer lasting and harder to abuse (by design)
06:32TEttingerI've gone from maybe 4 no-doz-equivalent caffeine pills a day to, most days, a half of a caffeine pill after the "baby dose" of vyvanse wears off by the evening.
06:32TEttinger800mg caffeine to 100mg is a big help :)
07:08Xackhi, is it possible to specify a pure Java class as :main for leinengen?
07:12Xacki need to do this because of https://github.com/libgdx/packr/issues/33
07:32gfredericksXack: what's the goal there? to make it your startup class in an uberjar?
07:33Xackgfredericks: yes
07:34Xackthe packr utility (as linked above) doesn't seem to want to play well with play-clj, and i'm trying to make leiningen use a standard Java class, however, it wants to look for "-main", which AFAIk I can't do, and leads to syntax errors
07:35Xacki would like it to use the "main" function, if possible
07:35Xackif it isn't, i have no idea what else to do :(
07:35gfredericksbut an uberjar is your only use case for this?
07:35Xackwell, not really, lein run also
07:36Xackan uberjar is used in order for packr to work "properly"
07:36XackIIRC uberjar packs clojure with itself, is that correct?
07:36Xackvery new to this :P
07:36gfredericksyes
07:36gfrederickslein run can take a class already I think
07:36Xackgfredericks: moment
07:37gfrederickstry `lein run -m My.Class`
07:38XackException in thread "main" java.lang.IllegalStateException: Attempting to call unbound fn: #'crateincinerator.core.desktop-launcher/-main, compiling:(/tmp/form-init2641406317692387679.clj:1:72)
07:39Xackgfredericks: leininegen wants a function called "-main", apparently
07:39Xackoh.
07:39Xackyep, i derped
07:39Xackone sec
07:42Xackheh, if i read it correctly (the full stacktrace), it told me that the java wrapper was actually being run, and that it was an error in the java wrapper code
07:42Xackthanks!
07:45gfredericksnp
07:46gfrederickswrt the uberjar, I didn't have a lot of luck checking the leiningen source. It looks like the `jar` task can take a main argument, but I'm not sure how to get the rest of the uberjar functionality back if you do that
08:05nonubysince there is no mapcat-indexed (i require the idx as part of map op) is it better to do (filter identity (map-indexed map-op coll)) or (concat (map-indexed (fn [idx i] (if (map-op idx i) [i] []))) coll)?
08:07hyPiRion(for [[idx i] (map list (range) coll) :when (map-op idx i)] i) perhaps?
08:07hyPiRionI feel it reads better at least
08:15nonubynice
09:03m1dnight_is there a thing such as a namespace bound variable? So that every thread/namespace that calls a function in namespace X can access it?
09:05Bronsam1dnight_: if you fully namespace qualify a symbol and the namespace is loaded, the var is accessible everywhere
09:05Bronsae.g. clojure.string/join
09:05m1dnight_yeah, but I'm talking about an atom, for example
09:06m1dnight_I'm going to try it
09:06m1dnight_that might be best :p
09:06Bronsayou still have to hold an atom in a var
09:23gfredericks,(def obj (atom (ref (agent (future (promise))))))
09:23clojurebot#<CompilerException java.lang.SecurityException: no threads please, compiling:(NO_SOURCE_FILE:0:0)>
09:23gfredericks,(def obj (atom (ref (agent (promise)))))
09:23clojurebot#'sandbox/obj
09:23gfredericks,obj
09:23clojurebot#<Atom@ce4dda: #<Ref@123a08e: #<Agent@2fcb4f: #<core$promise$reify__6499@25a311: :pending>>>>
09:32martinklepschcan someone point me to good examples of https://github.com/stuartsierra/component in use?
09:35m1dnight_"Attempting to call unbound fn: #'clojure.core/unquote""
09:35m1dnight_but my source runs fine on my laptop
09:35m1dnight_sems like core is not loaded, or what?
09:35Bronsa,~1
09:35clojurebot#<IllegalStateException java.lang.IllegalStateException: Attempting to call unbound fn: #'clojure.core/unquote>
09:36m1dnight_but, it compiles/runs fine on my laptop? :p it's the exact same source
09:36m1dnight_i tried lein clean, lein deps and lein run
09:36m1dnight_nothing works
09:36Bronsait must be hitting a different code path for some reason
09:36Bronsalook for unquotes outside syntax-quote
09:38m1dnight_it points me to a line where I have `(let ~letbinds ~condody)
09:38m1dnight_seems to be fine to me
09:39Bronsamaybe the value of letbinds or condody has contains an unquote, I can't really help you without the code
09:39m1dnight_mmm
09:39m1dnight_it's really weird, I pushed/pulled again, but seems to be broken
09:39m1dnight_ill just work on my laptop I guess
09:42m1dnight_aha!
09:42m1dnight_i forgot to lein clean on laptop
09:42m1dnight_I'd set the status of my problem to solved but that'd be non-idiomatic so i'll create a new problem, but a solved on
10:21m1dnight_Cool, that seems to work in a minimal testcase
10:21m1dnight_just goes to show how bad I understand namespaces and all that
10:21m1dnight_I have a namespace with an atom and that value is the same for everyone who accesses that namespace (everyone being thraeds)
10:21m1dnight_so it's like a static field or something?
10:46augustlare there any rules of thumb for when I should use transients? Only when doing more than n updates, for example? If that's the case, what is n? :)
10:54justin_smithgood morning everyone. I have a brainstorm to make a lib where I can describe a DAG where each node is a shell command or a closure with a method that reads as many bytes as it can get from an inputstream, and then outputs some number of bytes on an outputstream. Before I jump in, does something like this exist? basically max/msp with a mixture of unix stdin/stdout processes and clojure functions of inputstream/outputstream (without
10:54justin_smithpretty picture you get with max/msp)
10:55justin_smithor, like a shell pipeline where "tee" is implicit, and you can add/remove processes in arbitrary places in the pipeline while it is running
10:55justin_smith(and clojure functions can be inserted between programs, of course)
11:12Xackhm
11:12Xackcan anyone give me an example of switching to a title-screen after so many seconds in play-clj?
11:13sveriHi, is it possible to create a namespace in memory during runtime, add some records to it and then referrence these records from a different namespace just as it was normal code?
11:17justin_smithsveri: yes, you can do all this in a normal repl
11:19sverijustin_smith: yea, I just found about create-ns and intern. So, it's basically possible to have users create records which are loaded during runtime in a user specified namespace
11:19sverithis sounds awesome
11:19justin_smithsveri: not only that, you can run the ns macro at runtime
11:20sveriI have been watching Hickesy intro to clojure almost one year ago and now I get what he meant when he said that its possible to alter the code during runtime
11:20justin_smithbut yes, if for some reason that wouldn't work (avoiding eval I guess?) you can use create-ns and intern
11:21justin_smiththe things that won't really work in a repl (without some complexity) are gen-class and gen-interface
11:21sverijustin_smith: hm, eval is new to me, is it an abstraction over intern and create-ns?
11:21justin_smithsveri: it allows executing arbitrary code at runtime. It is the function the repl calls after reading your lines of code.
11:22sverijustin_smith: I see, is it as evil as eval in javascript?
11:22justin_smitha repl is basically (loop (-> read eval print) (recur))
11:22godd2sveri if you're evalling arbitrary user inputted string
11:23justin_smithgodd2: but that seems to be the very premise of the project?
11:24mavbozosveri: read-string also can execute code
11:24mavbozosveri: http://clojuredocs.org/clojure.core/read-string
11:25sverimavbozo: thank you
11:25gfredericks(defn eval [form] (str "#=" (pr-str form)))
11:25gfredericksoh forgot to call read-string too
11:26sveriSo if I do eval and want to create records in a namespace I would have to add the ns declaration to the evaled form, right?
11:27gfredericksoften with eval you wrap the call in (binding [*ns* some-ns] (eval ...))
11:27sverigfredericks: does the ns have to exist? or is it created on the fly if it does not exist? and are records recreated if it did exist before?
11:28gfredericks,(create-ns 'treehouse.fort)
11:28justin_smithsveri: ns used in a repl is exactly like ns in a file
11:28clojurebot#<Namespace treehouse.fort>
11:29gfredericks,(binding [*ns* (the-ns 'treehouse.fort)] (eval '(inc 41)))
11:29clojurebot#<CompilerException java.lang.RuntimeException: Unable to resolve symbol: inc in this context, compiling:(NO_SOURCE_PATH:0:0)>
11:29justin_smithsveri: except for :gen-class
11:29justin_smithgfredericks: why not just use ns?
11:29gfredericks,(ns treehouse.fort)
11:29clojurebotnil
11:29gfredericks,(binding [*ns* (the-ns 'treehouse.fort)] (eval '(inc 41)))
11:29clojurebot42
11:29mavbozosveri: have you watch How Clojure Works http://www.youtube.com/watch?v=8NUI07y1SlQ ?
11:30sverimavbozo: thank you, I did some time ago, but clojure was to new to me then, however, might be a nice fit now, thank you
11:30mavbozosveri: maybe the explanation in that video can answer your questions.
11:30sveri(inc justin_smith)
11:30lazybot⇒ 131
11:30sveri(inc gfredericks)
11:30lazybot⇒ 104
11:30sveri(inc mavbozo)
11:30lazybot⇒ 1
11:31mavbozosveri: puredanger here pointed it to me a couple days ago. Still trying to understand though.
11:33gfredericks,(defn factor [n] (let [[p] (->> (range) (drop 2) (filter #(zero? (rem n %))))] (if (= n p) [n] (cons p (factor (/ n p))))))
11:33clojurebot#'sandbox/factor
11:33gfredericks,(factor 104)
11:33clojurebot(2 2 2 13)
11:37justin_smithmavbozo: I ended up watching that "how clojure works" vid, and it was a good overview / refresher
11:37justin_smithit also ends up setting the stage / motivation for things like arrdem 's oxcart
11:37eric_normandhow does one read edn tagged literals in clojurescript?
11:42gfrederickseric_normand: looks like you can rebind cljs.reader/*default-data-reader-fn*
11:42eric_normandI'm confused
11:43gfrederickscould you describe what your input is and the output you want?
11:46gfredericksthat var is an atom for some reason, so you'll presumably want to bind it to (atom (fn ...)) :/
11:46gfredericksthere are also the side-effecty routes via cljs.reader/[de]register-[default-]tag-parser!
11:52gfredericksI wonder what on earth is the use case for deregister-default-tag-parser
12:02bbloomaugustl: benchmark benchmark benchmark
12:02zeapoHey!
12:03pdurbinjustin_smith: ah, you must mean https://www.youtube.com/watch?v=8NUI07y1SlQ
12:05m1dnight_I'm reading through the clojure style guide by batsov
12:05justin_smithpdurbin: yeah, I was responding to mavbozo who pasted that link above
12:05m1dnight_And he states that (defn foo [x] (if (pos? x) (foo x) (bar x)))
12:05m1dnight_is worse than (hold on)
12:06pdurbinjustin_smith: oh. now I see the link. thanks
12:06m1dnight_(defn foo [x] {:pre [(pos? x)]} (bar x))
12:06m1dnight_but, in the former you can specify your own exception
12:06m1dnight_is there something like that possible with preconditions
12:07justin_smithm1dnight_: no, they always throw AssertionErrors (which are not even Exception subclass, they are Error subclass)
12:07m1dnight_oh okay
12:07m1dnight_thnx
12:08luxbockI'm stuck on this 4Clojure problem: https://www.4clojure.com/problem/121
12:09luxbockI can get the correct form with symbol replacement easily, but 4Clojure tells me that eval is bad
12:09luxbockso I'm wondering if my approach of building the form I want to evaluate first is misguided and I should be doing something else?
12:11justin_smithluxbock: eval is usually bad, not just in 4clojure
12:11justin_smithluxbock: what you need is a function or datastructure that takes a symbol, and returns the function for that symbol
12:12justin_smithluckily you have a comprehensive list of the symbols you need to use right there on the page
12:12luxbockhmm ok
12:14justin_smithluxbock: looking through people I follow on clojurescript, pretty much all of us did some kind of recursive mapping of the input, checking for nesting and recursing to calculate the nested value, or otherwise calculating a result if nothing is nested at that level
12:14justin_smitherr wat - "looking through the people I follow on 4clojure"
12:14justin_smithdunno where that "clojurescript" came from
12:14justin_smithmisfired brain cylandar
12:15justin_smithcylander - wtf brain
12:15luxbockalright that's good to know, I just wanted to avoid following a dead end path
12:35justin_smithhow do I type-hint a protocol? can I type-hint the defprotocol, or do I need to just type-hint the implementations?
12:35dnolen_justin_smith: no type hinting of protocols is supported
12:36justin_smithdnolen_: that covers that then, thanks!
12:36justin_smith(inc dnolen_)
12:36lazybot⇒ 7
12:36justin_smith(inc dnolen)
12:36lazybot⇒ 17
12:37kevinfishI want to develop a pay per access server app first in clojure then eventually migrate it into a protected stand alone browser app (like perhaps on phonegap or firefox OS). Does anyone have any advise on the best way to do this? Like, which server to run (e.g. one built in clojure)? I have some experience in lisp and have been studying clojure for a while now but not written anything significant in it.
12:39justin_smithhttp server?
12:40kevinfishjustin_smith: well, i'm thinking if I'm going to do a big chunk of the calculations on the server (to be formatted into a html template) then it might be best to have the server running clojure also.
12:40justin_smithhttp-kit is pretty awesome for a standalone if so. If you use ring, you have multiple servers to choose from and can use one in development and swap out to another in production/staging with no breakage
12:41kevinfishjustin_smith: oops, not talking to me. sorry
12:41justin_smithkevinfish: yes, I was talking to you
12:41justin_smithyou said server, but did not mention what kind :)
12:42jkjkevinfish: i'd default to nginx frontend proxy that does https itself and forwards requests to clojure-ring (jetty?) app running on somet other port in localhost
12:42kevinfish justin_smith: well that's pretty much the crux of my question. Should I run a clojure http server (if such exists)?
12:42justin_smithkevinfish: like I said, use ring, there are a bunch to chose from but they are all ring compatible
12:42justin_smithring is a clojure abstraction for http servers
12:42kevinfish justin_smith: ok, I'll start googling that, thanks
12:43justin_smithkevinfish: "lein new ring foo" will generate a clojure project called foo using ring
12:43justin_smithand if you don't have lein, that's pretty much your mandatory first step with clojure usually
12:43kevinfishjustin_smith: yes, got it. Did get that far :)
12:44jkj....but then again... nginx-clojure thingy is probably the fastest choise, but a bit more complex to set up... using standalone app with e.g. http-kit as the server is prolly nice too but i'm for reason having some doubts on giving https to the app's care
12:44kevinfish justin_smith: I'm just hoping that my server code that generates the html can eventually be migrated to the browser as clojurescript with minimal changes
12:44justin_smithlein new ring will create a project using an embedded jetty server, but ring will let you port that to run under tomcat, or an external jetty container, or standalone httpkit or whatever
12:44Bronsajustin_smith: you can type hint the return value of protocol functions though
12:45Bronsae.g. (defprotocol p (^tag f [_])) will work
12:45justin_smithBronsa: inside the protocol definition? or in the definition of individual implementations?
12:45justin_smithBronsa: AHH! that's what I was looking for, thanks so much
12:45Bronsajustin_smith: in the defprotocol
12:45justin_smith(inc Bronsa)
12:45lazybot⇒ 72
12:45justin_smithletting dnolen_ slide without a dec, because he's awesome enough
13:19justin_smithBronsa: so are record fields hintable too? also, is there a good document showing all the valid places for hints?
13:20Bronsajustin_smith: yeah record fields are hintable
13:22justin_smithBronsa: do you know a blog post or a place in clojuredocs that is comprehensive and accurate about hinting positions?
13:22Bronsajustin_smith: both for proto fns and type/record fields primitive types are not supported btw
13:22Bronsajustin_smith: no. mostly because the clojure compiler is extermely inconsistent
13:23justin_smithcool, but something like ^bytes or ^"[B" would work, right?
13:23Bronsayes
13:23justin_smithBronsa: that's sad
13:23Bronsajustin_smith: my suggestin is just set *warn-on-reflection* to true and try it out
13:23justin_smithcool, that makes sense
13:23justin_smithwe should at least have a "type hinting wiki" or something lol
13:23justin_smithor we can just come here and ask Bronsa or puredanger.
13:24Bronsajustin_smith: I've been complaining about it for a while, I made a clojure-dev thread a while ago but nothing came out of it
13:24BronsaI just work around the compiler quirks now
13:25justin_smitharrdem: how about making this a topic on grimoir?
13:26justin_smithit's a wiki, after all
13:47arrdemwhat am I adding to Grimoire now?
13:47arrdemwow justin is disco. first time I remember seeing that...
13:52arrdemBronsa: if you have and can share notes on what does and doesn't type hint I'd be happy to retype it into thalia/Grimoire
13:53sobelare there any well-known sites deployed on clojure-nginx that i could use for reference? (i don't want to tell my manager we'll be the first that i know of...)
13:54sobeleven better if there's an open project i can use for tech reference but i'm prepared to manage my own code soup-to-nuts just the same
13:54godd2sobel clojars *might* be ?
13:54godd2sobel https://github.com/ato/clojars-web
13:56sobelhm, if it is the NC deployment bits are not in that repo
13:56xeqiits is not
13:56xeqiit uses nginx to proxy to jetty
13:57sobelhttps://github.com/ato/clojars-web/blob/d69f95ab801c1482cd32721f0e9aee48d4893914/SYSADMIN.md
14:01pdkwoah guys
14:01pdki know i might not have showered yet
14:01pdkbut you don't need to all run at once
14:01m1dnight_okay namespaces again.
14:01m1dnight_they are killing me.
14:01m1dnight_would somebody be so kind to look at what I'md oing wrong?
14:01justin_smithm1dnight_: specific question?
14:01justin_smithI'll take a look if you have a paste of it
14:01m1dnight_yeah, class nto found again
14:01m1dnight_yeah ,just a sec
14:02m1dnight_https://github.com/m1dnight/freakin-namespaces
14:02m1dnight_this
14:02m1dnight_it are two simple files and it keeps complaining about the RetryEx
14:03m1dnight_I fixed it before in my other project (which utilizes both these files)
14:03m1dnight_So i did the same steps for this project but i cant get it running (using lein run)
14:03m1dnight_are you freakin kidding me
14:03m1dnight_now it compiles
14:03m1dnight_oh dear god
14:04m1dnight_I changed *nothing* :|
14:04m1dnight_just took a shower :p
14:04justin_smithm1dnight_: once again you put - in the class name
14:04Bronsads
14:04justin_smithm1dnight_: for generated classes - must be translated to _
14:04justin_smithm1dnight_: this was the problem you had last time
14:05m1dnight_yeah, I had that before
14:05m1dnight_so I tried regular dashes
14:05m1dnight_while figuring it out :p
14:05m1dnight_because I have that indeed, in my original project
14:05justin_smithm1dnight_: import is for classes, - is not a valid constituent char for a class
14:05m1dnight_so I thought it couldve been something weird
14:05m1dnight_indeed
14:06m1dnight_is there some cache in leiningen i should be aware of?
14:06m1dnight_All I did each time was lein clean && lein compile && lein run
14:06justin_smithtry lein clean
14:06justin_smithOK
14:06m1dnight_strange, very very strange
14:06m1dnight_but hey, it works :p
14:06m1dnight_thnx though
14:06justin_smithlein compile should not be needed, lein run will do compiling if it needs to
14:06justin_smithbut check out the eastwood plugin
14:07justin_smiththat can help find "sketchy" stuff that isn't a compile error but is probably wrong https://github.com/jonase/eastwood
14:08arrdemalso you don't want to chain lein via &&... lein do is your friend
14:09arrdemunless for some reason you enjoy starting and killing JVMs
14:12justin_smitharrdem: so, what are your thoughts about adding an entry describing valid places for type hints?
14:12justin_smith(to grimoire that is)
14:12arrdemjustin_smith: I'm open to it. 0.4.0 has a structure for adding full articles, and I think having a type hinted article linked to by forms that can deal with type hints makes sense
14:13arrdemI should finish 0.4.0 someday T_T
14:13justin_smithcool
14:14justin_smith(defn ^HTML document [] "<head></head><body>Hello World!</body>") here's your type hinted article, all ready to go
14:14justin_smith:P
14:21andyfjustin_smith: If you?re interested in helping writing the content of a type hinting wiki, I could help. It wouldn?t be a quick job double-checking all of the details, though, if you want it to be accurate.
14:21justin_smithandyf: awesome! maybe I'll throw together a draft and share it with you later
14:22andyfThere are a *few* details in the Eastwood docs, but they don't even try to cover protocols, records, etc. https://github.com/jonase/eastwood#wrong-tag
14:42justin_smithandyf: how sad, with-out-str does not check "Reflection warning" messages - I was hoping I could make a set of unit tests that assert that warnings are or are not present for various definitions :(
14:44justin_smithdoes not capture them, I mean
14:46andyfjustin_smith: You can with shell scripts invoking lein test and parsing the output, but a bit more work.
14:46justin_smithoh, wow
14:46justin_smithyeah, that's possible, but really there should be something more elegant
14:47andyfWait, have you tried rebinding *err* instead of *out*? I think I do that in Eastwood and it works.
14:47justin_smith,(binding [*err* *out*] (with-out-str (defn l [foo] (.count foo))))
14:47clojurebot""
14:48justin_smithwell, that also gives an empty string when reflection warnings are on
14:48andyfhttps://github.com/jonase/eastwood/blob/master/src/eastwood/util.clj#L519-L531
14:48amalloyjustin_smith: it shouldn't
14:48justin_smith,(binding [*err* *out* *warn-on-reflection* true] (with-out-str (defn l [foo] (.count foo))))
14:48clojurebot""
14:48amalloyCompiler prints to RT.errPrintWriter, which is *err*
14:48andyfThen do eval inside of with-out-str2 as defined there.
14:48justin_smitham I doing that more?
14:48justin_smith*wrong?
14:48amalloyjustin_smith: yes
14:48amalloyyou can't bind *warn-on-reflection* usefully
14:48amalloyyou have to either set! it, or use eval
14:49justin_smithamalloy: OK I was using it this way for sharing purposes, I have it turned on in a repl
14:49amalloybecause the error is issued at compile time, whereas the binding is put in place at runtime
14:49justin_smithamalloy: but nothing I do seems to capture that error printout
14:49justin_smithwhich I do see..
14:49andyfjustin_smith: try eval inside of my with-out-str2 or your own variant
14:51justin_smith,(binding [*err* *out* *warn-on-reflection* true] (with-out-str (eval '(defn l [foo] (.count foo)))))
14:51clojurebot#<CompilerException java.lang.SecurityException: denied, compiling:(NO_SOURCE_PATH:0:0)>
14:51l1xhey guys, has anybody used clojure/tools.logging? i was wondering where should i place the log4j.properties file in the lein project tree and how could I have all the different imported Java libs logging the same way across the entire Clojure project
14:51justin_smithandyf: the above fails to capture it as well
14:51justin_smithamalloy: I will check out you with-out-str2
14:51justin_smith*your
14:52andyfTry (set! *warn-on-reflection* true) first, then that expression without warn-on-reflection binding after that?
14:52andyfI'll try it out locally
14:52amalloys/amalloy/andyf
14:52justin_smithamalloy: oops, thanks
14:53justin_smiththat would have made it a little harder to find
14:56andyfjustin_smith: I can get it to work with with-out-str2, but not a small variant of your examples above. I'm heading out to lunch, so low motivation to figure out why right now :)
14:57justin_smithandyf: OK, thanks for the hints
14:57justin_smithmaybe this is a cider issue...
15:11justin_smith$mail andyf (util/with-out-str2 (eval '(defn l [foo] (.count foo)))) did the trick, thanks
15:11lazybotMessage saved.
15:12justin_smith$mail andyf turns out (with-out-str (binding [*err* *out*] (eval '(defn l [foo] (.count foo))))) does too
15:12lazybotMessage saved.
15:13zerkmsjustin_smith: I've already had a sleep and you still here!
15:13justin_smithzerkms: I was only up for a few hours last night
15:13justin_smiththen I slept again
15:13justin_smitheither that or I am an unsleeping all-knowing immortal, you can believe that if you wish
15:14zerkmsjustin_smith: right before my daughter woke me up I've had a dream about runtime exceptions due to mutating immutable
15:14zerkmssomeone was coding too much yesterday
15:14kenrestivoyou can never code too much
15:14justin_smithI dreams about step debugging in cider being possible
15:14justin_smithit was glorious
15:14BronsaI've found so many bugs I wasn't aware of in my code while falling asleep
15:15justin_smithoh yeah, and sometimes I wake up with the perfect design to solve something that I was mulling over the day before
15:15kenrestivohammock-driven debugging
15:16zerkms"My MacBook Pro has gone to sleepZZZzzz…" <--- why people still do that :-S
15:16BronsaI like to think that t.a wouldn't be as good as it is now if it wasn't for andyf and my hypnagogic thoughts
15:16justin_smithI think it is automatic - or do you mean leave the sleep function on?
15:16rkneufeld_zerkms: a lot of clients do it by default :(
15:17zerkmsI mean - pointing out mbp
15:17justin_smithit's kind of like "my mercedes is parked a few blocks away" - mention the brand at every juncture if it's a status symbol
15:17rkneufeld_zerkms: it seems to be the default for Textual.app
15:18rkneufeld_I have a bouncer, but I just changed mine from that exact message, having never set it to that.
15:19justin_smithBronsa: so I figured out how to capture the reflection warnings as strings, so I should be able to make the documentation as a github repo where you are meant to read the tests, and you can run them to verify that every claim in the codebase is accurate
15:19justin_smithsince each claim would be made in the form of defining something that may or not induce a reflection warning
15:19justin_smithas long as the warnings are consistent and accurate, we're golden
15:21amalloyso justin_smith, what is different about with-out-str2 that makes it work where the binding/eval approach didn't?
15:21justin_smithamalloy: see my second mail to andyf - with-out-str / binding / eval worked too, I was just nesting things wrong
15:21amalloyoh good
15:22justin_smith"(with-out-str (binding [*err* *out*] (eval '(defn l [foo] (.count foo))))) does too"
15:23justin_smithmy mistake was putting the binding outside the with-out-str
15:23justin_smithinstead of visa/versa
15:23amalloyhah, indeed
15:24justin_smithamalloy: btw if you restart lazybot it should have commands in /msg working again
15:24SagiCZ11hi, i guess that relying on indexes is not a good programming practice, but can i assume that in map entry, the value is always 'second'? or is there a better way to acess it?
15:24amalloy&(doc val)
15:24lazybot⇒ "([e]); Returns the value in the map entry."
15:25justin_smithSagiCZ11: it is always second, but as amalloy indicates, val is more clear
15:25amalloySagiCZ11: use val, or destructure it
15:25amalloy(let [[k v] e] ...)
15:25augustlI have an object that is in a vector with ~millions of items in it. Is it fast to get the index of that object in the vector?
15:25amalloyno
15:26SagiCZ11amalloy: thanks a lot.. i knew about vals, didnt know about val, btw is the destructuing form calling second or val on this example?
15:26justin_smithaugustl: if you knew the index, getting the element at that index would be relatively fast
15:26augustlamalloy: k, thanks :)
15:26justin_smithor if it were a sorted-set
15:26amalloySagiCZ11: well, it's calling (nth e 2)
15:26amalloyer, (nth e 1)
15:26augustlthe idea is to store the history of an atom in some sort of data structure. It probably makes sense to store "version" in the item itself, then
15:26SagiCZ11amalloy: i see, but i guess 'val' states my intentions better
15:27augustlthis is all nice and single threaded etc ;)
15:27SagiCZ11augustl: wouldnt you use meta data for that?
15:28augustlwell, the version is part of the domain, so it makes more sense to have it in the item itself imo
15:28augustlit's just a map anyways, so adding version to it is not a problem
15:28justin_smithaugustl: what about putting it in a proper persistent storage (ie. a db of some sort)
15:28justin_smithif you care about all the versions it has had in a session, maybe you would also care between sessions?
15:29augustlthat could also work. It's an experiment at this stage, I want to see how much history I can store with persistent data structures
15:29augustlbut old data isn't vital to the system, it's only used for "support" tasks so we can know what the data looked like at a given point in time to reproduce bugs etc
15:29SagiCZ11augustl: why do you need the history? just wondering, sounds memory intensive
15:31SagiCZ11i see
15:31amalloyjustin_smith: yep, looks good
15:32augustldon't say Datomic!
15:32justin_smithaugustl: postgres or mysql would do the job just fine
15:33augustljustin_smith: implementing persistent data structures on top of SQL? Doesn't sound trivial :)
15:33justin_smithaugustl: why persistent? just don't use alter
15:33justin_smitherr update
15:33justin_smithjust create new records
15:34amalloySagiCZ11: right, val is good if you only care about the val. if you need both key and val, destructuring is usually clearest
15:34augustlthe state consists of a couple of hundreds of entity per day, that gets modified as time passes
15:34SagiCZ11amalloy: alrighty
15:34augustljustin_smith: so that's the tricky part - modifying the entities
15:34clojurebotexcusez-moi
15:35justin_smithaugustl: there are well established techniques for keeping extensive records and also keeping the db manageable. One basic idea is to only create new records, never modify old ones, and as the db grows, move the oldest ones into a different database (perhaps on another server) so all the data is still available, but the oldest data is not slowing down your most heavily used set
15:36augustlyeah sure, but that still means I'm the one that have to model time, if I need that I prefer to drop in something that does the job for me :)
15:37justin_smithaugustl: multiple entries with the same id key, the one with the newest time field is the actual current value
15:40sveri1justin_smith: augustl I have been doing that in a larger php application with mysql some time ago, you can get started easily, but it somehow became PITA fast, escpecially as we switched to java / hibernate and were not really able to modle our datastructure to hibernate, part of the reason was the history. So I am not saying it cannot be done, but you really have to take care to do it right
15:41justin_smithsveri1: yeah, I am sure hibernate wasn't very cooperative
15:41augustlhibernate is great, you can just think of your objects as in-memory objects and stuff will just work, no problems whatsoever. Right?
15:42zerkms"never modify old ones, and as the db grows, move the oldest ones into a different database" --- we employ the same scheme ^2
15:42zerkmsit's called bitemporal (if someone didn't hear)
15:42zerkmsso you not only have audit for the records but audit for audit as well
15:42justin_smithzerkms: thanks for the lingo :) - I had heard of the technique but not the name
15:44justin_smithzerkms: the wikipedia page for temporal database says postgres supports it directly - is that the db you used?
15:44zerkmshttp://en.wikipedia.org/wiki/Temporal_database#Using_Transaction_time
15:44zerkmswe use postgresql but it's implemented on application level
15:44justin_smithcool
15:44zerkms... in php
15:44zerkms:-D
15:45sveri1augustl: uhm, no, you also have to know about all the quirks you can run into with hibernate, you better read a lot before you use it
15:45augustlsveri1: was kidding ;) Painfully aware of the quirks
15:46sveri1augustl: hehe, I hoped that, but wanted to make sure in case someone thinks, hey, cool, lets just use it :D
15:47justin_smithsveri1: augustl: ever see the wikipedia page for object-relational-impedence-mismatch? parts of it read like a paragraph by paragraph argument between a db guy and a java dev last I looked
15:47sveri1actually, at my current job we decided to do some auditing into database and did it via jdbc, funny moment when the consultants asked why we did not use hibernate and I had to keep calm not starting ranting about it
15:47justin_smithhttp://en.wikipedia.org/wiki/Object-relational_impedance_mismatch
15:47augustljustin_smith: haha
15:50mavbozobesides datomic, are there any temporal database that has in-memory storage?
15:50augustlare there any temporal databases besides datomic?
15:51justin_smithaugustl: the wikipedia page mentions a few, but does not mention datomic at all http://en.wikipedia.org/wiki/Temporal_database
15:52augustlmost of them seems to be audit hacks over row based rdbms-es
15:52zerkmsguys, how would you unit test a function that writes into a channel synchonously? For sake of simplicity let's say it just accepts a channel and writes to it
15:53mavbozozerkms: what's the function output?
15:54justin_smithzerkms: create the channel and a very small block of code that sleeps than reads. Verify that the write was synchronous based on timing, and verify correctness as apropriate.
15:54zerkmsit does not matter in this case. let's say `nil`
15:54zerkmsjustin_smith: what if function is broken and *does not* write to the channel?
15:54mavbozowell, why test a function that already been tested by core.async devs?
15:54zerkmsdoes it mean we would use alts!! in the unit test to save ourselves?
15:54justin_smithzerkms: then kill your unit test, and consider it failed - hanging is clearly failure
15:55zerkmsmavbozo: I'm testing my function, which sometimes may be broken
15:55zerkmsjustin_smith: hm, so how the overall call would look like?
15:56zerkmsand what unit testing framework it is trending?midje?
15:57sveri1zerkms: clojure.test
15:57zerkmsok
15:58zerkmsI've seen people use them together - clojure.test as main assertion library and midje as aux for re-running and some additional check functions
15:59justin_smith(let [then (.getTime (Date.)) ch (chan) reader (go (Thread/sleep 300) ...)] (do-block-write ch) (is (> 300 (- (.getTime (Date.)) then)))) ; this is a general idea at least
15:59zerkmsjustin_smith: yep, exactly like I thought. Thanks
16:00justin_smiththere may need to be a unit conversion in case sleep and .getTime aren't the same unit...
16:00justin_smithI always forget
16:01justin_smith&(- (.getTime (java.util.Date.)) (do (Thread/sleep 300) (.getTime (java.util.Date.))))
16:01lazybot⇒ -319
16:01justin_smithlooks about right!
16:02justin_smithof course you can be all fancy and wrap the time stamping in a more readable function, I like naming it "stamp" as in time-stamp
16:02zerkmsyep
16:02zerkmsI actually asked because I expected unit testing frameworks to already include shortcuts
16:03zerkmssince it looks like a frequent pattern
16:04justin_smithzerkms: hmm, that's a good question
16:06zerkmssomthing like (delayed-call [fn timeout]) perhaps
16:06zerkmserr: not delayed, cannot think of a good name
16:06zerkmstimeouted-call :-D
16:07justin_smitha grep of the midje sources didn't find anything promising at a first scan
16:10justin_smithnor does expectations
16:24dbasch&(System/currentTimeMillis) justin_smith
16:24lazybot⇒ 1416086635094
16:25justin_smithdbasch: I keep forgetting that one
16:26dbaschthere’s also ##(System/nanoTime)
16:26lazybot⇒ 12615169313167376
16:26justin_smith&(> (count "(System/currentTimeMillis)") (count "(.getTime (Date.))"))
16:26lazybot⇒ true
16:26justin_smith:P
16:26dbaschbut do a benchmark :P
16:26justin_smithOP
16:26justin_smithfair point
16:27justin_smithyeah, that creates an object I don't really need, of course that will be slower
16:28zerkms##(System/nanoTime) <--- what ## means here?
16:28lazybot⇒ 12615336358064166
16:29dbaschsurprisingly my benchmark shows they’re almost the same
16:29SagiCZ11zerkms: it just tells lazybot to evaluate what follows
16:32SagiCZ11i am having memory issues again.. it's weird, maybe clojure makes me forget some basic stuff.. but i almost never got a leak in java
16:33SagiCZ11is there anything suspicious memory-wise about this line?
16:33SagiCZ11(with-open [r (io/reader file-path)] (apply str (interpose \newline (next (line-seq r)))))
16:33rs0looks like that will buffer the entire file in memory
16:33zerkmsyou read whole file into memory
16:34SagiCZ11i need to since i want to write it to a different file
16:34justin_smithwell, except for the newline
16:34rs0SagiCZ11: no, you don't
16:34andyfSagiCZ11: str creates a Java StringBuffer and appends to it. Memory-wise, I would expect that to first allocate a separate string for each line of the file, and then append them all, which could require several reallocations.
16:34rs0SagiCZ11: you stream it from one file into another
16:34andyfMaybe you just want slurp ?
16:34justin_smithSagiCZ11: what about string/join instead of apply string on interpose? that should perform much better
16:34SagiCZ11andyf: i would use slupr but i need to omit the first line
16:34rs0SagiCZ11: why not just call a filesystem copy operation?
16:34zerkmsjustin_smith: isn't it the same?
16:34rs0ah, ok
16:34justin_smithno
16:35zerkmsI've read that clojure optimizes them both to StringBuilder
16:35andyfSagiCZ11: Use .indexOf to find the first newline, and then print out a substring of the string in memory
16:35justin_smithzerkms: interpose creates the collection, and then passes that to string
16:35justin_smith*str
16:35zerkmsbut collection must be lazy
16:35justin_smithzerkms: whereas string/join directly works with a stringbuilder, skipping a bunch of intermediate stuff you don't need
16:35andyfsubs will allocate a new string, so you might want to avoid that, and see if there is a way to write out a substring of an existing string without explicitly allocating one, which would require looking up Java docs.
16:36justin_smithzerkms: sure, but str is not, so apply str forces the whole thing
16:36zerkmsyes, but str is built on top of StringBuilder
16:36justin_smithzerkms: sure - but interleave still has to run
16:36zerkmswhich must be as efficient as string/join
16:36justin_smithno
16:36zerkmsok
16:36rs0clearly the solution here is to use (drop 1) as part of a transducer stack
16:36justin_smithinterleave still runs
16:36justin_smithzerkms: the lazy seq still has overhead
16:36dbaschSagiCZ11: all you want to do is write everything but the first line?
16:37SagiCZ11also, i cant leave it lazy inside the with-open call, i have to evaluate it
16:37justin_smithyou are creating cells and immediately throwing them away
16:37SagiCZ11dbasch: i guess? but i am joining multiple files (without their first line) together
16:37dbaschSagiCZ11: still, you don’t need to keep anything in memory except for the line you’re reading/writing
16:37rs0SagiCZ11: just checking--is there a reason you're doing this with Clojure and not a bash script?
16:38SagiCZ11rs0: i know little about clojure and less about bash
16:38andyfSagiCZ11: If you want to make it as memory-friendly as possible, I'd recommend slurp, followed by Java String .indexOf, followed by write a subset of the string without allocating a new one, e.g. the write method that takes an offset https://docs.oracle.com/javase/7/docs/api/java/io/Writer.html#write(char[],%20int,%20int)
16:38dbaschSagiCZ11: by join you mean concatenate all fhe files minus the first line?
16:39SagiCZ11andyf: i see.. i still dont understand how could that not fit into 1 GB of heap space
16:39rs0andyf: why not just use a BufferedInputStream and call readLine? you don't need to index into the string
16:39rs0andyf: er, i'm thinking of BufferedStreamReader. or something. not sure what the clojure equivalents are, if any
16:39andyfSagiCZ11: Actually, if you really want it to be memory friendly, then just alternate reading and writing single characters, or a small string buffer of a fixed size. Don't slurp at all.
16:39justin_smithrs0: all java classes are available in clojure
16:40rs0justin_smith: I realize that, but there are a lot of more idiomatic wrappers around a lot of the java IO classes. slurp and spit are great examples
16:40rs0justin_smith: nobody wants to write new BufferedReader(new InputStreamReader(System.in)) in java *or* clojure
16:40SagiCZ11andyf: yeah i wanted a simple solution, the files in question are 120 MB total, why wouldnt they fit in the heapspace i dont understand
16:41justin_smithrs0: sadly, there is no good wrapper for BufferedReader (I know this because it is needed for read)
16:41andyfSagiCZ11: If you know lines are typically short, you can modify your original example using line-seq to write the line strings inside the with-open, and never append strings together.
16:42justin_smithrs0: and if there were, it would just be a function in clojure.java.io that would be implemented as #(BufferedReader. %)
16:42andyfSagiCZ11: If they are ASCII or mostly so, then note that reading them as strings converts every byte of file into 2 bytes of UTF-16 in Java strings in mem
16:42rs0"short" meaning, say, a few kilobytes
16:42SagiCZ11andyf: i need the files zipped.. i have a function which takes a file name and a huge strings, and creates zip file containg one text file with all the files concatenated together.. i dont think i could zip it line by line
16:42rs0SagiCZ11: if you're writing this as a standalone program for a one-off task, Clojure is almost certainly the wrong choice. you want a scripting language
16:43andyfSagiCZ11: I haven't done it before, but there are Java classes like BufferedReader / writer that can be 'layered' on top of other readers/writers that zip it while streaming through.
16:43dbaschSagiCZ11: that’s trivial in bash
16:43SagiCZ11:(
16:44justin_smithzerkms: about a 4x difference in performance https://www.refheap.com/93437
16:44rs0in bash you could do something like
16:45rs0(for i in file1 file2; sed -e 1d $i) | gzip > output.gz
16:45SagiCZ11i don't even have bash
16:45dbaschSagiCZ11: are you on a windows box?
16:45andyfSagiCZ11: is it convenient to use a shell script in your context? It might save time if so. If it helps to have it in Clojure, it can be done without using much memory.
16:47andyfI haven't used the Java Zip writer/stream classes before, but here is a Java example of some of the classes available: http://stackoverflow.com/questions/4308276/how-to-zip-a-file-while-writing-to-it
16:47SagiCZ11dbasch: yes, sorry
16:47SagiCZ11andyf: i dont know.. i also have functions that recognize the format of the file, and convert it to a correct one and such things, i dont think i could do this in bash when i dont have no experience with it
16:48andyfI don't know of anything already written in Clojure for this. Nothing in clojure.core, I'm almost certain, but there may be a Clojure lib. The thing is, if you know the few Java classes needed, it looks like not many lines of Java interop in Clojure
16:48SagiCZ11it says OutOfMemory exception but i dont see it hitting the heap space limit in jvisualvm..
16:49rs0SagiCZ11: it's also possible that the JVM is trying to allocate an array with too many elements (more than Integer.MAX_VALUE)
16:49andyfa good way to be certain this won't cause memory issues is to write it using methods/classes that process/zip/etc. the file contents as the data flows through, without ever allocating strings containing complete file contents.
16:49rs0SagiCZ11: which you can't fix by increasing your heap size
16:49SagiCZ11it just does this little hop and crashes http://i.imgur.com/mPSVcKV.png
16:50justin_smithSagiCZ11: and the crash is an oom?
16:50SagiCZ11rs0: it says it on Arrays.copyOf call, so that might be possible
16:50SagiCZ11justin_smith: yes, OutOfMemoryError Java heap space java.util.Arrays.copyOf
16:51SagiCZ11whats the max array size in java?
16:51SagiCZ11i have about 1 200 000 elements in it i guess
16:52justin_smithSagiCZ11: IIRC it is ##(Integer/MAX_VALUE)
16:52lazybot⇒ 2147483647
16:52SagiCZ11i see
16:52SagiCZ11so weird
16:52rs0does anyone know how to do this in powershell?
16:54SagiCZ11wait.. if the string is backed by a single array..
16:54justin_smithSagiCZ11: this best answer would be maybe 7 lines of clojure interop tops http://stackoverflow.com/questions/1091788/how-to-create-a-zip-file-in-java
16:55justin_smithSagiCZ11: and it can be adapted to write a fixed buffer size at a time in a loop
16:56justin_smithor a line at a time, or whatever
16:56SagiCZ11thanks..
16:56justin_smithSagiCZ11: note the putNextEntry call - that starts a new file, so you could create arbitrary files as you stream
16:56justin_smith(new file within the same zip file, that is)
16:57SagiCZ11i only ever want one file in one zip file
16:57justin_smitheven easier :)
16:58SagiCZ11i dont like manipulating bytes directly, seems to low level
16:58rs0SagiCZ11: i'm with you on that
17:00amalloySagiCZ11: are you trying to work with zip files? have you looked at https://github.com/Raynes/fs/blob/master/src/me/raynes/fs/compression.clj ?
17:00justin_smithSagiCZ11: something like (let [f (io/file "d:\\test.zip") out (java.util.zip/ZipOutputStream. (io/output-stream f)) e (Zipentry. "mytext.txt") lines (next (line-seq source))] (.putNextEntry out e) (doseq [line lines] (.write out (.getBytes line))) (.closeEntry out) (.close out))
17:01rs0SagiCZ11: i think from a long-term perspective, the best thing for you to do is either to learn powershell or bash (install cygwin since you're on windows)
17:01sveri1SagiCZ11: go the cygwin route, its more portable than powershell
17:02SagiCZ11amalloy: i didnt find anything when i was looking for it, thanks
17:02SagiCZ11justin_smith: thank you
17:02justin_smithSagiCZ11: that code is not guaranteed to work, but should be a decent start if cross referenced with that SO link I posted
17:03SagiCZ11justin_smith: thanks this helped a lot, i didnt know how to do this
17:04justin_smithwhile this is much easier to do in bash, I think the exercise in translating java idioms to clojure interop is useful
17:04SagiCZ11rs0: i definitely do need to learn bash.. you are right, but as justin_smith just said, i need to learn clojure as well, so at least its an exercise
17:05rs0SagiCZ11: if you already know java, you'll get more benefit out of learning bash than out of learning clojure
17:05rs0SagiCZ11: and i'm an enormous fan of clojure
17:05SagiCZ11rs0: and even a bigger fan of bash i see
17:05rs0SagiCZ11: no, it's just a matter of marginal utility. better to know one scripting language and one JVM language than no scripting languages and two JVM languages
17:06SagiCZ11justin_smith: so in your example, if i have 'lines' as an input and keep them always lazy before entering the packing function, the whole string would be never realized in memory, correct?
17:06justin_smithcorrect
17:07SagiCZ11justin_smith: thank you
17:08justin_smithSagiCZ11: I've actually proved this with the profiler before (I may have the code around somewhere) - the clojure compiler can tell when lines can't leave scope, and when it's head is not accessed, and when both of these hold true it does not hold onto used items
17:09SagiCZ11rs0: i have written some bash scripts.. for initializing our company database after boot up and i didnt enjoy it very much.. it all seemed complicated and non-standard. also, since i dont have a linux machine, where you use bash all the time, it would take me a lot of time to learn
17:09rs0SagiCZ11: you can get the basics done with cygwin. bash is weird and mediocre but there's nothing even remotely as useful for day-to-day automation
17:10SagiCZ11justin_smith: i see, thats good stuff
17:10rs0SagiCZ11: i gave you a one-liner that basically uses sed, gzip, and IO redirection to do something that you can't even do in clojure without a nontrivial amount of code
17:12rs0although i think i technically used the zsh for loop syntax
17:12SagiCZ11rs0: but i just gave a minimal example, what i do is way more complicated, also because i dont know all about the source files, i need to explore them and REPL and file-sqeq is fantastic in this, but i guess bash has no problem filtering or printing first lines or anything for that matter
17:13rs0fair enough. but you can do some very very sophisticated things with unix because the tools compose so well
17:14justin_smithrs0: SagiCZ11: right now I am trying to translate a bash script that randomly fails into a clojure program that interconnects program inputs and outputs and makes sure each of those programs stay running. So on the one side I wish using clojure for shell processes were easier, on the other side I wish reliability in shell programs was easier.
17:14justin_smithrs0: very true, regarding tool composition
17:17SagiCZ11justin_smith: one more little thing to the previous topic, with this approach i avoid realizing the whole files in memory, but then i cant use (with-open) on the source file right? i will need to rearange my code to close them manually
17:17justin_smithSagiCZ11: actually that could be adapted to with-open, just take out the close call and move the opening call out to the with-open
17:18justin_smithSagiCZ11: I just tried to keep it literally line by line the same as the java logic
17:18SagiCZ11i mean on my source files not on the destination files
17:19rs0justin_smith: shouldn't that be an Erlang program? =)
17:19justin_smithwell, you could do (with-open [dest "dest-file"])
17:20justin_smithrs0: lemme just go tell the client they can't demo the product on monday because I can't complete my job until I learn erlang first. I am sure that will go over swell :)
17:20justin_smithrs0: in all seriousness, I bet this would be very easy to do in erlang, and I may just spend some time learning it if I keep doing work like this
17:24rs0justin_smith: I'm not sure what you mean by "randomly fails"
17:24rs0justin_smith: are these processes communicating over ordinary pipes?
17:24olivierrrhttps://github.com/functional-koans/clojure-koans/blob/master/src/koans/13_recursion.clj#L4-7
17:25justin_smithrs0: yes
17:25rs0justin_smith: i wonder if you could use a FIFO as the unix equivalent of a BlockingQueue
17:25justin_smithrs0: 3 input sources, each of which multiplexes to 12 data format translators, which each feed an analyzer, which then feeds into a clojure program handling all 36 inputs
17:26justin_smithand yes, this is using fifos at the process / clojure barrier
17:26rs0neat!
17:26justin_smithrs0: the trick is keeping track of 36*2 + 3 programs
17:26justin_smithbecause that's a lot to keep track of...
17:27rs0what do you have to keep track of? just running/dead, so you can nanny processes that fail?
17:27SagiCZ11and how would i add a newline after each line to the zip file?
17:27justin_smithrs0: mostly just running/dead. my shell skills don't scale nicely to that kind of process count
17:28justin_smithSagiCZ11: (.getBytes
17:28justin_smith"\n")
17:28rs0justin_smith: have you found any off-the-shelf solutions that do this kind of multi-process nannying at scale?
17:28justin_smithsorry, hit return by mistake
17:28SagiCZ11so its not \newline anymore?
17:28justin_smithrs0: haven't, no
17:28justin_smithSagiCZ11: \newline is a character, that method expects a byte array
17:28justin_smiththe write method, that is
17:29justin_smithrs0: there is probably some awesome tool that would make this simple and I have been wasting my time :)
17:29rs0justin_smith: have you looked at Upstart?
17:29SagiCZ11so it would be (.getBytes (s/join line "\n")) ?
17:29rs0justin_smith: or even conventional init.d scripts?
17:30justin_smithrs0: so I set up 75 init scripts?
17:30justin_smithrs0: an init script ensures that one program is running, as I understand it
17:31rs0justin_smith: i'm wondering if Upstart is more sophisticated than its system v ancestor. the "asynchronously start a process and then nanny it in case it dies" aspect of Upstart seems like it might be a good fit for your problem. but i don't know what else it's complected with
17:33justin_smithrs0: I can't reinstall the os, it is OpenSuSe 11.1
17:33justin_smithI don't think upstart runs on that
17:34SagiCZ11,(.getBytes "hello")
17:34clojurebot#<byte[] [B@bf47df>
17:34SagiCZ11,(.getBytes (conj "hello" "\n"))
17:34clojurebot#<ClassCastException java.lang.ClassCastException: java.lang.String cannot be cast to clojure.lang.IPersistentCollection>
17:35rs0,(.getBytes (str "hello" "\n"))
17:35clojurebot#<byte[] [B@1905335>
17:35justin_smithSagiCZ11: why not just output the "\n" as a separate write step?
17:35SagiCZ11justin_smith: why not indeed.. havent thought of that.. that way i avoid another array copy
17:37llasram&(let [{:keys [:foo]} {:foo "bar"}] foo)
17:37lazybot⇒ "bar"
17:37llasramIs that intentional
17:37llasram?
17:37Bronsayes
17:37Bronsasince 1.6
17:37llasramOk, good
17:37Bronsait's to support destructuring of :: style keywords
17:37llasramThat's what I thought + vaguely rememered
17:38Bronsa,(let [{:keys [::foo]} {::foo "bar"}] foo)
17:38clojurebot"bar"
17:38llasramExplicitly namespaced symbols work too, but namespace aliases aren't resolved, which makes them rather more clunky :-(
17:38Bronsayeah
17:39akhudekhmm, so honeysql doesn’t support unions or intesections it seems
17:39SagiCZ11after all the changes i no longer have any memory issues... thank you all for the ideas, tips and help
17:42olivierrrhttps://github.com/functional-koans/clojure-koans/blob/master/src/koans/13_recursion.clj#L4-7
17:42olivierrrstuck on that koan, anyone got some hints?
17:42Bronsaolivierrr: is 0 even?
17:43olivierrri think so
17:43Bronsaolivierrr: and if n-1 is even? is n even?
17:43llasramolivierrr: May also help to notice that they pretty clearly only expect a solution which works with non-negitive integers
17:43olivierrrBronsa: no
17:44Bronsaolivierrr: you just solved that koan then, just write those answers in the clojure code
17:44llasramOh geez, Github's syntax-highlighting for Clojure is still kind of crazy
17:47akhudekdoes anyone know of something like honeysql that does support union?
17:47olivierrraah, got it Bronsa, thanks
17:47Bronsaolivierrr: np
18:06technomancyllasram: I heard they stopped using pygments in favour of textmate highlighters
18:07technomancyhttp://p.hagelb.org/sisko.gif
18:07llasramAn interesting descision
18:07technomancytextmate. highlighters.
18:07llasramI'm sure they had legitimate reasons
18:08derpdoes anyone here use ergoemacs for clojure development?
18:10technomancyderp: in general "starter kit" type things cause lots of problems and aren't widely recommended here
18:10technomancy(speaking as the creator of the first starter kit)
18:36andyfBronsa: Holy cow. I just ran latest Eastwood against clojure.core and it didn't throw an exception. I haven't tried in almost a year.
18:38Bronsaandyf: nice!
18:40andyfI was updating some slides about Eastwood for hiredman to use at the Conj if he wants them, was writing some exceptions that we do not test against, and decided to double-check whether it really is still a problem. I had assumed it would always cause problems for one reason or another, what with all that early bootstrap code, and defining fundamental macros.
18:41Bronsaandyf: well t.e.jvm has been able to compile clojure.core for a while now so it makes sense that eastwood does too
18:42andyfok, didn't realize that.
18:42andyfNo bugs found :)
18:42andyflots of warning, but not bugs
18:43Bronsaonce I get to fix tanal-100 I'll release t.a/t.a.j 0.7.0
18:48Bronsaandyf: FYI it is highly likely that in the next release :raw-forms will store info about the fully resolved var name, I still haven't made up my mind on what's the best approach
18:49andyfok. You may have noticed that I have :eastwood/partly-resolved-forms added in Eastwood, since it is useful in some places to avoid mistaking which Var is first.
18:50andyfIt only resolves the first var in each :raw-forms element
18:51Bronsaandyf: I have indeed. And I'd be happy to keep it as is if it wasn't that it's possible - even though unlikely - that the ns env mutates during macroexpansion, possibly making a later resolve-var inconsistent with the one that originated the macroexpansion
18:51allenj12has anyone here used enclog before?
18:51allenj12https://github.com/jimpil/enclog
18:52andyfBronsa: the stuff of nightmares
18:54Bronsaandyf: and then there's always the issue that since the macroexpander is open, I have to be careful with the assumptions I make in t.a about what macroexpand will return
18:55Bronsaandyf: ideally the best approach would be to let the macroexpander guide :raw-forms, but I'm still trying to decide if complicating the impl is worth it
18:56Bronsat.a.jvm's macroexpander is already quite complex with all the desugaring it needs to to
18:57andyfI'm collecting a few statistics for the updated eastwood slides. Didn't realize I've filed 73 tickets on tools.analyzer. Looks like my 'batting average' (baseball term) is 58/73=0.795 for non-declined/duplicates :)
18:57Bronsaheh
19:52derpdoes someone have an emacs config streamlined for clojure dev
20:11derp:technomancy haha I actually used your starter kit!
20:13derp:technomany thanks for telling me to be weary of starterkits
20:54arrdemI should open source my emacs config at some point...
20:54arrdemfor *nix hosts it's modular enough to be a "starter kit" within reason
20:54technomancydown that road lies madness
20:55technomancybut it's good to have something from which others can steal ideas
20:55technomancynice to be able to just drop a URL in chat too
20:56arrdemeh it's madness only if open srcing makes you clean/maintain it beyond what you find usable
20:57technomancyjust don't let anyone use it as a starter kit
20:57technomancythe moment you get a pull request, burn it to the ground
21:12oskarkvHm does anyone know of a way/tool to get a dependency graph of dependencies between functions?
21:13gfredericksI have a half-assed library that does that
21:13gfredericksalthough I guess if you didn't mean visualization in particular it might not be as helpful
21:14gfredericksmaybe you could rip some code out of it
21:14gfrederickshttps://github.com/gfredericks/clj-usage-graph
21:15gfredericksoskarkv: ^
21:15oskarkvgfredericks Thanks i'll take a look. I wanted to visualize my own code. :P
21:20csd_Is it bad style to use an atom within a let statement, and mapping an anonymous function that increases the atom as it operates?
21:23dnolen_csd_: generally bad style unless there's a really good reason
21:24gfrederickscsd_: it smells like reduce
21:24csd_just rewriting some CL that does the same thing, curious what would be idiomatic clojure
21:24csd_i'll see if i can use reduce
21:37andyfSometimes (like now), I wish I had something like with-out-str, except it limited the size of the string produced to a max specified length in chars, to keep the output (intended for debugging) short. Ideally it could even allow the body that prints the output to stop immediately if it reached that limit, but I'm guessing that isn't easy or even possible to implement.
21:38gfredericksa special print-writer thing?
21:38gfredericksit could throw an exception when you get to the limit
21:39gfredericks(throw (ShutUpError.))
21:41andyfgfredericks: I guess I could write a new subclass of StringWriter ...
21:41gfrederickseverything is solvable via another subclass of something
21:42justin_smith gfredericks: could one write a useful program where the only thing you do is make subclasses of things/
21:42gfredericksI believe so
21:42gfredericksperhaps in the context of a subclassing framework?
21:42justin_smiththis would be an interesting esolang maybe
21:42gfredericksdo we get to use interfaces too?
21:42justin_smithhmm
21:43andyfand yeah, throw an exception if it hits the limit, thrown from the append method or something like that, and document the behavior so people hopefully won't use it for capturing output of code that fails to clean up if the exception is thrown
21:43gfredericksandyf: you gonna throw this in a real-life for-other-people library?
21:43justin_smithandyf: with-lazy-charsequence, using a lazyseq of char?
21:44andyfNot yet, anyway.
21:44andyfMy current desire is that I like to use clojure.inspector to examine tools.analyzer ASTs, but sometimes the strings produced are so long that it is too slow or memory-intensive.
21:44andyfIn those cases, I won't be looking at the entire contents of the strings anyway, only the first 200 chars or so.
21:44gfredericksthose ASTs are not very tree-like
21:45gfrederickslast time I looked at them
21:45andyfnot sure I see why they aren't tree-like
21:45gfredericksandyf: I think there's supposed to be a cider something-something for this use case
21:45andyfsome kind of cider data-inspector?
21:46gfredericksandyf: I meant not tree-like in the sense that they have a lot of objects that appear multiple times
21:46gfredericksandyf: yes
21:46andyfit is an implementation detail whether those things are identical or not :)
21:46andyfbut it is a lot faster that they are identical
21:46gfredericksit might not fit in memory otherwise
21:47gfredericksand it might not reasonably print regardless
21:47andyfsure, DAG in implementation, but tree as represented in the inspector. I remove a few keys throughout before inspecting them, most times, and it is useful to use an ordered-map from the useful lib to guarantee keys are in a particular order, for debugging.
21:48gfrederickssuch like ##(nth (iterate (partial repeat 10) 42) 10)
21:48andyfI'll remember the cider thing for possible future reference, but that is a yak I don't want to shave today
21:48lazybotjava.lang.OutOfMemoryError: Java heap space
21:48andyfI'm strictly emacs+clojure-mode now
21:48gfredericksminimalist
21:48justin_smithandyf: with inferior-lisp?
21:49andyfI pick my battles, and cider sounds like a hassle I don't want yet
21:49andyfjustin_smith: Eastwood I test so often from the command line, I am (gasp!) often debugging with printf and re-run
21:50justin_smithandyf: ah, so not even inferior-lisp then.
21:52andyfPerhaps I should make a slide including this to demonstrate my development workflow, where I'm one of the cavemen in front: http://s238.photobucket.com/user/JeffreyBSG/media/cavemen_zps869695fb.jpg.html
21:52andyfBut I look more like the guy in the back
21:52andyfcan't say I actually feel the pain of what I'm doing, if there is any. Gets the job done.
21:55justin_smithandyf: the main thing I would miss is auto-complete
21:56andyfemacs dynamic-abbrev works
21:57andyfalthough maybe the auto-complete you mention does something dynamic-abbrev does not
21:57justin_smithandyf: does dynamic-abbrev complete names that you require from libraries but don't have open in buffers?
21:58andyfno, so that is a difference
21:58andyfI don't close many buffers, though, and have same emacs running for weeks at a time
21:58justin_smithandyf: oh, that is the name for what M-/ does!
21:58justin_smithI use that often
21:59josiah14granted I already have a working underrstanding of Java, Ruby, and Haskell, what's the relative difficulty in learning Clojure? Is it something I could power through a tutorial on in a week or two and then figure out something like the Caribou framework in a month or less (given I have used Rails, but not anything for Haskell like Snap)
21:59justin_smithjosiah14: if you know all three, it will just be the syntax. And the syntax is very simple.
22:00josiah14hmm. cool
22:00justin_smithI mean clojure has its quirks, anything does
22:00justin_smithbut I don't think it has much that one of those doesn't, other than lispy syntax
22:01andyfjosiah14: A book like Emerick et al's Clojure Programming would be handy
22:01josiah14i was reading on some websites that those new to Clojure might have trouble picking up something like Caribou, but I didn't know if that was because the assumption is that newcomers would be unfamiliar with FP in general, or whether it was relatively Clojure specific
22:01scottjor braveclojure.com if you must have something free
22:01andyfbut not necessary
22:01justin_smithjosiah14: I am one of the Caribou authors, fyi the more common approach in clojure is to use something lighter weight
22:02josiah14So I gathered as I browesed through the various frameworks out there
22:02josiah14what's the main reason for that?
22:02josiah14justin_smith: ^
22:03justin_smithjosiah14: the general clojure preference is to use small composible libs
22:03justin_smithcaribou is modular, as much as we could make it so, but really we didn't design it to be lightweight
22:03josiah14makes sense, I would expect that to be a trend in any functional language, come to think about it
22:03justin_smithjosiah14: but for the specific niche we developed it for, it can be pretty great if I may say so myself. That niche being making websites where the frontend guys don't do clojure, and rapidly getting an admin / cms up and running where a client or producer can upload content from the getgo
22:04josiah14although Haskell frameworks tend to be somewhat sizeable for some reason
22:04justin_smithjosiah14: in fact in clojure "framework" isn't even a popular term
22:04josiah14justin_smith: that sounds like a use-case i would be interested in
22:04josiah14similar to the problem Rails tries to solve, justin_smith
22:05justin_smithyeah - it was developed as a replacement for rails that did not require as many server resources, and with a lot less magic
22:05josiah14justin_smith: I like the sound of that
22:06justin_smithjosiah14: cool! I hope you found the docs, they are comprehensive. I am usually in #antler, and sometimes the other devs are too. We were funded by a company we worked at to work on caribou, but that project ended and we went our separate ways, so caribou development is much slower now. But I still work with it and sometimes even make updates.
22:06josiah14justin_smith: At first, I was considering using something like MFlow or Yesod, but I want to get this site up and running relatively quickly and easily, and without Heroku being easily accessible with Haskell (I know I could compile a binary, but I don't really want to go down that road), Clojure started looking a lot more attractive
22:07justin_smithjosiah14: yeah, technomancy has made sure uploading to heroku is easy
22:07justin_smithjosiah14: another thing is that due to being jvm based, and having really easy interop, it is very easy to deploy clojure webapps to aws elastic beanstalk
22:07justin_smithor any other turnkey apache tomcat based thing really
22:09josiah14justin_smith: that sounds relatively nice. Although, to hear that development is slowing is maybe a little concerning in that I think this site may potentially have to last for a while and be able to flex and develop
22:09justin_smithjosiah14: no matter what you use - caribou or not, heroku or aws or whatever else, if you are doing a webapp in clojure you will likely be using ring btw, and it is worth looking at the basics of using ring
22:09josiah14cool, I'll definitely be doing that. everything I have seen seems to be built on top of Ring
22:10justin_smithjosiah14: we've slowed down a bit with new features, but I have had no stability issues with deployed caribou sites, if that helps at all :) but things like liberator are pretty intreguing
22:10josiah14justin_smith: I may peek at Liberator. It sounds familiar.
22:11josiah14justin_smith: How is caribou at parallel request processing?
22:11justin_smithjosiah14: depends on the server implementation, but the throughput is very good (depending partially on how you use /cache the db of course)
22:12justin_smithjosiah14: I like standalong http-kit a lot
22:12josiah14justin_smith: sounds like it's worth at least a download and experimentation
22:12josiah14I must go, but this has been really helpful. Thanks, justin_smith
22:13justin_smithjosiah14: yeah "lein caribou new" gets you an app that immediately runs and has an admin up to play with
22:13justin_smithjosiah14: np
22:13justin_smithjosiah14: err, I mean "lein new caribou"
22:19oskarkvgfredericks how does clj-usage-graph/generate normally take? It has like run for a minute and tools.analyzer is still working
22:20oskarkvhow long*
22:33oskarkvgfredericks something called filtered_tree_seq$walk just keeps calling itself :P
22:34justin_smithsounds like a cyclical dependency? but technically those aren't allowed in clojure...
23:05marchdownI’m learning clojure and I seem to misunderstand I/O facilities. I want to read a number of lines to loop through from stdin, then, well, loop through them. Here’s what I’ve got so far: https://gist.github.com/marchdown/d1388e064570439a39fb but recur says that’s not a tail position. What am I doing wrong?
23:05oskarkvmarce808 with while you don't need recur, I'm pretty sure
23:05oskarkvmarchdown
23:05jeremyheilermarchdown: I think you want "when"
23:06jeremyheilernot "while"
23:06marchdownDidn’t work with when either.
23:06andyfalso (recur t (dec t)) instead of the recur you have
23:07oskarkvmarchdown you seem to have one too few ) on the println line
23:07andyfwait. You want 2 values in the loop, one an integer and one a string?
23:07marchdownI can use lein but I can’t find clojure.jar or clj in my PATH on osx :/
23:07marchdownso how do I test it quickly? I’ve been using lein repl and repl in LightTable.
23:08andyfOh, you want to read an integer from the first line? (read-line) returns a string, not an integer. Need something like (Long/parseLong (read-line)) to assign as initial value to t in loop binding
23:09marchdownandyf: how about (loop [t (Integer/parseInt (read-line))] ?
23:09andyfand then you want (recur (dec t))
23:09andyfmarchdown: that will work, too, as long as the number fits in a 32-bit signed int, which it most likely does
23:10andyfrecur gives new values for loop names, always in order they are in the loop line, so don't use names in recur
23:10oskarkvmarchdown you probably want to put the loop in a function that you can call to try it
23:11oskarkvthen you can call it from the repl
23:12andyfoskarkv: Although I'm not so sure reading stdin from REPL always works cleanly, depending on which way you start the REPL
23:13oskarkvandyf oh ok, don't usually do that :P
23:13marchdownso… how do I run it so that stdin/stdout work as expected?
23:14oskarkvmarchdown try it from the repl, if that works it's the easiest
23:15oskarkvor you could use `lein run` maybe
23:18andyfmarchdown: I don't do this often, but if you don't mind going through a few setup steps, lein-exec may be useful for creating Clojure programs you run from the command line: https://github.com/kumarshantanu/lein-exec#executable-scripts (that is the middle of the docs, scroll up to start from the beginning)
23:19andyfIgnore lein 1.x instructions, assuming 'lein version' output on your system says you have version 2.x.y
23:19marchdownhmm thanks
23:19technomancystdin should work from lein repl these days
23:20technomancyand most lein-exec usages can be reduced to an alias that points to lein run -m clojure.main
23:21andyftechnomancy: Doesn't lein run -m clojure.main require running it from inside of the lein project directory?
23:22oskarkvmarchdown how did you indent the code in that gist btw? It was not "correct", and it would have helped you if it was
23:24technomancyandyf: no, it works anywhere now
23:24marchdownoskarkv: thanks. I’ve pasted it from an html form. I’ve a version in a lein project locally, which I’m currently trying to massage into executable form.
23:24technomancyandyf: provided there are no deps
23:26marchdownlein run *arg* seems to work.
23:26oskarkvmarchdown ok but you were using LightTable? It should be able to indent correctly for you, probably
23:26marchdownNow for stdout and when/while/recur stuff.
23:27andyfmarchdown: while is a loop by itself, so unless you need a nested loop don't do while inside loop
23:28andyfuse if, when, or some variant of those to detect your continue-the-loop condiiton
23:31marchdownNope, neither while nor when work for me here. How is that not tail position?
23:32marchdownandyf: should I then use a let form outside while?
23:32andyfis your code still parenthesized as in your first gist?
23:32marchdownyes
23:33andyfdid you read the comment above about incorrect parens?
23:34andyfwhat editor are you using?
23:34marchdownvanilla emacs and sometimes LightTable.
23:35andyfNo auto-indenting when you press tab key at the beginning of a line?
23:35marchdown^^ Not sure. I’ve rejiggled it around and rewrote it a couple of times meanwhile. But there’s a general pattern of (let [t (read-me-a-number)] (do-stuff) (recur (dec t)))
23:36andyfgeneral patterns are thrown off pretty badly if the parens aren't right :)
23:36marchdown:)
23:37andyfis it set up to show you the matching paren whenever the cursor is on a paren? Such little niceties are not 100% necessary, but they can improve checking such things 10-fold.
23:37andyfalso setting up auto-indenting for Clojure code can have the same benefits in alerting you to incorrect parentheses
23:37marchdownWhat I seem to misunderstand now is how to keep the scope as narrow as possible, read a bunch of stuff with loops and conditionals.
23:38marchdownMaybe I’m thinking of let-forms wrong.
23:38marchdown^*about let-forms
23:38andyfThe general structure of (loop [t <number>] (when (pos? t) <something> (recur (dec t)))) is correct for what you want
23:38andyfas long as the parens match around the <something>
23:39marchdownOK, thanks.
23:39marchdownI see, I have one closing paren missing.
23:39andyfif they are off around the <something>, and you make up the difference at the end, then the recur can wind up as a sub-expression of the <something>, and then it likely won't be in tail position.
23:40andyfright. the suggestions for setting up editor for auto-indenting with tab at beginning of line, and for highlighting matching parens, can help you quickly catch such mistakes.
23:40TEttingerandyf: when is wrong there
23:40marchdownBut shouldn’t recur be inside the inner loop if there are several?
23:40TEttingererr maybe
23:40TEttingeris it supposed to recur if the number is not positive?
23:40andyfSo you don't need nested loops for this case.
23:40amalloyTEttinger: no, it's a correct translation of the original code
23:40TEttingeroh ok
23:41amalloywhich was (loop [...] (do whatever) (if x (recur)))
23:41andyfIf you had a case needing nested loops, recur is always matched with the closest loop expression that the recur is inside of
23:43andyfIn Clojure, (loop ...) doesn't loop unless it has at least one occurrence of recur inside of it.
23:43amalloymarchdown: also, since you are using emacs anyway, i recommend trying out paredit-mode. it makes it impossible to have unbalanced parens
23:43amalloyit's a bit of an adjustment to get used to, so maybe don't try it if you are already feeling overwhelmed with other stuff, but you should try it eventually
23:44marchdownamalloy: I’m procrastinating on paredit because of keymap conflicts. I know that’s the proper way to do work.
23:44amalloyinteresting. what conflicts?
23:45amalloy[unhelpfully derailing the actual productive conversation]
23:45marchdownI’ll get back to you after I waste another evening on this :)
23:58marchdownhow do I reload core.clj from lein repl? (use :something)..?
23:59marchdown(use appname.core :reload), is that it, or is there a better way?
23:59oskarkvmarchdown i like tools.namespace :P