#clojure log - Dec 06 2014

The Joy of Clojure
Main Clojure site
Google Group
IRC
List of all logged dates

0:00 rritoch: justin_smith: Thats why I asked you, I know you understand these transducers better than I do but as far as I can tell anything that you would use reductions for would be replaced with a stateful transducer and either (into [] ...) or (sequence ....)

0:02 justin_smith: I've yet to run into any situation where a transducer would be preferable, in this particular case a simple map (or for) will work, but then again I'm not dealing with statistical analaysis or anything else that requires a lot of function composing

0:03 justin_smith: I'm mostly just looking for excuses to try the transducers, even if they're not the ideal solution to the given problem :)

0:04 justin_smith: rritoch: the main win for transducers is if you are implementing a new "thing" which things like map and filter and reduce would work on, or if your sequence operations are your performance bottleneck

0:04 ie. the way transducers version of map and filter are replacing the map and filter in core.async

0:12 rritoch: I haven't yet had a good excuse to work with core.async yet. I tried to prepare the codebase I work with to use asynchronous processing, but the project manager removed the code. So unless some client demands a high-performance version of the app with more parallelization than I really won't be able to use it for awhile.

0:16 As far as I know there isn't a stable async http client with https support yet either, which is another thing preventing me from trying core.async

0:17 justin_smith: that's surprising, because the underlying java libs are https compatible.

0:18 I just ran (slurp "https://google.com") in my repl and it worked. That's not async of course.

0:20 nhanH: What is the operator "->" called again?

0:21 ie how do I google it

0:21 justin_smith: thread-first

0:21 nhanH: okay thanks

0:21 justin_smith: or use symbolhound

0:21 http://symbolhound.com/?q=-%3E+clojure

0:21 nhanH: oh that's new to me! Thanks!

0:21 justin_smith: symbolhound is great for weird language syntax

0:22 nhanH: also, hopefully you know about clojure.repl/doc, clojure.repl/source and clojure.repl/apropos

0:23 nhanH: yeah I do, I just don't have access to the repl right now ... just trying to implement "->" in java

0:24 justin_smith: good luck figuring out the types for that! I guess you can just say every argument needs to be a list starting with a callable

0:24 List of Object of course

0:25 wait, no, because methods work for -> too...

0:42 rritoch: nhanH: I've never tried it, but something like .the following may work. Object MyHyphenGt(Object[] x) { Clojure.var("clojure.core","->").applyTo(PersistentList.create(Arrays.asList(x))); }

0:43 Assuming you have a clojure runtime in your java app

0:50 Hmm, Maybe not. I see that -> is a macro, how do you execute a macro from Java?

1:03 How about Object MyHyphenGt(Object[] x) { Compiler.eval(PersistentList.create(Arrays.asList(x).insert(0, Symbol.create("clojure.core","->")),true); }

1:03 Should that work?

1:14 This also brings me to another question, since it seems using eval on a macro would require operating on symbols, is there some way of generating something like gensym's in java to wrap values?

1:17 I can think of an ugly hack of possibly creating a temporary namespace, interning all of the values as generated of that namespace, passing the symbols to eval, and then removing the namespace when it's done, but there must be an easier way.

1:22 lodin: Is there any way to get a list of all loaded java classes?

1:23 josiah14: which should I choose when it does not matter, mod or rem?

1:24 I know in some languages there is a lot less overhead in one rather than the other

1:45 rritoch: lodin: If you are using leiningen You can add [org.reflections/reflections "0.9.9-RC1"] to your dependencies and use the code (.get (.get (.getStore (org.reflections.Reflections. "" (into-array org.reflections.scanners.Scanner [(new org.reflections.scanners.SubTypesScanner false)]))) org.reflections.scanners.SubTypesScanner) (.getName java.lang.Object))

1:47 lodin: This will list any loaded java classes that have been instantiated, technically this code lists classes that have extended java.lang.Object which should be every class that's been used

1:49 lodin: rritoch: Thanks. I'll try it out.

1:49 rritoch: lodin: It is acting wierd though, it isn't showing clojure classes, like PersistentVector

1:50 lodin: I suspect there are classloader issues involved here

1:51 lodin: rritoch: In the repl it's giving me just an empty vector. Clojure 1.6.0.

1:51 andyf: rritoch: I haven?t used Clojure from Java at all, but I would guess that either (a) you don?t use macros invoked from Java, or (b) you invoke clojure.core/eval on Clojure expressions containing macro invocations.

1:52 rritoch: lodin: Ok I figured it out, don't pass an empty string, pass nil

1:53 lodin: rritoch: Now that's a different story! :-)

1:53 rritoch: Try (.get (.get (.getStore (org.reflections.Reflections. nil (into-array org.reflections.scanners.Scanner [(new org.reflections.scanners.SubTypesScanner false)]))) org.reflections.scanners.SubTypesScanner) (.getName java.lang.Object))

1:53 That is returning all classes

1:54 At least I assume it is due to the HUGE amount of spam

1:55 Using nil instead of an empty string I get 4504 classes returned

1:58 andyf: Thanks, I think that is the same as the Compiler.eval((PersistentList)... syntax

1:59 andyf: Any idea how to produce gensyms? Typically gensyms are used in let forms so I'm guessing I would need to somehow use a Compiler.LetExpr

2:01 andyf: I'm probably going to use this exercyse to become familiar enough with the compiler to start implementting namespace isolation.

2:01 andyf: rritoch: invoke clojure.core/gensym maybe?

2:02 lodin: rritoch: Maybe I'm missing something things I'm not a Java programmer, but I just took a random class from the java class library "java.awt.AlphaComposite", but I only have four classes that match #"(?i)awt" and that's com.sun.java.accessibility.util.AWTEventMonitor and com.sun.java.accessibility.util.AWTEventMonitor$AWTEventsListener.

2:02 s/things/since/

2:03 rritoch: andyf: That sounds like a good idea, generate a LetExpr, evoke clojure.core/gensym for each item and then set the macro call as the body

2:03 lodin: If i type java.awt.AlphaComposite in the repl it confirms the class exists.

2:05 rritoch: lodin: For reflections to return a specific class that class needs to be used first

2:05 lodin: Mmm-hmm.

2:05 rritoch: lodin: Java classloaders are lazy, they don't load classes until they're requested

2:07 lodin: There is really no way to get a list of any possible class that can be loaded by the current classloaders, a few examples of this is that jars (which are zip files) aren't required to include directory entries. You can also have URL's on your classpath, and there's no "standard" for getting a list of files from a web site.

2:09 lodin: So when I evaluate "java.awt.AlphaComposite" in the repl, then what happens?

2:10 rritoch: lodin: It will use a classloader to resolve the class. In every current version of clojure it uses Class.forName("java.awt.AlphaComposite") since your using the fully qualified class name

2:11 lodin: This behavior is a bit of a bug though and has been patched

2:11 lodin: How is it a bug?

2:11 rritoch: lodin: Either way, Class.forName uses the system classloader (the classloader that loaded the class java.lang.Class)

2:12 The system classloader then checks it's cache for the classname, if the class isn't in the cache it searches it's "classpath"

2:12 andyf: rritoch: Well, a patch has been written. It isn't in Clojure yet.

2:12 rritoch: lodin: It is a bug because nearly everything in clojure uses a "root" classloader

2:13 andyf: Yeah, please let me know when/where I can upvote that patch, I really like it :)

2:14 andyf: This ticket, I think: http://dev.clojure.org/jira/browse/CLJ-979

2:14 rritoch: lodin: Either way, if your new to java you should really stay away from classloaders

2:14 lodin: Classloaders are difficult to deal with even for expert java developers

2:14 andyf: Do you have an account on JIRA? If you see your name near the upper right, you are logged in. If you see "Log in", you can click on that to create a JIRA account.

2:15 rritoch: andyf: Ok, thanks. I'll create an account

2:16 andyf: Then go back to the CLJ-979 ticket link after you are logged in, and look for a "Vote" link near upper right part of page.

2:16 lodin: rritoch: Yeah, I'd rather not. I'm doing some tooling stuff, and this came up.

2:16 andyf: well, right hand side of page, not at the top but a little ways down.

2:16 rritoch: lodin: The best way for you to view the situation right now is that if you get a class not found exception than you probably have a missing dependency, in other words your trying to access a class from a library that you don't have loaded.

2:17 lodin: If you are using leiningen you can see all loaded libraries using 'lein classpath'

2:18 lodin: rritoch: Does anyone not use leiningen? :-)

2:18 andyf: Some people use Maven directly, but not using Leiningen for Clojure is definitely in the minority.

2:20 Look for "what tools do you use" near the bottom of the 2014 Clojure survey results if you are curious: https://cognitect.wufoo.com/reports/state-of-clojure-2014-results/

2:21 rritoch: lodin: I've used clojure directly without leiningen, once, for 5 minutes, but I don't think that counts

2:21 lodin: :-)

2:24 rritoch: Anyhow, I have to get back to work... This chatroom is very destracting, but in the few weeks I've been here I've learned more than I did working solo for months.

2:25 lodin: rritoch: Thanks for your help.

2:26 rritoch: lodin: I hate to beg for reputation, but think you could (inc rritoch), I'm hovering at a perfect zero so far

2:26 lodin: (inc rritoch)

2:26 lazybot: ⇒ 1

2:26 lodin: Sure :-)

2:26 rritoch: thanks :)

2:30 andyf: I'm on jira now, so how do I upvote the patch which uses baseLoader() ?

2:30 andyf: you can vote for tickets. There isn't a way to vote for particular tickets.

2:31 voting for a ticket means you want it to be resolved, not necessarily by a particular patch.

2:31 You can add a comment saying whatever you wish, if you have a reason to prefer a particular patch over another.

2:32 Sorry, I mean to say "there isn't a way to vote for particular *patches*"

2:33 rritoch: andyf: Thanks, I upvoted the ticket, though I'm strongly for the baseLoader() solution, but I still think it should check for any interned version of the class first

2:34 andyf: You can add a comment stating your opinion, and any reasons for it.

2:36 rritoch: andyf: Ok, I'll do that later, first I need to build a remote authentication system, once that's done I'm free to start working on clojure/core issues. I know I'll have time available monday, but I'm hoping to get started before then.

2:37 andyf: I really want to get this namespace isolation, I know simply bypassing the problem and allowing namespace conflicts will come back to haunt me if I don't deal with it now.

2:38 andyf: Good bug hunting

2:53 rritoch: Is there any REPL "terminal"? (A stand alone GUI REPL)

2:54 I constantly find myself having to launch a new shell, browse to a random project, and launch lein repl... It would be much easier if I could just add something to my quick-launch bar (microsoft).

2:56 andyf: Is there an existing Windows terminal that you can configure to start up a command window in the desired project directory?

2:56 I'm not familiar with anything you describe, but that doesn't mean it doesn't exist.

2:57 rritoch: andyf: Honestly I'm not sure, I also haven't looked into all of the features of powershell, this may be something I can get powershell to do for me

2:57 andyf: I did start a project for testing purposes

3:21 TEttinger: rritoch: I think you can set up any cmd shortcut to run with a specific command on windows, but you could also just make a .bat file

3:22 rritoch: TEttinger: I think I'm looking for something like https://github.com/alandipert/clj-swingrepl but it doesn't seem to work on my machine, it just hangs.

3:24 TEttinger: well the custom cmd application thing that visual studio gives you is just a shortcut with the target: %comspec% /k ""C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\vcvarsall.bat"" amd64

3:24 there are others, that one is the x64 tools prompt

3:25 %comspec% is an env var that leads to the full path to cmd.exe

3:26 substitute the vcvarsall.bat for the path to lein.bat and amd64 for repl and you should be set, rritoch

3:26 that shortcut can be pinned to the taskbar

3:28 rritoch: TEttinger: Ok thanks. That should work, I'll just need to set a current working directory to a test project

3:28 TEttinger: then I would just make a bat file and launch it

