#clojure logs

2015-12-24

00:00devthgood point. i should start doing that.
00:00justin_smithlike I might have :sql/db and :mongo/db as two bindings in the same config
00:00devthcool
00:00justin_smithdevth: in practice you want to minimize the amount of code that uses the config map
00:01justin_smithmostly you should be able to use pure functions that don't need config
00:01devthin my chat adapters, almost everything i care about doing is side-effectful :)
00:01justin_smithbut some functions need to guide or negotiate stateful stuff, or interact with the real world, and they all need the config
00:01devthrecieve messages, list users, list channels, post messages, connect, disconnect
00:02justin_smithdevth: it doesn't need to be that way, there are ways to do pure calculations on data structures, and derive the side effects at the system boundary. This tends to lead to contagious sanity.
00:02devthusing free monads? :)
00:02justin_smithheh, if you want to use that terminology you may, but I don't think I am talking about that specific thing
00:03devthi haven't really seen clj in that style
00:03justin_smithdevth: I was thinking more of eg. what they call the interpreter pattern - in your pure code you build up data describing your decisions / needs. Then at the system boundary you do all the side effects this implies, and propagate the resulting data back to where it might be needed.
00:04justin_smithdevth: reagent is a good example of this
00:04devthlike haskell
00:04devthcool
00:04justin_smithdevth: in clojure it's a little more ad-hoc, we don't have the implicit stuff haskell gives you
00:04justin_smithbut hey, less magic is good right?
00:05devthdepends on the magic :)
00:06neoncontrailsjustin_smith: I just jumped in, in what way is Clojure less magical than Haskell?
00:06justin_smithneoncontrails: no monads!
00:07neoncontrailsjustin_smith: is an atom not a monad?
00:07justin_smithneoncontrails: so you need to explicitly pass the pure context describing operations to the boundary layer code that does effects, if you want that kind of design
00:07TEttingerScala's implicit keyword is also pretty much forbidden blood magic
00:07sohailjustin_smith: I tried the following where src/cljs/test.clj exists: http://pastebin.com/tb2JdHMC
00:07devthi.e. clj is not a pure FP lang like haskell
00:07sohailbut when starting the repl, I get clas not found exception: test.repl
00:08justin_smithsohail: right, you haven't required test.repl yet
00:08devthTEttinger: implicit is what powers type classes in scala :)
00:08sohailjustin_smith: how do I do that?
00:08neoncontrailsIn what way does Clojure's atom type differ from monads in Haskell?
00:08justin_smithsohail: with the require function, of course
00:08neoncontrailsIt seems like the motivation is very similar.
00:09devthmaybe similar motivation, but with an atom actual mutation is happening. just happens to be thread-safe.
00:09TEttingerdevth: and it does totally different things depending on where it occurs
00:09devthTEttinger: yeah, can be a night mare
00:09justin_smithneoncontrails: a monad carries an implicit context between chained operations, an atom manages shared state between threads. There are specific monad using things in haskell that are much like clojure atoms, but I don't think it's an apple to apple comparison.
00:10devthmonads let you simulate imperative-style coding while still being pure
00:10justin_smithneoncontrails: for the IO monad in haskell, you cannot do operations that interact with the real world outside of the monadic context that chains effects
00:11justin_smiththis is very different from clojure, where we can easily insert a println call into any function we like
00:11devthand even when you use the IO monad, you're not performing side effects. you're describing them. it's up to the haskell runtime to perform them for you.
00:12justin_smithdevth: exactly - you are building up a description of the tasks, the compiler decides how it all works out
00:12justin_smithand you can even do pure operations to build those chains of task descriptions
00:13justin_smithsohail: you can use the require function
00:13justin_smith,(doc require)
00:13clojurebot"([& args]); Loads libs, skipping any that are already loaded. Each argument is either a libspec that identifies a lib, a prefix list that identifies multiple libs whose names share a common prefix, or a flag that modifies how all the identified libs are loaded. Use :require in the ns macro in preference to calling this directly. Libs A 'lib' is a named set of resources in classpath whose contents...
00:13neoncontrailsGotcha. devth: so what you're saying is that swap! functors are still mutative, because they're changing the value associated with the atom, even if they're not changing the literal contents of the atom?
00:14devthnot sure what you mean by changing value vs literal contents. aren't you changing the literal contents?
00:15devthatom is a container right? you can put things in it. and mutate them.
00:15justin_smithneoncontrails: value vs. identity - atoms change value - have different contents - do not change identity
00:16neoncontrailsdevth: my understanding is that swap! just creates a new data structure and changes the pointer, so the old one can still gracefully persist, eventually to be garbage collected
00:17neoncontrailsthis could be wrong, of course
00:17justin_smithneoncontrails: swap! does not change the identity, but it does replace the contents
00:17justin_smithI think talking about pointers here only muddies the issue
00:17devthright. i didn't mean mutate the data structure inside of an atom. i mean change the value of an atom.
00:18justin_smithbut you are right, it does not mutate the contents, it replaces them
00:18neoncontrailsgot it. I think we're on the same page
00:19devthnow i'm thinking about transients inside of atoms :)
00:20justin_smithtransients are allowed to mutate, but make no promise to do so, and correct code must be written as if they did not mutate their contents
00:20devthyeah. too bad correctness verification is left up to humans in this case.
00:20justin_smithyes, this is the general theme of the differences between haskell and clojure
00:21justin_smithin haskell, the machine will enforce all sorts of things for you, but there's more effort needed to describe things in the proper way that makes haskell's compiler happy
00:33justin_smithI found the primate Rich Hickey https://www.youtube.com/watch?v=Snl4U8HPdtQ TEttinger did you know apes could tie knots?
00:35TEttingerhttps://www.youtube.com/watch?v=EMbWDRzqNhc
00:36TEttingerprimate prometheus
00:37justin_smithTEttinger: oh, *that* promethius - the earlier horrifying stuff we were talking about had me worried for a moment
00:37TEttingerhaha
00:39justin_smithTEttinger: man if I had to choose from being able to put up a hammock or start a fire, I don't even know which one I would pick
00:39TEttinger"he likes the taste of cooked food"
00:45TimMcOK, maybe I'll go with "earnest".
01:08justin_smithoh wow, I almost want to throw a script at this page http://christmasinfairbanks.com/
01:10turbofailneeds sandstorm playing in the background
01:10justin_smitheasy enough to fix
01:11turbofailand a script to sync the lights to it
01:11justin_smithyou could take over a light via a PWM derived technique
01:12justin_smithyou send repeated commands for a given light
01:12justin_smithif you want the off state, you leave it off longer than on
01:12justin_smithif you want the on state, you leave it on longer than off
01:13justin_smitheveryone else with their individual clicks would hardly effect things at all
01:14turbofailuntil somebody else gets the same idea anyway
01:14justin_smithheh, right
01:29mindbender1How best to apply a sequence of functions to an object?
01:29mindbender1I need the output of the previous fn to be the input of the next and yet I don't know the actual fns until run time.
01:30turbofail((apply comp [- (partial + 3) (partial * 10)]) 1)
01:30turbofail,((apply comp [- (partial + 3) (partial * 10)]) 1)
01:30clojurebot-13
01:31rhg135reduce
01:32rhg135comp too
01:34mindbender1rhg135: example?
01:34turbofail,(reduce (fn [a f] (f a)) 1 [- (partial + 3) (partial * 10)])
01:34clojurebot20
01:35mindbender1turbofail: I gues I need to reverse a normal list to apply'ing comp to it?
01:35mindbender1*before apply'ing
01:36turbofailno, a normal list works the same way
01:36turbofail,((apply comp (list - (partial + 3) (partial * 10))) 1)
01:36clojurebot-13
01:36turbofailif you're going to use reduce you'd need to reverse the sequence of functions relative to how you'd use it with apply comp
01:38mindbender1turbofail: okay. thanks
01:53TEttingerso... lein repl seems to be completely clueless about unicode on windows
02:00TEttingerjustin_smith: your prior recommendation of java -jar clojure.jar works fine though
02:33visofhi guys
02:33visofhow can i connect to the current clojure process from repl?
02:34visofand interact with the loaded in memory variables
02:36turbofailyou can only do that if you're running an nrepl server in that clojure process
03:47jonathanjcan't you use liverepl to connect to it even if you're not running an nrepl?
03:48jonathanjhttps://github.com/djpowell/liverepl
03:48jonathanjStart a Clojure REPL connected to any running Java or Clojure process
03:48jonathanjwithout needing the process to be setup in any special way beforehand.
04:31domgetterAre there any good Youtube videos showcasing this "repl development" thing I keep hearing about?
04:33jonathanjcan i use `memoize` with defrecord or reify?
04:33domgetterI'm under the impression that it's something more than just firing up lein repl and typing in stuff. Then it'd be no more than irb. If there aren't any good youtube vids, lemme know if you know any good blog posts explaining it
04:38domgetterjonathanchu: I don't think so because memoize takes a referentially transparent function, and defrecord and reify are both macros.
05:19jeayeIs there a cleaner way to do:
05:19jeaye(into [(nth item 0) (nth item 1) (nth item 2)] (some-data))
05:19jeaye(take 3 item) gives a list, but I need a vector.
05:24domgetterjeaye does this cut it? (into [] (take 3 (range)))
05:25jeayedomgetter: I also need (some-data) to go in.
05:25domgetterjeaye what is (some-data) ? a list? vector? map?
05:25jeayeboth item and (some-data) are vectors.
05:27domgetter,(into [] (take 3 (concat [3 4] [ 7 8 9])))
05:27clojurebot[3 4 7]
05:28jeayeah, close
05:28jeaye,(into [] (concat (take 3 [1 2 3 4 5]) [4 5 6]))
05:28clojurebot[1 2 3 4 5 ...]
05:28jeayeMore accurately represents my issue, but concat will do it.
05:28jeayeThanks, domgetter
05:28domgetterah you wanted the first three and then all of some-data. got it
05:28jonathanjcan i provide a default implementation for a protocol method?
05:29domgetterand also, concat is lazy
05:29domgetter,(into [] (take 5 (concat (take 3 [ 5 6 7 8]) (range 1000000))))
05:29clojurebot[5 6 7 0 1]
05:30jeayeDoesn't affect anything, in this case.
05:30spaceplukis there any good commandline autoformatter I can use with vim?
05:31jeayespacepluk: gg=G
05:31jeayespacepluk: Or do you want more?
05:31spaceplukjeaye: I'm using that but it doens't work when the code is in a single line (aka. stuff from the repl)
05:31jeayeRight.
05:32jeayespacepluk: You can easily hook one up using pprint
05:32jeayeIt allows you to set max width and the like. I haven't seen any that're vim-ready.
05:33spaceplukdoes pprint indent "code" taking into account special forms, etc?
05:34jeayeHm, no, it doesn't take into account special forms.
05:35ridcullyspacepluk: cljfmt?
05:36jeayespacepluk: If you get something hooked into vim, ping me. I'd be interested in using it.
05:36spaceplukjeaye: sure :)
05:38spaceplukridcully: I'm trying that, thanks
05:44domgetterWhat is an "nrepl server"?
05:44spaceplukoh, it has the same problem with huge single line expressions
05:45domgetterwhat sorts of things can connect to the "nrepl server" that lein has created when I ran lein repl?
05:52spaceplukdomgetter: usually you evaluate stuff in your program straight from your editor
05:53spaceplukdomgetter: so you can change things while the program is running
05:53spaceplukdomgetter: or inspect the program's state
05:55domgetterspacepluk: I'm not sure what you mean. " straight from your editor " You mean like a watchter? Or copy-paste? or something else more magical?
05:55spaceplukdomgetter: this is clojurescript but is very illustrative -> https://www.youtube.com/watch?v=KZjFVdU8VLI
05:56domgetterSo does Figwheel load the whole file over again?
05:57spaceplukfigwheel yes
05:57spaceplukbut you can evaluate only parts if you want to
05:57domgetterand I thought Figwheel uses websockets to do it's job. Is that not the case?
05:57spaceplukyou can use it with nrepl with piggieback
05:58spaceplukit's a bit tricky though
05:58domgetterI don't understand that statement
05:58spaceplukhttps://github.com/cemerick/piggieback
05:58domgetter"You can use it with nrepl" I don't even know what this means
05:59domgetterI read that nrepl was a network repl, and I don't know what a network repl is
05:59spacepluknrepl runs on the jvm
05:59spaceplukyour program runs the nrepl server
05:59spaceplukand you send expressions to evaluate through the network
06:00domgetterOkay. "nrepl runs on the jvm" I understand what this means. "your program runs the repl server" I'm lost again.
06:00domgetterIf the jvm runs nrepl, how does my program run nrepl?
06:01spaceplukbecause the are in the same jvm instance
06:01domgetterso does my program run it, or does it just interact with it?
06:01spaceplukor if you're using clojurescript then the jvm runs nrepl+piggieback and you program runs somewhere else
06:01ridcullyspacepluk: you mean, you have a huge oneliner in your vim, you save it while the cljfmt plugin is on and it wont format that line properly?
06:01spaceplukdomgetter: they run side by side as far as I can understand
06:01spaceplukridcully: yes
06:02ridcullyhow long is that line? i have not used it other than regular code
06:02domgetterspacepluk: okay. so "you send expressions to evaluate through the network".
06:02domgetterI send (+ 2 3) from where to where?
06:02spaceplukridcully: stupidly long hehe, it's an edn I get from the repl as one line
06:03spaceplukdomgetter: from some nrepl client (your editor, leiningen's console, etc.)
06:04jeayespacepluk: Maybe you want vim-fireplace.
06:04domgetterspacepluk: Wait, isn't leiningen running an nrepl server? Or is it doing both at the same time?
06:04spaceplukjeaye: I'm already using that :)
06:04domgetternREPL server started on port 60261 on host 127.0.0.1 - nrepl://127.0.0.1:60261 is what I get when I run lein repl
06:04ridcullyspacepluk: have you tried running it standalone. never used it - but iirc you can also use it from lein (cljfmt that is)
06:04jeayespacepluk: Then, instead of using the repl, you can use vim and properly format your code.
06:04spaceplukdomgetter: I think the console is also a client but I'm not sure
06:05domgetterspacepluk: alright no prob. Thank you for taking time to explain this to me
06:05spaceplukdomgetter: np :)
06:08spaceplukjeaye: the problem is that oneliners aren't formatted properly afaict
06:08spaceplukridcully: I'll try that in a bit
06:42troydmdnolen: http://dev.clojure.org/jira/browse/LOGIC-177
06:43troydmdnolen: the thing I've talked about yesterday
07:30NockNocxwould you delcare this definiton "a function f assigns an output f(x) to every input x" by an expression?
07:30NockNocxI mean in clojure function style
08:27noncomNockNocx: what do you mean?
08:27NockNocxnevermind
08:28noncomNockNocx: to me there's too much noise in the statemtnt.. for example, "assigns" - what do you mean by that? functions do not assign anything... but i don't know what you implied
08:28noncomah ok
09:42dnolentroydm: ok I can reproduce that. Not sure when I will have time to look at it - so patch welcome.
09:45troydmdnolen: okey, I'll try to investigate the root of the issue, if I'll find the cause I'll let you know
09:46dnolentroydm: it's definitely as you say something to do with the output bit
09:46dnolenI suspect reification
10:38troydmdnolen: so far from what I see the problemy is indeed in reifyg function
10:39troydmdnolen: also as I'm not familiar with how this whole reification works it's hard to understand if the issue is related to walk* function or not
10:40dnolentroydm: it's likely
11:16justin_smithpi@raspberrypi ~ $ time java -cp bench.jar clojure.main -e '(println "hello")'
11:16justin_smithpi@raspberrypi ~ $ time java -cp bench.jar clojure.main -e '(println "hello")'
11:17justin_smithpi@raspberrypi ~ $ time java -cp bench.jar clojure.main -e '(println "hello")'
11:17justin_smithpi@raspberrypi ~ $ time java -cp bench.jar clojure.main -e '(println "hello")' => hello => real 0m7.345s
11:17justin_smithoh sorry!
11:28justin_smithanyway, about 8 seconds startup, uses about 30 megs for a repl
11:28justin_smithnow to do some testing with criterium
11:32justin_smithso (assoc {} :a 0) takes 25 ns on this box, 673 ns on the raspberry pi
11:38xemdetiajustin_smith, just to be nosy what jvm are you using on the pi
11:39justin_smithjava version "1.8.0" Java(TM) SE Runtime Environment (build 1.8.0-b132) Java HotSpot(TM) Client VM (build 25.0-b70, mixed mode)
11:42xemdetiais that oracle though
11:42justin_smithyeah, hostspot is oracle
11:43xemdetiaI am too used to looking at non-Oracle JVM outputs apparently!
11:44justin_smiththis is the java that came pre-installed on the default raspbian distro
11:46xemdetiayeah I am just reading about that, I didn't realize they actually were shipping a full oracle jvm
12:32sohailis there a way to "look up" a function value at the time of invocation? The problem I'm having is trying to make a page reloadable via figwheel: (.requestAnimationFrame js/window -interpolation-loop) <-- if figwheel reloads, it seems to still use the old value for the function
12:33zophyhi
12:39sohail nevermind, the issue was actually with reloadability via clojure.async
12:43raeTae9aSo I want to create an eDSL and I don't want to manually walk and parse incoming sexps, what library can help me with that?
12:44raeTae9aI'm sure I've seen a talk about something like what I need on the late clojure\conj or some other conference, but I can't find the library the talk was about.
12:46justin_smithraeTae9a: maybe you want instaparse?
12:46xemdetiaraeTae9a, instaparse? edn?
12:47justin_smithraeTae9a: if the data is coming in as sexps, you could use read / read-string and then work with the nested structures returned
12:47justin_smith,(read-string "(+ (foo bar) (baz) quux)")
12:47clojurebot(+ (foo bar) (baz) quux)
12:47justin_smithit gives you the parsed structure, but doesn't evaluate anything
12:48raeTae9ajustin_smith: um, the problem is not to parse the string, the problem is to transform the given data (which is already in edn).
12:48raeTae9aI'm sorry I confused you by using the word "parsing".
12:48raeTae9aI need something like instaparse, but for sexps, not for plain text.
12:49raeTae9aSo I can specify the structure of sexps I expect and it would "parse" it and throw error if the structure doesn't match.
12:50justin_smithprismatic/schema is good for describing structures you expect
12:53raeTae9aI'm not being clear enough. Schema is not what I want either. Imagine you're writing some def* macro: (defmacro deffoo [& more]) - here you have to manually "parse" that more collection. What I want is something like: (defmacro' deffoo [name doc-string? (foo bar? :as coll)*] ...), and then it would return arguments in a map: {:name ..., :doc-string nil, :coll [{:foo ... :bar ...}]}
12:55justin_smith,((fn [name doc-string & [foo bar :as coll]] {:name name :doc-string doc-string :foo foo :bar bar}) 'a 'b 'c 'd)
12:55clojurebot{:name a, :doc-string b, :foo c, :bar d}
12:56raeTae9aAh, here is that talk: https://www.youtube.com/watch?v=kt4haSH2xcs -- but that guy's github doesn't have that lib, guess he's still working on it.
12:56justin_smithraeTae9a: that stuff is going to be in his cursive editor
12:58lambda-11235Another talk is https://www.youtube.com/watch?v=o75g9ZRoLaw, the library is at https://github.com/jclaggett/seqex.
13:00raeTae9alambda-11235: thanks, I guess that's it! I'll the talk right now, thank you once again.
13:09sohailis there a way with leiningen to compile clj file as cljs?
13:09sohailI've got some common logic and I want to use it both client and server
13:09justin_smithsohail: this is what cljc is for
13:10justin_smithif a cljc file is on the source-path, both cljs and clj can use it
13:10sohailcool, thanks justin_smith
13:37sohailin world.cljc, I have (defrecord World ...) but when I :refer map->World it doesn't seem to exist. Am I missing something?
13:38justin_smiththe syntax would be :refer [map->World]
13:38sohailI am using that syntax
13:39justin_smiththen you are doing something else wrong, because that works
13:39sohail"referred var world/map->World does not exist"
13:39justin_smithdo you have a world.clj or world.cljs that the compiler might pick up instead?
13:39sohailI do not
13:39justin_smithand are you using clojure 1.7 or newer?
13:40sohailclojure 1.7.0, clojurescript 1.7.170
13:42sohailso I have client.cljs referring to world.cljc
13:42sohailI confirmed that it IS using the right file
13:43justin_smithsohail: when I make a file with (defrecord World []) and then require it with (require '[world :refer [map->World]]) it works
13:44sohailjustin_smith: world.cljc and client.cljs?
13:44justin_smithsohail: this is from clj, I didn't set up cljs for this
13:44sohailyeah I suspect it's a cljs issue
13:44justin_smithno
13:45justin_smithone moment, getting cljs, this works
13:45sohailwhy so certain?
13:45justin_smithsohail: because I do this every day at work
13:45justin_smiththis isn't a broken feature
13:45sohailok
13:47sohailso odd
13:47sohailI added (defn make-world [] (-> World)) and :refer [make-world] and it works fine
13:49justin_smithmake-world returns the class not an instance
13:49sohailI meant the referring
13:50justin_smithsure, just saying
13:50sohailoops I see the typo
13:50sohailwas actually using map->World
13:57justin_smithsohail: it works https://gist.github.com/noisesmith/8127c7e3540c6333f9f3
13:57justin_smithand now I know how to use cljs.jar directly, which is cool
13:57sohailomg
13:57sohailI had deftype... /facepalm
13:58justin_smithsohail: well I glad you figured it out, and I got something out of it anyway because I finally got off my ass and learned how to use cljs.jar :)
13:58sohaileveryone wins!
13:58sohail:)
13:58sohailthanks for helping though... pebkac
14:13BRODUSthe clojurescript channel is dead so i'll ask here, is anyone here familiar with om?
14:13sohailBRODUS: I'm using it right now, but I probably can't help you
14:14BRODUSI'm trying to grok whats happening in the second code block here, https://github.com/omcljs/om/wiki/Advanced-Tutorial , specifically the IDidMount implementation
14:15sohailwhat's the issue
14:20BRODUSi just don't understand the motivation for whats happening there, data about the table is being put on the request channel that the owner exposes, including a response channel
14:21justin_smithBRODUS: this is being done so that the reply to the response channel can be propagated back - sending a message including a response channel is a common core.async idiom
14:21BRODUSand in the second sexp in that go block, it looks like the code waits to take an item from the response channel and update the table state
14:22justin_smithBRODUS: go blocks return immediately
14:22justin_smiththe set-state! call will happen after the response is read
14:22justin_smith(async, of course)
14:22BRODUSright, but youre still creating code that waits for something to appear on the channel
14:23justin_smithyes
14:24justin_smithBRODUS: the message will be handled by the serve function defined prior, and it will put the result on res
14:26BRODUSok i get it
15:09sohailis there a double-ended queue in clojure?
15:10justin_smithBRODUS: the message will be handled by the serve function defined prior, and it will put the result on res
15:10justin_smithsorry
15:14hiredmannot included in the languge, the jvm has mutable deques built it though, and immutable deque libraries exist
15:16sohailhm, I'd rather stick to clojure data structures. Maybe I can just take the performance hit for the infrequent operation
16:40domgetterIs this a place to ask clojurescript questions or is there a different more appropriate channel?
16:41domgetterIf so, why does (js/console.log 6) not print to the console in Firefox?
16:44ridcullythere is also #clojurescript, but usually no one minds
16:44ridcullyabove statement prints just fine in firebug
16:44ridcullydo you have switched your console to a higher loglevel by accident?
16:45domgetterInteresting. You're right that it prints in firebug
16:46domgetterI get this from the console (from right-click Inspect-Element console): https://gist.github.com/domgetter/4d995efa1f86c1e4be43
16:47ridcullyyeah don't see output on the internal console too with fx43
16:48ridcullydidn't bother me, since i don't use it
17:01felixndoes clojure have something like haskell `where`? my problem inherently has a lot of branching, and the code is hard to understand with lots of nested lets. it would be nice if I could just declare all the bindings, then lazy eval bindings as needed
17:03justin_smithfelixn: why do your lets need to nest?
17:04justin_smithalso you can do something like a lazy binding with (delay (f x)) - you need @ to access the value, and the first time you do so it is forced
17:04felixnjustin_smith: only when I know something about the value, can I then check for nested values in the data
17:04felixn:O
17:06justin_smith,(let [a (delay (do (println "forced a") (+ 1 1))) b (delay (do (println "forced b") (+ @a 22))] nil)
17:06clojurebot#<RuntimeException java.lang.RuntimeException: Unmatched delimiter: ]>
17:06justin_smithoops
17:06justin_smith,(let [a (delay (do (println "forced a") (+ 1 1))) b (delay (do (println "forced b") (+ @a 22)))] nil)
17:06clojurebotnil
17:06justin_smith,(let [a (delay (do (println "forced a") (+ 1 1))) b (delay (do (println "forced b") (+ @a 22)))] a)
17:06clojurebot#object[clojure.lang.Delay 0x20ae4a7b {:status :pending, :val nil}]
17:07justin_smith,(let [a (delay (do (println "forced a") (+ 1 1))) b (delay (do (println "forced b") (+ @a 22)))] @a)
17:07clojurebotforced a\n2
17:07justin_smith,(let [a (delay (do (println "forced a") (+ 1 1))) b (delay (do (println "forced b") (+ @a 22)))] @b)
17:07clojurebotforced b\nforced a\n24
17:07justin_smithfelixn: maybe that helps?
17:08justin_smithusually you won't even need delays though
17:08felixnhttps://gist.github.com/munro/8a7073b09dc3e02d7605 <-- justin_smith: yea thanks a lot, that's so cool!
17:09justin_smithfelixn: does the delay do anything there?
17:09felixnin that example it would obviously return nil, but I have some bindings that try to do calculations on wrong types
17:09justin_smithoh, got it
17:10justin_smithfelixn: it's also useful for error handling / short circuiting - being able to build up nested calculations but not realizing the ones you don't need in a particular conditional branch
17:18justin_smithfelixn: also, notice you can use bindings from one let clause in the next
17:18justin_smithwithin a single block (unlike eg. the let in common lisp)
17:18felixnjustin_smith: oh yea I'm doing that, I smashed a bunch of branching into one cond :D
17:23felixnit felt wrong even doing (count x) multiple times, so I was using nested lets. not sure if memoizing is faster than recounting, but pulling all the binding setup out of my logic made the code way more readable
18:28j-pbdeftype can't implement finalize right?
18:30justin_smith,(deftype T [] Object (finalize [this] (println "gone")))
18:30clojurebotsandbox.T
18:31justin_smithj-pb: finalizers run much later than you might expect
18:32justin_smithsometimes, never
18:34justin_smithj-pb: here I use a function that will create a lot of churn, to make the gc happen that will clean up the object: https://gist.github.com/noisesmith/73a632ff0bf2774c2958
18:37j-pbjustin_smith: yeah, I need it to release some JNI resource :/
18:37j-pbI'd prefer to avaoid it as well ^^
18:37justin_smithj-pb: what about allowing the code to manually release the resource, then releasing in the finalizer just in case?
18:38justin_smithwell, only releasing if it is hanging around, of course
18:39j-pbjustin_smith: yeah, but that might accidentally invalidate a lot of other stuff
18:39j-pbI'm writing a rocksdb wrapper
18:39j-pbyou get a connection object, then you can deref it to get a snapshot of the current db state
18:39j-pbthe problem is that the snapshots need to be manually released
18:39j-pbhowever, you can iterate over the snapshots with seq's and the like
18:40j-pbso releasing a snapshot might invalidate a lot of seqs mid read
18:41j-pbjustin_smith: do deftypes require their super finalizer to be called somehow?
18:42justin_smith"super finalizer" ?
18:42j-pbfaik finalize doesn't propagate up the object hierarchy, so if a superclass requires the call of finalize, it has to be done manually in java
18:42j-pbsuper.finalize()
18:43justin_smithj-pb: a deftype can't have a super
18:43j-pbyeah, I was just wondering if maybe there is some clojure implementation detail that actually requires this ^^
18:44justin_smithj-pb: clojure just uses the jvm, it doesn't change any of that core stuff - the closest you might get is the extra stuff it makes for protocols that make them different from interfaces, but even that doesn't change how interfaces work
18:44j-pbyeah, actually protocols led me to that thought
18:45j-pbthanks ^^
18:58sohailis there some simple way to check if a value falls in a range? like a in [0,4)
18:59justin_smith,(< 10 42 1000)
18:59clojurebottrue
18:59justin_smith,(< 10 420 100)
18:59clojurebotfalse
18:59sohailah
19:00sohailclever
19:00j-pb,((into #{} (range 10 100) 42)
19:00clojurebot#<RuntimeException java.lang.RuntimeException: EOF while reading>
19:00j-pb,((into #{} (range 10 100)) 42)
19:00clojurebot42
19:00j-pb,(boolean ((into #{} (range 10 100)) 42))
19:00clojurebottrue
19:00j-pb,(boolean ((into #{} (range 10 100)) 101))
19:00clojurebotfalse
19:00justin_smithj-pb: sure, if you want to do it the hard way
19:00j-pb:P
19:01j-pbyeah I was about to add, don't do this it's just a horrible proof of concept to show off as many clojure features in one go as possible :D
19:01justin_smithhaha
19:01TEttingernow add destructuring
19:01j-pbbetter
19:01j-pbcore.match
19:01TEttingerOm
19:01j-pbom.next
19:02justin_smithswearjure
19:02TEttingerseq abstraction...
19:02j-pblol
19:02TEttingertransducers
19:02tolstoyGenerate the byte-code to a file, then load it back in?
19:04j-pbalright guys I'll head to bed, it's late here in germany, have a nice feast everybody :D
19:04justin_smithI've got to use that saying more often
19:04justin_smithhave a nice feast!
19:04j-pb:D
19:05tolstoyBetter ring then, "Enjoy a delightful repast."
19:27justin_smith,(do (def a 'b) (def b 'c) (def c 'd) (def d 'e) (def e 'f) (def f 'g) (def g 'a))
19:27clojurebot#'sandbox/g
19:27justin_smith,(apply str (iterate eval 'a))
19:27clojureboteval service is offline
19:27justin_smithoh wait, that won't work
19:28justin_smith,(apply str (take 400 (iterate eval 'a)))
19:28clojurebot"abcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefg...
19:29justin_smith,(def m {:a :b :b :c :c :d :d :e :e :f :f :g :g :a})
19:29clojurebot#'sandbox/m
19:29justin_smith,(apply str (take 400 (iterate m :a)))
19:29clojurebot":a:b:c:d:e:f:g:a:b:c:d:e:f:g:a:b:c:d:e:f:g:a:b:c:d:e:f:g:a:b:c:d:e:f:g:a:b:c:d:e:f:g:a:b:c:d:e:f:g:a:b:c:d:e:f:g:a:b:c:d:e:f:g:a:b:c:d:e:f:g:a:b:c:d:e:f:g:a:b:c:d:e:f:g:a:b:c:d:e:f:g:a:b:c:d:e:f:g:a:b:c:d:e:f:g:a:b:c:d:e:f:g:a:b:c:d:e:f:g:a:b:c:d:e:f:g:a:b:c:d:e:f:g:a:b:c:d:e:f:g:a:b:c:d:e:f:g:a:b:c:d:e:f:g:a:b:c:d:e:f:g:a:b:c:d:e:f:g:a:b:c:d:e:f:g:a:b:c:d:e:f:g:a:b:c:d:e:f:g:a:b:c:d:e:f:g:a:b:c:...
19:31ridcullyis this your ipv16 addy?
19:31justin_smithheh
19:34TimMcjustin_smith: Oh man, I haven't done any swearjure in forever. I'm probably out of practice!
19:35justin_smithTimMc: since Raynes will be taking refheap down for good, I am trolling through to find the stuff I need to turn into gists, and as I go I'm also finding some old code memories
19:37TimMcWait, refheap is going away? D-:
19:37justin_smithTimMc: haxors were using it for haxing
19:37TimMcRaynos: Say it ain't so!
19:38TimMcjustin_smith: Nooo, Raynes should just turn off writes.
19:39TimMcExisting pastes could be rendered to static pages so it wouldn't even need a DB or a JVM.
19:39justin_smithTimMc: that will be the first step
19:39justin_smithor so he said
19:40TimMcMaybe I'll archive all refheap links from this room.
19:40TimMcIf he's planning on taking it down, I should contact The Angel of Death over at the Internet Archive to make sure they get a scan of it.
19:41ridcullydarn, now it's slayer time
19:41TimMchttps://en.wikipedia.org/wiki/Archive_Team
19:52TimMcThis gets me the IDs of all refheap links in my IRC: grep '(https?://)?(www\.)?refheap\.com/(paste/)?[0-9a-f]+' -P -rho chatlog/ | sed 's|/paste/|/|' | sed 's|.*\.com/||'
19:58TimMcOK, archiving.
20:08TEttingerawww crap how's my lazybot going to paste stuff
20:08TimMcfffff, efnet IRC thinks I'm running a Tor exit and won't let me connect
20:18princesoHow to create a function by a macro that may be called by itself? http://pastebin.com/L2CN57uB
20:32TimMcprinceso: I'm unclear on what you're trying to make.
20:35TEttingerprinceso: essentially a function that is executed when it's read, right?
20:35TEttingerI am pretty sure clojure doesn't allow that except with reader literals, and even then it's rather limited
20:36princesoTimMc thanks: A looping function. repeat the body for new bindings
20:36TEttingerwhat about loop doesn't work here?
20:36TEttinger(doc loop)
20:36princesoTEttinger thanks: yes
20:36clojurebot"([bindings & body]); Evaluates the exprs in a lexical context in which the symbols in the binding-forms are bound to their respective init-exprs or parts therein. Acts as a recur target."
20:38princesoTEttinger jusot was playing with loop-recur and it failed at some point
20:50TimMc3619 refheap pastes archived so far
21:00TimMcHmm, should have used the JSON API so I could get author information.
21:11sohailis there a way to generate a permutation of elements in two lists? so [a b] [c d] -> [[a c] [a d] [b c] [b d]]
21:12sohailpresumably doseq has to do this
21:13justin_smithsohail: doseq can only generate nil
21:14sohailright, I mean a way to generate the *permutation* so that I can map over it
21:14justin_smithlike I said, doseq can only return nil
21:15justin_smithit never returns any other value
21:15justin_smith,(for [x '[a b] y '[c d]] [x y])
21:15clojurebot([a c] [a d] [b c] [b d])
21:15sohailI see
21:15sohailthanks
21:43amalloysohail: that's called the cartesian product, by the way, not permutations
21:47sohailamalloy: right, brain fart AxB
21:47sohaillearning clojure, clojurescript and trying to do a programming challenge... #nerdholidays
21:49sohailso what happens when you build up a whole whack of teeny modifications to an object? say (-> obj tweak tweak tweak tweak). Are these ever optimized? Can they be?
21:50sohailsay tweak is something like assoc
21:50justin_smithsohail: clojure itself does almost 0 optimization. The vm does some optimizations, the kinds it does are complex but well documented.
21:52sohailit just seems wasteful to create 4 new objects to modify 4 fields in a loop
21:52justin_smithsohail: so you are always better off doing (assoc m :a x :b y :c z) rather than (-> m (assoc :a x) (assoc :b y) (assoc :c z)) - clojure won't change the latter (much slower) into the former for you
21:53justin_smithsohail: what makes you think that creates 4 objects?
21:53justin_smithit's 4 calls, sure
21:53sohailthe docs: "When applied to a map, returns a ***new*** map of the same (hashed/sorted) type"
21:54justin_smithOK, in the sense of the container object yes. But likely the structure is shared between them.
21:54justin_smithsome structure, at least
21:55justin_smithbut yeah, don't do 4 assoc calls in a row, it's wrong and clojure won't fix that for you
21:55justin_smithassoc is varargs for a good reason
21:56ben_vulpesso i've got a project with ~180 lines of source and takes over 10 minutes to produce an uberjar with lein. where should i start poking to optimize this compile time?
21:57justin_smithben_vulpes: you can trade shorter compile time for longer startup by making a shim that calls require and resolve inside a function to load your real code at runtime
21:58justin_smithor even turn off aot altogether and manually specify the namespace that clojure.main should load at runtime
21:59ben_vulpesso if i specify the :main ns, and attach some aot never metadata to my -main fn, i might see speedup in compiling?
21:59justin_smithben_vulpes: by not compiling
22:00justin_smithby not specifying a :main, and not :aot compiling
22:00justin_smithby not having an actual -main, and using clojure.main, telling it to load and run your ns
22:01justin_smithwell you should still have a -main I guess - it just won't generate the class java runs
22:02justin_smithben_vulpes: :aot is recursive - things you require will get aot compiled too - which is why the shim thing works out
22:02justin_smithonly aot the one ns, that's super fast because it doesn't have any top level deps except clojure.core (already compiled in clojure.jar)
22:02ben_vulpeshm
22:02ben_vulpesthese are new depths for me
22:03justin_smiththen you have (defn -main [& args] (require 'my-actual-ns) (apply @(resolve 'my-actual-ns/my-actual-main-fn) args))
22:03justin_smiththat way, the stuff still gets launched, despite not being aot compiled
22:04ben_vulpesgotcha
22:04justin_smiththe resolve is needed, of course, because otherwise the function would fail to compile
22:04ben_vulpesokay, so i'm somewhat accustomed to just uberjar'ing these things up via lein: where would i stick that -main fn, and how would i boot it with clojure?
22:05justin_smithben_vulpes: you still run uberjar
22:05ben_vulpesjava -jar my.jar my/-main << something like that?
22:05justin_smithben_vulpes: I described two approaches
22:05justin_smithif you use the shim with resolve, just java -jar my.jar
22:06justin_smithif you don't aot (not even a shim) you do java -cp my.jar clojure.main my.ns
22:06justin_smithben_vulpes: another fun trick up this same alley: java -cp my.jar clojure.main gives you a repl with all deps and code of your project
22:08ben_vulpesaha, i think i get it now.
22:09ben_vulpesneeded to reread thrice to understand the shim ns
22:09justin_smithben_vulpes: it just avoids compiling because its real deps (your actual code) are not loaded until -main is called
22:10justin_smithso it breaks the "recursive aot" chain
22:10ben_vulpesright on
22:11justin_smithben_vulpes: chances are you have some dep that compiles slowly - maybe one of those macro castles like core.match, core.logic
22:11ben_vulpesi just ripped byte-streams out
22:11ben_vulpesmight be datomic at this point
22:18justin_smithben_vulpes: if you do the shim, that should show you the minimal compile time, and you could see what happens if you add certain deps to the shim namespace (even if they are not explicitly used)
22:19justin_smiththat might help you narrow down what takes so long to compile
22:19justin_smithoooh - or you could profile the uberjar process
22:20ben_vulpesgood thinking, justin_smith
22:21ben_vulpeson the dep-muntzing via shim ns
22:22ben_vulpesinterestingly, this still takes longer than booting via leiningen and them compiling my tiny core ns from emacs
22:23justin_smithben_vulpes: any chance you are using a weird filesystem for target/ ?
22:24ben_vulpesnope, vanilla mac drive
22:28ben_vulpesah jesus i know precisely what the problem is.
22:28justin_smithoh?
22:28justin_smithlemme guess "sh sleep 50000" as a prep task?
22:29ben_vulpeswell defs with side effects but yeah
22:30justin_smithoh that'll do the trick, lol
22:30justin_smithben_vulpes: dirty secret: a big reason for my using the shim method above is that it is easier than teaching and reteaching all my coworkers how shitty defs with side effects are and how not to do them
22:31TimMcoh dear
22:31ben_vulpes24s
22:31TimMcCertainly not the only reason, though.
22:31TimMcben_vulpes: Coming into this in media res, but are you looking to find out why compilation is slow?
22:31justin_smitha more pleasant way to put it is "not aot compiling reduces the differences between development environments and deployed code"
22:33ben_vulpesTimMc: more or less
22:33ben_vulpesand pebkac was the diagnosis
22:34TimMcAh, what was it?
22:35ben_vulpesside effects in defs
22:36TimMcfun times
22:36TimMcben_vulpes: This is a script that will modify your codebase to show compilation progress, by the way: https://gist.github.com/timmc/7359898
22:37TimMcI've used this before to locate a thing that was making the compiler freak out and give a useless error message.
22:37justin_smithTimMc: my least favorite part of switching from linux all the time to using osX at work was finding out that osX sed -i is weird
22:38TimMcUh oh, what does it do?
22:39justin_smithTimMc: http://blog.remibergsma.com/2012/09/18/sed-inline-editing-different-on-mac-osx/
22:39amalloyosx grep is terrible too. doesn't support a bunch of stuff i use regularly. but you can install the gnu tools on top of them
22:39TimMcben_vulpes: If compilation is still too slow, I also have this lovely hack for compiling onto a ramdisk: https://gist.github.com/timmc/6c397644668bcf41041f
22:39justin_smithamalloy: you can, but I was making a tool that a whole team of osx users were running :( it was sad
22:41TimMcjustin_smith: I don't understand "sed: -i may not be used with stdin" -- the example specifies a file argument, so why is it trying to read from stdin?
22:41justin_smithTimMc: the message is garbage, the fix is to supply '' as your backup file suffix
22:42TimMclovely
22:42justin_smithso -i becomes -i ''
23:00justin_smith,(= (sort "mr. creamy shirts") (sort " merry christmas."))
23:00clojurebottrue
23:01ben_vulpesclever ramhack TimMc
23:03TimMcI have no idea if it works on mac. :-P
23:04justin_smithTimMc: if I had a mac here I'd test, I left my work machine at the office
23:04TimMcIt works *really* well for me on linux. I have a script I run atfter startup that runs that script in every dev directory, and I can't recommend it enough.
23:06TimMcBear in mind that the reason I need this is probably because I have an encrypted hard drive.
23:07justin_smithTimMc: same here, so it looks interesting
23:08justin_smithTimMc: have you considered making it a plugin I could add as a prep-task in my repo?
23:08justin_smith(maybe with a conditional "is this linux" check)
23:09justin_smithI guess it could just be put in there via lein exec now that I think about it
23:12TimMcIt needs sudo to mount the fs. Maybe there's a FUSE thing I could do...
23:14TEttinger,(= (hash (sort "mr. creamy shirts")) (hash (sort " merry christmas.")))
23:14clojurebottrue
23:14TEttinger(what did I expect)
23:16justin_smithTEttinger: I was using sort / = as an anagram test
23:24TEttinger,(= (sort "injured this smut") (sort "rude justin smith"))
23:24clojurebottrue
23:24justin_smithhaha
23:30TEttinger,(= (sort "some menger kitty treat") (sort "tommy streak ettinger "))
23:30clojurebotfalse
23:30TEttingermmm
23:31justin_smith,(defn anagram-helper [original] (fn [new] (reduce #(update % %2 (fnil dec 0)) (frequencies original) new)))
23:31clojurebot#'sandbox/anagram-helper
23:32justin_smith,(def tettagram (anagram-helper "tommy streak ettinger "))
23:32clojurebot#'sandbox/tettagram
23:32justin_smith,(tettagram "injured this smut")
23:32clojurebot{\space 1, \a 1, \d -1, \e 2, \g 1, ...}
23:32TEttinger,(= (sort "some menger kitty tart") (sort "tommy streak ettinger "))
23:32clojurebottrue
23:33justin_smith,(tettagram "some menger kitty tart")
23:33clojurebot{\space 0, \a 0, \e 0, \g 0, \i 0, ...}
23:33justin_smithsee- all zeroes means it's correct
23:33TEttingerheh
23:33justin_smithbut it helps you see which chars need adjusting
23:33TEttingeryep!
23:34TEttingeroh yeah, that classic clojure one-liner I always paste to summon nyarlothotep, I keep finding ways to improve on the technique now. it's longer, but I have the same algorithm in a java program now.
23:36TEttingerЖыдотуф руц пйцас, гогутяр шыскучэбаб - гйчапофёглор гюнуз ъсказюжин.
23:36TEttingerI'm sure in any actual russian-like language that's gibberish
23:36TEttingerit wasn't made using any dictionary
23:37TEttingerromanized, it's Zhydotuf ruts pitsas, gogutiar shyskuchebab - gichapofeglor giunuz ieskaziuzhin.
23:37TimMcYou take that back! My grandmother would never do such a thing.
23:37TimMc(No, I don't know Russian either.)
23:38justin_smith,(defn an [original new] (remove (comp zero? val) (reduce #(update % %2 (fnil dec 0)) (frequencies original) new)))
23:38clojurebot#'sandbox/an
23:38justin_smith,(an "cat" "taco")
23:38clojurebot([\o -1])
23:38justin_smiththat's the way to do it
23:38justin_smithtells you exactly what needs adjusting - negative means remove from right or add to left, positive means visa versa
23:38TEttingerkhuy, baba yaga, nyet, da. that's pretty much all I can remember
23:39justin_smithTEttinger: there's lots of useful day to day russian in clockwork orange
23:39justin_smithmoloko, horoshow, droogs
23:39justin_smithetc.
23:39TEttinger"one of the four principal cusses in russian", "a famous mythological witch", "no", "yes"
23:40TimMckvass
23:41justin_smithvodka: diminutive of water, like a cutesy name for some water
23:41justin_smith(voda is water)
23:42TimMchah
23:42justin_smitheg. katka is a nickname for kat
23:42justin_smithsame form
23:43TimMcI bought some kvass from the local Russian market last year. It's pretty good for something that tastes like raisin bread soda.
23:43justin_smithwe have a lot of russians here, I went to an awesome russian restaurant recently, they had like 30 different kinds of pickled things and 100 different kinds of vodka
23:44justin_smithI tried a vodka from vermont that tasted just a little bit like maple
23:45TimMcIt would be hard not to, it gets into the groundwater.
23:45TimMcthe people smell faintly of syrup
23:46justin_smithTimMc: ages ago, when I lived in vermont, there were squirrels that learned how to chew through the tubing that collected sap from the trees, and they would get fat on delicious maple sap in the fall and spring
23:47TEttingerhahaha
23:48TEttingermy brother wants one of these fat squirrels now
23:49justin_smithhaha
23:49justin_smithfat squirrels can be kind of cute
23:50TEttingerit's interesting, on the house balcony (which now has an area we use as a "cat-io", fenced in so the cats can go outside-ish and get sun and watch birds but not catch em), we used to get both squirrels and rats at different times of day
23:50TEttingerthe squirrels were ALWAYS territorial. but despite a nasty reputation, the rats were always friendly with other rats
23:52TEttinger(my 2 rat bites on my fingers have healed btw. the cat-io wasn't always sealed from rats... and a cat brought one downstairs like a baby. after 30 minutes, the rat was just fine but now outside, and I had mostly stopped bleeding profusely)
23:55sohailwhat is people's favourite websocket implementation for clojure + clojurescrpit? mostly for prototype purpose so productivity is important
23:56justin_smithsohail: sente is a cinch
23:56justin_smith(= (sort "yo justin, too rare festivus smith") (sort "some furtive joints, that is yours")
23:56justin_smithoops!
23:56justin_smith,(= (sort "yo justin, too rare festivus smith") (sort "some furtive joints, that is yours"))
23:56clojurebottrue