#clojure logs

2014-11-30

00:17xelxebargfredericks: just saw your sped up primes version. finding it quite instructive! in practice how often do you usually have to dig down into native Java structures? are we just hitting a "primes are particularly hard" wall?
00:19justin_smithxelxebar: it is more that in a tight loop the speed of a mutable thing can beat the safety and predictability of a clojure persistent data structure I think
00:20justin_smithbut of course you want to ensure you are doing this in the place where that speed is actually making a difference
00:28xelxebarjustin_smith: with an IPersistentList are we really copying the whole structure around every time we do something as simple as say (cons angelina-jolie justin-smith-list-of-booty)?
00:37zanesWhat’s the rule of thumb for when to reach for a lazy sequence vs a channel?
00:41rs0xelxebar: do you mean a persistent vector?
00:43justin_smithxelxebar: conjing to either a persistent list or vector does not copy the whole thing
00:44justin_smithbut it still does more allocation than conjing to a mutable structure, and sometimes that matters
00:44justin_smiththe jvm can allocate efficiently, but it isn't perfectly efficient
00:52xelxebarrs0: was trying to say "persistent list" as opposed to a mutable one
00:53xelxebarjustin_smith: does the allocation really differ enough to see a speedup of 30x or so like in gfredericks' case?
00:54xelxebarI guess if I really want to know what's going on I can look at the code...
00:54rs0xelxebar: i'm not sure what code you're referring to, but there are many reasons that mutable collections can be a lot faster. one of the biggest reasons is actually locality
00:54xelxebarrs0: locality? is this about caching?
00:55justin_smithxelxebar: yes, java.util.ArrayList is more efficient than a regular linked list. It has more cache coherency (the items are closer together in the heap) and that matters in tight loops.
00:55rs0xelxebar: yeah. with immutable persistent collections, the data in the collection tends to be more spread out across memory, which leads to more cache misses
00:55justin_smithhttps://www.refheap.com/94188 rs0 <- that is the code
00:57justin_smithxelxebar: going from randomly positioned items in a very tight loop to cache-friendly all-in-a-row can give 2 or 3 orders of magnitude improvement. Clearly this was not a super tight loop, so you only got ~30x improvement between the arraylist and the type hinting
00:57xelxebarrs0: here's a paste of both the slow and fast version https://www.refheap.com/94198
00:58justin_smithxelxebar: yeah, the type hinting also can prevent boxing / reflection, which may be the bigger deal than the cache friendliness here actually
00:59xelxebarjustin_smith: oh! so persistent lists can be thought of as being backed by linked lists or something and mutable lists as C-like arrays?
00:59rs0xelxebar: rich hickey actually gave at least one talk on persistent collections, let me find it...
00:59justin_smithxelxebar: depends on the specific list - ArrayList is backed by an array in memory, yes
01:00justin_smithxelxebar: java also has a LinkedList, it isn't used as often for obvious reasons
01:01justin_smithxelxebar: vectors on the other hand are made internally of a bunch of smaller underlying arrays but not quite as linear and coherent as an ArrayList
01:01xelxebarjustin_smith: what about a seq?
01:01justin_smithxelxebar: seq is not an implementation, it's a protocol
01:01justin_smitha while bunch of things implement seq
01:02justin_smithwhich kind of seq do you mean?
01:02xelxebarwell, what types are involved when I do (seq [1 2 3])?
01:02justin_smithif you mean PersistentList or LazySeq, those are linked lists
01:02justin_smiththat's a view of a vector
01:03justin_smithso it's as I said above about vectors, a bunch of smaller arrays in a tree
01:03justin_smithso not as bad as a simple linked list, not as linear as an ArrayList
01:03justin_smiththat's a tradeoff made in order to do persistence, basically
01:03justin_smith(as in the structural sharing part of persistence)
01:03rs0https://www.youtube.com/watch?v=UXdr_K0Lwg4 here's a talk on finger trees
01:04justin_smithrs0: but none of the vanilla clojure datastructures are fingertrees
01:04rs0i know that rich hickey has talked about clojure's persistent collections in some of his talks, i think at least one of The Value of Values and Are We There Yet talks about them
01:04rs0justin_smith: yeah, they're HAMTs
01:04xelxebarha. okay. so '(1 2 "mimosa") is a PersistentList?
01:04justin_smithxelxebar: rs0: hyperion has a good series of blog posts about how clojure vectors are implemented
01:05justin_smithxelxebar: use type and find out
01:05justin_smith,(type '(1 2 "mimosa"))
01:05rs0,(type '(1 2 3))
01:05clojurebotclojure.lang.PersistentList
01:05clojurebotclojure.lang.PersistentList
01:05xelxebarjustin_smith: that's the kind of answer I like!
01:05xelxebar,(type [1 2 3])
01:05clojurebotclojure.lang.PersistentVector
01:05justin_smithhttp://hypirion.com/musings/understanding-persistent-vector-pt-1 the start of the hypirion blog posts
01:05xelxebar;(type (seq [1 2 3]))
01:05xelxebar,(type (seq [1 2 3]))
01:05clojurebotclojure.lang.PersistentVector$ChunkedSeq
01:06rs0,`ISeq
01:06clojurebotsandbox/ISeq
01:06xelxebarrs0, justin_smith: thanks for the links
01:06justin_smithrs0: ?
01:06xelxebarwhat black magic did clojurebot just do??
01:06rs0justin_smith: at the REPL you can normally say `symbol to get the fully qualified symbol name. isn't the class for seq clojure.lang.ISeq?
01:06lazybotxelxebar: Definitely not.
01:07justin_smithrs0: clojure.lang is not in scope by default
01:07justin_smithrs0: so you just get a locally namespaced symbol
01:07rs0justin_smith: ah, i'm thinking of java.lang and clojure.core i guess
01:07xelxebarlazybot: ummm... thanks?
01:07justin_smithxelxebar: which magic?
01:07kenrestivowel that's a first, i just got a spam email with a zipfile with a minified javascript payload virus: https://www.refheap.com/94199
01:07justin_smithlazybot: are you confusing the newcomers again???
01:07lazybotjustin_smith: Yes, 100% for sure.
01:08justin_smithlazybot, are you sure that is a good idea??
01:08lazybotjustin_smith: What are you, crazy? Of course not!
01:08xelxebarwhat's sandbox/ISeq?
01:08justin_smithxelxebar: a symbol, he was trying for something else
01:08rs0,`methods
01:08clojurebotclojure.core/methods
01:08rs0,(methods clojure.lang.ISeq)
01:08clojurebot#<ClassCastException java.lang.ClassCastException: java.lang.Class cannot be cast to clojure.lang.MultiFn>
01:08rs0er
01:08rs0oh, that's right
01:08justin_smithmethods doesn't work on regular classes
01:09rs0i'd have to go through clojure.reflect i guess
01:09justin_smithrs0: you may want clojure.reflect/reflect, but that is super verbose
01:09justin_smithheh
01:10justin_smithxelxebar: that hyPiRion blog post does a great job of illustrating why vector uses smaller underlying arrays for structural sharing
01:11rs0will Java 6 still be supported by Clojure 1.7?
01:11justin_smithrs0: I think the minimum is still 1.5
01:12justin_smithlikely will be for a while
01:12rs0rich hickey mentioned a while back that invokedynamic could make type hinting obsolete
01:12rs0but that it would have to be done in addition to the current techniques, because it's only available on JDK7+
01:12justin_smithyeah, it would be a great win, but they want to be compatible with as many existing java ecosystems as possible
01:13xelxebarreading the hypirion post now! I'd kind of like to know what PersistentList is doing just for comparison.
01:13rs0xelxebar: i'm pretty sure PersistentList is just an immutable linked list
01:13xelxebarAlso, what is the 'I' in IPersistentList as opposed to PersistentList? "implementation"?
01:14justin_smithInterface
01:14rs0xelxebar: the opposite, Interface
01:15rs0xelxebar: have you looked at the clojure source code?
01:15rs0https://github.com/clojure/clojure
01:15xelxebarha! okay. just found the java file in the source
01:15xelxebarpublic interface IPersistentList extends Sequential, IPersistentStack{}
01:16rs0xelxebar: ag and selecta are your friends
01:17xelxebarare these functions?
01:17xelxebarand ag looks like silver to me, hehe
01:17rs0https://github.com/ggreer/the_silver_searcher
01:17rs0https://github.com/garybernhardt/selecta
01:18justin_smithxelxebar: if you don't know what an interface is, you may want to spend a few hours on a "java basics" tutorial, it will help you understand clojure a little better I think
01:18justin_smithoh wait, you meant is ag a function, never mind :)
01:19rs0ag and selecta are amazing. you can tear through very large code bases in any language
01:20xelxebarselecta looks really nifty
01:20rs0yeah, i mainly use it from within vim
01:21justin_smithyou can also use those (or even rgrep) with emacs and M-x rgrep (it lets you select the command it actually runs, and creates clickable / enter-to-follow links for each match)
01:21xelxebarnever have used ack myself, always just grepped stuff
01:21rs0xelxebar: yeah, i did that for years. trust me, ag and ack are better (for source code)
01:21rs0especially when you're searching source code under version control and you've got huge .git and .hg and .svn directories to ignore
01:22caternuse git grep?
01:22rs0if you want
01:23rs0but git grep is coupled to a particular version control system
01:23rs0ag works with everything
01:23caternhg grep
01:23caternsvn probably has something as well
01:23justin_smithsource-safe grep oh wait there is no such thing just kill myself
01:23rs0heh
01:24justin_smithcatern: rs0: I say we have a chemical showdown between hg and ag
01:25rs0hg seems to require a lot of plugins to be useful
01:26xelxebarjustin_smith: this? https://www.youtube.com/watch?v=-mdHoImEt3Q
01:28ggreerwhat?
01:28clojurebotwhat is a software archeologist
01:28ggreeroh, someone mentioned ag
01:28ggreernot me
01:31xelxebargod. the bots here sure are chatty
01:32xelxebarclojurebot, lazybot: if you've achieved sentience, no offense
01:32clojurebotNo entiendo
01:32ggreerhttp://geoff.greer.fm/ag/speed/ <-- in case you're curious
01:32ggreerack took 3 minutes to find the same results in that benchmark on my amd a4-5000
01:32xelxebarggreer: I was just peeking at that actually
01:33xelxebarwhat's going on with the i7??
01:33lazybotxelxebar: Uh, no. Why would you even ask?
01:34ggreerearlier versions of ag ignored too much stuff because they obeyed ignore rules incorrectly
01:34ggreerone of the directories in my ~/code on that machine contains dogecoin, which has a * in its .gitignore
01:35ggreerand old versions of ag made that a global *, not just an ignore rule in ~/code/dogecoin
01:35ggreerbasically, ag gets slower as it obeys .gitignore rules more correctly
01:36ggreeroh and the bottom graph with the i7 is old. I need to re-run it, but it takes about 10 hours and nothing else can run on that machine
01:36ggreerright now I'm fuzzing ag on that server
01:36ggreerno crashes/errors so far
01:36xelxebardogecoin! didn't know anyone legit used it
01:37xelxebarwell, the A4-5000 seems to behave as expected? is it just fewer data points?
01:37ggreerit has a smaller ~/code
01:37ggreerbecause it's a newer machine
01:38ggreerand the ignore rules in the codebases on that machine are a little different
01:38ggreerI should really create some canonical test data
01:38ggreerjust clone some popular projects like nodejs, the linux kernel, etc
01:38ggreerand benchmark ag searching them
01:38xelxebaroh okay. so these graphs aren't all precisely comparable
01:39mongosssssssssssHi, can I ask a noob question here or is there another channel that would be more appropriate?
01:39ggreerright. notice the "16GB directory, ≈2.4GB searched" and "8.3GB directory, ≈0.7GB searched"
01:39xelxebarmongosssssssssss: I have been blasting these guys with noob questions all day
01:41xelxebarggreer: in the interest of science, I think the idea of a canonical test data is a good one
01:41ggreeryeah. toss in on the giant list of stuff to do :)
01:42ggreer*it
01:42mongosssssssssss:) question: I'm trying to determine if a file is present in a directory (think trigger file). I'm using (def dirlisting (.list (io/file "path"))) as per the clojure.org docs and that sorta appears to be working, not sure how to actually examine the contents. a (count dirlisting) gives me the right count. The question is, how can I access each file in that list? (doseq [f dirlisting] (print f))) just gives me lots of
01:42mongosssssssssss(I'll get to actual filename comparisons once I can actually determine what's going into that array)
01:44xelxebarggreer: now I'm stalking you. lol. I see you're on LessWrong! Several years back. I went on a binge and went through all the sequences over the course of a few weeks.
01:46mongosssssssssssOkay, nevermind, it appears Lighttable just doesn't show me what I need to show.. just did the same through the lein repl and it gives me what I'm looking for
01:46mongosssssssssssi wish there were a drclojure
01:46mongosssssssssss:/
01:47mongossssssssssshave a great night everyone
01:47rritochmongosssssssssss: You can always filter the results of https://clojuredocs.org/clojure.core/file-seq for just the files with the parent directory your looking for
01:48rritochmongosssssssssss: It isn't efficient if you have deep directories, but it saves coding time.
01:50ggreer:)
02:01kenrestivoi've found a heisenbug. (for [[foo bar baz] (make-stuff blah)] foo) won't compile, says there's either 1 or 3 args to for. and (for [x (make-stuff blah) :let [[foo bar baz] x]] foo) won't compile either. but (for [x (make-stuff blah] (let [[foo bar baz] x] foo)) works fine
02:02magthehow do I get leiningen to copy data files?
02:09justin_smithmagthe: into a jar for example?
02:11justin_smith,(for [[a b c] (repeat (range))] c) ;; kenrestivo
02:11clojurebot(2 2 2 2 2 ...)
02:11kenrestivohuh
02:11justin_smith,(for [[a b c] (repeat (range))] b c) ;; kenrestivo
02:11clojurebot#<ArityException clojure.lang.ArityException: Wrong number of args (3) passed to: core/for>
02:11magthejustin_smith: ah, should have mentioned I'm playing with cljs, so just straight forward copy for now (but into jars would be good to know too)
02:12justin_smith~ping
02:12clojurebotPONG!
02:12kenrestivoso, what am i seeing there? is destructuring not supported in for forms?
02:12justin_smithkenrestivo: the error is for having too many things in the body
02:12justin_smithhas nothing to do with the destrucuring (see my first example)
02:12kenrestivoin the body?
02:13justin_smithafter the binding form
02:13kenrestivooh... but isn't the body an implicit do?
02:13justin_smithnope
02:13kenrestivoaha! that's it then, thanks.
02:13justin_smithyou would expect that, wouldn't you? but no
02:14kenrestivowow, i could swear i've had multiple forms inside the body of a for, but i guess not.
02:24magthejustin_smith: :resource-paths doesn't seem to offer any way of copying files into place (I'd like to get both "static CSS" and generated CSS to end up in the same folder on compile)
02:25magthejustin_smith: lein-resource threw an UnsupportedOperationException on me when I tried using that
02:33justin_smithmagthe: yeah, I am less familiar with the ins and outs of where things can go with clojurescript
02:42magthejustin_smith: oki, I just posted a question to SO... hopefully someone will bite :) and I can put up the christmas tree instead of hanging in here ;)
02:44magthejustin_smith: thanks, you'll likely see me drop in here again in the future... clojure/clojurescript is absolutely interesting, but there is quite a lot of options and details to familiarise oneself with
02:53hiredman [clojure.test.check.clojure-test :refer [defspec]]
02:53hiredman [clojure.test.check.generators :as gen]
02:54hiredmangeez, sorry, mispasting out of control
02:54rritochIs there any decent documentation or tutorial on making leiningen hooks? For situations like the one magthe is explaining I've needed to resort to creating custom plugin/tasks to manually wrap compile, but per the documentation it seems that it should be possible to do using hooks.
02:55rritochI've yet to find any example of a post-compile hook though
03:11ffwacomis there a way to get the fully qualified symbol for let?
03:12ffwacomnvm got it
03:13rritoch,`let
03:13clojurebotclojure.core/let
03:14ffwacomcheers :)
03:14rritochffwacom: That is how I'd do it, but I'm still not entirely sure how ` functions, and regularly run into problems from unexpected behaviors
05:01afhammadCan someone explain what this macro does in cljs.core.clj (defmacro js-str [s] (core/list 'js* "''+~{}" s))
05:28rritochlafhammad: That appears to cast a clojure value into a javascript string. In javascript ''+ casts the remaining values into strings, so ''+7+1 equals "71"
05:48yguanhi there, I know there is destructive assignment for vector in 'let': (let [[a b] [1 3]] (println a b), is there something smilar for map in 'let'?
05:51luxbockyguan: yep there's a lot you can do
05:51luxbockhttp://blog.jayfields.com/2010/07/clojure-destructuring.html
06:33foodooI have several subnamespaces and I like to declare one of these subnamespaces as private so that I can break things in the future. What is the idiomatic way to do this?
08:27foodooI have several subnamespaces and I like to declare one of these subnamespaces as private so that I can break things in the future. What is the idiomatic way to do this? [repost from 2 hours ago]
08:27Bronsafoodoo: clojure doesn't have any notion of subnamespaces or private namespaces
08:28Bronsafoodoo: `foo.bar` is not related to `foo` in any way
08:28Bronsafoodoo: usually when people need a "private" namespace, they use a .impl segment in the ns name
08:29foodooBronsa: I see. Thanks
08:54SagiCZ1can i define two defn functions in one namespace with the same name? i thought it was impossible
08:56MorgawrSagiCZ1: you can use defmulti and multimethods to achieve something like that
08:57Morgawror use function definitions with multiple number of parameters
08:57SagiCZ1Morgawr: yeah but the repl didnt complain when i loaded the file.. seems like repl bug
08:57Morgawrah
08:57Morgawrit probably gets re-defined
08:57Morgawrin order of evaluation
08:57SagiCZ1i see
08:57Morgawrso the latter definition overrides the previous one in the repl (I assume)
08:57SagiCZ1makes sense
08:57SagiCZ1kinda
09:03BronsaSagiCZ1: (def foo 1) (def foo 2) is always allowed
09:03SagiCZ1Bronsa: ok.. didnt know that
09:03BronsaSagiCZ1: it should only be used for repl interaction though
09:03SagiCZ1yeah i expected my editor to warn me about refedining the var in the file
09:04BronsaSagiCZ1: the eastwood linter will warn you about that
09:04SagiCZ1maybe its no var, sorry my terminology is not perfect
09:04Bronsahttps://github.com/jonase/eastwood
09:04Bronsahttps://github.com/jonase/eastwood#redefd-vars
09:04gfredericksSagiCZ1: it is a var
09:05SagiCZ1ok good guess
09:29SagiCZ1how could i obtain the index of a smallest number in a vector?
09:30SagiCZ1,(.indexOf [-10 1 2 3] (apply min [-10 1 2 3]))
09:30clojurebot0
09:30SagiCZ1any way to make this better?
09:34gfredericks,(def nums [-10 1 2 3])
09:34clojurebot#'sandbox/nums
09:35gfredericks,(->> nums (map-indexed vector) (apply min-key second) (first))
09:35clojurebot0
09:35SagiCZ1seems more clojury to me.. thanks
09:35SagiCZ1(inc gfredericks)
09:35lazybot⇒ 112
09:43justin_smith$mail yguan that's not destructive update, that's shadowing, things that use the previous binding won't be affected eg. (let [a 0 b (fn [] a) a 1] [a (b)])
09:43lazybotMessage saved.
09:57gfredericksman I'm learning all sorts of weird things about regexes
09:57SagiCZ1i need to mimick simple comparison of each element with each, which is simple achievable by classical for loop, but i strugle with it in clojure.. example [:a :b :c] --> ([:a :b] [:a :c] [:b :c])
09:58SagiCZ1,(def x [:a :b :c])
09:58gfredericks,(def xs [:a :b :c])
09:58clojurebot#'sandbox/x
09:58clojurebot#'sandbox/xs
09:58SagiCZ1wow
09:58SagiCZ1ok
09:58gfredericks,(for [i (range (count xs)) j (range i)] [(xs i) (xs j)])
09:58clojurebot([:b :a] [:c :a] [:c :b])
09:58SagiCZ1oh.. indexes
09:58SagiCZ1why not
09:58SagiCZ1thanks again gfredericks
09:59gfredericksthere's another approach that's not quite solidifying for me
09:59gfredericksthat avoids indexes
09:59SagiCZ1this relies on the fact that xs is a vector huh?
09:59gfredericksyeah
09:59gfrederickshere I'll get a better one
09:59SagiCZ1maybe some partition magic
10:00gfredericks,(for [[x & xs] (iterate rest xs) :while xs, y xs] [x y])
10:00clojurebot([:a :b] [:a :c] [:b :c])
10:00gfredericksambiguous naming there
10:00gfredericks,(def my-things (range 5))
10:00clojurebot#'sandbox/my-things
10:00gfredericks,(for [[x & xs] (iterate rest my-things) :while xs, y xs] [x y])
10:00clojurebot([0 1] [0 2] [0 3] [0 4] [1 2] ...)
10:01SagiCZ1i dont understand the comma in the while statement
10:01AimHereClojure commas are whitespace
10:01gfredericksI shoulda put even more commas
10:01gfredericks,(for [[x & xs] (iterate rest my-things), :while xs, y xs] [x y])
10:01clojurebot([0 1] [0 2] [0 3] [0 4] [1 2] ...)
10:01gfrederickslike that
10:01SagiCZ1oh of course
10:01gfredericksI only use commas for multiple pairs on one line
10:02SagiCZ1good idea, i shall adopt that if you dont mind
10:02gfredericksnot at all
10:02gfredericksso here's what I learned about regexes
10:02gfredericks,#"normal stuff {"
10:02clojurebot#<NoClassDefFoundError java.lang.NoClassDefFoundError: Could not initialize class java.util.regex.PatternSyntaxException>
10:02gfredericks,#"\Q{"
10:02clojurebot#"\Q{"
10:03gfredericksoh geez guess what #"\Qabc\E*" does
10:04gfredericksthis is getting a lot harder to parse
10:04gfredericksI think I need a separate analyzer phase
10:20gfredericksoh here's a good one; try to justify this:
10:20gfredericks,#"x++"
10:20clojurebot#"x++"
10:20gfredericks,#"x+++"
10:20clojurebot#<NoClassDefFoundError java.lang.NoClassDefFoundError: Could not initialize class java.util.regex.PatternSyntaxException>
10:20gfredericks,#"x+++"
10:20clojurebot#<NoClassDefFoundError java.lang.NoClassDefFoundError: Could not initialize class java.util.regex.PatternSyntaxException>
10:20gfredericksclojurebot that is a weird exception
10:20gfredericks&#"x+++"
10:21lazybotjava.util.regex.PatternSyntaxException: Dangling meta character '+' near index 3
11:17gfrederickshaving a surprising hard time figuring out how to express "anything but this specific character" in instaparse
11:53vermahey any clojuredocs devs around?
11:53vermaI wonder what is used to handle Ctrl+P, Ctrl+N stuff
11:53vermaI think the code is open, I can jump in :)
12:02gfredericks,(pr-str "\u0000")
12:02clojurebot"\"
12:03gfredericks&(pr-str "\u0000")
12:03lazybot⇒ "\"
12:05justin_smith&(map int "\u0000")
12:05lazybot⇒ (0)
12:06justin_smith&"\u0000"
12:06lazybot⇒ "
12:06justin_smithwtf
12:06justin_smithwhat happened to the other "
12:07gfredericks,#"*"
12:07clojurebot#<NoClassDefFoundError java.lang.NoClassDefFoundError: Could not initialize class java.util.regex.PatternSyntaxException>
12:07justin_smithoh, it's an irc client thing
12:07gfredericks&#"*"
12:07lazybotjava.util.regex.PatternSyntaxException: Dangling meta character '*' near index 0
12:07gfredericks&#"{0}"
12:07lazybot⇒ #"{0}"
12:08DrCherryTried to learn clojure in a weekend for job programming challenge. Whoops!
12:09andyfDrCherry: Depending upon how much the challenge expected you to learn, that could be a very difficult thing to accomplish.
12:11DrCherry@andfy, I thought I was pretty smart. Lol. I haven't given up but my expectations are adjusted on an hourly basis.
12:13AimHereLearning a new language in a weekend is likely feasible if you're not being exposed to a new paradigm or two
12:13andyfI came to Clojure after having serious hobby time with Common Lisp and Scheme, and I still found it to be a bit of a learning curve, getting used to immutable data structures by default especially.
12:13AimHereI'd expect it would help loads to have been exposed to a functional programming language, or a lisp
12:15andyfDrCherry: I don't know what the job interviewers expect, but I bet partial credit will be given based upon what you were able to learn, and explain about what you did.
12:16DrCherryI've kept a journal of all the work I've done and illustrated my methodology.
12:17DrCherryI don't know what they expect exactly but this has been one rabbit hole after another. I'm using all the time I was given and feel pretty okay about it.
12:17DrCherryI have no lisp background and they know.
12:17nicl_Hey all, is it a crazy abuse to introduce an edn tag which accepts arguments?
12:17nicl_I was thinking of using it as a simple templating library
12:18nicl_(where the underlying structure is edn, but I want to inject some values and nest things)
12:18DrCherryThis weekend has been my kobayashi maru.
12:19nicl_alternatively, can anyone suggest a simple, non-html-oriented, templating library for this?
12:30justin_smithnicl: there are already edn tags that take arguments
12:30justin_smith #inst "0000-01-01T00:00:00.000-00:00"
12:30justin_smith&#inst "0000-01-01T00:00:00.000-00:00"
12:30lazybot⇒ #inst "0001-01-01T00:00:00.000-00:00"
12:31niclSorry, I meant a context provided to interpret the tag, but which exists outside of the edn datastructure
12:32nicljustin_smith: Sorry, I meant a context provided to interpret the tag, but which exists outside of the edn datastructure
12:32justin_smithnicl: yeah, sounds like you want a templating library
12:35nicljustin_smith: yeah, I think you’re right. I could probably do it with edn, but it would be messy
12:35nicljustin_smith: (to ensure the right context was used at the right time)
12:35justin_smithedn is really meant for vanilla clojure stuff, the "extensible" stuff if limited
12:35niclalthough, I could create clojures for it
12:35nicland pass those in to the reader function at each stage
12:36niclhmm
12:36niclstill an abuse
12:36nicl*closures
13:54danielszmulewicztechnomancy: ping
14:17kenrestivois there a way to sub to a *set* of topics in core.async?
14:17kenrestivoi naively tried (async/sub pub #{:test :blah} sub) ... didn't work. can't find docs and having trouble finding where the source of sub* is
14:17kenrestivobecause sub just wraps sub* and i can't seem to locate it
14:21eredkenrestivo: have you tried using a mix?
14:22kenrestivooh, good idea, thanks. i'm still trying to wrap my brain around core.async. really enjoying it.
14:23kenrestivomix is hilarious. it's so obvious rich started out as an audio engineer. "A mix supports soloing, muting and pausing ..."
14:24eredi found it by searching for mux actually
14:25eredwhich is weird because i've never done hardware either
14:27kenrestivoi guess i could create multiple subs and mix them
14:28kenrestivoit just seems heavyweight and kind of verbose to me.
14:28kenrestivoand maybe slow? not sure what the peformance implications are of all these abstractions
14:34munderwoHey all. Im trying out generative testing. I have a map that has a structure, and I was to create the string values from a generator. Is there a declarative way I can just build a map, and generate the values?
14:35munderwoI can generate a random map, but Im really looking to be able to build {:foo “somerandomstring :bar “someotherstring”}
14:35munderwowhere :foo and :bar are always set.
14:44poushkarCould someone help me here: https://gist.github.com/vitaly-pushkar/61daa08c9cefb78a5395 - It logs error “Uncaught Error: Assert failed: Invalid Hiccup form: [nil] (valid-tag? (nth v 0))”
14:44poushkarit comes from line 9
14:47Frozenlockpoushkar: first off, I think your line 8 will never appear...
14:47Frozenlockshould be something like [:div [layout/menu] [...]]
14:48poushkar@Frozenlock I am following this tutorial: https://github.com/reagent-project/reagent-cookbook/tree/master/recipes/adding-a-page
14:48poushkarthey do it like that. here https://github.com/reagent-project/reagent-cookbook/blob/master/recipes/adding-a-page/src/adding_a_page/core.cljs line 9
14:48poushkarshit :D
14:48poushkarthanks
14:48Frozenlock:-p
14:49poushkarI am blind
14:49FrozenlockI'm not sure this will solve your error however
14:50poushkarI am blidnly following that example, and sometimes I don’t really understand what I am doing. For example, this “component-will-mount” doesn’t seem to run my routes code and so app state is not set, so it is null.
14:55FrozenlockI'm not fond of secretary and routes myself. I would suggest you make a '1 page' app as a tutorial.
15:01devnSo, I know it's *kind of* self-explanatory, but if I asked you what the docstring for clojure.core/destructure is, what would you say?
15:02gfredericksI would not know
15:07gfrederickslooks like it doesn't have one? it's not really useful for users, so I think the worst possibility is somebody confuses it for something useful
15:14bbloom,(java.util.Date.) ; dammit irc
15:14clojurebot#inst "2014-11-30T20:12:23.505-00:00"
15:14bbloomgfredericks: i was time traveling again. wtf is wrong w/ my irc client?
15:16justin_smithbbloom: in erc there is a numeric "lag" indicator
15:16justin_smithbbloom: so when I get in a weird time warp, I always notice the lag tells me so as well
15:16gfredericksbbloom: perhaps your client is a late bloomer?
15:17bbloomtextual has /lagcheck apparently
15:17justin_smithalso, you can always /msg lazybot $ping
15:17justin_smithand see how long it takes to reply
15:18justin_smithif it takes a while, one of you is lagged :)
15:18gfredericksand it's not lazybot
15:19justin_smithgfredericks: well, lazybot could also be lagging...
15:35kenrestivobbloom: it might not be your client, but rather your internet connection?
15:35bbloomkenrestivo: maybe, but my connection is otherwise fine... unless time warner is fucking w/ IRC traffic
15:36gfrederickshaha why would a ISP care what you're using their network for right haha that'd be silly
15:36kenrestivotcpdump -w wtf.pcap -s 2000 port 6667 ... run that for a while, then dump it into xplot.org ?
15:38kenrestivoi dunno, i've just spent the last month or so debugging weird internet latency problems, it's not fun.
15:40justin_smithTIL irc servers are coordinated in a tree structure
15:40justin_smithwhat a weird architecture
15:40kenrestivoactually tcpdump -w wtf.pcap -s 2000 port 6667 or port 6697 if you use ssl. plot/graph that with xplot.org, it'll show you latency, broken connections, etc
15:41kenrestivoirc is kind of a quirky protocol.
15:41kenrestivobtw, i found a bug in irclj, it doesn't handle QUIT messages.
15:42kenrestivoso if a user QUITs, they show as perpetually connected. PARTs work fine though.
15:42justin_smithalso TIL /ping - 00:00.00 to bbloom from me, 00:00.04 to kenrestivo
15:42justin_smithkenrestivo: oh, interesting
15:42justin_smithkenrestivo: this is with the latest irclj?
15:43justin_smithit seems like this would be easy to fix
15:43kenrestivo"0.5.0-alpha4"
15:43kenrestivodunno if that's "latest", but it's the latest i was using in this app last i noticed the bug and decided "meh, i'll deal with it later"
15:43gfredericksI quit using irclj because it seemed to silently just not work right
15:44gfrederickswas working fine for a while, and with no changes it just ceased to function
15:44justin_smithkenrestivo: seems like a small fix that could be done right here https://github.com/Raynes/irclj/blob/master/src/irclj/process.clj#L133
15:44gfredericksmaybe freenode changed something?
15:44kenrestivoi had a problem with irclj not reconnecting properly
15:45justin_smithgfredericks: I updated lazybot to the latest irclj, and since then lazybot has been very reliable (compared to when it was using the previous version)
15:45kenrestivojustin_smith: yeah, copy/paste the process-line "PART" and change it to "QUIT". i think i tried that, didn't work, don't remember, it was a few months ago
15:45justin_smithremember when lazybot would always go offline on weekends?
15:45gfredericksjustin_smith: yeah I updated too and it didn't seem to make a difference
15:45gfredericksnow I'm using a dang Socket and everything seems okay
15:45gfredericksI figured out how to do it by reading the irclj code, go figure
15:45kenrestivothose dang sockets
15:46kenrestivosocketing all over the place.
15:46justin_smithgfredericks: well, next step is to reify it into another irc lib, right?
15:46gfredericksjustin_smith: inevitably
15:46gfredericksmake a yak pile
15:46justin_smiththat would be a good name for an irc client library
15:46kenrestivowhat is a yak pile?
15:47justin_smithkenrestivo: the line at a yak barbershop
15:47kenrestivoshave shave shave
15:47kenrestivoi dunno if that'd be considered yak shaving or NIH.
15:48kenrestivowhat? fix another library? feh. i'll just start from scratch and write another one.
15:48justin_smithNIH would be if he never even tried irclj
15:48justin_smithstarting from scratch rather than fixing is a gray area I think
15:48kenrestivoit's always a tough decision
15:49kenrestivoand a gamble on two unknowns
15:49kenrestivothe thing you don't know how to fix, and the thing you haven't written yet.
15:50justin_smithkenrestivo: I didn't figure out how to use core.async until I made my own totally silly CSP lib. It's a learning strategy.
15:50justin_smithor can be
15:50kenrestivoyeah, i do that too. sometimes it helps to understand things from first principles.
15:50kenrestivoright now i invested a lot of time in gloss, and am rewritign to just use bit-and, bit-or, etc
15:51justin_smithbecause gloss was insufficient?
15:51kenrestivoit was overly sufficient.
15:51justin_smithhaha
15:51kenrestivoi mean
15:51kenrestivo(.get (gio/contiguous (gio/encode (apply g/bit-seq (repeat 8 1)) [0 1 2 3 4 5])))
15:52kenrestivoversus (apply bit-or (for [bn [0 1 2 3 4 5 6 7]] (bit-shift-left 1 bn)))
15:53kenrestivosomeone looking at that first line would go "aaaah! wtf is he doing there?!" versus looking at the second line, they'd be all, "oh, he's just doing x << y"
15:54kenrestivoi suspect there are a lot of bald yaks running around the mission.
16:35danneui have a list of 175,000 words that i'm turning into a single regexp by joining them together like /^foos|^foo|^bar|.../ to create one massive regexp i can apply on a constantly-changing string to see if it starts with any of those 175k words. (from longest to shortest)
16:35danneuit performs much faster than i thought it would. is it compiling into something smarter than a iterative compare on each word?
16:36gfredericksprobably
16:36gfredericksa simple enough regex can be compiled into a state machine that only has to look at each char once
16:36gfredericksand the regex you describe is definitely simple enough
16:37danneumy bottleneck seems to be GC pauses on the "constantly-changing string"
16:37clojurebotHuh?
16:38gfredericksdanneu: you could maybe optimize that with a custom CharSequence?
16:38danneugfredericks: oh yeah, this is clojurescript
16:39gfredericksnevermind then :)
16:41danneuit's kinda shamefully dumb, too: http://jsfiddle.net/prsgju91/
16:42gfrederickswell if you wanted to push that bottleneck by using some sort of custom mutable "string", it's conceivable you could compile your regex yourself into a function that operates on those mutable strings
16:45justin_smithdanneu: have you thought about building a trie?
16:46justin_smiththat should perform much better than an re, and the code to build it would be much more readable than the re or re-builder code
16:47danneuoh, i'm just being limited by react batching
16:47justin_smithdanneu: https://gist.github.com/samuelclay/4596630
16:47danneui mean, that's why the ui gets so slow
16:47justin_smithdanneu: well, I think the intelligibility bonuses are good regardless of the perf
16:48danneujustin_smith: i agree, thanks
16:48danneuthat's all this project is
16:49justin_smithof course the trie should be built server side, and the client should only have to do the lookup part
16:56andyfdanneu: https://github.com/noprompt/frak
17:12gfredericksjustin_smith: why would a trie perform better than an re?
17:16justin_smithgfredericks: there are more ways to get RE construction wrong
17:16justin_smithgfredericks: though an optimal re will effectively be a trie anyway
17:17justin_smithgfredericks: though to be fair the example I was thinking of was routing, which is a comparison of multiple regex checks vs. one trie, which doesn't apply here
17:21gfredericksroger
17:21clojurebotNo entiendo
17:22gfredericks~roger is <reply> Yes entiendo
17:22clojurebotRoger.
17:22gfredericksclojurebot is just a big pile of easter eggs
17:25hiredmanclojurebot: clojurebot is just a big pile of easter eggs
17:25clojurebotc'est bon!
17:31TEttinger~roger
17:31clojurebotYes entiendo
17:31TEttingerwhat is the <reply> ?
17:31gfredericks~TEttinger is Yes Entiendo
17:31clojurebotA nod, you know, is as good as a wink to a blind horse.
17:31gfredericks~TEttinger
17:32clojurebotTEttinger writes really hideous clojure
17:32gfredericks~TEttinger
17:32TEttingerlol
17:32clojurebotTEttinger writes really hideous clojure
17:32gfredericks~TEttinger
17:32clojurebotTEttinger is Yes Entiendo
17:33TEttingerso it just takes out the "{topic} is " part
17:33gfredericksyep
17:33gfrederickshighly useful:
17:33gfredericks~ping
17:33clojurebotPONG!
17:33gfredericks~guards
17:34gfredericksSIEZE HIM!
17:34TEttinger$guards
17:34lazybotSEIZE HIM!
17:34gfredericks~botsnack
17:34gfredericksThanks can I have choclate next time.
17:34TEttinger~gourds
17:34clojurebotSQUEEZE HIM!
17:36arrdemanyone know of a phrase chunking engine in clojure or with clojure bindings?
17:37arrdemnevermind google results were good
18:34justin_smithgfredericks: also, tries are guaranteed linear (worst case) on the input, regardless of dictionary size. I don't know if a regex has that guarantee in general?
18:35metellusdoesn't seem like it would
18:35gfredericksjustin_smith: I think a classical regex does
18:36gfredericksi.e., you just convert it into a DFA and that's linear
18:38gfredericksso I was guessing that in practice a hand-rolled trie would be slower, since the regex is presumably implemented at a pretty low level
18:40justin_smithyeah, that's a good guess, as long as you aren't using backtracking or anything
18:41gfredericksI wonder if matching groups is a non-classical feature...
18:46justin_smithgfredericks: I don't think so. I can't think of a matching group that would require a backtrack of any sort.
18:47gfrederickswhat's the easiest backtracking regex?
19:00TEttingergfredericks: \b ?
19:02TEttingerhttp://www.regular-expressions.info/wordboundaries.html if unfamiliar
19:10gfrederickshmmm
19:10gfredericksI'm trying to think of an example with \b that isn't obviously linear
19:10justin_smithTEttinger: I'm not even sure - is it possible to create a regex that doesn't backtrack if the re-engine is a backtracking one? I saw one result that seemed to imply that regular meta-characters like + or * would backtrack...
19:11justin_smithit was from that same regular-expressions.info site actually
19:11justin_smithhttp://www.regular-expressions.info/catastrophic.html
19:12gfredericks((abcd)+(abce)+)+
19:12gfredericksthat's still not backtracky
19:13gfredericksI don't think
19:15TEttinger,(re-find #"x+x+y" "xxxxxxxxxxxxxxxx")
19:15clojurebotnil
19:16TEttinger,(re-find #"(x+x+)+y" "xxxxxxxxxxxxxxxx")
19:16clojurebotnil
19:16TEttingerhm
19:16gfredericks,(re-find #"(x+x+)+y" "xxxxxxxxxxxxxxxxy")
19:16clojurebot["xxxxxxxxxxxxxxxxy" "xxxxxxxxxxxxxxxx"]
19:17TEttinger,(time (re-find #"(x+x+)+y" (apply str (repeat 1000 \x))))
19:17clojureboteval service is offline
19:17TEttingerlol
19:17TEttingersee???
19:17lazybotTEttinger: How could that be wrong?
19:18TEttinger##(time (re-find #"(x+x+)+y" (apply str (repeat 1000 \x))))
19:18lazybotExecution Timed Out!
19:18TEttinger##(time (re-find #"(x+x+)+y" (apply str (repeat 100 \x))))
19:18lazybotExecution Timed Out!
19:18TEttingerwow
19:18TEttingerthat is catastrophic
19:33justin_smithTEttinger: so get this - there is a port of nethack to emacs, where all interaction with the game engine is via stdin / stdout / stderr and all output from the game engine is sexprs
19:33justin_smithso I am messing around with a clojure program that does something interesting with those sexprs... or will eventually
19:34justin_smithmaybe starting with an ai-assist, and building up to a full AI I am thinking
19:34justin_smithfor values of AI ~= "can beat a few levels of nethack"
19:36TEttingernice, justin_smith
19:38TEttingeran AI that can beat a human at Go is considered an extreme challenge to write, but human vs. human is probably 50/50 at equivalent skill levels/ranking. a human that can ascend in Nethack normally takes hundreds of serious attempts before succeeding. An AI that can perform better than a human at nethack, well...
19:39TEttingerto be fair, the AI can be aware of the entire nethack wiki with a few (slurp)s
19:39justin_smithyeah, I'll start with "gets as far as the oracle half the time", then maybe start beating sokoban if I get that far
19:39justin_smithyeah
19:40justin_smithor even the spoiler files that come in easily parsible form from a standard package
19:40justin_smithbut before that I can even just hard code a bunch of reasonable default choices
19:40justin_smithand start with a barbarian (fewer choices to make)
19:41TEttingerDCSS might be an interesting newer game to try to beat, a lot of options there. just a bot that can uncover new strategies to some of these games would be amazing
19:41justin_smithyou can get pretty far in nethack with barbarian, + walk up to every monster and bash it over and over + a blacklist of monsters to not touch or run from
19:42TEttingerI can't remember, do you heal over time in nethack?
19:42justin_smithyeah
19:42justin_smithbut you get hungry too
19:43justin_smithbut even a bot that gets your char to the first condition of "got to level 10" or "something happened it doesn't know how to deal with" is a cool thing to have
19:44justin_smithand remember that a bot that succeeds in getting to level 10 in 1% of trys can probably get you a good playable leveled up character in under a minute
19:45justin_smithTEttinger: the thing is that DCSS doesn't likely have an emacs backend, whereas nethack already has a version that is tailored to interact with a lisp
19:45TEttingerah yeah
19:49justin_smithhere's a screen dump of me interacting with it via the repl, and just dumping everything it sends to *out* https://www.refheap.com/94226
19:51justin_smithlooks like it will be pretty trivial to turn those numbers into glyphs, and get the status line into a hashmap
20:13justin_smithhttps://github.com/noisesmith/nethacker/blob/master/src/org/noisesmith/nethacker.clj -- what I have so far
20:20justin_smithmaybe I should start by making a json API
20:39mdeboardping
20:39mdeboard&(ping)
20:39lazybotjava.lang.RuntimeException: Unable to resolve symbol: ping in this context
20:44justin_smith$ping
20:44lazybotjustin_smith: Ping completed in 0 seconds.
21:02gfredericks,(def ping '$ping)
21:02clojurebot#'sandbox/ping
21:02gfredericks,ping
21:02clojurebot$ping
21:02lazybotclojurebot: Ping completed in 0 seconds.
21:02clojurebotNo entiendo
21:47justin_smithis it possible to express "a future that will be a number when dereffed" in prismatic/schema?
21:47justin_smithmaybe I don't want that because it would block when validating if it hasn't returned yet...
22:56gfredericks&#"x{]" ;; sure fine
22:56lazybotjava.util.regex.PatternSyntaxException: Illegal repetition near index 0
22:56gfredericks&#"[]{]" ;; wat
22:56lazybot⇒ #"[]{]"
22:58gfredericks&#"abc[]def{]"
22:58lazybot⇒ #"abc[]def{]"
22:58gfredericks&#"abcdef{]"
22:58lazybotjava.util.regex.PatternSyntaxException: Illegal repetition near index 5
22:59gfrederickshow can that even
22:59gfredericksoh wait
22:59gfredericksthat's one big character class
23:01TimMcSo... [ is greedy?
23:02gfredericksnot quite
23:02gfredericksjust that [] is special-cased
23:02TEttinger,#"[a]{]"
23:02clojurebot#<NoClassDefFoundError java.lang.NoClassDefFoundError: Could not initialize class java.util.regex.PatternSyntaxException>
23:02TEttingerwat
23:02gfrederickssuch that the second bracket is always a literal and never the closer
23:02TEttinger&#"[a]{]"
23:02lazybotjava.util.regex.PatternSyntaxException: Illegal repetition near index 2
23:03gfredericksthe meaning of ] changes based on whether or not it's the first character in the class
23:03gfrederickssame with - I think
23:06TimMcoy
23:06TimMcThat's just not right.
23:06gfredericksI'm going to sleep. Three internet points to anybody who can figure out these guys:
23:07gfredericks&#"\pC"
23:07lazybot⇒ #"\pC"
23:07gfredericks&#"\pD"
23:07lazybotjava.util.regex.PatternSyntaxException: Unknown character property name {D} near index 2
23:07gfredericksI scanned the docs and can't figure out what the first one means
23:09TEttingergfredericks: property
23:09TEttingerhttp://www.fileformat.info/info/unicode/category/index.htm
23:10TEttinger,(re-find #"\pC" "\u0001")
23:10clojurebot""
23:10TEttinger,(re-find #"\pC" "\t")
23:10clojurebot"\t"
23:11TEttingerthe first is Control properties, the whole set including format and miscellaneous C properties
23:11TEttinger,(re-find #"\pL" "alpha")
23:11clojurebot"a"
23:11TEttingerletters
23:12TEttingerN number, P punctuation, S symbol, Z separator (does not include the chars in \s)
23:13TEttingerM is mark, not sure what that is
23:13justin_smithTEttinger: so I got rid of the global in my nethack lib, and added schemas via prismatic/schema (I'd been meaning to try it for a while now), next step is to make a json/edn api I think (via a server or calls in the same process)
23:14TEttingerwowza
23:14justin_smithNethack As A Service
23:15justin_smithwhich will make it easy to make a frontend with 3.js or whatever else
23:24TEttingerheh.
23:25TEttinger4.js for visualizing hypercubes and 120-cells
23:27TEttingerwho needs drugs when you have geometry, anyway https://en.wikipedia.org/wiki/120-cell#mediaviewer/File:120-cell-inner.gif
23:28justin_smithnice
23:35allenj12hey im having a math brain fart can someone take a look at this? http://pastebin.com/XeBSbgCM
23:37TEttinger,(mapcat #(vector % % % %) (range))
23:37clojurebot(0 0 0 0 1 ...)
23:37TEttingerallenj12: ^
23:38allenj12TEttinger: but it needs to be robust, so if the number was 8 it would need to be 0 0 1 1... when the size of the pattern is 4
23:39TEttinger,(mapcat #(repeat 3 %) (range))
23:39clojurebot(0 0 0 1 1 ...)
23:39allenj12TEttinger: isnt there a way of doing it with just modulo?
23:39TEttingersure
23:40allenj12TEttinger: what would that look like? i think im close but not quite there
23:40TEttinger,(map #(mod (/ % 3) 3) (range))
23:40clojurebot(0 1/3 2/3 1 4/3 ...)
23:40TEttingerhm
23:40TEttinger,(map #(mod (int (/ % 3)) 3) (range))
23:40clojurebot(0 0 0 1 1 ...)
23:41TEttingerthere's a better way, I just can't remember...
23:41TEttinger,(map #(mod (rem % 3) 3) (range))
23:41clojurebot(0 1 2 0 1 ...)
23:41TEttinger,(map #(mod (div % 3) 3) (range))
23:41clojurebot#<CompilerException java.lang.RuntimeException: Unable to resolve symbol: div in this context, compiling:(NO_SOURCE_PATH:0:0)>
23:41TEttinger,(map #(mod (quot % 3) 3) (range))
23:41clojurebot(0 0 0 1 1 ...)
23:41TEttingerthere we go
23:41TEttinger&(map #(mod (quot % 3) 3) (range 100))
23:41lazybot⇒ (0 0 0 1 1 1 2 2 2 0 0 0 1 1 1 2 2 2 0 0 0 1 1 1 2 2 2 0 0 0 1 1 1 2 2 2 0 0 0 1 1 1 2 2 2 0 0 0 1 1 1 2 2 2 0 0 0 1 1 1 2 2 2 0 0 0 1 1 1 2 2 2 0 0 0 1 1 1 2 2 2 0 0 0 1 1 1 2 2 2 0 0 0 1 1 1 2 2 2 0)
23:42TEttingerthat what you're looking for, allenj12?
23:42allenj12TEttinger: i think so! thanks! need to go test it
23:42TEttingerno prob