#clojure logs

2013-08-09

00:02axle_512does anyone know if "network channels" for core.async are being developed? Rich hinted at it in his blog post when he introduced core.async.
00:05xeqiaxle_512: they've been thinking over some different ideas. In the mean time lynaghk has some interesting projects at https://github.com/lynaghk/zmq-async and https://github.com/lynaghk/jetty7-websockets-async
00:06axle_512xeqi: thanks
00:06xeqineither of them general "network channels" but possibly useful
00:13axle_512xeqi: if I understand correctly, lynaghk's websocket impl lets you use go routines with websocket IO?
00:13axle_512xeqi: if so, that's pretty freakin cool
00:14xeqiI think so, but I only saw it earlier and know very little about websockets
00:15axle_512I may tinker with it to see if I can understand it better. thanks fro the links.
00:19Apage43ooh
00:19clojurebotHuh?
00:20Apage43I have some aleph/websocket stuff I might see about converting.. though it's really so simple it might not be that helpful
00:23ToBeReplaced,((fn select-by
00:23clojurebot#<RuntimeException java.lang.RuntimeException: EOF while reading>
00:23ToBeReplaced [f & seqs]
00:23ToBeReplaced (when-let [non-empty-seqs (seq (remove empty? seqs))]
00:23ToBeReplaced (let [[[x & more] & others] (sort-by (comp f first) non-empty-seqs)]
00:23ToBeReplaced (lazy-seq (cons x (apply select-by f more others))))))
00:23ToBeReplaced identity [1 3 5] [6 7 9] [2 4 8])
00:23ToBeReplaced,((fn select-by [f & seqs] (when-let [non-empty-seqs (seq (remove empty? seqs))] (let [[[x & more] & others] (sort-by (comp f first) non-empty-seqs)] (lazy-seq (cons x (apply select-by f more others)))))) identity [1 3 5] [6 7 9] [2 4 8])
00:23clojurebot(1 2 3 4 5 ...)
00:45puredangeraxle_512: re network channels for core.async, Tim B has been working on approaches for that
00:46axle_512puredanger: thanks
00:50puredangeraxle_512: it is very challenging (maybe impossible) to match existing async channel semantics when the network and unreliability is in the mix, so the question then becomes what semantics are useful and how do they interact.
00:52axle_512puredanger: Does the 'go' language support network channels?
00:53axle_512puredanger: I imagine it's pretty difficult macro coding to get it right.
00:53axle_512puredanger: on the clojure side, that is.
00:53bbloomaxle_512: they had one at some point, but they cut it
00:54puredangeraxle_512: the coding is the easy part. understanding what to code in the first part is the hard part.
00:54puredangers/part/place/
00:54axle_512so pretty bleeding edge stuff then. Thanks for the info.
01:00puredangersurely
01:05eggheadbbloom: thanks for the help w/ the core.async stuff, it cleared up a lot
01:05bbloomegghead: my pleasure. explaining helps me too!
01:12ambrosebsbbloom: have you looked at turning js* nodes in CLJS into AST trees?
01:12bbloomambrosebs: i have a pretty old proof-of-concept branch: https://github.com/brandonbloom/clojurescript/tree/js-ast
01:14ambrosebsbbloom: nice
01:15bbloomambrosebs: yeah, i liked it :-) basically just search "js/" in compiler.clj
01:15ambrosebsbbloom: I need this done, I will continue your work.
01:15bbloomambrosebs: was dramatically slower, unfortunately
01:15ambrosebsah
01:15bbloomin theory, it could be made faster by piping the data structures directly into closure compiler
01:16bbloombut the internal AST for gclosure is an implementation detail & i had to call a bunch of private APIs via reflection
01:16bbloomsee also https://github.com/brandonbloom/clojurescript/blob/js-ast/src/clj/cljs/js.clj for the "dsl" of sorts
01:17ambrosebsDo you think it's a good idea to convert js* nodes to AST's post-analsis? ie. just before I type check it?
01:17bbloomwell, parsing JS fragments is a whole-nother problem
01:17ambrosebsI figured.
01:17bbloomi punted on that & just rewrote usages of js* to work w/ the js ast dsl i made
01:18bbloomvery macro-like
01:19bbloomdnolen said that it was ok to break js* though, since it's an impl detail
01:20bbloomi eliminated several uncessary usages of js* in core.clj{,s} but i'm not sure which of them made it back to master
01:20bbloomfor example: https://github.com/brandonbloom/clojurescript/commit/3f95b2abbc4294bcbeb46a996becbb08dd21f453
01:21bbloommy first few commits on that branch are illustraitive
01:22bbloomambrosebs: let me know if there's anything i can do to help! pure functions > printing side effects :-)
01:23ambrosebsbbloom: ok, I'll dive in.
01:23bbloomthe branch is pretty old, lots of stuff has chnaged
01:24ambrosebswould you advise starting again with the same approach on top of master?
01:24bbloomyeah, i think a manual rebase is probably a reasonable approach
01:24ambrosebsok
01:25bbloommy work is in lots of small commits, so you could probably just follow the pattern
01:25bbloomit also hints at how to do the work piecemeal, which was the hard part
01:26ambrosebsgood
01:27ambrosebsdo you think it will take long?
01:27bbloomambrosebs: gclosure's IR.java library provides a sensible api for building an AST. realistically, there is no need to use the gclosure ast, it was just the shortest path to getting a printer too
01:27ambrosebsis that where the reflection comes from?
01:28bbloomyeah
01:28ambrosebsgreat
01:28bbloomin theory, if we could bipass the printer, then the might be FASTER, but i couldn't figure out how to do that precisely
01:29bbloomalso, the gclosure optimizer expects very particularly shaped ASTs
01:29bbloomthey have a validator you can run, but i didn't bother b/c the printer seems to be much more permissive than the verifier & optimizer passes
01:29bbloombypass*
01:29bbloomlooks like i worked on it for one long weekend :-P
01:30ambrosebsyea, that's promising :)
01:30bbloomoh now i remember the bigger issue with bypassing the parser: creating type annotations
01:30bbloomhttps://groups.google.com/forum/#!topic/closure-compiler-discuss/OEwLWkw4Kug
01:42bbloomambrosebs: what do you need it for?
01:42ambrosebsbbloom: Typed CLJS
01:43bbloomglorious.
01:43bbloomthe js* form is fucking you up, huh?
01:43ambrosebsroyally
01:43ambrosebsI am stuck
01:44bbloomcould you maybe just add a type paramter to js* ?
01:44bbloom(js* Number "(~{} + ~{})" x y)
01:44bbloomsomething like that
01:45ambrosebsI still want to know what operation is happening
01:45ambrosebsI might as well break js* properly.
01:45bbloomambrosebs: why does the operation matter?
01:46ambrosebsbbloom: things like typeof give extra information
01:47bbloomambrosebs: ah. makes sense
01:47bbloomi think eliminating js* is easier than switching to a JS ast
01:48bbloomcheck out this trick: https://github.com/brandonbloom/clojurescript/commit/335d3e589bf175ff77d31acc36c6174bb54ce567
01:48ambrosebsOk. I've never used js before, so I'm glad you're telling.
01:49bbloombasically, that makes js/whatever work like a special form if the whatever is in a list of operators
01:49bbloomonly ~ and ^ required special treatment, which i punted on too lol
01:49ambrosebscool!
01:50ambrosebsdo you know how I can get a nice view of all the things you've changed?
01:51bbloomlearn to git n00b! :-)
01:51bbloomgit log `git merge-base master js-ast`..js-ast
01:52ambrosebsxD
01:53bblooms/log/diff or difftool, of course too
01:53ambrosebsyes of course >.>
01:54bbloomso since ~ and ^ were invalid syntax, and js/<< seemed odd given the name clojure.core/bitwise-shift-left....
01:54bbloomi figured that a more robust approach would be to create a js* namespace
01:54bbloombasically a virtual namespace bootstrapped by the compiler which was just a mapping of clojure-friendly-names to operator special forms
01:56ambrosebsok. and you'd have vars like <<, ~ ^ etc?
01:57bbloomwell yeah, so that commit i just linked you to has a set of vars like that, but since ^ and ~ are invalid identifiers, it would be more like a map '{bitwise-left-shift "<<" bitwise-not "~" …}
01:58ambrosebsoh ok, that's your virtual namespace, just a map.
01:58bbloomyeah
01:59bbloomanyway, i'm off to bed. good luck & let me know how it goes
01:59ambrosebscya!
02:44devnhello all
03:22callendevn: hi
03:26devncallen: good morning
03:26devncallen: what dost thou computeth?
03:29callendevn: ring middleware
03:29callennothing interesting
04:08clj_new_2345I need to reinsatll ubuntu. I'm at the grub prompt. Is there a way to force grub to boot from the cdrom?
04:08clgvclj_new_2345: wrong channel?
04:08clj_new_2345yes
04:08clj_new_2345sorry
04:09clj_new_2345habit of auto joining #clojure
04:09ordnungswidrig/join #clojure.de
04:37muhoothis looks like the long/wrong way: (defn name-to-fn [s] (var-get (resolve (symbol s))))
04:40clgvmuhoo: vars can be used as functions as well.
04:40clgv,((resolve (symbol "inc")) 0)
04:40clojurebot1
04:41muhoooh cool, better thanks
04:52Hail_SpacecakeI'm trying to install leiningen with the shell script method
04:52Hail_Spacecakebut it seems broken on my system
04:52Hail_Spacecakedoes it expect HTTP_CLIENT to already be defined?
04:54callenjesus christ that nick
04:55Hail_Spacecakelike, this script is really broken
04:55Hail_Spacecakeit's trying to call download_failed_messsage before it's defined
04:55Hail_Spacecakewhich I don't think you can do in bash
04:55callenHail_Spacecake: ...man, what's with the name?
04:55Hail_Spacecakecallen what about it?
04:55callenHail_Spacecake: futile?
04:56Hail_Spacecakeanyway this is the stable version of the script, I can't be the only one with this problem
04:56Hail_Spacecakefutile? not sure what you mean
04:58schmirtechnomancy: installation of the latest leiningen fails for me: /home/tt/bin/lein: line 57: /home/tt/.lein/self-installs/leiningen-2.3.0-standalone.jar.pending: No such file or directory
04:58schmiris this a known problem?
04:58callenHail_Spacecake: have you tried using refheap to post an error message?
04:58callenAlso this is the first I've seen of this.
04:59callennot that I am an authority or anything, but I lurk enough.
04:59Hail_SpacecakeI just asked in #leiningen, apparently this just broke
04:59Hail_Spacecakeah, yeah, there's a commit fixing it
04:59Hail_Spacecakethat is the latest commit
04:59Hail_Spacecakeand an hour old
05:01hyPiRionschmir: yes
05:01hyPiRionI'm working on a temporary fix as we speak
05:01schmirok. thanks!
05:02hyPiRion(just need to ensure it works everywhere)
05:55hyPiRiontemp fix: https://github.com/technomancy/leiningen/issues/1279#issuecomment-22384614
05:55hyPiRion(for Leiningen 2.3.0)
06:02weiwhat's the best way to diff two clojure data structures?
06:14samratwei: you might want to look at clojure.data/diff
06:27gavriwhat's the simplest way to get an instance of the ratio type representing 1/1 ?
06:28weisamrat: thanks
06:28gavri(rationalize 1) doesn't do it
06:28gavrineither does (rationalize 1.0)
06:28gavribut it works for (rationalize 1.5)
06:28llasramgavri: Why do you want a Ratio of 1/1 instead of just the (big)integer 1?
06:29H4nsis there something better than slime for clojure when one is an emacs user?
06:29gavriI've written a recursive method to generate the haromonic series
06:29gavriI'd like to call (numerator) on the argument to the function
06:29llasramH4ns: nrepl.el is the current standard
06:29gavriand I'd like to start from 1/1
06:29H4nsllasram: thanks
06:29gavriand then move to 1/2, 1/3 etc
06:30gavriit works fine if I start from 1/2
06:30gavribut I don't know how to start it off from 1/1
06:30llasramgavri: You probably want to wrap this in your own function, but: ##(clojure.lang.Ratio. (biginteger 1) (biginteger 1))
06:30lazybot⇒ 1/1
06:31llasramAlthough writing your own wrapper for `numerator` which handles integers is probably ceaner
06:31llasramcleaner even
06:33gavrithis breaks too: (numerator (* 2 (rationalize 1.5)))
06:33gavridoesn't this mean that a lot of code would break quite often?
06:34gavriif ratios end up with a denominator of 1 in intermediate results of calculations?
06:34gavriwhat am I missing here? :-?
06:34llasramI honestly don't think people use ratios very often :-)
06:34llasramIt does seem like `numerator` should be identity integers
06:35gavrior not at all, it seems :/
06:35gavriwouldn't it be better if ratios never reduce to integers unless explicitly cast?
06:35gavriif not, there'll have to be special cases everywhere
06:36llasramJust in the arithmetic functions
06:36llasramJust like `/` on integers results in ratios for non-integral results
06:37gavrithat's not as bad though, because ratios have more general capabilities than integers, right?
06:37llasramWell, except that ratios are much, much heavier-weight on the JVM
06:37gavrioh ok, got it
06:38gavrithere has to be a way for the programmer to indicate that they want to work exclusively on ratios though
06:38gavriso that clojure isn't enthusiastic about converting them back to integers
06:38llasramYou can reach into the Ratio class directly
06:38llasramBut I really think the solution is that `numerator` should work on integers
06:38gavria more general way than changing #numerator, I mean
06:38H4nsi need to write a simple web server that serves statically defined clojure data structures (literals) as json. nrepl.el, http-kit, now i need a json library. any recommendations? it'd be nice if i could generate json in a streaming fashion as i will eventually have to create the json from java instances.
06:38llasramgavri: Why more general?
06:38gavriok, thanks, llasram
06:39gavrifor example, what about denominator?
06:39llasramH4ns: cheshire is th de facto standard
06:39H4nsllasram: thanks again
06:39gavriand any functions that get added for ratios in the future
06:39llasramgavri: Well, ditto it should return `1` on integers :-)
06:42llasramSure.
06:42gavrihmm, okay, I'm new to clojure and really have no clue about the philosophies (if that's the right word) of the language
06:43gavrifor now, I'll add custom numerator/denominator functions
06:52gavrithanks, llasram
07:51dark_elementcemerick I am using custom repl connect in cljs with austin. https://www.refheap.com/17381 and Also making sure browser-connected-repl-js uses the same repl https://www.refheap.com/17431 I am doing this to send "Browser connected" status from cljs to server. But repl-print is not working with austin. It did work fine with piggieback.
09:20ToBeReplacedinterleave-by, from last night: https://gist.github.com/ToBeReplaced/6193452
09:20ToBeReplacedalso how do you get gist to show syntax?
09:22AnderkentToBeReplaced: there's a dropdown saying 'language' when you create a gist
09:22Anderkentit also tries to autodetect based on what you type
09:22Anderkent(or maybe only based on file extension)
09:23ToBeReplacedAnderkent: yeah it wasn't taking, had to change file extension.
09:39clgvhumm, spotted another asymmetry. why is there no mapv-kv similar to reduce-kv ...
09:40hyPiRionclgv: what is mapv-kv supposed to do?
09:41clgvhyPiRion: same as mapv but with the optimization of reduce-kv not to create intermediate seqs. well, seems it could be built on top of reduce-kv ^^
09:41hyPiRionah, alright
09:42clgvprobably thats the reason.
09:43clgv(defn mapv-kv [f m] (persistent! (reduce-kv (fn [r k v] (conj! r (f k v))) (transient []) m)))
09:43clgvah well, a bit typing would be saved ^^
09:49H4nsso, as a new clojure user, in order to start some experiments with http-kit and chesire, i create a leiningen project?
09:50ToBeReplacedH4ns: sounds good
09:50H4nsToBeReplaced: thanks for the confirmation :)
10:12abptechnomancy: https://leiningen.s3.amazonaws.com/downloads/leiningen-2.3.0-standalone.jar currently gives Access Denied :/
10:12clgvhow can I tell leiningen to aot everything for an uberjar? since the jar is started thousands of times I'd want to omit compiling every time
10:18hyPiRionabp: https://github.com/technomancy/leiningen/issues/1279 has some workarounds for now
10:22Anderkentclgv: doesn't :aot :all work?
10:22clgvAnderkent: only for the namespaces of the project
10:23Anderkenthm, but that should compile everything referenced by the project
10:23Anderkentunless you load libs dynamically, I guess
10:24clgvI get no info about the depency namespaces on stdout...
10:24hyPiRionAnderkent: It would only make sense for uberjars
10:24hyPiRionto compile deps aot, I mean.
10:24Anderkentlook at the classes dir - usually compiling a namespace builds class files for anything reachable from that namespace
10:24abphyPiRion: Thanks!
10:24AnderkenthyPiRion: I know, and it's a problem that you can't non-transitively compile
10:25Anderkentsee http://dev.clojure.org/display/design/Transitive+AOT+Compilation
10:26clgvhumm interesting. there are a lot of class files in the uberjar in dependency namespaces
10:27hyPiRionclgv: yeah, the dependencies themselves may be compiled aot and bundled in a jar.
10:27clojurebotclojars deployment is described by _ato in http://groups.google.com/group/clojars-maintainers/msg/4c66317ac3ecd9bb
10:27clgvhyPiRion: I just check one dep jar to verify
10:28clgvhyPiRion: ok. the original dep jar has no classes in it
10:28clgvso it seems to work with :aot :all
10:28hyPiRionclgv: oh, dang, I just opened an issue
10:30clgvhyPiRion: well not too bad, since someone with insider knowledge can now confirm that it works like expected...
10:31AnderkentClearly we should go and laugh at you in the issue description for not trying it first. :P
10:32hyPiRionAnderkent: This is possibly my third time I've posted a feature request where it was a documentation issue :p
10:32hyPiRionI'm a bit trigger happy when it comes to issues.
10:35ambrosebsBronsa: hows CinC coming?
10:38AnderkentWhy doesn't `add-watch` tell you what the current reference state was? There seems to be no way to reliably watch a ref for changes
10:40Anderkentsay you know what @ref is, and you want to watch for changes. if you (let [known-state @ref] (add-watch ref :key check-change) (check-change :key ref known-state @ref)) you might call check-change twice for the same change, if you do it in reverse order you might miss changes that happened between check-change and add-watch
11:04shiranaihitoi'm trying to make a custom lein template, but when i use it i get an error saying: "IllegalArgumentException: No method in multimethod 'do-copy' for dispatch value: [nil java.io.File]" .. any idea what's going on? (i'm new to clojure)
11:05shiranaihito( the directory for the new project gets created, along with the first source file )
11:05upwardindexI'm reading 2 bytes from a RandomAccessFile in 1 call to .read, however the JVM makes two one byte call to linux, any idea how to make it make only 1 call?
11:07Anderkentupwardindex: do you know if jvm is explicitly telling linux to read one byte, or if linux is just returning after reading 1?
11:08upwardindexAnderkent: It is explicitly telling linux to read one byte
11:08Anderkentshiranaihito: it seems you're using clojure.java.io/copy with a wrong set of args.. can you refheap your code?
11:09shiranaihitoAnderkent: well.. i'm just trying to follow the instructions here: http://yogthos.net/blog/34-Creating+Leiningen+Templates .. but with not much luck
11:09shiranaihitoand as mentioned, i'm new to clojure.. "refheaping" my code, whatever that means, is out of my reach for now :P
11:09hyPiRion~refheap
11:10hyPiRionaah, clojurebot
11:10llasramCome on, clojurebot -- step up
11:10hyPiRionhttps://www.refheap.com
11:10shiranaihito:P
11:10shiranaihitoah..
11:10hyPiRionclojurebot: refheap is<reply>https://www.refheap.com/
11:10shiranaihitowell, there isn't any code outside of what happens in that blog post
11:10hyPiRionOh, clojurebot has died :(
11:10llasramOr does it just need a space?
11:11llasramclojurebot: ping
11:11hyPiRion,(+ 1 2)
11:11llasramOh, dead.
11:11hyPiRionboo
11:11shiranaihitoit's probably because of MongoDB.. :p
11:12hyPiRionshiranaihito: I wouldn't be surprised actually :p
11:12futileflu time
11:12shiranaihito:P
11:12shiranaihitohyPiRion: yeah.. i'm convinced Mongo shouldn't be used, at least for now :)
11:12Anderkentshiranaihito: what lein version are you using?
11:12llasramshiranaihito: Even if your code is almost just copy-pasted from that blog post, it can still help to post it
11:12shiranaihito2.2.0, apparently
11:12llasramDon't be shy! refheap right up!
11:13shiranaihito:p
11:15Anderkentshiranaihito: I'd start with `lein new template my-lein-template` and see if the default thing works. Then try adjusting it to do what you want and see when it breaks
11:15shiranaihitowell, i've just been trying to list directories etc that would get created in a fresh project: https://www.refheap.com/b4ea0ef266f47f1ac9adc9b4c
11:15hyPiRionshiranaihito: There are some working ones here: https://github.com/stuartsierra/reloaded/blob/master/src/leiningen/new/reloaded.clj and https://github.com/hyPiRion/pirlib/blob/master/src/leiningen/new/pirlib.clj
11:16shiranaihitoah, i'll take a look at the working ones
11:16silasdavisis there a nicer way to write (map #(% m) [:a :e :c])
11:16silasdaviswhere m is a map
11:16silasdavis?
11:16llasramshiranaihito: I think I see your problem -- I believe your one-element vectors need to be just the bare strings
11:16shiranaihitooh?
11:16hyPiRionshiranaihito: the ["string"] must either be "string" (which will create a directory) or a ["string" (render "string")]
11:17hyPiRionyeah, the ->files function is a bit weird
11:17hyPiRionsilasdavis: (map m [:a :e :c]) ?
11:17shiranaihitohyPiRion: well, i have no idea what's going on there :p just copying that blog post :p
11:18shiranaihitowhat does "->" in front of a func name signify?
11:18shiranaihitohyPiRion: ["string" (render "string")] <-- what would happen here?
11:20Anderkentthe -> is just part of the function name
11:20shiranaihitoAnderkent: yes but is it a convention to signify something? like python's "__whatever" for something that's private
11:20hyPiRionshiranaihito: actually, it's not that hard to grok. ["string" "file contents"] would create a file named "string" and put "file contents" in it
11:21Anderkentit's usually used to imply threading something through a list of calls or conversion into something
11:21shiranaihitohyPiRion: ok but how would i know that will happen? :)
11:21shiranaihitoAnderkent: oh, ok
11:23hyPiRionshiranaihito: (render "string") takes the file "string" and uses the moustache renderer to work with the contents
11:23hyPiRionand it returns the contents of the rendering afterwards
11:24hyPiRionThere's a bit more on it here: https://github.com/technomancy/leiningen/blob/master/doc/TEMPLATES.md
11:24silasdavishyPiRion, who'd have thought a map was a function... yeah thanks I knew there was something wrong with that
11:24hyPiRionBut I wish I could've written more, unfortunately time is not what I have the most of in the world.
11:27shiranaihitois mustache considered some kind of standard choice for a templating library for use with clojure?
11:27shiranaihitoor is there something "better"?
11:27shiranaihitohm.. i think i already asked about this at some poitn
11:27shiranaihitosakdjds :p
11:28yazirianshiranaihito: ->Foo style fn names are typically constructors
11:28yaziriandefrecord automatically generates them
11:28hyPiRionshiranaihito: It's not better or anything, it's just what the leiningen template system uses.
11:28shiranaihitoyazirian: constructors? as in, for classes?
11:28yaziriani.e. (defrecord Foo [bar]) will cause (->Foo "baz") to work automagically
11:28yazirianthat's the convention
11:29llasramBut to be clear, that's not what `->files` is here
11:29yaziriana defrecord? no. a constructor? yes
11:29llasramErrr
11:29yaziriani.e. from the docstring "Generate a file with content."
11:29llasramIt instantiates files on disk. It doesn't create file objects. I can see whare you're going, but it's kind of a stretch
11:30shiranaihitollasram: you were right btw, thanks! :p
11:30llasramSee -- always share the code :-)
11:30shiranaihito:P
11:30shiranaihitoyeah
11:31silasdavisshiranaihito, I like laser
11:32silasdavishttps://github.com/Raynes/laser
11:32shiranaihitosilasdavis: ah yes, i believe i heard of that last time
11:32Anderkentupwardindex: after some investigations, http://hg.openjdk.java.net/jdk7u/jdk7u/jdk/file/fdd0d43ba0f9/src/share/native/java/io/io_util.c is where the magic happens I think. Can't find where IO_Read is coming from, but it doesn't seem like there's any flag you could set to make it request the 2 bytes
11:34llasramAnderkent: But it looks like the readBytes() function will try to read up to `len` bytes at a time
11:35Anderkentyes, but he said he asks for 2 bytes there.
11:35llasramRight?
11:35Anderkentand was investigating why it ends up being two system calls each asking for 1 bytes
11:35Anderkent*byte
11:35Anderkent(which I assume he knows from strace)
11:37upwardindexWell simpler than that I just printk in my character device :)
11:38Anderkentah, then it might be the OS that's asking for 1 byte from you, not java asking linux for 1 byte?
11:40upwardindexI'm not aware of any layer that would make that kind of decision, what are you referring to as "the OS"?
11:40Anderkentwell, I don't know much about how linux implements `read`. It's not unimaginable to me that it doesnt do block reads from character devices ...
11:41Anderkentin fact isnt the point of a character device that it only returns a byte at a time?
11:41nDuffAnderkent: those details are below the syscall layer.
11:41Anderkentwhere does printk sit?
11:41AnderkentI thought it was in the driver
11:41nDuffAhh.
11:42nDuffI wasn't following very closely.
11:42Anderkentso did I initially, but then he says printk in his char device
11:43rasmustoan aside: early_printk rules
11:46upwardindexMaybe SeekableByteChannel.read is the culprit here
11:47Anderkentwell, all the java bits should be very easy to debug
11:47Anderkentand you can see what the syscall arguments are with dtrace (or strace if you must)
11:48Anderkentthat should tell you where to look for the issue
11:49upwardindexAnderkent: the java bits are easy to debug when you know java ;) anyways, I'll use a workaround for now I don't have the bandwidth, taking notes of all your pointers in the issue, thanks a lot for your help
11:49Anderkentyou should be able to just attach eclipse or whatever to your process, put a breakpoint in the random access file and watch the arguments
11:50Anderkentoh well, good luck :)
11:51silasdaviswhat's the most elegant way to move from a 'maybe nil or [x,y,z]' to a '[] or [x,y,z]'?
11:52silasdavisi.e. convert nil to empty list, but otherwise keep list
11:52Anderkentlist or vector?
11:52TimMcor
11:52Anderkentnil is an empty list
11:52llasramsilasdavis: Most functions slet you treat `nil` as an empty sequence. Why do you find you need to?
11:52llasramAnderkent: Well, not quite: ##(= nil ())
11:52lazybot⇒ false
11:52Anderkentthat just means = is broken :)
11:53TimMcsilasdavis: (or foo [])
11:53upwardindexsilasdavis: (or mystuff [])
11:53llasramAnderkent: Why do you say that?
11:53TimMcNo, the seq abstraction is broken.
11:54Anderkenti'm half kidding, I find nil punning very annoying most of the time. But it seems it's here to stay, so let's pretend it's consistent
11:54TimMc() should always be the empty seq; nil-punning is cute but problematic.
11:54abpalways sequing for nil
11:55Anderkent##(seq? (seq nil))
11:55lazybot⇒ false
11:55Anderkent#thiscljlife
11:55silasdavisI sort of want a cons or a conj that will treat nil as an empty sequence
11:56Anderkenthuh?
11:56Anderkent##(cons 1 nil)
11:56lazybot⇒ (1)
11:56Anderkentoh you mean you want to keep it
11:57silasdavis##(cons nil [3])
11:57lazybot⇒ (nil 3)
11:57silasdavis##(cons [3] nil)
11:57lazybot⇒ ([3])
11:57Anderkentwell cons takes the thing to add first and the sequence second, that all seems reasonable to me
11:58silasdavisso I need the former to give me (3)
11:58Anderkenthuh?
11:58Anderkentcons is not concat :P
11:58silasdavis##(conj [] [3])
11:58lazybot⇒ [[3]]
11:58silasdavis##(concat [] [3])
11:58lazybot⇒ (3)
11:58silasdavis##(concat nil [3])
11:58lazybot⇒ (3)
11:58silasdavisAnderkent, concat.. thanks
12:04silasdavisIs there a nice way to move from a 'maybe x or [x]' to '[x]'?
12:05silasdavisi.e. treat a single element as a singleton..
12:06silasdavisin ruby you might do something like [val].flatten
12:07Anderkentuh, it's doable but I wouldn't recommend it. Leads to really weird behaviour when someone passes a list as x for example
12:07silasdavisbut that is less acceptable here
12:07silasdavisyes
12:08Anderkentbetter have a separate function that only takes a single arg and wraps it in a list then calls the main function that always takes a list
12:08Anderkentthen your api is cleaner
12:09silasdavisso nothing better than #(if (coll? %) % [%])
12:10AnderkentNot sure if coll? is the right predicate there
12:11silasdavishm no it's not, because it's true for a map
12:11silasdaviswhat can I use that will get all list types...
12:12Anderkentyou'll have a problem with strings too
12:12mattmossseq? or sequential?
12:13Anderkentsequential? does it I guess ... But I still think it's a bad idea :)
12:13mattmoss##(seq {:a 1 :b 2})
12:13lazybot⇒ ([:a 1] [:b 2])
12:13silasdavisthat looks like it's about right
12:13silasdavisAnderkent, why?
12:14Anderkent(defn do-foos [foos] ...) (defn do-foo [foo] (do-foos [foo])) is just much cleaner
12:14Anderkentas I said
12:14Anderkentinvariably leads to confusion
12:14Anderkentlike -> does it
12:14silasdavisyou might be right
12:14Anderkentand it always sucks
12:14silasdavis-> ?
12:15Anderkentthe threading macro ->. At least for it the allowed syntax is very restricted and the automagic list wrapping only happens for a single symbol... But still a pain and common source of confusion
12:16mattmoss##(seq nil)
12:16lazybot⇒ nil
12:16mattmossnope
12:16rasmustoand -> leads to ->> leads to -<>-> or w/e
12:20silasdaviswhere does the confusion come from?
12:21justin_smith(-> foo bar) is the same as (-> foo (bar))
12:21Anderkentbut different from (-> foo ((bar))) :P
12:21justin_smithbut (-> foo ((bar))) is a different thing altogether
12:21justin_smithjynx
12:21Anderkentninja
12:21justin_smithand they you have to do things like (-> foo (#(bar nil %)))
12:22justin_smithjust to change argument ordering
12:22justin_smithand the extra paren wrapping is odd
12:22justin_smithsince #(bar nil %) is not necceessarily returning a function of no args, and that returned value is not being called
12:22justin_smithinconsistent
12:24gfredericks(as-> x <> ...)
12:25Anderkent(<<- ...) is amazing too
12:27silasdavisso would you completely avoid them?
12:30AnderkentWhen designing a function I'd avoid taking a 'list-or-single-element', instead offer two functions one taking a list and the other taking a single element
12:31Anderkentthe caller will always know which one it wants to call anyway
12:33TimMcduck-wrapping
12:43Anderkentif it doesn't quack, wrap it in a duck? Gross imagery.
12:44RaynesAnderkent: lol
12:45Chousukethere's usually no reason to even provide the 1-item function unless it's the 90% use case or something :P
12:45Anderkentindeed. And even then, if it's only one sequence, consider varargs
12:46Anderkenthm actually that might not work for longer sequences, nvm that
12:46Chousukeat least in a language where the difference between a sequence and a single element is two characters.
12:51silasdavisyeah I've ditched the single item thing
12:52silasdaviswhats the best way to go from [x y z] to {x (f x) y (f y) z (f z)}?
12:53Raynes(into {} (for [[k v] a-map] [k (f v)]))
12:53Anderkentwhat
12:53Anderkentno
12:53RaynesOh, that was unrelated.
12:53RaynesSorry.
12:53Anderkent(into {} (map (juxt identity f) my-vector))
12:53RaynesYou're a bad person.
12:53AnderkentxP
12:53Anderkentsorry, that came out harsher than I intended
12:54justin_smithfor extra win, (def identity id)
12:54Raynes(mapcat (juxt identity f) l)
12:54Raynessilasdavis: ^
12:55justin_smithRaynes: I think the into {} version was actually right
12:55RaynesYou didn't seem to want a map.
12:56RaynesIf so, then indeed.
12:56Anderkent(into {} ) always looks strange to me
12:56Anderkentthere should be an easier way of converting a maplike seq back into a map
12:59justin_smith(def as-hash (partial into {}))
12:59silasdavisthanks
13:00silasdaviswhy do functions in clojure core tend to get defined for 0, 1, 2, 3 arguments before being defined for arbirtrary args?
13:00silasdavis(such as juxt)
13:00justin_smithI would hazard a guess it is for performance reasons
13:01RaynesIt is.
13:01hyPiRionyup, most likely perf reasons
13:01silasdavisI assumed that must be the case
13:01silasdavisdo you understand why?
13:01RaynesIt is definitely performance reasons, for I know this for a fact.
13:03Anderkentsilasdavis: I'd guess if the compiler can count the arg number and find the right implementation statically it saves a layer of indirection on runtime
13:03RaynesIn a lot of cases it's faster to take and work with a specific argument count than to seq them up and then unroll them, etc.
13:03justin_smithis it about avoiding the overhead of implicitly creating the sequence for the varargs, only to immediately destructure them?
13:03justin_smithanswered my question just before I asked it, thanks
13:03Anderkentyeah that sounds reasonable too
13:04justin_smithtechnically creating a seq and then destructuring it is a layer of indirection over the arguments, so you were on the right track
13:05silasdavisAnderkent, your first reason is a bit circular; the only reason there are multiple implmentations is give essentially identical implementations of lower arity
13:06silasdavisor do you mean the functions are possibly called from that have meaningfully different implementations
13:07silasdavisanyway the seq thing makes sense
13:07Anderkentsilasdavis: for functions where the low arity version does not call the high arity version I was guessing that calling a 2-arg function is cheaper than calling a var-arg function
13:08Anderkentdoes that address your point or am i misunderstanding/
13:09Anderkentafaik calling a vararg funciton is done by a wrapper that basically does (switch (count args) (case 1 (call-arity args[0])) (case 2 (call-2-arity arg[0] arg[1])) etc.
13:09Anderkentwhich is why there's a max count to varargs
13:10squidzcemerick: I am using your nice austin library and wondering how you normally restart your jetty server while developing. May be more of a compojure question.
13:10cemericksquidz: I don't
13:10cemerickWhy do you need to restart jetty?
13:10justin_smithAnderkent: I thought it created a seq, which is why kargs work with varargs
13:11squidzbecause I am making changes to my static resource and need it to be reloaded which it seems not to be doing
13:11squidzmy index.html
13:11justin_smithyou just reload the resource
13:11Anderkentjustin_smith: yeah you're right, it's a switch on the count of a seq then ifn.invoke(arglist.first(), arglist.next().first ...)
13:11justin_smithno need to restart the server
13:11Raynescemerick: http://cdn.memegenerator.co/instances/600x/40437985.jpg
13:11Anderkentand of course I ment max arity of function, not max count of varargs
13:12squidzso how do I reload it then?
13:12Anderkentwait, (merge a-map b-map) is the same as (conj a-map b-map)
13:12Anderkenthow come?
13:12justin_smithsquidz: use a middleware that notices when a resource changes, or at dev time you can just uconditionally load from disk it on every request
13:12Anderkentweird.
13:13cemericksquidz: what route do you have for serving your static resources?
13:13cemerickRaynes: s/always/ever need to/g
13:14squidzcemerick: here is what it looks like. Very simple https://www.refheap.com/17437
13:14cemericksquidz: yeah, that should never be a problem. Maybe your browser is caching? Shift-reload?
13:14xeqisquidz: is page the same as in the sample app?
13:14squidzwhere page was the enlive template that you provided in your documentation
13:15cemericksquidz: oh, there you go; you need to load the clojure namespace where the template is loaded by enlive
13:16xeqiI switched mine to laser to avoid the template caching
13:16squidzafter reavaling the whole core.clj with the enlive template inclueded, it should work
13:17squidzbut it doesnt
13:18squidzhere is the whole core.clj https://www.refheap.com/17438
13:22squidzokay nvm I had several nrepl sessions open and I was eval'ing in the wrong session
13:23cemericksquidz: :-D sorry, man
13:23squidzyeah sorry for the silly question thanks anyways for the help
13:24tieTYTcan you guys help me with something? I couldn't figure out how to implement step 4 of this answer in a functional way. How would you do that? http://gamedev.stackexchange.com/a/6045/31177
13:25tieTYTit's a simple for loop that goes: R = (some random int); T = 0; for o in os (T = T + o.w; if T > R then return o)
13:25Anderkentwell, you can do it with (loop) obviosuly, but that's not very nice
13:25tieTYTright I wanted to know how to implement this functionally
13:25tieTYTusing map and reduce, etc.
13:26justin_smithfor that sort of short circuiting, you could use iterate and drop-while the end condition is not met, then take the element that meets the condition
13:27Anderkentjustin_smith: the problem is that the condition is modified in every loop iteration
13:27justin_smiththen you make iterate return the variables which create the condition
13:27Anderkentright
13:27Anderkentyeah that makes sense
13:28tieTYTbut won't drop while give me the number? I'm trying to get the object
13:28justin_smith((comp :answer first) (drop-while (comp not :done) (iterate (fn []) {:done false :conditions [] :answer nil})))
13:28justin_smithsomething like that
13:29justin_smithbasically everything that would be a variable in the mutable version is a key in a map passed through iterate
13:29Anderkentyeah but that's not very nice either
13:29justin_smithbut it is functional
13:30tieTYTsounds like that algorithm is tough to do in fp
13:31justin_smithnah, not hard, just ugly
13:31Anderkentwell that particular algorithm is very iterative
13:31AnderkentI'm trying to think of a prettier one that would do the same
13:31justin_smithisn't there a form of reduce that can just short circuit at some step?
13:32hiredmaniterate + take-while
13:33ToBeReplacedis there anything I should know about using Thread/sleep inside of clojure.test?
13:33tieTYTsee the problem I think with reduce is
13:33hiredmanjustin_smith: reduce can short circuit, it is new feature
13:33justin_smithahh, that is the clean way to do it then, if you can use the new clojure
13:33justin_smithwhere are the docs on that?
13:34tieTYTactually nm, I don't know. Where I got stuck is, "this is easy to figure out when to stop using a reduce, but I want to return the o type and the memo would need to be an int before that. I must be doing something wrong"
13:34tieTYTi'm not sure if that thought process was clear
13:36tieTYTanyway I'm really using JS and underscore.js to write this code. underscore doesn't have an iterate
13:36tieTYTso I just did it iteratively :T
13:41noonianits easy to implement recursively :P
13:42xeqi,*clojure-version*
13:42xeqiclojurebot: are you broken?
13:44xeqi&*clojure-version*
13:44lazybot⇒ {:major 1, :minor 4, :incremental 0, :qualifier nil}
13:45tieTYTnoonian: can you show me?
13:45xeqisurprised hes still on 1.4
13:46justin_smithxeqi - I think it is intentional that clojurebot and lazybot are the two most recent versions
13:46xeqitieTYT: (let [r 7] (reduce (fn [t [i w]] (let [t (+ t w)] (if (< r t) (reduced i) t))) 0 [[0 1] [1 2] [2 3] [3 4] [5 6]])) will work in 1.5
13:47justin_smithahh, that is how to get the short curcuit
13:47xeqijustin_smith: ^ (doc reduced) is all I can find about the "short circuit"
13:47justin_smithI tried to google and found nothing
13:47justin_smithyeah, but how was I to know reduced was the thing to look for?
13:47tieTYTcool I'll have to check that out
13:47tieTYTwhy DO you need to short circuit? Couldn't you just leave the memo as it is for the rest of the reduce?
13:48xeqiunfortuantly.. wait for the irc collective?
13:48justin_smithseems silly
13:48justin_smiththat is, reducing on the rest of the collection when you already have the asnwer seems silly
13:48justin_smithalso, what if you wanted to reduce on an infinite lazy list?
13:49tieTYTfair points
13:49xeqitieTYT: the memo is t until the condition, then switches to i. The rest of the computation needs to know not to treat it as t then
13:49xeqiwhich can be done by using memo of [t i] or a map or such
13:49tieTYTok yeah. See that wouldn't conceptually be an option in haskell then
13:49tieTYTyou couldn't even consider this as an approach, right?
13:50tieTYTsorry, brb
13:50nooniantieTYT: in JS? or clojure?
13:51noonian,(doc reduced)
13:51clojurebot"([x]); Wraps x in a way such that a reduce will terminate with the value x"
13:51noonianhuh, thats seems very useful
14:04mdrogalisHey sritchie. :)
14:04sritchieyo
14:22tieTYTnoonian: either. I could probably understand the JS better though
14:29callenwhy does ritz only support breakpoints for slime?
14:31mthvedtis it safe to write code that relies on the #= reader macro
14:31nifffhello room:) ,how slower are immutable data stractures?i made a program that has a lot of large vector and maps changes and its slow,maybe its my implementation or it is because of immutable data structures?
14:32nifffi love clojure,just worrying if its slow...
14:32nooniantieTYT: here's a recursive version, it uses underscore and is untested
14:32nooniantieTYT: http://pastebin.com/k0wxW3Ja
14:32TimMcmthvedt: Safe as in security or safe as in future-proof-ness?
14:33nooniannifff: are you sure its not just slow to startup because of the jvm startup time? they should be pretty efficient in general
14:33TimMcmthvedt: And is it your code, or data you are reading?
14:33mthvedtTimMc: future-proof-ness
14:34nooniantieTYT: oops, I had 0.w in there instead of o.w but you get the gist
14:37nifffi am thinking that maybe the garbage collector make my program slower,because i use heavy data stractures
14:37gfredericks2dericks
14:37nooniannifff: is it still slow if you call your function from the repl?
14:38nifffyes i use the repl,
14:38nifffthe similar program in javascript its 10x fastewr
14:38noonianwhat does the #= reader macro do?
14:38noonian,#=(println "test")
14:38clojurebot#<RuntimeException java.lang.RuntimeException: EvalReader not allowed when *read-eval* is false.>
14:38noonian,#=17
14:38clojurebot#<RuntimeException java.lang.RuntimeException: EvalReader not allowed when *read-eval* is false.>
14:38gfredericksnoonian: it evals the contents at read-time
14:39nooniangfredericks: ah, thanks
14:41tieTYTnoonian: ah ok, I like that. Thanks
14:41tieTYTnoonian: you might want to answer that here: http://stackoverflow.com/questions/18152343/how-can-this-imperative-code-be-rewritten-to-be-more-functional
14:41nooniantieTYT: no problem, be careful if you have a lot of objects though because you could potentially blow out the stack
14:41nifffdoes anyone know how much slower are persistent data structures?my programa is 8x slower than a javascript one,can this caused by the data structures being immutable?
14:42nooniannifff: can you post a code example of what you are doing thats slow?
14:42nifffi use large vectors and hash maps,and i assoc values
14:42nifffall the time
14:43dnolennifff: it just depends, you may be able to use transients in hot spots. Still if performance is critical, you can write CLJS so that it maps directly to the JS you would write.
14:46dnolennifff: if you want specific performance advice you will probably need to paste your code somewhere
14:53[1]nifff-
14:56nifffhttps://www.refheap.com/17443
14:56nifffif anyone have a llok
14:59dnolennifff: oh oops, I thought this was CLJS, but not matter, that's pretty unidiomatic looking code.
14:59dnolens/not matter/no matter
15:00dnolennifff: atoms won't make it any faster, paste your version sans atoms
15:00callendnolen: you can write Fortran in any language.
15:01dnolennifff: also are you using leiningen?
15:01nifffyes i use counterclockwise
15:02dnolennifff: you may need to set explicit server settings in your project.clj since Lein uses bad defaults
15:02dnolenor used to (not sure about 2.3.0)
15:02xeqifor some value of "bad"
15:02dnolenxeqi: bad for benchmarking
15:02dnolenxeqi: or profiling
15:03nifffhttps://www.refheap.com/17444
15:03dnolennifff: that code also looks like it needs work :)
15:04nifffits a freak :)
15:04technomancy.|
15:04dnolennifff: make sure JVM -server settings is enabled
15:04nifffhow to change this?
15:04technomancydnolen: -server is actually impossible to turn off these days
15:04technomancyunless you're running a 32-bit JVM
15:04dnolentechnomancy: not on OS X
15:05technomancywow, they still haven't made the jump yet?
15:06nifffthe question i have is it the persistent data or my code?how slower are persistent data? 2x 4x 8x :)
15:06dnolentechnomancy: all I know is that I need to enable -server explicitly in Lein now
15:07dnolennifff: there's too much code to tell, but different data structures have different profiles - you can benchmark different cases yourself :)
15:07nooniannifff: I would guess it's the code, but I can't really read the code so I'm not sure
15:07nifffthanks people for trying,when you have a large data structure with a lot of assocs what you use?
15:08nifffi used vectors and maps
15:08noonianwell, you can use a single assoc to put multiple keys in at the same time
15:08noonianI'm not sure what you mean lots of assocs
15:08dnolennifff: vectors and maps, but it looks like you're trying to do Binary Decisions Diagrams with persistent data structures?
15:09nifffyes thats i am doing binary decision diagrams
15:09nifffi made the program its ready but slow
15:09TimMcmthvedt: I think #= will probably stick around for a while, but I'd bet it is undocumented so that people won't use it...
15:09dnolennifff: I don't really the benefit of immutable data here when speed is the goal usually with BDDs
15:10nifffwhat data structure to use?
15:10dnolennifff: I'm assuming you're using arrays in Java?
15:10dnolennifff: use them in Clojure
15:11nifffok i will use java arrays,and i will compare the perfomance,thanks
15:11nifffbye room:)
15:11dnolennifff: make sure to use (set! *warn-on-reflection* true)
15:11dnolennifff: w/ arrays you have to be careful w/ type hinting
15:11nifffok but i dont know what that means :)
15:12nifffi will read java interop first
15:12dnolennifff: bingo :)
15:21jcromartieIs Aleph (still) the best way to write a simple TCP server in Clojure?
15:21jcromartieI feel like it's gotta be
15:22ztellmanarguably just using java sockets could be simpler, for some definition of simple
15:22ztellmanbut aleph is more idiomatic
15:23futile_pst ztellman what OS you on
15:23ztellmanos x
15:23futile_ztellman: use any window manager?
15:23ztellmannope
15:23futile_oh wait this is off topic
15:24technomancyjcromartie: there's no one right answer; it depends on the shape of your problem.
15:24jcromartietechnomancy: I know you've got a lib
15:25futile_anyone used Instaparse?
15:25technomancynot really
15:26technomancyjcromartie: if you're mostly just shuffling bytes around you'd be better served with Aleph. if your connections end up doing substantial work on the same node, (so that each node can't service more than a couple thousand connections at a time) use raw sockets.
15:27technomancys/just //; didn't mean to trivialize it
15:27ToBeReplacedjcromartie: i use (cl)jzmq for persistent tcp
15:27ztellmanfeeling very trivialized over here :)
15:27clojurebotNo entiendo
15:27jcromartieztellman vs technomancy: FIGHT
15:27TimMcclojurebot: You *wouldn't* entiendo.
15:27clojurebotI don't understand.
15:28technomancyjcromartie: honestly if you need it to be fast you should just use node.js, duh
15:28callenapparently my entire career has been just shuffling bytes around
15:28callenTIL
15:28TimMc"Chris Allen: Electron pusher"
15:28technomancyhttp://p.hagelb.org/async.jpg
15:28jcromartietechnomancy: I don't need web scale or big data
15:28TimMcThat's your business card right there.
15:28jcromartie:|
15:28jcromartie:P
15:30technomancyjcromartie: I spun the server-socket lib out of old monolithic-contrib but don't really have any intention of using or maintaining it
15:30jcromartieyeah
15:30technomancyshould probably mention that in the readme
15:30jcromartieI see that. It's just there, which is fine. I'm glad it's that simple.
15:31jcromartiebut let's say you wanted to write a MUD
15:31jcromartie(I'm trying it right now, with Aleph)
15:32technomancyan excellent! ideahttps://github.com/technomancy/mire
15:32jcromartieeverybody loves MUDs
15:32technomancyerr--an excellent idea
15:45jcromartieztellman: so do you see Lamina being built on core.async in the future, or do you see core.async taking the place of Lamina in projects like Aleph
15:45jcromartieztellman: also, are you completely sick of this question yet?
15:45ztellmanjcromartie: I see Aleph being equal-opportunity w.r.t. stream representation
15:47ztellmanprobably by default the channels will be core.async, since that's where the momentum seems to be, but Lamina and core.async are different enough in their goals/implementations that they can coexist
15:50ToBeReplacedztellman: how are their goals different?
15:51ztellmanToBeReplaced: see the comments at the bottom of http://clojure.com/blog/2013/06/28/clojure-core-async-channels.html
15:51ToBeReplacedthanks
15:53ztellmanit may turn out that Lamina's unique qualities only matter to me and a few other people, but they help with my day-to-day job, so I think I'll keep it around for a bit longer
15:55ToBeReplacedi haven't had the pleasure to work with Lamina yet -- i do have the need to treat queues as streams often though
15:56ztellmanToBeReplaced: I find it to be a nice way to think about/process streams of data
15:56ztellmanbut it's kind of a sprawling mess of functionality right now
15:57ztellmanI'm in the process of trying to extract functionality that doesn't need to be coupled to its particular stream representation
15:57ztellmansee https://github.com/ztellman/narrator among others
15:58ToBeReplacedinteresting; i'm interested in the stream operators over channels for times where blocking is acceptable
15:59ToBeReplacedmap* etc. over channels being populated elsewhere -- that sort of thing is really clunky over BlockingQueues
16:00ztellmanyeah, also bifurcation of queues
16:05pbostrom+1 to lamina, nice library, even if it was crappy, the viz stuff would make up for any short comings
16:06ztellmanpbostrom: thanks, the viz stuff is in its own library too, now :)
16:06ToBeReplacedsplitting a lazy-seq is weird too though
16:07ztellmanToBeReplaced: splitting a lazy-seq is risky, the consumers may go at different rates and cause a memory leak as a result
16:07ztellmanyou want the consumers to be coupled
16:07ztellmanor at least aware of each other
16:08ToBeReplacedyou have related problems splitting off of queues though if one queue gets filled up
16:09ToBeReplacedi think splitting is necessarily hard -- no matter how you do it you need to deal with the different consumers
16:12ztellmanToBeReplaced: that's because the topology of the queues is implicit; there's no way to know when a given message has cleared your dataflow
16:12ToBeReplacedi take it back -- you can at least handle a memory leak b/c you can block at the site of the split and prevent A from getting any more action until B does its job
16:13ztellmanyes, though that has the TCP bufferbloat issue of waiting for all the queues to fill up before you get any backpressure
16:13ToBeReplacedyeah, generates thunder hard and fast
16:14ztellmanan interesting property in Lamina is that if a message lands in a queue, it returns a promise representing the consumption of the message
16:15ztellmanif it travels through multiple queues, it yields a promise that yields a promise that yields...
16:15ztellmanbut this allows you to actually know when a message has actually cleared the topology, including actually clearing the TCP write buffer, etc.
16:16ztellmanso you know exactly how much is in flight at any given time
16:19ToBeReplacedwhen would you travel through multiple queues without coming off? i would have assumed that coming off would cause the promise to yield
16:20ToBeReplacedtrying to understand how that's different from asking a queue "hey what's your size, and how many you got?"
16:22ztellmanToBeReplaced: when you have multiple queues pipelined together
16:22ztellmanwhich happens reasonably often, when it's easy to compose operators together
16:22ztellmanso there's a difference between clearing the queue(s) closest to you, and clearing the entire topology
16:23ztellmanto be fair, this may not be significantly better than just using blocking queue semantics
16:23ztellmanbut it's an interesting space to experiment in
16:23ToBeReplacedah, so it's the operators responsibility to relay the messages back?
16:24ztellmankinda, it's mostly implicit
16:24ztellmanall channels have queues, which are bypassed if there's something downstream
16:25ztellmanif you're doing something clever like batching or flattening streams messages, you need to correctly handle the return values you get from propagating them downstream, but the provided operators do that for you
16:26ToBeReplacedokay
16:37qedI want to make a function that is called like: (foobar :a 1 :b 2) -- how do people typically write the definition so the args can be treated like a map?
16:38llasramqed: ##((fn [& {:as args}] args) :a 1 :b 2)
16:38lazybot⇒ {:a 1, :b 2}
16:38qedthanks llasram
16:49upwardindexIs there any other way to write foo/bar ?
16:50upwardindexI mean (foo/bar)
16:50TimMcqed: You don't.
16:50TimMcIt's really irritating to call such functions, especially if you want to apply args to them.
16:51TimMcInstead, what you want is (fn [foo bar & [{:keys [a b]}] ...), which is called with an optional final map argument.
16:52llasramupwardindex: In what sense?
16:53upwardindexllasram: trying to do something like this https://www.refheap.com/17447
16:54upwardindexbut ~module/initialize is trying to ~ "module/initialize" instead of only "module"
16:54llasramupwardindex: Huh. Well, you can do `~(symbol (name module) "initialize")`
16:55llasramI'm not sure how advisable that is though -- definitely not a common pattern
16:57upwardindexllasram: yes I see, there might be something else i can do if I approach the problem differently
17:03upwardindexHow could I make a function that receives a list of namespaces and calls the foo method in each one
17:05llasramupwardindex: Well, exactly the same way as ^^
17:05llasramIt's the idea of having the particular name of a function embedded in a macro which isn't a common idiom
17:06noonianhmm, just going off the docs of in-ns, I might try something like (binding [*ns* namespace] (foo)), but I haven't had a use case for that and not sure how that'd work
17:06noonian,(doc in-ns)
17:06clojurebot"([name]); Sets *ns* to the namespace named by the symbol, creating it if needed."
17:06llasramupwardindex: Oh, you said a *function*
17:06llasramin-ns won't do what you want, because of how dynamic vars interact with compliation
17:07llasram`resolve` is the thing to look at if you can't be disuaded
17:07noonianyeah, in-ns seems to rebind the var at the top level, but a local binding might work using binding
17:07noonian,(doc resolve)
17:07clojurebot"([sym] [env sym]); same as (ns-resolve *ns* symbol) or (ns-resolve *ns* &env symbol)"
17:07llasramOh, `ns-resolve` right
17:07noonian:D there you go
17:08upwardindexnoonian: thank you!
17:08upwardindexI guess the cleaner way would be to define an interface?
17:09llasramOr just let users pass in a function to call?
17:09nooniannp
17:10noonianyeah, a list of functions (from w/e namespace) instead of a list of namespaces is how I would go about it
17:11upwardindexllasram: I might be over-refactoring it's just that the code is quite redundant
17:11upwardindexI'll medicate on that, thanks guys!
17:12llasramnice
17:13ToBeReplacedin Leiningen, can dev profiles specify environment variables?
17:15llasramToBeReplaced: If you're referring to https://github.com/weavejester/environ and lein-environ, then yes
17:16llasramLeiningen has no builtin to set arbitrary environment variables via project.clj
17:16llasrams,builtin,built-in way,
17:18ToBeReplacedllasram: what about jvm-opts? i want that "lein test" runs with something, anything, different from "lein run"
17:18qedCan I programatically call methods like: (for [meth '(.fooBar .barBaz)] (meth "ABC"))?
17:18ToBeReplacedpreferably lein run != lein repl != lein test
17:19llasramToBeReplaced: You can set JVM properties via `:jvm-opts`, if that's what you actually need. People use them similarly to environment variables, but they aren't the same thing :-)
17:19ToBeReplacedqed: you'd have to create anon functions aroud them (for [meth [#(.fooBar %) #(.barBaz %)] (meth "ABC"))
17:19technomancyToBeReplaced: the repl and test tasks both check for profiles named :repl and :test respectively
17:19qedToBeReplaced: Sounds like a job for a macro
17:20ToBeReplacedjvm-opt would work for me; i don't grok leiningen profiles -- can i specify jvm-opts within a profile, and it'll get merged with the top level jvm-opts?
17:20llasramquackv4: Not really, actually. There's `memfn` from the olden-days, but the #(...) syntax is shorter, more flexible, and allows you to provide type hints
17:20qedi think you meant me llasram
17:21llasramhah!
17:21llasramYou are correct
17:21technomancyToBeReplaced: :jvm-opts from profiles will get appended to :jvm-opts in defproject top-level
17:21ToBeReplacedllasram: technomancy: thanks, sorted
17:21technomancyToBeReplaced: it won't be "merged" in a key-value sense, but it will be combined
17:21ToBeReplacedright
17:21tbaldridgednolen: JIRA is giving me problems atm, but that set! async bug is fixed.
17:22qedllasram: you say memfn from the olden days like it's a bad thing
17:22dnolentbaldridge: excellent!
17:22llasramqed: It's unofficially deprecated. It probably wouldn't have existed if the #(...) had appeared earlier
17:23llasram(is my understanding, anyway)
17:23dobry-deni'm writing simple ring middleware to redirect `/hello` -> `/hello/` but not `/hello.jpg` -> `/hello.jpg/`. Would it be sufficiently robust to just look for a trailing extension to see if i don't need to redirect?
17:23technomancyI like memfn =(
17:23technomancyqed: rich doesn't like it though
17:23llasramI bet you also like kittens! And sunshine! Ugh. What kind of monster are you?
17:23technomancyrawr
17:24technomancyI'm not totally clear why bare .methodCall symbols couldn't be implicitly memfn'd
17:24callenI'm puzzled by memfn when we have nice function literals.
17:24bbloomtechnomancy: has to do with overload resolution
17:25technomancybbloom: and probably because you wouldn't want that when it's in the call position
17:25llasramWhat about #.method as reader syntax for memfn?
17:25technomancyand caring about call position is tacky
17:25technomancycallen: fewer tokens
17:25bbloomjust like how you can't take the value of a macro without applying it to forms, you can't take the value of a method call without applying it to argument types
17:25callentechnomancy: what's the matter, don't like #(%)!@@@@@ ?
17:26technomancycallen: aren't you CL types supposed to complain about all the extra syntax clojure has? =)
17:26qedllasram: so what i want to do is take a seq of java methods, all of which take 1 argument. I want to generate fn names like "foo-bar?" from "isFooBar". Is that doable?
17:26callentechnomancy: one would almost think you like Lisps.
17:26callentechnomancy: yes, that's what I'm lampooning.
17:26callentechnomancy: I prefer words and parens and little else, although vectors have won me over.
17:26technomancybinding: it's not the same as calling.
17:26technomancy#truefacts
17:27llasramqed: That's more usefully-doable, because you can do all the mangling at macro-expansion-time and even provide sane type-hints
17:27ToBeReplacedqed: yeah, macro-it-up
17:28ToBeReplacedharder to get the method names though
17:28bbloomtechnomancy: but to fully clear up the auto memfn-ification of .methodCalls: it's doable if the compiler was defunctionalizing
17:28bbloomtechnomancy: that is, all higher order operations would be inlined
17:28ToBeReplacedat least, hard to do it sensibly (and do all the right things around overloading)
17:28bbloomtechnomancy: but since functions are reified into IFn instances, then we can't do it, except as a potential optimization
17:29technomancybbloom: yeah, I'm OK with "it would introduce a bunch of special cases resulting in unpredictable behaviour" I gueeeeeeess
17:29qedllasram: how do I pass in '(.fooBar)?
17:29bbloomi don't think it's a special case or unpredictable behavior. it just requires a smarter compiler
17:30technomancycallen: my favourite part is how people complaining about square brackets seem to be oblivious to the fact that they sound *just* like the "too many parens lol" crowd
17:30qedllasram: (so it's callable later)
17:30llasrambbloom, technomancy: As continue to think about it, do you know if anyone has proposed #.method as reader syntax for auto-memfn'ing? Inside my head at least it seems really convenient
17:30technomancyllasram: could you experiment with it in user space using data_readers or whatever?
17:31llasramOh! Yes
17:31bbloomllasram: it would require the compiler to use either reflection (slow) or to perform inlining & then would either need to A) fallback to reflection or B) error out for dynamic function use
17:31llasrambbloom: Oh, I was totes envisioning reflection
17:31llasramMaybe some invoke-dynamic love in the future
17:32bbloom*shrug* i think making it harder to use reflection is a good thing
17:32callentechnomancy: that's largely why I don't complain, the syntax doesn't bother me. That having been said, there's something pleasantly and quietly conversational about Lisp.
17:32bbloomtechnomancy: the thing about the "extra" syntax in clojure is that scheme etc *already has special syntax for lists*. In fact, scheme has a binary infix operator for creating pairs & the parens are shorthand for that
17:33llasramqed: You'd write a macro which too the bare symbol names for the methods: (defmethodfns SomeType isFooBar isBazQuux)
17:33bbloomtechnomancy: in theory, the pair dot operator is a concrete constructor & you could have polymorphic implementations of lists
17:33llasrams,which too,which took,
17:33bbloomtechnomancy: extending that idea to maps & other data types is a NO BRAINER
17:33bbloom(now that i've used with clojure)
17:33llasrambbloom: I mostly agree with you, but think making it easier to use Clojure is a good thing :-)
17:33callenbbloom: Lispers didn't like the dot either.
17:33callenjust fyi
17:34bbloomcallen: but the dot is actually the opposite problem. it's going from something abstract (list notation) to something concrete (pair notation)
17:34technomancybbloom: from what I can tell other lisps don't bother with maps
17:34bbloomtechnomancy: which blows my mind
17:34callenit's not really complicated
17:34callenmost maps as they are used in most languages don't need to be actual maps
17:35callenjust associative pairs
17:35bbloomsure, we've got association lists too, but we call them PAM
17:35bbloomchoosing to use a concrete representation is a bad plan
17:35callenI know there's a concrete impl that is similar
17:35callenthere's a *reason* I use Clojure after all
17:35callenI'm just making the point that Lispers were accustomed to picking and choosing the bits they wanted.
17:36callenwhether that be an assoc list or hash-table
17:36technomancyI get the feeling in scheme hash-tables are only used if you don't know the possible keys up-front.
17:36bbloomyou can think of clojure's syntax as being a pre-macro compiler pass which evaluates forms corresponding to abstract data types
17:36technomancywhich is why it doesn't bother people that they don't have usable literal syntax, as far as I can tell
17:37callenI'm not saying I mind Clojure syntax, I'm saying it took me time to stop being grumpy about it and I understand why others might be.
17:37callentechnomancy: thanks again for limit-break :P
17:37technomancybut stuff like update-in seems more onerous with hash-tables or alists or whatever
17:38bbloomupdate-in is glorious.
17:38technomancycallen: cool; at least someone is using it
17:38bbloomit's like 90% of lenses without a phd :-)
17:38callentechnomancy: Ritz is too baroque, I have to use it.
17:38tomjack90%??
17:38lazybottomjack: What are you, crazy? Of course not!
17:39callenbbloom: you've insulted tomjack's hobbies.
17:39bbloomtomjack: ok 20%, whatever. go give me the other 80% as simply as keywords & vectors work w/ update-in :-)
17:41tomjackit's one point in a whole space, I'd say 0% :)
17:41bbloomnope, i'm going with the 80/20 rule :-P
17:41callenbut for the rest of us, it's 80%
17:43callennew rule, if I can't grep around for what the JIRA ticket is referencing and nobody answers my question on the JIRA task, it's not getting done.
17:43technomancywhat's wrong with the old rule of "if it's on JIRA, it's probably not getting done"?
17:43bbloomso the nice thing about update-in & friends is that you get something lens-like without having to A) create an entirely separate set of objects or B) use data with quoting/unquoting wrapper objects
17:43tomjackbbloom: yeah 80/20 probably applies :)
17:47callentechnomancy: I like to try.
17:47callenI also like a clean JIRA panel so that I can do other things.
17:53leif-pHey everybody. Can anyone point me to some design docs for core.async and/or suggestions of non-trivial applications to hack on to learn it? tbaldridge, I'm looking in your direction.
17:56tbaldridgeleif-p: there's this, but like you said, it's trivial https://github.com/clojure/core.async/blob/master/examples/walkthrough.clj
17:56tbaldridgebesides that and the golang talks/tutorials, I don't really have much else.
17:57leif-ptbaldridge: what about design docs? Did you work off of any papers / implementations when composing that gnarly macro / compiler?
17:58bhaumanleif-p: I'm assuming your aware of this https://github.com/swannodette/async-tests
17:58tbaldridgeleif-p: I got the ideas from https://github.com/scala/async#how-it-works , but the actual code/design is my own work.
17:59tbaldridgeleif-p: it's one of those things where C#, and Scala both do similar transforms, but from what I've been able to find, haven't really published how they do it.
18:00tbaldridgeThere's also this, that might help a bit: http://hueypetersen.com/posts/2013/08/02/the-state-machines-of-core-async/
18:00bbloomtbaldridge: scala's approach uses shift/reset (delimited continuations) & is documented here:
18:01bbloomhttp://infoscience.epfl.ch/record/149136/files/icfp113-rompf.pdf
18:02tbaldridgebbloom: you're thinking of Scala's CPS transform, the code I linked to is from the async implementation, https://github.com/scala/async#comparison-with-cps-plugin
18:02bhaumanleif-p: there's also this: examples from Hoare's paper rewritten in core.async https://github.com/nodename/async-plgd
18:02tbaldridgeLeave it to scala to implement two ways of doing the same thing
18:03leif-ptbaldridge: Yeah, I saw async-tests, and it seemed UI-focused, but it *will* probably help me get my head around the programming model. The docs you and bbloom just sent will probably be enough for me to muddle through (and keep me busy for a long while). Thanks, all!
18:03bbloomah, my misunderstanding. thanks for the correction
18:05bbloomoh interesting, they are doing local state machines too. cool
18:17devnhttp://www.flipscript.com/data/AMBICBar_K1W1M0G1b2363X1,1-207,50;G0c4c95X1,51-207,100;G231b61X1,101-207,150;G512c16X1,151-207,200;S2G917341X1,201-207,250;S2Gff96ffX1,251-207,300;S2Gfbefa3X1,301-207,350;S2Ge2e2e2X1,351-207,400;G323232X1,401-207,450.pngx?dv=0&amp;cq=99&amp;tn=0&amp;rg=1&amp;gs=2&amp;ff=3&amp;w1=clojure&amp;w2=&amp;ff=3&amp;pk=369970934
18:17devnyeesh, sorry about that URL
18:33mikerodn00b question probably, but how do I change the value of a Var without re'defing it? I am getting this "IllegalStateException Can't change/establish root binding of: my-var with set clojure.lang.Var.set (Var.java:233)" using set! . I know that I can use alter-var-root, but is that my only option?
18:33mikerodI'm not wanting to just dynamically rebind it either.
18:34RaynesDon't.
18:34bbloomyeah, what Raynes said
18:34bbloombut also, you can use alter-root-var with constantly
18:34RaynesBut don't.
18:34bbloomyeah, what Raynes said again
18:35mikerodRaynes: bbloom this is only for a testing scenario with code I'm not keeping around
18:35RaynesIf you really need state, use an atom or something.
18:35mikerodmore of an interactive thing
18:35bbloommikerod: in that case, use with-redefs
18:35mikerodbbloom: Ok, so what is a use-case of set! and var-set? Just out of curiousity.
18:35mikerodcuriosity*
18:36bbloommikerod: dyhnamic bindings are mutable
18:36bbloomlike if you need a thread local atom or something, you can just var-set inside a binding form
18:36bbloombut it's pretty rare / often a bad plan
18:39mikerodbbloom: Ok, that makes sense.
18:39bbloomhttps://groups.google.com/forum/#!topic/clojure/PCKzXweeDeY
18:39bbloomthat post actually explains it pretty clearly
18:39bbloomthe reason mutable vars is OK is b/c they have dynamic extent, so they can't escape via a closure
18:39bbloomwhich means you can't break thread safety
18:40mikerodThat makes sense. Thanks for the link, reading through it.
18:41mikerodSo *warn-on-reflection* is an example of a dynamic Var. I see it is defined in RT. It seems I can do a (set! *warn-on-reflectoin* true) from within the REPL.
18:41bbloomand if you use bound-fn, you're essentially cloning (part of) the execution environment, so mutating a dynamic var in your extent won't affect bound-fns which can modify the dynamic vars in their isolated dynamic extents
18:43bbloommikerod: looks like RT.java calls push-thread-bindings on startup
18:43bbloombasically, warn-on-reflection is bound in the dynamic extent of main
18:44bbloomoh no, more accurately:
18:44bbloomthere is a try/push/finally/pop in there, which is akin to the binding macro
18:44bbloomand it wraps the file loading process
18:44mikerodAh, that makes sense.
18:45mikerodThat's what initially threw me off that I couldn't def a Var similarly and use set! on it. Makes sense now that it fits into being bound in the dynamic extent.
18:46bbloomunfortunately (or thankfully?), clojure's module loading logic is not pluggable in anyway, otherwise you could do the same trick. in theory, you could imagine registering a hook that gets passed the loading thunk & you could wrap a binder around that
18:46bbloombut clojure doesn't offer such a feature
18:51mikerodYeah, I guess that doesn't upset me too much really since I haven't really ran into wanting to do this much before anyways.
18:52bbloomuse with-redefs :-)
18:53mikerodNow that I look again, I see this same binding mechanism is used in clojure.main. Thanks for helping me understand that. Enlightening. with-redefs is workable.
18:57cromneyanybody run into an issue where InetAddress/getByName works, but InetAddress/getAllByName fails to resolve the same hostname?
19:00akurilinQuick style question: is it reasonable to place argument checks into a do block, assuming they either do nothing or throw an exception?
19:00bbloommikerod: this also reminds me of something i was wondering a few months ago: I wonder if performance is the *only* reason why lazy-seq & friends don't use bound-fn. i suspect so
19:01hiredmanI imagine the other reason is binding conveyance is just gross
19:01bbloomhiredman: you think that even for thunks?
19:02hiredmanyes, which doesn't mean I don't do it, because it is useful
19:02hiredmanbut it can cause all kinds of edge cases which I wish just weren't there
19:03bbloomwhich edge cases are you thinking about in particular?
19:03hiredmanfor example what does the clojure predicate thread-bound? mean?
19:03bbloomi spend a lot of time thinking about dynamic extent, effects, and context. since they seem to be kinda the unsolved "hard" problems in the functional world
19:03hiredman(I think it is thread-bound?)
19:04bbloom(doc thread-bound?)
19:04clojurebot"([& vars]); Returns true if all of the vars provided as arguments have thread-local bindings. Implies that set!'ing the provided vars will succeed. Returns true if no vars are provided."
19:04cromneyakurilin: have you looked at pre-conditions?
19:04bbloomhm, i've never felt the need for such a predicate, i couldn't imagine what i need it for....
19:04bbloomwhat have you used it for?
19:04hiredmandoes it mean that the var was bound in this thread, or that the binding was conveyed, and if I have a macro that tries to establish a thread local binding, and only one binding
19:06hiredmandoing binding conveyance in lazy-seqs brings even more edges
19:07bbloomso part of the issue is the "full" capture of bindings
19:07bbloominstead of a delimited capture
19:07hiredmanmiles of edges
19:07bbloomlike if i have a *current-thread-id* and it's set to 5
19:07bbloomthen i bound-fn, and then run that on another thread, i'm fucked
19:07hiredmanassuredly
19:08bbloomthere is a need for delimiters: http://okmij.org/ftp/Computation/dynamic-binding.html#DDBinding
19:08hiredmanwhich, future and agent sends now helpfully do for you :(
19:08bbloombound-fn is akin to a full, non-composable continuation :-/
19:09hiredmanso, you know, leave it out, if I need to capture the dynamic environment I can capture it lexically and rebuild it myself
19:10bbloomyeah, ok, you've prompted me to think about it and caused me to sell myself what you're offering :-)
19:10hiredmanbut rich maybe has some idea for building a conditional system using them or something
19:10hiredmanhe mentioned something like that at his conj keynote where he said binding conveyance was going to happen
19:12bbloomseems like core.async greatly diminishes the pressure to do something like that
19:12bbloomb/c you can establish dynamic bindings in "forked" sub processes
19:12bbloomand then you just parameterize both of them with a channel
19:12bbloomthe same channel, i mean
19:13bbloomif java & javascript had fast, restartable exceptions, it might be a different story
19:13noonianwhat is a good place to point people at who are interested in learning Clojure but don't have much (or any) background in cs and/or programming?
19:15hiredmannoonian: the best place to start is with some problem you want to try and solve
19:15bbloomhiredman: on a related note. i wish there were explicit dynamic parameters, and implicit static parameters. right now, we've got 2 diagonal corners of that 2x2 grid & the other 2 corners are lonely
19:15bbloomactually, hm. i guess passing around atoms cover the explicit dynamic parameters thing, to some extent
19:16noonianhiredman: thanks, but I would like a good starting resource to point someone at when the other options they are considering are learning python or ruby and the like from somewhere like code academy or udacity
19:18cromneynoonian: O'Reilly has some great videos that Neal Ford and Stu Halloway recorded called Clojure Inside Out
19:18cromneynot free, but worth the investment imho
19:19cromneynoonian: codeschool has some free Clojure vids iirc
19:19hiredmannoonian: let them go there, the closest thing to those kind of classes are maybe the clojure training stuff the relevance guys do, but that is sort of few and far between
19:19technomancybbloom: doesn't closing over something count as an implicit lexical parameter?
19:19noonianthanks guys
19:20hiredmanonce they have experience with other stuff, clojure should be very attractive to them and you won't be able to stop them picking it up
19:21mikerodbbloom: Interesting topic. This is the first I've looked into bound-fn. This gave me some things to add to the reading list.
19:21bbloomtechnomancy: i guess so, but it seems kinda rigid compared to what scala & haskell can do w/ implicit arguments
19:21noonianyeah, I'm just trying to present Clojure as an alternative because I doubt they are aware of it at all
19:22bbloomtechnomancy: although, those rely on a type system, i guess you could imagine an untyped variant of them. not sure what it would look like tho
19:22technomancybbloom: "implicit" is uncomfortably close to "magic" in my experience
19:22technomancybut I haven't used haskell or scala
19:22bbloomi can't change the literature, but i'd s/implicit/contextual/
19:22callenI have, I like it.
19:23bbloomoh, so interestingly, it seems haskell's implicit parameters are type checked, but resolved by NAME not by type
19:23callentechnomancy: imagine refinements but not retarded. Like that.
19:23bbloomscala's implicit parameters are resolved by type, which seems dumb to me
19:23callener, implicit arguments, not Scala implicits, sorry.
19:23bbloomhttp://www.haskell.org/haskellwiki/Implicit_parameters
19:23callenI misunderstood
19:25bbloomtechnomancy: compare to the approach here: http://www.scala-lang.org/old/node/114
19:26bbloombound-fn pushes/pops bindings on top of the dynamic bindings, which involves a linear scan of the bindings
19:26bbloomin theory you could just *set* without supplementing the implicit bindings map
19:27bbloomi'm not sure how either scala or haskell handle implicits with respect to closures tho
19:28bbloomalso, it seems common to want to transfer some subset of dynamic vars to implicit ones. there is this temptation to not pass *vars* but it makes sense to leave the dynamic extent world when you ultimately call a function that wants that argument from the lexical extent of the caller
19:29callenbbloom: closures themselves can have implicit arguments in Scala
19:29callenhttps://issues.scala-lang.org/browse/SI-1492
19:30bbloomgotcha. i take issue with the dispatch by type, however
19:31callenthere's a lot to take issue with in Scala, it's not a language for people whose dicks get raw at freckles on a pretty girl's face.
19:31callenmost people are just happy to have a non-trivial type system.
19:31bbloomi have no idea what that means, but i'm quite certain it's inappropriate in here
19:31callenbbloom: whining about relatively unimportant flaws.
19:33cromney..
19:57callencromney: are you not entertained?
20:00TimMccallen: Gonna have to agree with bbloom here.
20:09callenTimMc: I would too, if I were you.
20:11llasramwow
20:12travisrodmanhello clojurians... i have a java compilation issue
20:12travisrodmani am building in maven, using a java class that has a static initializer
20:13travisrodmanand when the clojure code is compiled, it seems to be executing the initialization of the class
20:13travisrodmaninstead of just compiling the code
20:13technomancytravisrodman: clojure code can't be compiled without being run
20:13travisrodmanit works fine building in lein, and i am using the theoryinpractise plugin in maven for the build
20:14travisrodmanhmm
20:14llasramtravisrodman: Importing a class in Clojure forces the class to be loaded, which will run any static initializers on the class
20:15travisrodmanthat is unfortunate... is there any way to work around this without modifying the original java code?
20:15technomancymost likely lein wasn't doing any compilation at all
20:15technomancytravisrodman: you could resolve the class at runtime. it's pretty awkward though.
20:15technomancyand slow
20:15travisrodmanthanks for the immediate feedback btw...
20:15technomancyor just don't AOT the clojure code
20:16llasramtravisrodman: Not that I'm aware of. In code I control I've just been pushing things I want deffered into static inner classes
20:16llasramdeferred even
20:16llasramNo, I was right the first time -- just have erc-spelling-mode off somehow
20:17travisrodmanunfortunately, the clojure code is primarily providing a dsl for the java, so the clients are looking to compile as part of the maven build
20:18travisrodman@technomancy: what would the class resolution at run-time look like... i can google that if the answer is too involved.
20:18llasramtravisrodman: I'm not entirely following. Can you provide more details?
20:18technomancyI guess it's basically just reflection
20:19travisrodman@technomancy: right... see, I am using gen-class to output interfaces that can be utilized by the java in the larger system, so the AOT is somewhat necesary, I believe
20:19travisrodman@technomancy: in that case, how would you not compile the code, or would it be deferred in some manner i am not aware of if the clj's were just included in the jar
20:20llasramtravisrodman: Oh! Instead, you can write Java stub classes which load Clojure namespaces and invoke functions via the Clojure Java APIs
20:20travisrodman@llasram: what can I clarify for you?
20:20llasramI believe your last statement clarified sufficient
20:20llasramsufficiently even
20:21llasramOh, and FYI, in IRC you generally just refer to someone's handle directly. No need for an `@` prefix
20:21travisrodmanah, thanks
20:21llasramtravisrodman: Here's an example of the style I've adopted lately: https://github.com/damballa/abracad/blob/master/src/java/abracad/avro/ClojureDatumReader.java
20:22technomancyyeah, you could bridge the gen-class->regular-clojure with runtime require and write your regular clojure using the class normally
20:22travisrodmantechnomancy: okay, i will look into that
20:23travisrodmanllasram: thanks. i will look that over, but i am in the unfortunate position of not being able to bend the java to my will, but i am sure it will be worth looking at none-the-less
20:24travisrodmanthanks, very much, for the feedback
20:24llasramtravisrodman: Oh, sure, but you can add new Java. The philosophy is that you write Java to interface with Java, write Clojure to actually implement the program logic
20:26travisrodmanout of the interest in understanding, why, during the maven build, would the code behave as though initialized, as opposed to just compiling, as you would with any other java? is it because it needs to run through the clojure compiler, and that is causing the instantiation?
20:27travisrodmanllasram: in a sense, that is what the clojure is doing, i am using proxy to generate classes-on-the-fly so an entirely distinct group of users can augment functionality, without java or the original code
20:28travisrodmanit is just that the some of the calls rely on classes in the java to support the dsl, and this is where this issue is coming in.
20:28travisrodmanthanks for the code sample though... always expanding my understanding... I appreciate it
20:30llasramtravisrodman: In Clojure compiling are less distinct than Java. You're essentially running some code, and just saving off the classes which are being dynamically generated. The running-of-code which loads namespaces loads any classes which are `:import`ed, which runs their static initializers
20:30llasrams,compiling,compiling and running,
20:30travisrodmanllasram: that is very intersting... so in reality, instead of wrapping from the clojure perspective, you are consuming from the java side... very nice.
20:31travisrodmanllasram: got it, in a sense, how the macros are expanding and replacing themselves with their executed values, until it finally settles on the final bytecode?
20:31travisrodmanllasram: am i understanding that correctly? that was a bit of a statement that turned into a question.
20:32llasramWell, macros don't really enter into the picture, except in that macro-expansion is a step in code compilation. More to the point is that in Clojure, the compilation unit is the top-level form
20:32llasramAnd compilation/run time are only distinguished per top-level form
20:33llasramSo once you've executed the `ns` form when loading a file
20:33technomancywhich is really *so* much simpler than the alternative
20:33llasramEverything needs to be set up for anything which follows -- e.g., including code which depends on classes having been loaded
20:33technomancyif you look at the crazy backflips racket has to do to have a separate non-runtime compile phase... whew.
20:34llasramI really should look at Racket more...
20:34llasramtravisrodman: I need to idle for a bit, but best of luck!
20:34travisrodmannp... thanks for the info
20:36travisrodmantechnomancy: thanks for the tip on that i will check it out. i am sure the solutions you are presenting are cleaner, more straightforward, and in the end, better, it is good to know the alternative
20:53Guest9805Hi, everyone. I'm having trouble understanding a few methods in Clojure relating to Java interop. I saw a solution to a 4Clojure problem that used the (.get) method from Java, and I can't seem to find for the life of me what that function does or where it comes from. Mind you, I'm not a Java programmer, so it's been extra difficult.
20:58Guest9805Anyone?
20:58clojurebotJust a heads up, you're more likely to get some help if you ask the question you really want the answer to, instead of "does anyone ..."
21:01hyPiRionGuest9805: I wouldn't worry too much. It's most likely done on a vector or a map, in which case it is equivalent with a normal get
21:03Guest9805Ah, okay. Just tried both in the REPL, and they seem to work the same way. I guess that solution wasn't very idiomatic.
21:03hyPiRionyeah, sounds a bit strange
21:08mthvedtis there a way to make compojure not automagically wrap your return values in certain routes
21:18xeqimthvedt: you could return a ring response yourself
21:19mthvedtxeqi: i want to return a map that's handled by ring middleware
21:28xeqimthvedt: and what is compojure doing to the map?
21:29xeqisticking it in :body ?
21:29mthvedtxeqi: compojure routes add :headers, :response, and an empty :body to any APersistentMap
21:29xeqiah, yeah https://github.com/weavejester/compojure/blob/master/src/compojure/response.clj#L23
21:32mthvedti have middleware that turns maps into JSON responses, which compojure is interfering with, so that's annoying
21:51jonhbnls
21:52coventryWhere would I find documentation for standard Server-Sent-Events code? (The pedestal tutorial is referring to it on the Making the Service wiki page.)
22:14coventryOh, it's a javascript concept. I was looking for it in a clojure context.
22:24eggheadcoventry: it's something a server does that js can pay attention to
22:25eggheadcoventry: https://developer.mozilla.org/en-US/docs/Server-sent_events
22:47coventryegghead: thanks.
22:48muhoomthvedt: there's a ring-json-middleware, IIRC
22:48mthvedtmuhoo: stackoverflow suggests compojure breaks that middleware also
22:51muhooi dunno. i'm doing a project rght now that retrns json for api endpionts, have not had any problems.
22:52muhoodoign it manually, i..e (fn [req] {:status 200 :body (json/ncode (do-stuff req)))})
22:53muhooor rather (GET "/foo" req {:status 200 :body (jon/encode (do-stuff req))})
22:53eggheadi'm doing some fun edn over websockets
23:14llasramHuh. This is interesting. A *data-readers* tagged literal constructor can return arbitrary forms, which are then treated as what has been just read by the reader. If the function returns forms which represent code and the forms are being compiled, the tagged literal can inject arbitrary code to be compiled
23:15llasramMaybe this intentional. It seems consistent. But I found it surprising at first
23:20xeqillasram: or the data reader could just eval the string itself
23:40Apage43here's my json-response https://github.com/couchbaselabs/mortimer/blob/master/src/mortimer/web.clj#L26-L30
23:41Apage43which i copy around because the existing middleware I've run across uses data.json, and I prefer cheshire