3:29 rritoch: TEttinger: I was just hoping there was maybe something like a GUI interface to leiningen, where you can select dependencies, profiles, etc. before launching

3:29 TEttinger: err, I think shortcuts let you specify where tehy start

3:53 wirrrbel: "lein repl" takes forever to start, is that due to my underpowered laptop?

3:56 rritoch: wirrrbel: It could be your internet connection, you can try adding :update :always to your project.clj and see if that helps, though if you change your dependencies you may need to run lein deps or lein -U jar

3:56 wirrrbel: Err, :update :never

3:58 wirrrbel: If you have :aot :all set you may want to comment that out while your developing, otherwise it will try a compile before launching the repl.

3:59 wirrrbel: hmm, kind of think that overall its my 5-6 year old macbook

3:59 :update :never does not speed it up

4:00 rritoch: wirrrbel: Well, for some of my projects my repl takes forever to start so these are the things that I do to speed it up

4:05 wirrrbel: rritoch: thanks for your help!

4:29 sveri: Hi, how do I convert a clojure data structure (vec / map) to a pretty formatted string?

4:30 hellofun`: svery clojure.pprint/pprint ?

4:31 sveri: hellofunk: returns a string?

4:31 andyf: sveri: with-out-str around stuff that prints to *out* will put it in a string instead.

4:31 hellofunk: sveri consider with-out-str

4:32 sveri: andyf: ah, thats nice, thank you both :-)#

4:32 hellofunk: ah andyf beat me to that one

4:33 andyf: sveri: The Clojure cheatsheet has some things like this categorized somewhat by function: http://jafingerhut.github.io

4:33 Check out the "IO" section about a page down on the right side.

4:34 sveri: I see

4:34 looks nice :-)

4:37 hm, could it be that pprint and with-out-str dont workin clojurescript?

4:37 andyf: pprint doesn't exist there, I think.

4:38 sveri: ok, that explains my problems :D

4:38 nonetheless, thank you

4:38 andyf: I'm not sure, someone may have ported the fipp lib to ClojureScript, which also does pretty-printing.

4:38 sveri: -> goint to #clojurescript

4:39 andyf: https://github.com/jonase/fipp/compare/cljs

4:39 Sorry, I meant this link: https://github.com/jonase/fipp

4:40 sveri: hm, the PR seems to be merged to 0.4.1-Snapshot, which was never released

4:41 this looks good: https://github.com/shaunlebron/cljs-pprint

4:42 oh, no, I was wrong

4:44 Hm, reading through all this and cljs jira it seems like there is nothing finished yet

5:31 profil: How does a set decide if an item is equal? Is it possible to change that comparison?

5:35 whodidthis: so i got this macro thingie but im not sure how to get the final result unquoted or something, anyone know if its still possible? https://www.refheap.com/94485

5:39 AeroNotix: whodidthis: what is the macro supposed to do?

5:40 whodidthis: with that example def depth-1 and depth-2

5:40 at the moment it just returns the list(?) as seen

5:40 AeroNotix: just generate named functions that return integers?

5:40 TEttinger: seems like you shouldn't be consing a list and should just call do and def, but I am not good with macros

5:41 hell, you don't even need the do

5:43 AeroNotix: whodidthis: I'll write this for you

5:43 sec

5:43 rritoch: profil: if you look at the source code for PersistentHashSet you will see that there is a constructor where you can pass in your own IPersistentMap impl, and it uses the containsKey method from the Associative interface to determine if an item is going to be unique to the list.

5:44 profil: So you should be able to extend an existing map with your own containsKey method to override the default functionality

5:46 AeroNotix: whodidthis: https://gist.github.com/AeroNotix/214dd3aef7998c317524

5:46 you should always break macro code out into small portions

5:46 never try to do too much inside a macro's body

5:46 because it gets confusing very fast

5:47 HTH

5:47 whodidthis: oh, cool

5:48 AeroNotix: Also, I guess you were trying to ensure depth was evaluated once or something when you assigned it to the d#?

5:48 pyrtsa: profil: Alternatively you could play with (reify Object (equals [a b] ...) (hashCode [a] ...)) to define your own equality semantics for the items you put to the set. But I would recommend using a map data structure instead.

5:48 whodidthis: i use it with a var

5:48 like (def-depths depths)

5:48 AeroNotix: I see

5:48 yes

5:49 whodidthis: i somehow got it to work without the assigning to d# part but then got owned when i put that in

5:50 AeroNotix: var expansion is tricky

5:50 it's easier to write macros which just work with literals

5:50 and probably more easily understood for people using your macros.

5:52 whodidthis: they wouldnt use it, i just want a set of depths def'd, kind of like yesql returns the queries as functions

5:52 yesql code too mysterious for me to understand sadly

5:54 AeroNotix: All code is mysterious until you understand it

5:55 whodidthis: quite, need to put another syntax quote in to expand the var and then code returns a list again

5:58 AeroNotix: you need to remember that the code expansion happens when the variables don't have any values

5:58 they're just symbols and s-expressions

5:58 So trying to create the values from a symbol, isn't going to work.

5:59 Returning code which expands into a for loop that needs to be eval'd at runtime could work, but requires a runtime call to eval, which is gross.

6:00 Do you *need* to def these things as a top-level def?

6:00 whodidthis: does seem to be so :S and theres no eval in clojurescript either

6:01 AeroNotix: whodidthis: do you need to have them as a def?

6:01 whodidthis: ill work with your thingie and write the map into the call then! many thanks for explanation

6:01 AeroNotix: Because defs are essentially globals.

6:01 and those are bad, mmkay

6:02 whodidthis: would be nice to call depths/depth-1 and color/lightgrey-1 instead of (get-in color/colors [:lightgrey 1])

6:03 globals shouldnt be to bad in their separate namespace i thinks

6:03 profil: rritoch, pyrtsa: okay, thats sounds a bit hard.. Maybe I'm doing this wrong? I want to have a data structure that consists of coordinates and parent coordinates, and use those in the set, only caring about coordinates and not the parent.

6:04 rritoch, pyrtsa: I have read about records, maybe I should use that?

6:04 AeroNotix: whodidthis: it's up to you, but pervasive use of global defs is a code smell imho. The more you use it, the more you rely on it and the harder your code is to test and reason about.

6:06 whodidthis: seems to work great for om's DOM functions

6:06 AeroNotix: Whatever. I'm done here.

6:06 whodidthis: at least i like it better than sablono, but many thanks again for code and var expansion explanation

6:07 AeroNotix: nw

6:08 whodidthis: you should read some proper literature on macros

6:08 justin_smith: $mail wirrrbel there are some tricks to get lein repl to start much faster https://github.com/technomancy/leiningen/wiki/Faster in particular LEIN_FAST_TRAMPOLINE or skipping nrepl and directly running clojure.main instead both shave off a lot of startup time

6:08 lazybot: Message saved.

6:21 rritoch: profil: If you use records you should be able to override the equiv method to control what the record considers as equivalent

6:24 profil: It took me some digging but it appears that the default set uses clojure.lang.Util/equiv to determine if items are equal. Records implement IPersitentCollection so you need to use equiv instead of equals to establish equality within a default set.

6:26 profil: rritoch: alright, thanks :)

6:53 ffwacom: is Rich Hickey from the future?

6:54 justin_smith: nope, he is from the far past

6:54 $last rhickey

6:54 lazybot: rhickey last listened to: 100s - Inglish Outro (feat. Ice Cold Perm) [IVRY]

6:54 justin_smith: err

6:54 $seen rhickey

6:54 lazybot: rhickey was last seen quitting 76 weeks and 4 days ago.

6:54 justin_smith: though it's interesting to see what he listens to I guess

7:02 profil: you may find this SO answer of mine useful http://stackoverflow.com/questions/26622511/clojure-value-equality-and-sets/26622863#26622863

7:03 profil: justin_smith: I realized that I could just use an ordinary map {[x y] [parent-x parent-y]}

7:05 justin_smith: oh, I thought you wanted a comparison that ignored the parents

7:08 profil: yeah, and thats what map does?

7:09 justin_smith: I see, so you would merge things into the map

7:09 I thought you wanted a set of maps

7:10 profil: just like `(conj {[1 1] [0 1], [1 2] [1 3]} {[1 1] [1 0]})`

7:11 rritoch: profil: I wasn't able to get this done with defrecord as defrecord stopped me from changing the equiv method, but I was able to do it with deftype

7:12 justin_smith: rritoch: likely the solution you found looks much like my or puredanger's answer in the above SO link

7:13 rritoch: No mine is much simpler

7:13 I just can't paste, it'll take me some time to get this typed out

7:15 ,(deftype IgnoreParent [parent y] clojure.lang.IPersistentList (equiv [this o] (and (instance? (class this) o) (= (.y o) (.y this)))))

7:15 clojurebot: sandbox.IgnoreParent

7:15 rritoch: ,(= (IgnoreParent. 99 1) (IgnoreParent. 99 1))

7:15 clojurebot: true

7:15 rritoch: ,(= (IgnoreParent. 99 1) (IgnoreParent. 99 2))

7:15 clojurebot: false

7:15 justin_smith: rritoch: you can use y in the place of (.y this)

7:18 rritoch: justin_smith: Do you know why IPersistentList isn't identified? I thought everything in java.lang.* and clojure.lang.* was supposed to be available without a fully qualified name?

7:18 justin_smith: no

7:19 the ns macro makes all of clojure.core's vars available in the ns you create, but clojure.lang is not imported anywhere by default

7:21 rritoch: justin_smith: Well I've been meaning to ask about that. It is the number one reason for me getting compiler errors since I always assume I can just use clojure.lang.* classes without importing them

7:22 Anyhow, I have about an hour to play so I'm finally going to checkout clojure from github so I can start playing with it

7:24 I just have to be careful to not use any custom builds in client projects.... That could end badly

7:28 justin_smith: rritoch: as long as the project.clj explicitly points at your group/artifact, and you make the artifact available, it can at least be tractable

7:29 now if you build it and don't change the group and version string, that could be very messy indeed

7:32 rritoch: Ok, so if I change the version in pom.xml that won't interfere with pulls?

7:33 justin_smith: well, changing group should suffice actually

7:34 rritoch: btw, your deftype does not suffice for hash equality https://www.refheap.com/94488 - two items with identical fields are not considered identical to hash-maps or hash-sets

7:35 s/to/by/

7:35 rritoch: justin_smith: It should, I just dug into the sources of all of that and hash sets use equiv for IPersistentMap's

7:35 justin_smith: rritoch: no it should not, see the SO above

7:36 rritoch: Only one way to test

7:36 justin_smith: hash insertion does not use equiv

7:36 rritoch: and see my link above for said test

7:37 (the refheap one that is)

7:39 rritoch: Well, I traced the source code and I see persistentHashSet uses the impl map's containsKey

7:40 From there I saw it was using a root INode, but obviously I ended up looking at the wrong INode implementation class

7:40 justin_smith: oh, it works for hash-maps, but not hash-sets

7:40 rritoch: The one I looked at was checking Util/equiv

7:40 justin_smith: I guess they hash differently, which is odd

7:41 rritoch: ,(deftype IgnoreParent [parent y] clojure.lang.IPersistentList (equiv [this o] (and (instance? (class this) o) (= (.y o) (.y this)))))

7:41 clojurebot: sandbox.IgnoreParent

7:41 justin_smith: rritoch: I don't know if you were trying to make it work with hash-sets, but if you only needed hash-maps, your version does actually work

7:41 I am surprised that hash-maps and hash-sets hash differently to be honest

7:41 rritoch: ,(set [(IgnoreParent. 2 1) (IgnoreParent. 3 1)])

7:41 clojurebot: #{#<IgnoreParent sandbox.IgnoreParent@7a80e3> #<IgnoreParent sandbox.IgnoreParent@a3f1cc>}

7:42 justin_smith: ,(into {} [[(IgnoreParent. 1 2) 9] [(IgnoreParent. 1 2) 8]])

7:42 clojurebot: {#<IgnoreParent sandbox.IgnoreParent@17e2e9> 8}

7:42 justin_smith: weird!

7:42 TIL

7:43 rritoch: Yeah, that shouldn't be the case, I think hashsets use hashmap as the impl

7:43 justin_smith: but clearly they use a different comparison for insertion

7:45 rritoch: Hmm, how can I leak the impl?

7:48 ,(def a (set [1]))

7:48 clojurebot: #'sandbox/a

7:50 rritoch: ,(.getDeclaredField (class a) "impl")

7:50 clojurebot: #<NoSuchFieldException java.lang.NoSuchFieldException: impl>

7:52 rritoch: ,(.getDeclaredFields (class a))

7:52 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: a in this context, compiling:(NO_SOURCE_PATH:0:0)>

7:52 justin_smith: &(require '[clojure.reflect :as reflect])

7:52 lazybot: ⇒ nil

7:52 justin_smith: &(map :name (:members (reflect/reflect #{})))

7:52 lazybot: ⇒ (withMeta empty asTransient _meta createWithCheck create cons create clojure.lang.PersistentHashSet meta createWithCheck cons EMPTY disjoin create createWithCheck withMeta)

7:54 rritoch: The hashset extends APersistentSet with a private field impl which I need to make accessible to see it

7:55 Anyhow, good cheat-case

7:55 I'll just make it public and recompile

7:55 justin_smith: &(:bases (reflect/reflect #{}))

7:55 lazybot: ⇒ #{clojure.lang.APersistentSet clojure.lang.IObj clojure.lang.IEditableCollection}

7:55 justin_smith: &(map :name (:members (reflect/reflect clojure.lang.APersistentSet)))

7:55 lazybot: ⇒ (size remove get count setEquals clojure.lang.APersistentSet add equals removeAll clear toArray addAll retainAll invoke toArray iterator _hasheq contains hasheq toString containsAll seq impl _hash hashCode isEmpty equiv)

7:55 rritoch: Hmm, you got at the impl

7:57 justin_smith: &(filter #(= (:name %) 'impl) (:members (reflect/reflect clojure.lang.APersistentSet)))

7:57 lazybot: ⇒ (#clojure.reflect.Field{:name impl, :type clojure.lang.IPersistentMap, :declaring-class clojure.lang.APersistentSet, :flags #{:final}})

7:57 justin_smith: has a final flag, but no private flag?

7:59 aha, I get it, there is no :private flag, but it lacks the :public flag

8:01 rritoch: Yeah, and my test environment is screwed up

8:01 I checked out from windows so I have windows newlines, but I can only compile from linux

8:02 Normally I don't have a problem, but the build script won't run

8:02 justin_smith: &(into [] (.getDeclaredFields clojure.lang.APersistentSet))

8:02 lazybot: ⇒ [#<Field int clojure.lang.APersistentSet._hash> #<Field int clojure.lang.APersistentSet._hasheq> #<Field final clojure.lang.IPersistentMap clojure.lang.APersistentSet.impl>]

8:02 justin_smith: so there's the field for you

8:03 rritoch: Hmm

8:03 justin_smith: I guess you would want to .setAccessible or something on it

8:03 rritoch: ,(.getDeclaredField clojure.lang.IPersistentMap "impl")

8:03 clojurebot: #<NoSuchFieldException java.lang.NoSuchFieldException: impl>

8:04 rritoch: ,(.getDeclaredField clojure.lang.IPersistentSet "impl")

8:04 clojurebot: #<NoSuchFieldException java.lang.NoSuchFieldException: impl>

8:04 justin_smith: &(.setAccessible (last (.getDeclaredFields clojure.lang.APersistentSet)))

8:04 lazybot: java.lang.SecurityException: You tripped the alarm! clojail.testers.ClojailWrapper@78f78a33 is bad!

8:04 justin_smith: hahaa

8:04 ,(.setAccessible (last (.getDeclaredFields clojure.lang.APersistentSet)))

8:04 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: No matching field found: setAccessible for class java.lang.reflect.Field>

8:04 justin_smith: hrmph

8:04 rritoch: ,(.getDeclaredField clojure.lang.APersistentSet "impl")

8:04 clojurebot: #<Field final clojure.lang.IPersistentMap clojure.lang.APersistentSet.impl>

8:05 rritoch: ,(. setAccessible (.getDeclaredField clojure.lang.APersistentSet "impl"))

8:05 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: setAccessible in this context, compiling:(NO_SOURCE_PATH:0:0)>

8:05 rritoch: ,(. setAccessible (.getDeclaredField clojure.lang.APersistentSet "impl") true)

8:05 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: setAccessible in this context, compiling:(NO_SOURCE_PATH:0:0)>

8:05 rritoch: ,(.setAccessible (.getDeclaredField clojure.lang.APersistentSet "impl") true)

8:05 clojurebot: nil

8:05 rritoch: :)

8:06 ,(def a (set [1]))

8:06 clojurebot: #'sandbox/a

8:06 justin_smith: ahh, I forgot the arg

8:07 rritoch: ,(.get (.getDeclaredField clojure.lang.IPersistentMap "impl") a)

8:07 clojurebot: #<NoSuchFieldException java.lang.NoSuchFieldException: impl>

8:07 rritoch: ,(.get (.getDeclaredField clojure.lang.APersistentSet "impl") a)

8:07 clojurebot: #<IllegalAccessException java.lang.IllegalAccessException: Class sandbox$eval237 can not access a member of class clojure.lang.APersistentSet with modifiers "final">

8:07 rritoch: :(

8:07 So close

8:09 Though clojurebot should really be blocking that setAccessible

8:10 Anyhow, I think this is finally going to compile, but that may take awhile since this is my first attempt... I'm better off just testing outside of sandbox.

8:12 Hmm

8:12 That error isn't from the bot, I get the same error about accessing finals from repl

8:13 looks like I'll need to strip off the final and make it public

8:13 justin_smith: &(.setFinal (last (.getDeclaredFields clojure.lang.APersistentSet)) false)

8:13 lazybot: java.lang.SecurityException: You tripped the alarm! clojail.testers.ClojailWrapper@6faf8224 is bad!

8:13 justin_smith: ,(.setFinal (last (.getDeclaredFields clojure.lang.APersistentSet)) false)

8:13 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: No matching method found: setFinal for class java.lang.reflect.Field>

8:13 rritoch: Hmm

8:13 justin_smith: blergh (works in my repl)

8:14 rritoch: Doesn't work in mine

8:14 justin_smith: oh wait, never mind

8:14 rritoch: Where you able to see what is in the impl by default?

8:14 justin_smith: I missed the error with the reflection warning in my repl

8:17 rritoch: Well, build time was 4 minutes 55 seconds, I just need to rebuild, install, and restart my repl and I should be able to see what is in the impl

8:18 Once we have that it should be easy to figure out why set's are acting differently thanmaps

8:19 justin_smith: rritoch: I expect you will find the keys are the hashes, created via .hashCode

8:20 rritoch: justin_smith: Probably, but I really thought impl would be a PersistentMap

8:21 justin_smith: right

8:21 rritoch: Either way, there should be consistency between hashes and maps so we probably just found a bug

8:21 justin_smith: a map, with hash codes as keys, and maybe vectors as the vals?

8:21 not so sure of that

8:24 rritoch: I just hope hicky doesn't mind that I'm jailbreaking my clojure runtime, lol

8:25 Where is clojure's licence?

8:25 I really should have read that first

8:25 Bronsa: it's the EPL, you can do whatever you want with your runtime

8:25 rritoch: Ok, good :)

8:28 Morgawr: I have a very long string I need to wrap around multiple lines (for a lib I'm making) and I want to split it every X characters and turn it in a list of strings (or vec or whatever)

8:28 how can I do that?

8:31 rritoch: ,(partition 2 "ABCDEF")

8:31 clojurebot: ((\A \B) (\C \D) (\E \F))

8:31 rritoch: ,(map str (partition 2 "ABCDEF"))

8:31 clojurebot: ("clojure.lang.LazySeq@be2" "clojure.lang.LazySeq@c22" "clojure.lang.LazySeq@c62")

8:31 rritoch: hmm

8:31 Morgawr: rritoch: need apply str, but yeah thanks :)

8:31 rritoch: ,(map pr-str (partition 2 "ABCDEF"))

8:31 clojurebot: ("(\\A \\B)" "(\\C \\D)" "(\\E \\F)")

8:32 Morgawr: (map (partial apply str) (partition 2 "ABCDEF"))

8:32 ,(map (partial apply str) (partition 2 "ABCDEF"))

8:32 clojurebot: ("AB" "CD" "EF")

8:32 rritoch: yep :)

8:33 ,(map (comp apply str) (partition 2 "ABCDEF"))

8:33 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (1) passed to: core/apply>

8:33 rritoch: ,(map (comp str apply) (partition 2 "ABCDEF"))

8:33 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (1) passed to: core/apply>

8:34 rritoch: Hmmm, guess not

8:36 Anyhow, I have this jailbroken, so let's see

8:37 Back to the source code

8:38 impl is a PersistentHashMap

8:38 So sets and maps should behave the same, but they aren't

8:40 ,(deftype IgnoreParent [parent y] clojure.lang.IPersistentList (equiv [this o] (and (instance? (class this) o) (= (.y o) (.y this)))))

8:40 clojurebot: sandbox.IgnoreParent

8:41 rritoch: ,(def a (IgnoreParent. 2 1))

8:41 clojurebot: #<CompilerException java.lang.IllegalArgumentException: Unable to resolve classname: IgnoreParent, compiling:(NO_SOURCE_PATH:0:0)>

8:41 rritoch: ,(deftype IgnoreParent [parent y] clojure.lang.IPersistentList (equiv [this o] (and (instance? (class this) o) (= (.y o) (.y this)))))

8:41 clojurebot: sandbox.IgnoreParent

8:41 rritoch: ,(def a (IgnoreParent. 2 1))

8:41 clojurebot: #'sandbox/a

8:42 rritoch: ,(def b {a "1"})

8:42 clojurebot: #'sandbox/b

8:42 rritoch: ,(.containsKey b (IgnoreParent. 3 1))

8:42 clojurebot: false

8:43 profil: is it possible to break free from the surrounding list in this example https://clojuredocs.org/clojure.core/hash-map#example_542692cfc026201cdc326e23 ? I want to return a map directly

8:43 Bronsa: rritoch: plase don't abuse clojurebot. you can query it to get a repl

8:45 rritoch: Bronsa: This isn't meant to be abusive, the issue is why does this deftype behave differently within sets than it does within maps

8:45 Bronsa: rritoch: I meant it as "don't spam #clojure with your repl experiments"

8:48 rritoch: Ok, I'll just use pastebin

8:59 justin_smith: I'm exposing PersistentMap/root now in my latest build to see why this is happening. I'm starting to think the first soluion of making a custom map type by overriding containsKey would be an easier route for this issue.

9:02 Is there any way to more quickly compile clojure than by just running ant? Each rebuild takes 5 minutes

9:13 Bronsa: rritoch: I use mvn -Dmaven.test.skip=true install

9:15 rritoch: s/install/package/ if you don't want to install the snapshot jar in your local maven cache

9:16 rritoch: Bronsa: Ok, I haven't actually tried to just use mvn install after my changes, I've been compiling first with ant

9:17 Bah!

9:17 I figured out the issue, I'm again mistaking persistenthashmap with persistentmap

9:18 When using {} it isn't a persistenthashmap, which is why maps behave differently than sets when dealing with a typedef that has equiv method overridden

9:20 Either way, the root of a persistenthashmap is the $BitmapIndexedNode so the rest should be easy to figure out

9:25 justin_smith: You were right, PersistentArrayMaps use Util.equiv for comparison, and sets are using the hash from Util.hasheq

9:25 Isn't that a bug though, shouldn't all of clojure use the same method to determine equivalence?

9:25 Unless explicity overridden?

9:26 Bronsa: rritoch: can you summarize the issue for me?

9:27 rritoch: profil: Posted the problem of creating objects that within a set would be considered equivalent even if they have different parents

9:27 err, Bronsa:

9:28 anyhow... I thought it could be done by creating an IPersistentMap deftype with a custom equiv

9:29 But while they pass equivalency tests in clojure, they're not considered the same within sets, justin_smith thought it was because of the hashes, but to verify it I exposed a few final vars in clojure so I could verify

9:29 So now the problem is if there's a way to get the hashes to also match

9:30 So they'll behave correctly within sets

9:34 As far as I can tell now, the only way to do it is to provide a custom impl to the set (or just pass a PersistentArrayMap to the set as the impl).

9:34 Since I don't think overriding "hashCode" is a good idea, even if it is possible.

9:35 I never tried.

9:38 Looking at this code it would be possible to implement IHashEq, not an easy task without knowledge of cryptography, and generate hashes that only use the child data.

9:40 But either way, shouldn't sets be using PersistentArrayMaps instead of PersistentHashMaps by default to provide consistency across clojure in evaluating equivalency?

9:47 profil: Here is the a final solution that works ,(deftype IgnoreParent [parent y] clojure.lang.IPersistentList (equiv [this o] (and (instance? (class this) o) (= (.y o) (.y this)))))

9:48 profil: By implementing equiv and hasheq you get equivalence and the same hashes so they should work the way you need them to.

10:31 timvisher-xubunt: macros are written in jvm clojure land for clojurescript, right? so shouldn't i just be able to (require '[clojure.tools.trace :refer-macros [trace]]) in a clojurescript file?

10:33 dnolen_: timvisher-xubunt: won't work if tools.trace includes runtime defs

10:36 timvisher-xubunt: dnolen_: also doesn't work if trace isn't a macro :)

10:37 dnolen_: timvisher-xubunt: in general very few macros tend to work that don't have explicit ClojureScript support in mind

10:37 timvisher-xubunt: oof. it does use clojure.pprint though, and that sadly still has not been ported. :(

10:37 dnolen_: timvisher-xubunt: yep there's been a ticket for that for a very long time - still no takers

10:37 timvisher-xubunt: turns out trace is a pretty simple function. for some reason i thought it was a macro

12:03 mattrepl: if one had a large-ish csv file (1.3gb size, 2m lines), how would one read that file into a nested vector, where the outer vector contained an element for each record from the csv, and the inner vectors contain an element for each field. The fields are stored as strings.

12:05 trying the obvious: (vec (data.csv/read-csv rdr)), which results in huge memory usage

12:06 jeremyheiler: mattrepl: that's a lot of data, so yeah, it'll be huge in memory

12:06 mattrepl: thinking it was something about the implemetnation of LazySeq and Cons cells which I don’t understand, I also tried using doseq over the read-csv result and conj!’ing into a transient vector. that also blows up memory

12:06 gfredericks: mattrepl: yeah memory should be about the same either way

12:07 mattrepl: but you’d think 8gb (max heap size) would be sufficient?

12:07 gfredericks: mattrepl: does the jvm crash?

12:07 not sure what "blows up memory" means

12:07 I agree it sounds like it should fit

12:07 mattrepl: no crashing, I mean it reaches the maximum size and chugs along, but garbage collection is constantly occurring

12:57 justin_smith: $mail rritoch I think it is likely about that java truism that you need to override hashCode if you override =. The way in that StackOverflow answer is actaully the simple way to do it. http://stackoverflow.com/questions/26622511/clojure-value-equality-and-sets/26622863#26622863

12:57 lazybot: Message saved.

13:17 Guest89063: I read an article about clojure web programming the other day

13:18 I had an example with HTML marked up as a big nested clojure map

13:18 It looked horrific

13:19 Are there any options for clojure templating that allow for embedding into HTML? a la integrated ruby or php?

13:27 justin_smith: I don't have messages for nick changes turned on, but if Guest89063 is still around, yes, there are a number of options for html templating with Clojure

13:29 seangrove: Jesus christ though, 230 lines

13:29 For the initial commit

13:29 The node world is causing me sadness

13:35 gfredericks: ~Guest89063 was a fleeting visitor who quickly disappeared into the night

13:35 clojurebot: Gabh mo leithscéal?

13:35 gfredericks: ~Guest89063 |was| a fleeting visitor who quickly disappeared into the night

13:35 clojurebot: Ik begrijp

13:35 gfredericks: are those the same language?

13:36 justin_smith: welsh and dutch I think

13:37 irish and dutch?

13:43 superbob: I need a bugfix in master of freact. How do I pull unreleased libs into my projects?

13:44 justin_smith: superbob: react, the javascript lib?

13:45 superbob: justin_smith: Sorry, I meant "freactive": http://documentup.com/aaronc/freactive

13:45 justin_smith: that's much easier

13:45 download, fix, change the group (or at least the version string) and run lein install

13:46 after that you can use the newer version by asking for that group / version

13:46 you can put it on clojars with "lein deploy clojars"

13:46 but usually lein install is enough

13:46 superbob: Excellent, thanks.

13:47 npm has 'npm link', which is super handy.

13:47 For this sort of thing.

13:49 justin_smith: superbob: that's almost identical to lein checkout deps

13:49 but I actually like lein install better, it's simpler imho

13:49 superbob: here's how to do that with lein https://github.com/technomancy/leiningen/blob/master/doc/TUTORIAL.md#checkout-dependencies

13:50 superbob: Cool. Cheers.

13:50 justin_smith: it doesn't mention how to make the links though, but that's not super hard "ln -s /full/path/to/target place"

14:12 dnolen_: ClojureScript now has vars - the static parts that make sense anyway

14:13 ns-interns & doc work on master - also working on a largely compatible rewrite of clojure.test w/ an eye towards alternate tests reports and core.async support

14:13 which means testing support will be built in - :none will work

14:14 gfredericks: woah vars

14:15 seangrove: Ah, damn. If I update my version of clojurescript and get a NPE with cljsbuild, what am I missing? This happens frequently enough that I recognize it, but I don't remember the cause

14:15 dnolen_: seangrove: wrong version of Clojure usually

14:16 seangrove: That makes sense

14:16 gfredericks: dnolen_: is there a writeup somewhere on the design so I don't have to resist peppering you with questions?

14:17 dnolen_: gfredericks: it's pretty simple there are still no first class namespaces and there vars are not first class, you can only do static things (i.e. no resolve)

14:17 Bronsa: dnolen_: I'm a bit worried about the evaluation semantics of metadata on the def symbol

14:18 dnolen_: in clojure that metadata is always evaluated, in cljs it looks like only :test meta will be evaluated now ?

14:18 gfredericks: dnolen_: any of the indirection that clj-jvm has on var usage?

14:18 dnolen_: Bronsa: for now, not really interested in supporting the general case at the moment

14:19 Bronsa: I just want to fix testing once and for all and provide the infrastructure so that people can build things properly i.e. not like clojurescript.test :)

14:21 Bronsa: dnolen_: gotcha, it's just causing me a bit of pain for t.a.js but I can deal with it

14:21 dnolen_: btw https://github.com/clojure/clojurescript/commit/54b75eca6fdb6a5959253a9b2addbcf3119567a7#commitcomment-8863289

14:21 dnolen_: Bronsa: yeah definitely has to be done in a semi-hacky way but this is pretty big portability win IMO.

14:23 Bronsa: I don't really understand the problem with that

14:23 Bronsa: ,`(defmacro var [])

14:23 clojurebot: (clojure.core/defmacro var [])

14:23 Bronsa: ,`(var 1)

14:23 clojurebot: (var 1)

14:24 Bronsa: ,*ns*

14:24 clojurebot: #<Namespace sandbox>

14:24 Bronsa: that's not going to return '(sandbox/var 1)

14:25 dnolen_: meaning that if a user namespace shadows cljs.core/var, ns-interns will pick that rather than cljs.core/var

14:28 seangrove: I don't suppose there's much cljs could do to throw a more useful stack trace here, is there? http://dl.dropbox.com/u/412963/Screenshots/k6.png

14:30 dnolen_: seangrove: core.async could maybe do something - not specifically a cljs thing

14:30 gfredericks: what do you mean "indirection"?

14:31 seangrove: dnolen_: Ah, yes, that's what I meant, sorry. I wonder if there's a way to be devtools-friendly with this stuff

14:31 dnolen_: seangrove: probably, I suspect someone with some time on their hands could do something nice instrumenting for core.async under Chrome DevTools

14:32 Bronsa: hrm that's actually not enough, #'foo is a reader thing

14:34 gfredericks: dnolen_: I mean that it's logically an extra hop; so e.g., the behavior of (def x 42) (defn get-x [] x) (alter-var-root #'x inc)

14:34 perhaps ^ that sort of thing doesn't apply somehow?

14:34 dnolen_: gfredericks: vars aren't actually a fully reified thing this what I saying about "static" earlier.

14:34 gfredericks: so I'm curious what doc does

14:34 dnolen_: gfredericks: the vars in ClojureScript are just user space hooks into the information in the analyzer

14:35 gfredericks: oh interesting

14:35 Bronsa: dnolen_: ah damn. so it's either making var a special form in cljs too or tweaking tools.reader

14:35 dnolen_: Bronsa: actually you have to change the reader, special form isn't enough

14:36 #'foo -> (var foo) via the reader

14:36 Bronsa: dnolen_: right, but if var is a special form there's no chance of shadowing it via macros.

14:37 dnolen_: Bronsa: ah hmm

14:37 Bronsa: that's why it works in clj

14:37 dnolen_: you chose what you prefer, I have no issues about opening the dispatch table in t.reader

14:38 dnolen_: Bronsa: ah right, I think special form is better in this case.

14:38 Bronsa: ok

14:44 dnolen_: Bronsa: ah ok, I had forgetten that var could not be shadowed in Clojure (I know you were saying this but wasn't sinking in)

14:47 superbob: Clojurescript question; when I eval (.replace "12121212" "2" "z") in the browser, I get "1z121212"

14:48 All instances of 2 should become z, according to the docs.

14:48 Am I doing something daft?

14:49 justin_smith: superbob: is there .replaceAll like there is in java?

14:49 superbob: There's not.

14:50 justin_smith: what about "2/g" instead of "2"

14:50 or more likely it would be "/2/g"

14:50 Bronsa: superbob: have you tried using clojure.string/replace?

14:51 superbob: Bronsa: Doh, thanks.

14:51 Bronsa: I'd just assumed that's what I was using.

14:51 Bronsa: np

14:52 .replace is interop

15:45 dnolen_: Bronsa: thanks for the sanity check, var is now a special https://github.com/clojure/clojurescript/commit/91153fa7d26f55cc466ac1d24184ba78bac7cf72

15:48 bbloom: dnolen_: static var support!!

15:48 mmmm #' yum

15:49 dnolen_: bbloom: yep :)

15:53 bbloom: dnolen_: https://github.com/brandonbloom/clojurescript/compare/var-form~3...var-form?expand=1 <- old but familiar :-)

15:55 dnolen_: bbloom: heh for sure, definitely never completely thought it was a bad idea, the renewed interest driven by wanting to get clojure.test properly ported

16:19 CaptainLex: I'm getting this error

16:19 "Java.lang.ClassCastException: null"

16:20 no other trace

16:20 or line number

16:20 Is there some category of problems that can cause this kind of nonsense?

16:22 gfredericks: CaptainLex: doesn't sound familiar; where are you seeing that? at the repl?

16:22 CaptainLex: gfredericks: I'm seeing it in LightTable. I tried to reproduce it in the repl but I don't have a main so I don't think lein jacked in

16:23 (I also asked in the LT room, but that place is a ghost town)

16:24 andyf: Two possibilities I can think of (but I don?t use LightTable): There is an option when you start a JVM that disables some optimizations that can cause stack traces to be eliminated.

16:25 (2) LightTable is postprocessing some or all stack traces to try to clean them up, and is too aggressive in this case.

16:26 For the first possibility, see: http://stackoverflow.com/questions/4659151/recurring-exception-without-a-stack-trace-how-to-reset

16:26 amalloy: andyf: my money is on (1)

16:26 andyf: Looks like the JVM option that should prevent the optimization in question is -XX:-OmitStackTraceInFastThrow

16:26 I don't know if there is an easy way to make LightTable use that when it starts a JVM.

16:28 Here is a project.clj file that has that command line option enabled by default, which it appears someone uses with LightTable, but will work for anything that uses Leininge: https://github.com/stoyle/clojure-workshop/blob/master/project.clj

16:30 amalloy's money is good enough for me :-) (insert nice thing to amalloy here that lets me stay on for another 24 hours)

16:39 CaptainLex: Thanks guys! Unfortunately a preponderance of issues and time constraints have pushed me to switching this particular project to JavaScript

16:39 So this'll just be one for the ages

16:40 gfredericks: ha

16:41 ~java.lang.ClassCastException is time to rewrite in JavaScript

16:41 clojurebot: Alles klar

16:42 amalloy: uncaught type error: undefined is not a function? or however that message goes

16:43 andyf: "uncaught type error: you are probably using the wrong programming language"

16:44 "NPE: Have you considered a career in cosmetic engineering?"

16:46 CaptainLex: Haha I don't prefer JavaScript either, but it's a language I know and it has the algorithm I need to do this paper for school

16:46 I was adapating one in Clojure that was written for a different use case

16:47 The one I found in JS was written for the same one

16:48 andyf: "WeirdExceptionYouveNeverHeardOfException: You are a fluke of the universe. Give up." (hat tip to National Lampoon's Deteriorata)

16:48 CaptainLex: Hahaha

16:53 andyf: hmmm. Easter-egg option for creative Eastwood lint warning messages.

16:57 mattrepl: 1.3gb csv file, 2.6m lines, 70 columns. how much heap space would you estimate is used for a nested vector of column values, i.e.: (def data (vec (csv-read rdr)))?

17:01 between representation of strings and overhead for persistent vectors, i’d guess ~3gb

17:02 the actual is ~t0gb

17:03 err, ~10gb

17:07 danneu: in my web apps, i've always signed my cookies by default. and i use a signed cookie of {:session-id <UUIDv4>} for authentication. but my friend says it's silly to sign a UUIDv4 since it's already cryptographically secure.

17:08 but someone just pointed out to me that RFC 4122 says that UUIDs should not be relied on for security capabilities. - https://groups.google.com/d/msg/datomic/Jo0KJp9JfLA/MwGxH5b_sD4J

17:08 is my friend wrong?

17:09 or is the RFC just talking about UUIDs in general and not v4 in particular?

17:10 andyf: mattrepl: How many column values per line on average?

17:10 2x is pretty much automatic for ASCII strings read into Java UTF-16 strings.

17:10 mattrepl: each line has the same, it’s about ~70, many are empty strings

17:11 right, so that’s ~2.6gb, let’s even be generous and round up to 3gb. then 7gb for persistent vectors? something seems wrong…

17:12 andyf: 70 fields per line?

17:12 mattrepl: yes

17:12 andyf: Each one will be its own Java object with 16 bytes of overhead on a 64-bit JVM (iirc)

17:13 if put into a Clojure vector, unless it is one of the primitive vector types, which should use less, I think.

17:14 mattrepl: so we have 2.6m PersistentVectors of 70 String objs each

17:16 andyf: 2.7gigabytes, you mean?

17:17 kenrestivo: any idea the status of this? http://dev.clojure.org/display/design/%27Lean%27+Runtime i recall that at cljwest, rich endorsed either this or a similar project. did anything ever happen with it?

17:17 andyf: Yeah, it all adds up. I don't have a good guess for how to estimate the other 5 gigabytes you are seeing, but if you are keeping the original line strings around, plus extracted ones, those are copies of each other with Java 7 and later.

17:17 mattrepl: i was counting the number of vectors. but yes, 2.7gb ofor references

17:19 original shouldn’t be kept, csv-read returns a LazySeq of PersistentVectors and we consume it (without holding onto head) to create the PersistentVector of PersistentVectors

17:19 andyf: Are all fields values that are the same type of Java primitive, e.g. long or double? Or is it a mix?

17:20 profil: When checking a value, is there a better way than doing `(cond (= item "something") .. (= item "something2") .. ..)`?

17:21 andyf: profil: case is useful if all comparison values are compile-time constants.

17:21 mattrepl: all field vals are strings. no type conversion done by data.csv/csv-read

17:22 profil: andyf: yeah "something" and "something2" is constant strings

17:22 mattrepl: it looks like references are 8 bytes for 64-bit jvm (which is what i’d expect)

17:22 gfredericks: does anybody know if ThreadLocal is a common jvm technique to reduce allocations of create-and-discard resources?

17:23 andyf: mattrepl: Yes, for each of your fields in a vector, there is not only the 16 bytes of overhead per String object, put another 8-byte reference in the vector to point to it.

17:23 gfredericks: and/or if there's any reason it would be inappropriate for that use

17:26 mattrepl: andyf: ok, so that’s 4gb already and that’s not including actual string data. or the references to the nested vectors

17:26 andyf: mattrepl: If there were a convenient string type in Java that represented strings in memory as UTF-8, it would save significant memory for processing ASCII files.

17:27 but yeah, it wouldn't save all of the pointers or object overheads in this case.

17:28 Is it convenient in this application to do the field-splitting on an as-needed basis?

17:28 mattrepl: was thinking about that, trade time for space savings

17:30 yeah, it’d be fine to do, just makes data.csv less useful. could process a line at a time, but some csv files (not this one though) have multi-line field values

17:31 andyf: Perl can be nice for some text-file hacking :)

17:31 But having a common language for many tasks is good

17:32 gfredericks: How could ThreadLocal's help reduce allocations?

17:34 mattrepl: hah, yes. just crazy that there’s an order of magnitude increase in space for this. having some sort of on-the-fly vector may be useful. in this case just filtering out fields not used for processing will be fine.

17:34 amalloy: profil: and if they're not constants, (condp = item ...) expands to your cond

17:34 gfredericks: andyf: e.g., if you need a byte array for a temporary thing, the ThreadLocal lets you have one per thread, so you don't need to make new ones

17:36 andyf: mattrepl: It can be surprising until you do the math on what the implementation does. A UTF-8 in-memory string plus value types in a future JVM, taken advantage of by Clojure's vectors, could reduce a lot of this, but those are all just pre-slideware right now

17:37 gfredericks: where each thread is mutating its local object over time?

17:37 gfredericks: andyf: right, presumably resetting it & mashing it for a short time

17:37 andyf: oh, maybe you mean that rather than repeatedly temporarily allocating and deallocating such an object, the thread just 'caches' the previously-allocated one and uses it again later?

17:38 gfredericks: based on the docs ThreadLocal seems like the obvious tool but I haven't really heard of anybody using it

17:38 andyf: right -- and using ThreadLocal instead of just a single global object makes it threadsafe

17:38 but otherwise the single global object accomplishes the same thing

17:39 andyf: That sounds similar to lots of C libraries that do their own internal memory mgmt, using malloc only for large chunks, because they believe they can do it better (and maybe they can).

17:39 gfredericks: right; it's manual mem mgmt for sure

17:40 amalloy: hm. that is not working

17:41 andyf: --- amalloy tweaks settings on the iron fist ---

17:42 sorry, still amused by the "rule with an iron fist" comment you made.

17:42 amalloy: andyf: feel free. i enjoy being amusing

17:44 $mail technomancy so someone sent me a spam PM and i tried to ban them but i don't think it worked. i tried setting +b on all of '(*!~juuo@213.143.61.98, *!juuo@213.143.61.98, *!~juuo@*) but this juuo person is still in the channel. what am i missing?

17:44 lazybot: Message saved.

17:46 Bronsa: amalloy: you need to kick him

17:46 amalloy: oh, really?

17:46 Bronsa: just issue a +k as well? which of those three forms do i want to use?

17:47 Bronsa: amalloy: banning will just prevent them from writing/joining but will not kick them

17:47 amalloy: no just /kick juuo

17:47 amalloy: k

17:47 mattrepl: and /kickban juuo would do both

17:48 Bronsa: mattrepl: depending on the IRC client /kickban might not be available

17:48 mattrepl: Bronsa: true

17:50 Bronsa: amalloy: you messed something up with the ban

17:50 amalloy: Bronsa: okay? how to fix? also /kick doesn't seem to be doing anything

17:51 Bronsa: amalloy: you're kicking him but he's auto-joining back because the ban isn't working

17:51 amalloy: oh. i have join/part hidden :P

17:52 Bronsa: amalloy: just try /mode #metamorphism +b juuo and then /kick juuo

17:52 AimHere: amalloy, perhaps you need to change the 'juuo' in your banstrings to 'juio'

17:52 Bronsa: err amalloy #clojure

17:53 amalloy: AimHere: oh, you're right. i read the username wrong

17:53 success!

17:53 Bronsa: yup that worked

17:53 amalloy: $unmail technomancy

17:53 lazybot: Deleted unread messages from amalloy to technomancy

17:53 Bronsa: amalloy: you're using erc right?

17:54 amalloy: Bronsa: no

17:54 AimHere: Now you've got to clear those spare ban entries before the *real* juuo shows up!

17:54 amalloy: indeed, AimHere

17:54 every few months we have a get-together where everyone teases me for using pidgin

17:54 Bronsa: heh

17:56 amalloy: thanks for the help, guys

17:56 Bronsa: amalloy: look at the bright side, now you can kickban those who laugh at you

17:57 amalloy: Bronsa: i've got my eye on andyf

17:59 andyf: The eye ... the eye .... can't hide

18:13 bitcrusher: anyone using cursive?

18:13 derping on parens and brackets, it won't let me enter them

18:22 justin_smith: bitcrusher: do you have structural editing turned on?

18:23 bitcrusher: probably on, its on by default

18:23 that might be the problem

18:23 gonna change that now, see if it fixes the problem, its annoy :/

18:24 cfleming: bitcrusher: You can turn it off in the status bar at the bottom of the window

18:25 bitcrusher: cfleming: thx

18:26 so much better, almost threw my keyboard across the room

18:30 cfleming: bitcrusher: I'd recommend trying to get used to it, though.

18:31 bitcrusher: It's like touch typing - once you're used to it, you'll wonder how you ever lived without it.

18:32 bitcrusher: It's a pain to learn though.

18:42 profil: is it possible to use destructuring in a loop? like `(loop [[x y & xs]] ... )`?

18:43 Bronsa: ,(loop [[a] [1]] a)

18:43 clojurebot: 1

18:45 profil: Bronsa: ah, so I want `(loop [[x y & xs] THEVECTOR] ... )`?

18:46 Bronsa: well if thevector is your init value

18:46 ,(loop [[x] [3]] (if (zero? x) x (recur [(dec x)]))

18:46 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

18:46 Bronsa: ,(loop [[x] [3]] (if (zero? x) x (recur [(dec x)])))

18:46 clojurebot: 0

18:50 profil: Bronsa: great, thanks!

18:50 gfredericks: ,(loop [x 42] (if (zero? x) :heyhey (recur ((rand-nth [inc dec]) x))))

18:50 clojurebot: :heyhey

18:51 justin_smith: gfredericks: we should make that into a drunken-walk macro

18:52 well, it could probably just be a function actually

18:54 (defn drunk [test init ops] (if (test init) init (recur ((rand-nth ops) init) ops)))

18:54 gfredericks: forgot a recur arg

18:54 justin_smith: oh yeah, test should be in there too, of course

18:55 rritoch: What is the best/easiest way to get a list of all required (direct and indirect) of the current namespace?

18:55 gfredericks: ,(defn drunk [test init ops] (if (test init) init (recur test ((rand-nth ops) init) ops)))

18:55 clojurebot: #'sandbox/drunk

18:56 gfredericks: ,(drunk (fn [[x y]] (< 10000 (+ (* x x) (* y y)))) [0 0] (for [i [0 1] f [inc dec]] #(update % i f)))

18:56 clojurebot: [-100 1]

18:56 rritoch: I was ableto create namespace isolation using ThreadLocal memory, but for stability I want to copy all dependencies of the current namespace, and the current namespace, into the newly created "isolated" environments

18:56 gfredericks: ,(drunk (fn [[x y]] (< 10000 (+ (* x x) (* y y)))) [0 0] (for [i [0 1] f [inc dec]] #(update % i f)))

18:56 clojurebot: [100 7]

18:57 rritoch: I'm also considering adding in an assertion to ensure you can't enter a previously created namespacecontainer unless the current namespace already exists in the container.

19:05 This is what I have so far, and in Namespaces.jar the value of the namespaces static final property gets replaced with an instance of this NamespaceContainer

19:06 http://pastebin.com/vZaAMS53

19:15 ortuna: What is the best way to get run time stack errors on a 'lein ring server' session?

19:15 kenrestivo: i wrote a library for that, but you could simply write a ring wrapper and log it

19:16 http://github.com/kenrestivo/firealarm (should scrap it and write something around timbre instead, which didn't exist at the time)

19:23 amalloy: best way to get stack errors? (#(% %) #(% %))

19:26 ortuna: :D

19:26 @kenrestivo thanks, I'm checking out the wrapper now

19:29 kenrestivo: amalloy: is that a clojure forkbomb?

19:29 amalloy: kenrestivo: well, it doesn't fork

19:29 kenrestivo: it looks like two drunk guys staring at me

19:29 justin_smith: stackbomb

19:30 kenrestivo: ~stackbomb is a great punk rock band name

19:30 clojurebot: A nod, you know, is as good as a wink to a blind horse.

19:31 justin_smith: kenrestivo: indeed. Four data structures and a message(queue).

19:36 kenrestivo: ~stackbomb is a good punk rock band name, or (#(% %) #(% %))

19:36 clojurebot: A nod, you know, is as good as a wink to a blind horse.

19:36 rritoch: I'm just awestruck by the spam ##(into #{} (map (comp type second) (.getMappings *ns*)))

19:36 lazybot: java.lang.SecurityException: You tripped the alarm! class clojure.lang.Namespace is bad!

19:37 * rritoch #{java.lang.Class clojure.lang.Var}

19:38 rritoch: Is it even possible to get a list of dependent namespaces? I expected to see some namespaces in the mappings?

19:38 justin_smith: that's not how namespaces work

19:38 each var will have a namespace though

19:39 and you could collect them that way

19:40 rritoch: justin_smith: Thanks, I can do that, and walk those namespaces to get the list

19:44 justin_smith: (into #{} (map (comp :ns meta second) (.getMappings *ns*)))

19:45 hmm ##(into #{} (map (comp :ns meta second) (.getMappings *ns*)))

19:45 lazybot: java.lang.SecurityException: You tripped the alarm! class clojure.lang.Namespace is bad!

19:45 justin_smith: too bad

19:48 rritoch: Well I just learned my lesson about using in-ns

19:48 justin_smith: another good one ##(.getAliases *ns*)

19:48 lazybot: java.lang.SecurityException: You tripped the alarm! class clojure.lang.Namespace is bad!

19:48 justin_smith: :P

19:48 rritoch: CompilerException java.lang.RuntimeException: Unable to resolve symbol: into

19:48 justin_smith: (refer 'clojure.core)

19:48 that fixes it

19:49 well, (clojure.core/refer 'clojure.core) is more like what you need

19:49 and of course you can just use ns

19:49 which does that for you

19:49 rritoch: justin_smith: Well I just did an in-ns back to user and that recovered my repl

19:50 justin_smith: there is nothing to "recover" though. It's just a namespace without the default mappings, but you can still use clojure.core/* explicitly

19:51 rritoch: Well, I have the first part of this puzzle solved (into #{} (map #(.ns %) (filter var? (map second (.getMappings *ns*)))))

19:52 justin_smith: I'm just not sure how to best do a recursion, typically in this case I'd check if anything new was added to the list since the last sweep, but I've never needed something like that in clojure.

19:54 justin_smith: you could use set/difference to get anything in the new set that was not in the previous

19:54 if you have both handy

19:55 ##(clojure.set/difference #{1 2 3} #{1 2 3 4})

19:55 lazybot: ⇒ #{}

19:55 * Bronsa slays all the AOT bugs

19:55 justin_smith: ##(clojure.set/difference #{1 2 3 4} #{1 2 3})

19:55 lazybot: ⇒ #{4}

19:55 justin_smith: Bronsa: it would be awesome if you did!

19:56 Bronsa: justin_smith: well CLJ-979 CLJ-1457 CLJ-1544 and CLJ-130 now all have patches. now I just need to convince puredanger to include them for 1.7

19:56 justin_smith: that's awesome

19:56 rritoch: That would require two sets, and possibly doing a double sweep

19:57 justin_smith: rritoch: how does one find a difference without having the previous result handy?

19:57 you need the old result no matter what

19:58 rritoch: I should be able to do loop [m #{} c (count m)] ... (recur (...) (count m)

19:58 justin_smith: I don't need the difference really, I just need to know if anything new's been added since the last loop, I really don't care what was added in each iteration

19:58 justin_smith: wait, what are you even trying to do?

19:58 OK, right, and in order to know if anything has changed, you need the previous result

19:58 and a new one

19:59 rritoch: Trying to get all deep namespace dependencies of the current namespace

19:59 From clojure first, then xlate it to java

20:00 justin_smith: I'm using a set though, since I'll only be adding to the set a count of the number of items in the set is sufficient to determine if anythings been added

20:00 justin_smith: OK, you still need to generate the set twice, and set/difference provides more information than count does

20:00 but whatever works

20:02 rritoch: justin_smith: This is actually a fairly common type of recursion, I'm surprised there's no utility that simplifies the process

20:03 This is probably a good case for a transducer though

20:04 My usual pattern for this case is to use (flatten (map ....)) when the function can produce a list that needs to be added

20:05 justin_smith: And I need that entire function repeated until it doesn't produce anything new

20:06 andyf: rritoch: This is what is used in the tools.namespace lib: https://github.com/clojure/tools.namespace/blob/master/src/main/clojure/clojure/tools/namespace/dependency.clj#L52-L63

20:06 rritoch: Actually, that isn't going to work. I can only check each namespace once, otherwise a race condition could turn this into an infinite loop

20:06 andyf: Checking that now ...

20:11 andyf: Yeah, that's good. I didn't think of mapcat

20:13 profil: How would I go about sorting a vector with maps by the length of one of the values? "[{:key '(1 2 3 4)} {:key '(1 2 3)}]"

20:15 andyf: profil: something like (sort-by (fn [x] (count (:key x))) my-vec)

20:15 justin_smith: &(sort-by (comp count :key) [{:key '(1 2 3 4)} {:key '(1 2 3)}])

20:15 lazybot: ⇒ ({:key (1 2 3)} {:key (1 2 3 4)})

20:16 profil: I dont understand the comp function, is it like haskell's (.)?

20:17 justin_smith: as opposed to ##(sort-by :key [{:key '(1 2 3 4)} {:key '(1 2 3)}])

20:17 lazybot: java.lang.ClassCastException: clojure.lang.PersistentList cannot be cast to java.lang.Comparable

20:17 justin_smith: profil: that sounds right. It is classical function composition like from math class.

20:18 profil: justin_smith: so your example is a function like "(count (:key X))" where X is the input?

20:18 justin_smith: right

20:19 profil: justin_smith: and if I wanted to sort by another value also, would this be correct "(sort-by (juxt (comp count :key) :otherkey) vector)"?

20:20 andyf: yep

20:20 profil: &(sort-by (juxt (comp count :key) :otherkey) [{:key '(1 2 3 4) :otherkey 10} {:key '(1 2 3) :otherkey 12}])

20:20 lazybot: ⇒ ({:key (1 2 3), :otherkey 12} {:key (1 2 3 4), :otherkey 10})

20:20 profil: alright, thanks guys

20:21 rritoch: andyf: It is really too bad that transitive function is private, this function would be good for clojure.core

20:22 andyf: You can use it even though it is private, e.g. (#'name.space/private-fn-name args)

20:23 or if your project has a compatible license, just copy the source code into it.

20:24 rritoch: Well, right now I'm just in repl so I'm just going to copy the source :)

20:29 I'm not sure how to test if it's working, but I think this worked

20:30 (defn direct-deps [ns] (into #{} (map #(.ns %) (filter var? (map second (.getMappings *ns*))))))

20:30 (transitive direct-deps (conj #{} *ns*))

20:31 As far as I can tell I think that gave me all of the dependencies (deeply)

20:31 justin_smith: ,(= (conj #{} *ns*) #{*ns*})

20:31 clojurebot: true

20:32 gfredericks: back to fun with regexes

20:32 ortuna: does clojure do cache/tail call optim. when calling a function in a look multiple times?

20:32 loop*

20:32 justin_smith: ortuna: well, recur is always a tail call

20:32 gfredericks: ortuna: probably not, but I can't tell what you mean so you might want to give an example

20:32 justin_smith: but it doesn't cache

20:32 rritoch: gfredericks: That is the first time I've heard anyone use the word fun and regex in the same sentance.

20:33 gfredericks: rritoch: I think I just learned that \Q...\E inside [...] is a NOOP

20:33 justin_smith: ortuna: you may want to memoize your function

20:36 ortuna: justin_smith: yes, was wondering if I need to do that. I have a function call to foo within a doseq. foo also calls a (.getWidth bufferedimage). Since bufferedimage is not different between each iteration will this be optimized? I know the proper thing to do is memoize it which I will do, but it made me wonder because the executing is very fast(not expected after ~ 130,000 calls).

20:37 justin_smith: ortuna: I would be surprised if .getWidth was doing any calculation at all

20:37 image formats hold their width as a static bit of data

20:37 it should be a simple lookup

20:38 there is an open source jdk (or you could just profile it) if you want to double check that though

20:39 ortuna: justin_smith: I'll take a look, still new to clojure so figuring the Clojure/Java world out :D

20:40 justin_smith: criterium is great for microbenchmarks like "how long does it take to run .getWidth on a BufferedImage"

20:40 $google clojure criterium

20:40 lazybot: [hugoduncan/criterium · GitHub] https://github.com/hugoduncan/criterium

20:40 ortuna: oo thanks

20:40 justin_smith: I suggest having it as a dep in ~/.lein/profiles.clj so it's always available during dev

20:40 TEttinger: gfredericks: were you the one who asked about \pC in regexes?

20:44 gfredericks: TEttinger: yeah

20:45 TEttinger: it's a weird one huh. did you get my reply?

20:45 gfredericks: yep

20:45 I probably inc'd you too

20:45 TEttinger: haha thanks

20:46 gfredericks: (inc TEttinger) ;; for good measure

20:46 lazybot: ⇒ 32

20:46 TEttinger: those categories are mostly useful, but \pC matching \n but not \space is weird

20:46 danke

20:47 gfredericks: TEttinger: I'm trying to parse regexes and it's the hairiest thing ever

20:47 TEttinger: oh man

20:47 have you read the unicode standard yet?

20:48 it's only what, 2500 pages...

20:48 gfredericks: I'm about to try to figure out by exhaustive experimentation what '&' means inside [...]

20:48 TEttinger: nvm 1472 pages

20:49 it doesn't mean literal ampersand?

20:50 oh geez gfredericks http://www.regular-expressions.info/charclassintersect.html

20:52 gfredericks: TEttinger: exactly

20:52 oh crap I forgot to parse negation

20:52 TEttinger: &(re-seq #"[a-z&&[^aeiuo]]" "The quick brown fox")

20:52 lazybot: ⇒ ("h" "q" "c" "k" "b" "r" "w" "n" "f" "x")

20:53 gfredericks: negation makes intersection more interesting

20:53 TEttinger: &(re-seq #"[[^kq]&&[a-z]&&[^aeiuo]]" "The quick brown fox")

20:53 lazybot: ⇒ ("h" "c" "b" "r" "w" "n" "f" "x")

20:53 devn: gfredericks: did you know that in 1567 the man people claimed to have the longest beard in the world died by tripping over his own beard while running away from a fire?

20:54 gfredericks: devn: no

20:55 TEttinger: devn, glad my beard is trimmed then

20:55 devn: gfredericks: the hello world program you wrote earlier on twitter was really impressive

20:56 justin_smith: the rate of death by tripping and falling over things is my favorite counter-argument to over concern about things that are scary but statistically irrellevant

20:56 gfredericks: justin_smith: what is that rate?

20:57 justin_smith: http://www.cdc.gov/nchs/fastats/accidental-injury.htm

20:57 andyf: gfredericks: Aren't there existing libs that parse regexes you might use/

20:57 use?

20:57 clojurebot: Only use :use with :only.

20:57 devn: gfredericks: also, you forgot thong.

20:57 andyf: Seems like a lot of work to get all the cases right.

20:58 devn: gfredericks: wait, that's unvoiced.

20:58 profil: justin_smith: how do I say that I want to sort largest first in my last example?

20:58 gfredericks: andyf: this is difficult to google for because of all the people trying parse random things with regexes

20:59 another day, another person in #clojure telling me I forgot thong.

20:59 profil: &(sort-by (juxt :otherkey (comp count :key)) [{:key '(1 2 3 4) :otherkey 10} {:key '(1 2 3) :otherkey 12}])

20:59 lazybot: ⇒ ({:key (1 2 3 4), :otherkey 10} {:key (1 2 3), :otherkey 12})

20:59 justin_smith: profil: sort-by takes an extra comparitor function

20:59 (doc sort-by)

20:59 clojurebot: "([keyfn coll] [keyfn comp coll]); Returns a sorted sequence of the items in coll, where the sort order is determined by comparing (keyfn item). If no comparator is supplied, uses compare. comparator must implement java.util.Comparator. If coll is a Java array, it will be modified. To avoid this, sort a copy of the array."

20:59 profil: &(sort-by (juxt :otherkey (comp count :key)) > [{:key '(1 2 3 4) :otherkey 10} {:key '(1 2 3) :otherkey 12}])

20:59 lazybot: java.lang.ClassCastException: clojure.lang.PersistentVector cannot be cast to java.lang.Number

20:59 devn: gfredericks: im serious though, i was thoroughly impressed by your hello world implementation. "hi everyone" is one of the shortest I've seen in the wild.

21:00 profil: justin_smith: as you see I cant use '>'

21:00 justin_smith: profil: > is not a comparitor

21:00 andyf: http://weitz.de/cl-ppcre/

21:00 Common Lisp, but maybe useful.

21:01 justin_smith: &(sort-by (juxt :otherkey (comp count :key)) (comp - compare) [{:key '(1 2 3 4) :otherkey 10} {:key '(1 2 3) :otherkey 12}])

21:01 lazybot: ⇒ ({:key (1 2 3), :otherkey 12} {:key (1 2 3 4), :otherkey 10})

21:02 justin_smith: (comp - compare) reverses the default comparator

21:02 gfredericks: devn: it's the same length as "hello world"

21:02 profil: justin_smith: oh, thats handy

21:03 devn: gfredericks: yes, but "hi everyone" handles the printing too

21:03 gfredericks: andyf: and it would have to be a lib aimed at parsing JVM regexes in particular

21:04 justin_smith: profil: the trick there being compare always returns a number indicating which input was larger ##(compare [0 1 2] [1 2 3])

21:04 lazybot: ⇒ -1

21:04 justin_smith: &((comp - compare) [0 1 2] [1 2 3])

21:04 lazybot: ⇒ 1

21:05 justin_smith: (flip compare) would be good for that too, if we had flip in clojure.core

21:07 Shoop: I need some help implementing four-letter word ladders (http://en.wikipedia.org/wiki/Word_ladder) in clojure. I created a hashmap of dictionary words to appropriate peers that are also dictionary words. However, I'm having trouble figuring out how to implement depth-first search to find the shortest "ladder" between 2 four-letter words. Can anyone give me a hand?

21:13 gfredericks: Shoop: you want undirected graph algorithms

21:14 justin_smith: yeah, there is probably something in the gremlin lib that would just spit out the answer

21:14 gfredericks: probably breadth-first makes more sense

21:14 justin_smith: yeah, especially given the guaratneed ubiquity of cycles

21:19 gfredericks: ,#"[&&&a]"

21:19 clojurebot: #<NoClassDefFoundError java.lang.NoClassDefFoundError: Could not initialize class java.util.regex.PatternSyntaxException>

21:19 gfredericks: ,#"[a&&&]"

21:19 devn: is there a lib with A* in it already?

21:19 clojurebot: #"[a&&&]"

21:23 profil: justin_smith: that comparator will affect both sorts, I want to sort the shortest list but the highest number, how do I achive that?

21:29 devn: ah, i should have guessed! http://clj-me.cgrand.net/2010/09/04/a-in-clojure/

21:29 and another from aria over at prismatic: https://github.com/aria42/mochi/blob/master/src/mochi/search.clj

21:30 last one I promise: http://nakkaya.com/2011/10/10/cheaplist-in-clojure/

21:31 speaking of nakkaya, has that guy ever been to the conj or euroclojure or something? he's had an excellent blog with lots of clojure in it since 2009.

21:33 justin_smith: profil: in that case, I would use sort, and pass a comparator function that does the right thing to each arg

21:34 profil: justin_smith: I solved it by doing (comp - :otherkey)

21:34 justin_smith: ahh, since it's a number that works for that special case

21:40 TEttinger: devn, a friend helped me implement a sorta dijkstra-A* hybrid that operates on a plain array http://ideone.com/GsHXtz

21:40 andyf: gfredericks: devn: What is this hello world / hi everyone you speak of?

21:42 david6789: hello, I'm sorry the useless shill but I'm testing erc so Hello world!

21:42 TEttinger: hey david6789

21:42 it works

21:43 CaptainLex: What when did we start talking about A*

21:43 justin_smith: andyf: https://twitter.com/gfredericks_/status/541252661526659074

21:43 CaptainLex: that's the algorithm that was giving me trouble earlier!!

21:43 justin_smith: CaptainLex: Shoop wanted something that is solved with A*

21:44 but hey, it's a graph algorithm, they are everywhere when you know how to look

21:44 Shoop: :d

21:44 :d

21:44 :D

21:44 capitalization is hard when caps lock is on

21:44 CaptainLex: Haha

22:01 gfredericks: &#"x??"

22:01 lazybot: ⇒ #"x??"

22:01 gfredericks: &#"x???"

22:01 lazybot: java.util.regex.PatternSyntaxException: Dangling meta character '?' near index 3

22:01 gfredericks: I love these

22:15 amalloy: gfredericks: these what?

22:22 gfredericks: amalloy: weird characteristics of jvm regexes

22:26 amalloy: gfredericks: that's a totally normal behavior any regex would have, though?

22:26 not a jvm quirk at all

22:30 gfredericks: amalloy: I sure don't understand why; what's okay about two question marks but not okay about three?

22:31 amalloy: a ? character after a quantifier (ie, *+?{...}) makes it lazy instead of greedy

22:32 justin_smith: so ?? means 0 or one, lazy

22:32 ?

22:32 amalloy: &(for [re [#"bare?" #"bare??"], s ["bar" "bare"]] (re-find re s))

22:32 lazybot: ⇒ ("bar" "bare" "bar" "bar")

22:33 gfredericks: amalloy: okay, you win this round, but I've got more up my sleeve

22:33 amalloy: so they're both *willing* to match bar or bare, but with the second ? bar is preferred, whereas without it bare is preferred

22:33 gfredericks: &#"x*+"

22:33 lazybot: ⇒ #"x*+"

22:33 gfredericks: &#"x+*"

22:33 lazybot: java.util.regex.PatternSyntaxException: Dangling meta character '*' near index 2

22:33 * gfredericks stands back with his arms crossed, smirking

22:33 amalloy: gfredericks: + makes quantifiers possessive

22:33 gfredericks: CRAP

22:33 what does that mean

22:34 amalloy: it's harder to think of an example for that one :P

22:34 * gfredericks to the googlemobile

22:35 amalloy: &(for [re [#"x?xy" #"x?+xy"], s ["xxy" "xy"]] (re-find re s))

22:35 lazybot: ⇒ ("xxy" "xy" "xxy" nil)

22:35 amalloy: the optional+possessive ? in the second regex refuses to backtrack after consuming the first x

22:36 gfredericks: this is going to be exciting

22:37 amalloy: gfredericks: the only jvm regex quirk i can remember is #"[][]"

22:38 gfredericks: looks like a parse error?

22:38 &#"[][]"

22:38 lazybot: java.util.regex.PatternSyntaxException: Unclosed character class near index 3

22:38 amalloy: which is a perfectly valid character class matching any left or right square brakcet, but the jvm refuses it

22:38 gfredericks: amalloy: do other languages accept that?

22:38 amalloy: of course. perl does, any other pcre engine does

22:39 gfredericks: ruby doesn't

22:39 amalloy: the jvm is probably detecting a nested character class

22:39 amalloy: if you want to include a ] in a character class, the only way is to put it first

22:39 there's no such thing as a nested character class

22:39 * gfredericks whips out his smirk

22:40 amalloy: oh

22:40 ?

22:40 gfredericks: you can nest them and intersect them too

22:40 &(re-matches #"[a[b]c]" "]")

22:40 lazybot: ⇒ nil

22:40 gfredericks: &(re-matches #"[a[b]c]" "b")

22:40 lazybot: ⇒ "b"

22:41 gfredericks: &(re-matches #"[a-z&&[^aeiou]]" "b")

22:41 ,(re-matches #"[a-z&&[^aeiou]]" "b")

22:41 lazybot: ⇒ "b"

22:41 clojurebot: "b"

22:41 zarkone: hello all! i want to use REPL with ring/compojure applications.. How should I connect?

22:41

22:42 amalloy: gfredericks: i've never seen that in any regex flavor. is that a jvm thing, or what?

22:42 gfredericks: amalloy: regular-expressions.info claims that intersection is a java/ruby thing; I think that implies nesting too, cuz I'm not sure why else nesting is useful

22:44 amalloy: huh

22:44 gfredericks: I didn't know this two weeks ago either

22:44 amalloy: okay, i didn't know about this feature, but i don't see how it impacts the parsing of [][]

22:44 gfredericks: because the second [ starts a new class

22:44 amalloy: oh, because the open-bracket confuses it

22:45 gfredericks: interestingly ruby gives a different error

22:45 SyntaxError: (irb):3: empty char-class: /[][]/

22:45 amalloy: gfredericks: does it say the same for []]?

22:45 gfredericks: it also says: warning: character class has ']' without escape: /[][]/

22:45 /[]]/ just gives the warning

22:46 /[]/ also gives the empty char class error

22:47 amalloy: sure, [] is illegal

22:47 i can't remember what the "fix" is to get java to treat something like [][], except for the obvious one of throwing in some backslashes

22:47 but i'm pretty sure there is some mess of just square brackets that it understands

22:49 gfredericks: i think that weird java/ruby character-class intersection feature is the first thing i've learned about regular expressions in about eight years

22:51 gfredericks: amalloy: I wonder how many times somebody has abandoned their plans to use a regex after discovering that their language doesn't have character class intersections

22:51 * kenrestivo mutters something about jamie zawnski's famous quote

22:53 andyf: Regexes are cool, until you get to the dark corners. I tend to avoid them.

22:53 I mean: I tend to avoid the dark corners of regexes. The bright spots I love.

22:54 TEttinger: amalloy, lucky you, I probably learned about regexes 8 years ago

22:54 andyf: But I don't want to implement them over again.

22:55 amalloy: andyf: most under-appreciated bright spot: /x flag

22:58 rritoch: andyf: For this namespace isolation code I'm making, what is the best way of getting it to be reviewed. Should I make a fork on github?

23:00 andyf: It is almost functional. I created a namespace, returned to the user namespace, and entered into an isolation successfully. The namespace I created was no longer there, but everything else was still functional

23:00 andyf: THings broke down when I tried to leave the isolated namespace, but I'm repairing that bug now

23:01 gfredericks: &#"*"

23:01 lazybot: java.util.regex.PatternSyntaxException: Dangling meta character '*' near index 0

23:01 gfredericks: &#"{0}"

23:01 lazybot: ⇒ #"{0}"

23:02 gfredericks: ^ matches the empty string

23:05 those curly-bracket quantifiers can handle pretty much any digit string it looks like

23:05 I'm impressed

23:06 TEttinger: &(re-seq #"{3}" "")

23:06 lazybot: ⇒ ("")

23:06 rritoch: Ok, I have namespace isolation fully functional

23:06 TEttinger: nice rritoch

23:07 rritoch: This is the code http://pastebin.com/Lg59dMyN

23:07 fendgit: Could someone please help me by explaining the idiomatic way that I could assoc a new k/v into each 'people' object in this map? http://pastebin.com/VJ1QjHtc

23:07 What's throwing me off is that the people array is a few levels deep

23:07 rritoch: It only requires on change to the existing code, which is documented at the top of the code

23:08 fendgit: I'm not quite sure how to create an updated copy of the entire map

23:08 gfredericks: fendgit: look at assoc-in and update-in

23:08 justin_smith: fendgit: for one thing, that layout of the data structure is not idiomatic for clojure at all

23:08 but yeah, assoc-in is exactly what you want

23:09 fendgit: gfredericks: thanks, will check that out

23:09 justin_smith: what's wrong with the layout of it? I'm definitely open to suggestions :)

23:10 rritoch: (clojure.lang.NamespaceContainer/enter) enters and (clojure.lang.NamespaceContainer/exit) leaves. The enter returns a pointer which can be used to return to the namespace in the future after you exit, assuming you can find a way to get data between the isolated areas. Since this is new I'm not exactly sure how that would be accomplished, but probably requires enter/exit/stash/re-enter

23:12 justin_smith: &(update-in [{:data {:people [{:id 1, :projects [{:id 1, :hours 20}]}]}, :end_date "2014-12-14T05:00:00Z", :start_date "2014-12-01T05:00:00Z"}] [0 :data :people] conj {:id 2, :projects []}) ; fendgit

23:12 lazybot: ⇒ [{:end_date "2014-12-14T05:00:00Z", :start_date "2014-12-01T05:00:00Z", :data {:people [{:projects [{:id 1, :hours 20}], :id 1} {:id 2, :projects []}]}}]

23:13 TEttinger: fendgit, the main thing is it really doesn't look like clojure with a lone bracket on a new line. also, you can use #inst literals

23:13 justin_smith: fendgit: I realize now it's json, I had mistaken it for edn at first

23:13 fendgit: sorry guys, I should've mentioned that at first

23:13 (that it's being output as JSON)

23:13 TEttinger: oh ok

23:13 fendgit: I'm grabbing that from a Postgres JSON field

23:13 justin_smith: fendgit: yeah, I figured that out when I put together my example above

23:14 fendgit: and so I've got the person ID, but I need to insert the person's name in there as well

23:14 justin_smith: so yeah, your first step would be to use cheshire to turn it into clojure data

23:14 fendgit: I am sure you can extrapolate from what I pasted above (the update-in)

23:15 fendgit: justin_smith: thanks!

23:15 andyf: rritoch: If you want to get it reviewed, you can publish it and put a link and description on the Clojure Google group, for example. Unless it implements some feature that someone dearly wants, you may or may not get any response.

23:16 rritoch: andyf: By publish do you mean fork on github?

23:17 andyf: That is a pretty easy way to publish it, yes, but any method will do.

23:17 rritoch: andyf: Ok, I'll try that

23:17 andyf: If you want something considered for inclusion in Clojure itself, then you really need significant interest by many people, or at least a few in the Clojure core team would have to really want it.

23:18 gfredericks: oh man parsing octal digits is tricksy

23:18 rritoch: andyf: I know a lot of people have had issues creating isolation in clojure, typically they do it with classloaders/OSGi, but require a seperate runtime even for the same version. This makes it possible to create isolated environments in a single runtime so you only need one runtume per clojure version.

23:19 andyf: Many, many proposals for chages to Clojure have been made, as you might guess, but the majority are not of interest to the Clojure development team, for a variety of reasons.

23:19 rritoch: andyf: Exactly why I didn't want to waste my time writing this code in the first place

23:20 andyf: But that is also why I seperated it from clojure as much as possible, so I can carry it to any future version of clojure

23:20 andyf: A waste of time is in the eye of the beholder. Did you implement something that you will use yourself? Did you learn something you find valuable? Neither is a waste of time, I think.

23:21 If your only purpose in writing modifications of Clojure is to get them in the standard distribution, then checking whether they are of interest first is important.

23:21 rritoch: andyf: I implemented something that I'd like to use, but I have no interest in maintaining a fork of clojure. I'm developing an web application that uses OSGi and really needs this feature for stability though, so it is a catch-22.

23:23 andyf: There are people that use patched versions of Clojure, with particular modifications that they value highly, in multiple development teams. I think those tend to be fairly small modifications.

23:24 If you don't need/want the latest release of Clojure, then there is no need to port the modifications to every new Clojure version that is released.

23:25 gfredericks: Are you implementing a parser for Java regexes, or you also want to implement a regex matcher, too?

23:27 rritoch: andyf: Well, in my experience projects like this go like Minix, the features are extremly powerful and never made it back into the linux core

23:28 justin_smith: Minix was not a linux offshoot though.

23:28 pllx: rritoch: what was Minix

23:28 gfredericks: andyf: a generator actually; so the opposite

23:28 justin_smith: pllx: an academic project, and very loosely the basis for linux

23:28 andyf: a test.check generator?

23:29 gfredericks: andyf: but it might be hard to implement a generator without implementing a matcher at the same time :P

23:29 yes

23:29 rritoch: I am probably have the wrong name, but there is an alternative kernel other than linux that provides built-in clustering

23:29 pllx: justin_smith: linux precursor

23:29 justin_smith: hurd?

23:29 right

23:29 rritoch: Not only did it fork from linux, I think it eventually forked from itself

23:29 andyf: gfredericks: Perhaps you could implement something that doesn't know about *every* corner case, and filtered them through the Java regex parser to eliminate bad ones?

23:29 justin_smith: hurd isn't a linux fork, it's an alternate kernel with a completely different architecture

23:30 andyf: Just brainstorming there. Might not be useful.

23:31 rritoch: Err: sorry, wrong name, its MOSIX http://fixunix.com/minix/523588-turn-minix-distributed-operative-system.html

23:31 gfredericks: andyf: yeah I've thought of a few different punting tactics; I'm still having fun though so haven't resorted to those yet

23:31 andyf: You want to use test.check to look for bugs in ... what?

23:31 rritoch: err wrong link

23:31 http://en.wikipedia.org/wiki/MOSIX

23:32 gfredericks: andyf: nothing in particular, it's just possible it'll be useful and a heck of a lot of fun to do

23:32 justin_smith: rritoch: mosix is a distributed system you can make out of multiple linux boxes. It's cool, but it's not a linux alternative, it's a way to coordinate multiple linux machines.

23:32 andyf: gfredericks: Reason enough.

23:32 rritoch: justin_smith: It is a linux alternative, the kernel is a fork of linux

23:33 justin_smith: This has been around a long time, every so often they have merged in new linux kernels, but for the most part it's incompatible with linux

23:33 gfredericks: andyf: wouldn't be surprised if steve miner would use it in herbert in place of re-rand

23:35 andyf: gfredericks: I can't recall why right now, but I was delving into some of the details of the Unicode regex details a year or two ago, probably because I was learning about Unicode for the first time, and it is staggering to me the effort that Tom Christianson put into Perl regex implementation and testing.

23:36 rritoch: justin_smith: Either way, since this never merged back with linux the hardware compatiblity is garbage, and because linus didnt merge this code in, linux still to this day doesn't have decent clustering.

23:37 I suppose it doesn't matter to the people who can just buy dedicated hardware, but to those scrapping together a cluster it's a problem.

23:37 justin_smith: rritoch: back when mosix was open source, I used a distro that shipped with the mosix stuff, I did not realize it was more than a driver module

23:37 gfredericks: andyf: being able to use test.check to compare with the existing jvm impl is pretty easy and powerful

23:37 rritoch: Anyhow, sorry for going so off topic

23:37 justin_smith: in terms of the kernel modifications that is

23:39 andyf: You have probably seen this: http://en.wikipedia.org/wiki/Comparison_of_regular_expression_engines

23:40 rritoch: Either way, I'll go the fork route and see how that goes, but this namespace isolation is extremly useful for modularizing clojure applications to ensure there aren't namespace conflicts.

23:40 andyf: Holy crud. Some regex engines implement a feature called there "recursion". Scary.

23:42 gfredericks: that was a new feature in some ruby version wasn't it?

23:43 andyf: I like my regexes the way God and Kleene intended them: recognizable by a finite state machine.

23:43 tbaldrid_: .NET had a feature like that too

23:44 gfredericks: andyf: I think there are milder features than recursion that make them non-regular

23:44 backreferences I think

23:44 andyf: (Disclaimer: andyf is not a recognized spokesman for either God or Kleene, and hasn't discussed the matter with either of them)

23:44 definitely, and I don't think I've ever used those features, either :)

23:44 gfredericks: ~andyf is not a recognized spokesman for either God or Kleene, and hasn't discussed the matter with either of them

23:44 clojurebot: In Ordnung

23:45 gfredericks: yeah I think #"(a*)b*\1" is non-regular

23:46 andyf: I'm imagining some grumpy old man shooing kids off his lawn while yelling at them to use context-free grammars for such things.

23:47 justin_smith: Spock saying "this grammar is highly non-regular, captain"

23:48 gfredericks: help I'm about to try to figure out what #"\11" means

23:49 andyf: gfredericks: Back away from the ledge!

23:49 gfredericks: yep; it's context sensitive

23:50 this is so impossible to do with instaparse

23:50 andyf: oh, you meant you wanted help understanding how it was interepreted by the regex engine. I misunderstood.

23:50 rritoch: andyf: I built the fork, any idea how to switch the remote to the fork so I can commit and upload?

23:50 andyf: I tried git remote set-url but its not working

23:51 andyf: Ok got it... It was git remote set-url origin ...

23:51 gfredericks: andyf: oh no you had the right kind of help

23:52 andyf: GitHub tends to have nice Google-searchable documentation for many such things. I do it rarely enough that I tend to assume it is only possible if you fork first, clone the fork, commit, and then push. At least, I know that will work.

23:53 gfredericks: man that really is hard to do without state in your parser

23:53 justin_smith: when I decide one of my git repos is ready for github, I create the github repo, then "git remote add origin <git uri>"

23:53 gfredericks: I think #"\7" matches nothing

23:54 justin_smith: so what exactly does #"\1" match?

23:55 gfredericks: the same I assume

23:55 I just like 7 better

Logging service provided by n01se.net