#clojure log - Jul 08 2014

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

0:02 TEttinger: ,(find-doc #"ns-")

0:02 clojurebot: -------------------------\nclojure.core/ns-aliases\n([ns])\n Returns a map of the aliases for the namespace.\n-------------------------\nclojure.core/ns-imports\n([ns])\n Returns a map of the import mappings for the namespace.\n-------------------------\nclojure.core/ns-interns\n([ns])\n Returns a map of the intern mappings for the namespace.\n-------------------------\nclojure.core/ns-map\n([n...

0:02 TEttinger: ##(find-doc #"ns-")

0:02 lazybot: java.lang.RuntimeException: Unable to resolve symbol: find-doc in this context

0:02 TEttinger: hm

0:02 ##(find-doc find-doc)

0:02 lazybot: java.lang.RuntimeException: Unable to resolve symbol: find-doc in this context

0:02 TEttinger: ##(find-doc "find-doc")

0:02 lazybot: java.lang.RuntimeException: Unable to resolve symbol: find-doc in this context

0:02 TEttinger: what

0:02 Frozenlock: lol

0:02 TEttinger: ,(find-doc "find-doc")

0:02 Frozenlock: of course :-p

0:02 clojurebot: -------------------------\nclojure.repl/find-doc\n([re-string-or-pattern])\n Prints documentation for any var whose documentation or name\n contains a match for re-string-or-pattern\n

0:03 TEttinger: ##(clojure.repl/find-doc #"ns-")

0:03 lazybot: ⇒ ------------------------- findfn.core/*ns-set* A set of namespaces where find-fn will look. ------------------------- clojure.main/main ([& args]) Usage: java -cp clojure.jar clojure.main [init-opt*] [main-opt] [arg*] With no options or args, runs an interacti... https://www.refheap.com/87959

0:03 * Frozenlock wants clojure.repl to be in every namespaces

0:03 TEttinger: well now you have the full link

0:04 lazybot may not include clojure.repl by default, but it does use refheap, and refheap is wonderful

0:04 Frozenlock: Pfff, I'm not going to type clojure.repl/find-doc

0:05 How can a bot use refheap? What's the use case?

0:05 TEttinger: ##(clojure.repl/find-doc #"clojure.core/ns-")

0:05 lazybot: ⇒ nil

0:05 TEttinger: ##(clojure.repl/find-doc #"clojure.core.ns-")

0:05 lazybot: ⇒ nil

0:05 TEttinger: hm

0:06 ,(doc "find-doc")

0:06 clojurebot: #<ClassCastException java.lang.ClassCastException: java.lang.String cannot be cast to clojure.lang.Symbol>

0:06 TEttinger: ,(doc find-doc)

0:06 clojurebot: "([re-string-or-pattern]); Prints documentation for any var whose documentation or name contains a match for re-string-or-pattern"

0:06 TEttinger: oh come on

0:06 then why do lazybot and clojurebot print different things

1:24 seancorfield: Is it my imagination or has this channel gotten a LOT quieter in the evenings than it used to be?

1:37 hellofunk: seancorfield it is likely your imagination.

1:44 seancorfield: hellofunk perhaps... but only two messages in an hour and change? used to be conversations all the time in the evenings...

1:44 Frozenlock: I have the same impression

1:44 Summer, maybe?

1:48 devn: seancorfield: pay no mind

1:48 seancorfield: everyone who used to peep late at night is now employed :)

1:49 Frozenlock: clojure ain't cool anymore

1:51 * hellofunk bangs lots of pots and pans around, smashing them into windows, tipping over imacs

1:51 hellofunk: wow, it's loud in here. too much activity

1:57 seancorfield: devn you might have a good point there

1:57 i'm kind of a night owl so i'm always online

1:58 but it may be that many of the old guard are now doing Clojure all day and don't bother with IRC at night?

1:58 hellofunk: anyone who uses Om, is there any reason why I couldn't put the Om atom in a separate namespace? there's no reason it must be in the same namespace as the Om root, right?

1:58 seancorfield: hmm, can't think of a reason hellofunk

1:58 ttasterisco: hellofunk: right

1:58 cj3kim: hello

1:59 ttasterisco: plus you can have multiple roots

1:59 hellofunk: ok

1:59 cj3kim: Question.

1:59 seancorfield: cj3kim yay! a discussion!

1:59 cj3kim: I have some software written in clojure that I would like to expose as an API on my node js server. Is this possible?

2:00 hellofunk: from a performance question (and i'm using cljs) if you reset! an atom map but only one item changes, would this have similar performance as just swap! with an assoc? are reset! and swap! mainly syntactic tools, or do they affect performance as well?

2:01 cj3kim: Anything is possible, but would there be a lot of effort in comparison to writing the server in clojure?

2:02 seancorfield: cj3kim not quite sure i understand what you're asking - sounds like you want to call from node.js to clojure/java?

2:02 cj3kim: seancorfield: yes

2:02 I want to take data from a POST request in node and pass it onto a clojure process

2:02 in the background.

2:03 seancorfield: spinning up a web server in clojure is pretty easy tho'... do you just want to expose your clojure stuff as a REST API?

2:03 why use node.js?

2:04 Frozenlock: cj3kim: I'd keep the clojure stuff in its own server... less stuff to debug if something goes wrong.

2:04 Frozenlock rule n.634: everything goes wrong.

2:04 seancorfield: yeah, exposing the Clojure stuff with its own REST API sounds simpler

2:04 cj3kim: hmmr, okay

2:05 thanks for the opinion :)

2:06 seancorfield: cj3kim the real question is probably more around how you'd handle responses and the async aspects of node.js in that context

2:07 cj3kim: seancorfield: I'm used to coding on Node.js, which is why the thought occurred.

2:07 Frozenlock: cj3kim: http://clojure-liberator.github.io/liberator/ makes thing even easier

2:08 cj3kim: Frozenlock: thank you

2:10 hellofunk: i'm guessing a reset! still takes advantage of persistent structures to minimize value changes so it would be similar overhead as a swap!

2:10 cj3kim: quick question, i'm doing a math heavy start-up with a friend. if necessary, could I pay one of you guys to refactor some areas of my code? ( I'm not the best at clojure)

2:16 Frozenlock: cj3kim: I'm sure you can find someone good with clojure/java math operations, but you would probably have a better luck in the americas-day-hours

2:23 mange: hellofunk: From what I understand reset! just changes the pointer inside the atom. It won't do anything magical if you've constructed an entirely separate object.

2:24 cj3kim: Frozenlock: Thanks. I will take that into account.

2:43 Frozenlock: seancorfield: Have you tried TokuMX http://www.tokutek.com/products/tokumx-for-mongodb ? (No question in particular, I'd just like your opinion if you have one)

2:44 seancorfield: Haven't looked at it Frozenlock

2:49 Frozenlock almost sounds too good to be true :) i'll have to take a look at that...

2:50 Frozenlock: seancorfield: Yeah, if it had geospacing I'd be all over it.

2:51 Keep me posted on your findings :-p

2:52 seancorfield: Frozenlock we're already relying heavily on some MongoDB 2.4.x stuff so I don't know how compatible TokuMX would be...

2:53 but i'll try it out

3:31 ttasterisco: seanaway:

3:31 hey, I think it's just your imagination https://github.com/ttasterisco/is-it-seancorfields-imagination-

3:50 evanmorgan: hello

4:18 sm0ke: how do i specify a classifier in lein?

4:19 i have 2 profiles and i want that when i do `lein with-profiles +pro1` it installs with a classifier prfo1

4:22 isnt there something like :classifier ?

4:26 otfrom: ANN: London Unconference on 24 July: Sign up here: https://www.eventbrite.co.uk/e/london-clojure-unconference-2014-tickets-5542965158

4:27 and good morning

4:30 kap: hello guys, i want to write a simple client/server in clojure

4:30 i am a super-beginner

4:31 the client part fetches a json and stores to couchdb

4:31 the server exposes a restful api

4:31 i was thinking of using Liberator for the server side

4:32 I was thinking of separating client (batch download and store)

4:32 and server

4:33 but i would like to share some memory between the two for quickly exposing freshly downloaded data from the client

4:33 there will be two processes then

4:33 is there a way to handle intra-processes data in clojure?

5:07 jonathanj: wouldn't it make sense to write the client and server as though they're on the same network (instead of the same computer)?

5:12 rurumate: how to wrap rabbitmq channel into core.async channel?

5:14 this is what I have so far, but q-chan is read-only and closes after one message: https://www.refheap.com/87966

5:14 is it possible to make q-chan an unlimited async channel that works "over the wire" ?

5:23 *to make q-chan return an r/w async.channel that you can take! from and put! into, as well as use <! and >!, and which delegates to lb/publish and lc/subscribe

5:32 kap: @joanathanj and send json from server to client when i need to fetch fresh data without passing from the db?

5:33 rurumate: In order to get rid of a callback, it's common to return a new channel that will receive a value, i.e. it's supposed to be take!n from. Is is also possible to create / return a channel that "listens" on a put! ?

5:34 kap: @jonathanj and send json from server to client when i need to fetch fresh data without passing from the db?

5:35 jonathanj: kap: i'm not exactly sure what you're asking, but presumably you know how to write network software

5:36 kap: :) i was thinking of having client and server on the same machine and share some memory intra-process instead of intra-network ;)

5:36 and wondering if there is a lib in clojure to do that...like osgi that can share memory between plugins

5:46 rurumate: oh I think I get it. just attach a taker on the channel before returning it

5:59 AeroNotix: hmm, clojure-mode doesn't seem to be highlighting properly any more. I updated it.

5:59 anyone else see this?

7:17 hellofunk: AeroNotix haven't updated in a while

7:36 mbac: hey what's something that always trips up noob programmers. so far i've got tabs vs. spaces and merge conflicts.

7:36 AeroNotix: the fact that all development is basically shovelling shit from one toilet to another

7:36 borkdude: complexity

7:39 mbac: AeroNotix: too real

7:41 koreth__: Novices get way too hung up on programming language selection in my experience. It matters, but it is not the initial decision whose lack of answer should block one from thinking about any other aspect of the problem.

7:43 (But maybe that's more abstract than what you wanted; not on the same level as tabs vs. spaces.)

7:46 wink: people ranting about languages if they haven't used more than 2

8:03 Glenjamin: mbac: mixing levels of abstraction within the same procedure

8:13 TimMc: mbac: The idea that all software is infinitely mutable, unlike hardware.

8:13 ("I'll just go and fix this" and then the sweater unravels.)

8:19 rurumate: AeroNotix: will clojure-mode highlight #_ comments correctly now?

8:20 AeroNotix: rurumate: didn't check

8:20 rurumate: in what way? Doesn't seem to do anything right now

9:23 TimMc: OK, free project idea: Given two git commits, display a namespace diff graph that shows which namespaces have been deleted, edited, or added by decorating the lines and boxes. https://github.com/timmc/nephila would be a good starting point.

9:28 rurumate: AeroNotix: right, doesnt't do anything, it should be red like a comment no?

9:29 hyPiRion: TimMc: (merge nephila codeq) ?

9:29 rurumate: AeroNotix: counterclockwise highlights it like a ;; comment

9:29 AeroNotix: I dunno, I'm sure your colours are different but still -- it does nothing right now

9:29 rurumate: it _should_ do something

9:31 TimMc: hyPiRion: whoa

9:32 hyPiRion: ...and then make a github web hook that generates the graph and uploads it as a comment to the pull request.

9:39 Glenjamin: is there a way to make clojure(script) throw away the tail of a list?

9:40 at the mo i'm doing (-> xs (conj x) (take 1000))

9:40 ssideris: Glenjamin: butlast

9:40 hm, sorry I don't think that's what you need

9:42 bacon1989: ping

9:53 TimMc: borkdude: PONG

9:53 bah

9:53 bacon1989: PONG

9:54 borkdude: Sorry, tab-completion + moderate latency.

9:59 hellofunk: i have a bunch of key value pairs where i will often need to look up one based on the other, thus sometimes it is the key I want when I search for the value. is there a better way to do this than have 2 separate maps with the keys and values switched?

10:04 cursork: hellofunk: 2 maps *might* maybe work. Are you prepared for multiple keys being returned by a lookup on one value though?

10:07 hellofunk: cursork so actually in my scenario both the keys and the values will always be unique

10:08 cursork besides, if i was storying one map's values as another map's keys, i wouldn't have multiple values or multiple keys anyway, since you can't have two identical keys in a hash-map

10:10 borkdude: why is clojuredocs still based on clojure 1.3 and is there a better newer alternative?

10:10 Kneiva: any idea why lein repl fails to start under cljs project? error message is: Error: Could not find or load main class clojure.main

10:10 Exception in thread "Thread-4" clojure.lang.ExceptionInfo: Subprocess failed {:exit-code 1}

10:11 if I go to parent directory lein repl works as expected

10:13 koreth__: borkdude: I use the Clojure cheat sheet at http://clojure.org/cheatsheet -- it links directly to the official Clojure docs for stuff that was added after 1.3, but to ClojureDocs for older stuff.

10:14 ddellacosta: hellofunk: I would just use group-by val, then you can directly access the values as hashmap keys

10:14 &(get (group-by val {:foo "foo" :bar "bar"}) "foo")

10:14 lazybot: ⇒ [[:foo "foo"]]

10:14 bacon1989: question for you guys regarding InputStream, how would I pass into the InputStream.read(...) command? it's expecting a byte array as the first parameter, which appears to be passed by reference

10:14 which doesn't make sense in the java world, and even less sense in the clojure world

10:14 koreth__: There was an effort to rework ClojureDocs to make it more capable (and bring it up to date) but as far as I can tell that effort has been completely stalled out for quite a while now.

10:14 bacon1989: unless i'm supposed to use transients?

10:15 ddellacosta: bacon1989: slight digression but have you taken a look at clojure.java.io? https://clojure.github.io/clojure/clojure.java.io-api.html

10:17 TimMc: hellofunk: Google Guava has BiMap, but it's not persistent. (Might be immutable, at least...)

10:18 cursork: hellofunk: No problem. I've just seen people make naive hashmap-reversing functions and end up in trouble

10:19 bacon1989: ddellacosta: interesting, but this is essentially creating a Java InputStream

10:21 doesn't appear to be any clojure methods here that jump out at me, how do I get data out of my input stream?

10:23 this is frustrating to no end, every single reader tries to read a file line-by-line, what if I have a constant 5mb binary? there are no lines!

10:23 ToxicFrog: bacon1989: clurp?

10:23 slurp, rather?

10:23 bacon1989: you mean slurp?

10:23 same problem, I feel like the implementation uses line-seq

10:24 because it only reads the first 5000 chars

10:24 ToxicFrog: It does?

10:24 bacon1989: testing using a web browser produces the correct results

10:25 hmm.. maybe it doesn't

10:25 appears to create a stringbuilder, and .read into it

10:25 hmm...

10:25 ToxicFrog: huh

10:26 user=> (let [s (slurp "/tmp/8M")] (.length s))

10:26 1048576

10:26 That's not the same result you're seeing, but it's not even slightly correct either

10:26 bacon1989: strange

10:27 andyf: bacon1989: Use Java read methods that work on InputStream objects using Java interop expressions: http://docs.oracle.com/javase/7/docs/api/java/io/InputStream.html

10:27 ToxicFrog: Oh wait, no

10:27 I typoed the invocation of dd

10:27 user=> (let [s (slurp "/tmp/8M")] (.length s))

10:27 8388608

10:27 WFM

10:27 joegallo: heh, good ol' disk destroyer

10:28 andyf: koreth_: The effort to rewrite ClojureDocs in Clojure (rather than the original Ruby implementation) is active recently: https://github.com/zk/clojuredocs/commits/clj-rewrite

10:28 bacon1989: I have something like this ToxicFrog http://pastebin.com/qNWRbhM5

10:28 output is: 1551324 2649

10:29 andyf: borkdude: If you don't want to wait for ClojureDocs to update (assuming it will), you can also try Grimoire: http://www.arrdem.com/grimoire/ https://github.com/arrdem/grimoire

10:29 bacon1989: content-stream is an EOFSensorInputStream from the org.apache.comm.http class, etc

10:30 borkdude: andyf thanks

10:30 andyf: Grimoire is not as quick & simple to add/edit examples as ClojureDocs is, though.

10:30 bacon1989: is clojuredocs sortof set up like a wiki?

10:31 andyf: bacon1989: yes

10:31 bacon1989: but based on a custom implementation of its own, AFAIK, not some widely used wiki software

10:35 Bronsa: ouch clojuredocs still links to clojure contrib :(

10:35 sdegutis: i made a wiki that has updated clojure docs, and imported all clojuredocs.org examples to it

10:35 and updated it for clojure 1.5.1

10:35 and people were like "screw you" so i deleted it.

10:39 bacon1989: why does this have to cause me so much grief

10:41 sdegutis: :)

10:41 bacon1989: grief is for when someone close to you dies

10:41 bacon1989: github wikis are for when you have a project that needs extra room for user-editable docs

10:42 bacon1989: my inputstream is something close to me, he just won't do what he's supposed to do

10:42 I think I might have to put him down

10:42 like an old dog

10:42 andyf: bacon1989: Have you tried Java .read ?

10:42 with a specified buffer size?

10:44 bacon1989: andyf: does such a method exist? there appears to be only a .read(), and a .read(buf[]), which puts values into buf[]

10:44 which i have no idea how to implement in clojure, do I use transients?

10:45 slurp is implemented to .read()

10:45 it stops at the first negative input, as outlined in InputReader, is it getting a false negative?

10:47 pandeiro: i would like to use midje for e2e testing with webdriver as a standalone program (ie, testing an environment, not a particular project's code base) - is this possible? advisable?

10:47 i just tried to use it inside a -main function and got Exception in thread "main" java.lang.ExceptionInInitializerError

10:47 andyf: sorry, busy there for a bit

10:47 .read(buf[]) is what I meant

10:48 pandeiro: i'm thinking i must have failed to initialize midje in some way

10:48 andyf: (byte-array 50) create a byte[] with length 50

10:50 pandeiro: i found this from 2011: https://github.com/marick/Midje/issues/12

10:51 or maybe my issue is with aot (i am using the standard `lein new app` boilerplate) but i understood i will need that in order to work with an uberjar

10:54 hm, looks grim: http://stackoverflow.com/questions/23018826/clojure-midje-using-aot-compilation-with-tests-inside-source-fails-to-run

11:03 andyf: bacon1989: In case you are still looking for a working example, read this: https://gist.github.com/jafingerhut/1c61ec6b99a7656895e0

11:07 bacon1989: thanks andyf, i'll give this a shot

11:13 andyf same results

11:14 it still maxes out at 2600 bytes

11:18 andyf: bacon1989: You mean it prints out one line that shows it reading 2600 bytes, or it prints out many lines saying it read that many?

11:18 (assuming you left the debug println in there)

11:18 bacon1989: andyf: I changed it to a bufsize of 512, and it prints out several reads

11:19 Read 512 bytes

11:19 Read 512 bytes

11:19 Read 512 bytes

11:19 Read 512 bytes

11:19 andyf: All of them max size except the last one?

11:19 bacon1989: Read 512 bytes

11:19 Read 89 bytes

11:19 1551324 2648

11:19

11:19

11:19 andyf: What is the size of the file you are reading?

11:19 bacon1989: 1551324

11:20 at least that's what the http-response says, but I know it's that big

11:20 andyf: no exception thrown?

11:20 bacon1989: nope

11:20 i feel like my client settings might have something to do with it, that's just a guess though

11:21 andyf: The InputStream is created from what?

11:21 bacon1989: it's created from the entity

11:21 ndaly: so I've been out of Java for a while, and now when I look around I keep seeing @stuff

11:21 wondering what it meant, I did a quick search

11:21 this reads like satire: http://docs.oracle.com/javase/1.5.0/docs/guide/language/annotations.html

11:21 bacon1989: andyf: http://pastebin.com/iC4zT9Ar

11:22 on line 7

11:22 this has worked just fine on every other call i've been making

11:23 but they've all been below the given length

11:23 I think I might start sending fake lengths, and see when the cutoff happes

11:23 *fake data of different lengths

11:25 andyf: I don't know what is going on there. I tested the code on some files on disk opened as InputStream, and it worked as expected. I would guess either the larger number is wrong, or the Java objects there are returning an InputStream that cuts off early for some buggy reason, but that is just guessing on my part.

11:28 bacon1989: yeah idk, it fails when I send a base64 Byte[2048]

11:28 this is rediculous

11:38 think I just figured it out!

11:38 http://stackoverflow.com/questions/6585191/string-that-came-as-http-response-cut-off-java-platform-android-3-0

11:39 haven't tried it yet, but I know i'm closing it partway through the request

11:41 that was it

11:42 ugh, what a pain in the butt

11:45 thanks for the help andyf, and ToxicFrog

12:00 TimMc: ndaly: How so?

12:17 Frozenlock: "If you operate a commercial Web site or online service that collects personally identifiable information through the Internet about individual consumers residing in California who use or visit your website, your Privacy Policy must be California Online Privacy Protection Act compliant." California jurisdiction: the world!

12:22 verma: is there something like clj->js for clojure that converts a clojure object to a java object ... e.g. a hashmap to java Map<>

12:23 sritchie: verma: you can just pass it to the map constructor, I believe?

12:23 verma: yeah, but I was wondering if there's something more flexible .. converts array to ArrayList e.g. as well

12:23 sritchie: verma: (java.util.HashMap. {“a” 1 “b” 2})

12:24 verma: sounds like a pretty easy protocol to write

12:24 I don’t think clojure has that, though, no

12:24 verma: why would you want to do that?

12:24 verma: the data structures conform to java interfaces

12:25 verma: why program against the specific java data structures when you could just use the interface, and keep the code nice and abstract

12:25 verma: sritchie, I want to push java objects to firebase, for http://github.com/verma/pani

12:25 sritchie, you're right, I haven't really tried pushing stuff directly, may be that'll just work :)

12:25 sritchie: yeah, give it a try

12:28 ndaly: TimMc: "Annotations do not directly affect program semantics, but they do affect the way programs are treated by tools and libraries, which can in turn affect the semantics of the running program."

12:29 does it seem like a good idea to add something to a language that officially makes it so you can't tell what the code will do by just reading it?

12:29 TimMc: ndaly: Ah, yeah, that's a pretty good line.

12:29 Glenjamin: you mean like macros?

12:29 :p

12:29 ndaly: Glenjamin: point taken :)

12:30 verma: sritchie, worked for maps :P trying other things

12:30 ndaly: Glenjamin: but annotations make me want to kill myself, and macros don't, so maybe I'm biased

12:31 gfredericks:

12:31 has anybody worked on getting the new lein-release feature to create tags and/or gsub the README?

12:31 TimMc: ndaly: Actually, it changes the behavior of *other* code, not the marked code -- unless you're bringing in bytecode weaving and other freaky things.

12:32 ndaly: bytecode weaving sounds like dark magic

12:32 TimMc: It allows you to inject behaviors into the code. :-/

12:33 ndaly: See https://code.google.com/p/gag/ for some horrifying examples.

12:34 Oh, I guess that's bytecode instrumentation, which is maybe different?

12:35 Glenjamin: @Roulette is awesome

12:38 jcromartie: any tips on troubleshooting startup times?

12:38 sometimes it takes ages to start a REPL

12:38 TEttinger: drip?

12:38 jcromartie: sometimes not

12:39 TEttinger: $google clojure drip

12:39 lazybot: [Clojure · ninjudd/drip Wiki · GitHub] https://github.com/ninjudd/drip/wiki/Clojure

12:39 technomancy: clojurebot: faster?

12:39 clojurebot: It's greek to me.

12:39 technomancy: clojurebot: faster boot?

12:39 clojurebot: It's greek to me.

12:39 jcromartie: I don't want to work around a slow startup

12:39 I want to know why :)

12:39 TEttinger: Drip is a launcher for the Java Virtual Machine that provides much faster startup times than the java command. The drip script is intended to be a drop-in replacement for the java command, only faster.

12:39 jcromartie: I guess I could println in my namespaces

12:39 technomancy: clojurebot: faster boot is https://github.com/technomancy/leiningen/wiki/Faster

12:39 clojurebot: Roger.

12:40 jcromartie: this is weird

12:40 first time, I get an OOM

12:40 then it works fine

12:40 TEttinger: jcromartie, the JVM needs to load 32 MB of "kernel" into RAM before it can do anything

12:40 jcromartie: starting from Cider

12:40 TEttinger: and that always takes time it seems

12:40 jcromartie: yeah, I am not talking about regular Clojure startup time

12:40 I'm familiar witht hat

12:41 Jaood: TEttinger: I don't think the problem is the JVM, it already starts up fast

12:41 jcromartie: this particular app is obscene

12:41 vince___: Hi, all. I'm teaching myself clojure, and I got stuck on the following (I think basic) thingy. Its about applying map on a HOF. Example

12:41 (map + [1 2 3] [4 5 6]) -> (5 7 9)

12:41 but... (??? + [[1 4] [2 5] [3 6]]) -> (5 7 9)

12:41 justin_smith: there is no hof there

12:41 vince___: which function to use for ???

12:41 lazybot: vince___: Yes, 100% for sure.

12:42 justin_smith: oh, I see

12:42 TEttinger: ,(reduce + [[1 4] [2 5] [3 6]]) -> (5 7 9)

12:42 clojurebot: #<ClassCastException java.lang.ClassCastException: clojure.lang.PersistentVector cannot be cast to java.lang.Number>

12:42 TEttinger: hm

12:42 jcromartie: (partial apply map)

12:42 justin_smith: ,(map (partial apply +) [[1 4] [2 5] [3 6]])

12:42 clojurebot: (5 7 9)

12:42 jcromartie: ,((partial apply map) + [[1 4] [2 5] [3 6]])

12:42 clojurebot: (6 15)

12:42 jcromartie: oops

12:43 oh I see

12:43 vince___: let me try

12:43 cbp: map #(reduce + %)

12:43 justin_smith: ,(map #(apply + %) [[1 4] [2 5] [3 6]]) is better actually

12:43 clojurebot: (5 7 9)

12:44 justin_smith: cbp: apply + and reduce + do the same thing, but the former should be faster

12:44 vince___: (reduce + [[1 4] [2 5] [3 6]])

12:44 justin_smith: vince___: not quite

12:44 vince___: gives me ClassCastException clojure.lang.PersistentVector cannot be cast to java.lang.Number

12:45 the one with map and apply works!

12:45 next step is to figure out why it works, but I consider that as an assignment :)

12:45 justin_smith: ,(map #(reduce + %) [[1 4] [2 5] [3 6]])

12:45 clojurebot: (5 7 9)

12:46 vince___: (map #(reduce + %) [[1 4] [2 5] [3 6]]) also work

12:46 thank you, justin_smith

12:46 justin_smith: vince___: if you look at the source for +, you will see why they both work :)

12:46 $source +

12:46 lazybot: + is http://is.gd/zSqIg7

12:46 Bronsa: justin_smith: reduce is actually faster

12:47 justin_smith: Bronsa: oh, interesting

12:47 I guess because of the arity dispatch overhead?

12:47 Bronsa: proably, I never investigated though

12:47 justin_smith: $source apply

12:47 lazybot: apply is http://is.gd/ffhNFw

12:48 justin_smith: maybe the overhead of apply

12:49 bacon1989: question: how do I slice an java array in clojure?

12:49 Bronsa: justin_smith: sorry I misunnderstood what you said before, arity dispatch is negligible, it's definitely because of apply overhead

12:50 justin_smith: apply has to count the args

12:53 vince___: is (map (partial reduce +) [[1 4] [2 5] [3 6]]) exactly the same as (map #(reduce + %) [[1 4] [2 5] [3 6]]) ?

12:53 hellofunk: ddellacosta thanks for group-by suggestion

12:54 gfredericks: vince___: it has the same return value, yeah

12:54 Bronsa: vince___: partial has some overhead over #()

12:55 vince___: okay, thanks

12:55 gfredericks: stack traces can be slightly less helpful with point-free style

12:58 rurumate: ok this seems to work; it's the langohr "getting started" example, with a touch of component and async: https://www.refheap.com/87981

12:59 not sure if doing it right

13:02 cespare: If you have (defrecord R [^String s]), if you have R in a macro, is there any way to get at the fact that s is type-hinted as a String?

13:02 Fare: wow, while reading the python grammar, I realized it has limited destructuring in its arguments, too

13:03 gfredericks: ,(defrecord R [^String s])

13:03 clojurebot: sandbox.R

13:03 gfredericks: ,(-> ->R meta :arglists)

13:03 clojurebot: nil

13:03 gfredericks: ,(-> #'->R meta :arglists)

13:03 clojurebot: ([s])

13:03 gfredericks: ,(-> #'->R meta :arglists ffirst meta)

13:03 clojurebot: nil

13:03 cespare: exactly :)

13:03 gfredericks: cespare: looks bleak

13:03 ,(->R 42)

13:03 clojurebot: #sandbox.R{:s 42}

13:04 gfredericks: that hint is just for interop in the record's body?

13:04 cespare: gfredericks: what does that mean?

13:04 Bronsa: ,(defrecord X [^long x])

13:04 clojurebot: sandbox.X

13:04 Bronsa: ,(X. "")

13:04 clojurebot: #<ClassCastException java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Number>

13:04 Bronsa: I love how type hinting is not consistent at all

13:05 gfredericks: cespare: I'm wondering what you're using the type hint for

13:05 cespare: wait, that suggests that maybe I could use java reflection to get at the type maybe?

13:05 maybe maybe

13:05 heh

13:05 gfredericks: Bronsa: does non-primitive type hinting result in behavioral changes to non-interop code anywhere in clojure?

13:05 Bronsa: gfredericks: not that I'm aware

13:06 gfredericks: ,((fn [^long x] ['inc x]) "a string")

13:06 clojurebot: #<ClassCastException java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Number>

13:06 cespare: gfredericks: I have a fast record access macro so that (rget r :foo) will (a) raise a compile-time error if foo is not a field and (b) compile down to (.foo ^R r), which is the fastest kind of access

13:06 gfredericks: Bronsa: seems consistent to me then, at least keeping a primitives vs non-primitives distinction

13:06 cespare: gfredericks: I want to make a similar thing for nested records

13:07 gfredericks: cespare: ah ha.

13:07 cespare: I guess I can make my own defrecord wrapper macro that records more type information in metadata.

13:08 gfredericks: metadata on what though?

13:08 cespare: R?

13:08 gfredericks: that's a class

13:09 Bronsa: gfredericks: sure it's consistent between deftype and fn, not consistent between primitive/not-primitive hints though

13:09 gfredericks: Bronsa: yeah but that's kind of jvm style. primitives act differently from Objects

13:10 cespare: gfredericks: define an extra method on it?

13:10 like getBasis

13:10 i dunno.

13:10 Bronsa: cespare: you can use getBasis to retrieve the tag

13:10 cespare: Bronsa: but not the hinted type

13:10 gfredericks: ,(.getBasis R)

13:10 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: No matching field found: getBasis for class java.lang.Class>

13:10 Bronsa: (-> (R/getBasis) first meta)

13:10 ,(-> (R/getBasis) first meta)

13:10 clojurebot: {:tag String}

13:10 gfredericks: magic!

13:10 ,(class (R/getBasis))

13:10 clojurebot: clojure.lang.PersistentVector

13:11 cespare: Bronsa: hmm, thanks. I thought that was the first thing I tried.

13:12 how long does the state of clojurebot hang around?

13:12 gfredericks: ~10 min

13:12 clojurebot: excusez-moi

13:13 cespare: ,(def r (->R "hello"))

13:13 clojurebot: #'sandbox/r

13:13 Bronsa: lol.

13:13 gfredericks: clojurebot: 10 min is 0.6944 centidays

13:13 clojurebot: 'Sea, mhuise.

13:13 Bronsa: ,(set! *warn-on-reflection* true)

13:13 clojurebot: #<IllegalStateException java.lang.IllegalStateException: Can't change/establish root binding of: *warn-on-reflection* with set>

13:13 Bronsa: ff

13:13 cespare: Bronsa: ah, that's what I was gonna do.

13:13 Bronsa: ,*warn-on-reflection*

13:13 clojurebot: false

13:13 technomancy: gfredericks: over half a kilosecond

13:13 Bronsa: weell

13:13 anyway http://sprunge.us/YQUW?clj this is funny

13:14 cespare: ,(.startsWith (.s ^R r) "h")

13:14 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: r in this context, compiling:(NO_SOURCE_PATH:0:0)>

13:14 cespare: ah, wiped?

13:14 gfredericks: technomancy: 19 microyears!

13:14 cespare: anyway, how come the field type hint doesn't come through?

13:14 Bronsa: cespare: all fields are compiled to Objects

13:15 except for fields with primitive type hints

13:15 cespare: Why?

13:15 clojurebot: cespare: because you can't handle the truth!

13:15 gfredericks: clojure is a big fan of Object

13:15 cespare: I'm getting that :|

13:15 gfredericks: cespare: usually type hinting is just used for avoiding reflection

13:16 not for affecting other parts of the byte code

13:16 primitives being the major exception

13:17 Bronsa: gfredericks: I find it ridiculous that we have to pay the price of a checkcast for every interop call & can't improve type inference just because the compiler likes to compile everything as an Object

13:17 gfredericks: ,(R/getFields)

13:17 clojurebot: #<CompilerException java.lang.RuntimeException: No such namespace: R, compiling:(NO_SOURCE_PATH:0:0)>

13:17 gfredericks: ,(.getFields R)

13:17 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: R in this context, compiling:(NO_SOURCE_PATH:0:0)>

13:17 gfredericks: ,(defrecord R [^String r])

13:17 clojurebot: sandbox.R

13:17 gfredericks: ,(seq (.getFields R))

13:17 clojurebot: (#<Field public static final clojure.lang.Var sandbox.R.const__0> #<Field public static final clojure.lang.Var sandbox.R.const__1> #<Field public static final clojure.lang.Var sandbox.R.const__2> #<Field public static final clojure.lang.Var sandbox.R.const__3> #<Field public static final clojure.lang.Var sandbox.R.const__4> ...)

13:18 gfredericks: ,(->> (.getFields R) (filter #(= "r" (.getName %))))

13:18 clojurebot: (#<Field public final java.lang.Object sandbox.R.r>)

13:18 gfredericks: Bronsa: that I cannot defend :)

13:18 silasdavis: I can extend an interface with a protocol, a protocol generates an interface, can I extend a protocol with another protocol?

13:22 gfredericks: silasdavis: I don't think so

13:23 silasdavis: does the interface generated have the same name as the protocol?

13:28 sm0ke: hurm

13:28 https://github.com/technomancy/leiningen/issues/1589

13:29 rurumate: ok now also made a github, it's been a productive day https://github.com/methylene/langohr-component-async

13:29 sm0ke: regarding this one..how do i have deployed jars renamed with the classifier name to coexist?

13:30 technomancy: sm0ke: it looks like the docs for that are missing. probably hugod knows; iirc he added that.

13:30 silasdavis: gfredericks, looks like you can: same name as the protocol, i.e. given a protocol:

13:30 my.ns/Protocol, an interface: my.ns.Protocol.

13:31 sm0ke: technomancy: let me put the comment on issue as well

13:32 technomancy: do you think the default behaviour should be to append -<classifier-name> to jar file?

13:33 technomancy: sm0ke: I think that's how it works

13:33 at this point you'd have to read the source of jar.clj

13:33 sm0ke: technomancy: ok so i can confirm this

13:34 putting :classifer "xyz" .. and grep xyz * in ~/.m2/.. shows classifier in the pom.xml

13:34 but the jar is always deployed with the same name

13:34 gfredericks: silasdavis: that's the interface though, not the protocol -- not everything that satisfies the protocol implements the interface

13:35 silasdavis: ah

13:35 what wouldn't?

13:35 sm0ke: sorry i mean *.pom

13:36 technomancy: sm0ke: gotcha. not sure if there's a way to fix that, but repro details in the issue report would be helpful.

13:36 sm0ke: ok i will update issue description

13:47 bacon1989: can anyone tell me why out is an empty list in this stream reading function? http://pastebin.com/j7v4GFub

13:48 gfredericks: bacon1989: don't use transients that way

13:49 bacon1989: but your main issue is that for is lazy

13:49 sm0ke: wow amazing that it doesnt work that way inspite of this

13:49 https://github.com/technomancy/leiningen/blob/master/src/leiningen/jar.clj#L175

13:49 technomancy: sm0ke: you may be the second or third person ever to use classifiers

13:49 gfredericks: bacon1989: transients should be used in the same way as the persistent data structures, i.e. by using the return value from conj!

13:50 bacon1989: ah

13:50 sm0ke: technomancy: :P

13:51 technomancy: you know what someday you would be doing so too and will thank me for reporting this :P

13:51 verma: sritchie, it works pretty well, only that I probably need to stringify-keys from keywords to strings, because they go as is and appear as :keyname on firebase :)

13:51 bacon1989: how the heck am I supposed to do this...

13:51 it seems like I need to write way more code than I should have to

13:52 justin_smith: bacon1989: you are using transients wrong

13:52 bacon1989: yeah, I got that, I was under the impression it was a mutable type, and conj! manipulated it

13:52 justin_smith: bacon1989: you need to bind to the return value of transients, they are not guaranteed to modify the value in place

13:52 bacon1989: apparently not

13:53 sm0ke: humm i am not sure if i am looking in the right place is jar.clj also responsible for deploying to local maven repo

13:53 bacon1989: actually, could I use set!?

13:53 justin_smith: no

13:53 bacon1989: or is that only for global vars, etc

13:53 justin_smith: use the return value as a loop binding

13:53 technomancy: sm0ke: might need install.clj and/or deploy.clj

13:53 bacon1989: justin_smith: i'd have to write a loop within a loop

13:54 justin_smith: (loop [out (transient [])] ... (recur (conj! out something)))

13:54 bacon1989: not that it's a big deal

13:54 sm0ke: aha

13:54 technomancy: jar function towards the end in jar.clj uses get-jar-filename*

13:54 bacon1989: justin_smith: is there an easy way to grab a subsection of a buffer?

13:54 sm0ke: instead of the classifed version

13:55 bacon1989: I mean, a byte-array

13:55 justin_smith: bacon1989: use reduce with conj! for the inner, instead of for

13:55 sm0ke: oh but it calls classifed function

13:55 justin_smith: bacon1989: sorry, that was not an answer to your last question

13:55 sm0ke: ugh

13:55 bacon1989: justin_smith: so a reduce over the array index using aget

13:55 justin_smith: bacon1989: subseq

13:56 err, never mind, not subseq

13:56 sm0ke: hurm but looks like it doesnt passes the classifier at all

13:56 bacon1989: byte-array is considered a sequence?

13:56 sm0ke: only suffixes if we do a uberjar

13:57 justin_smith: bacon1989: no, don't use subseq, I was wrong

13:57 gfredericks: ,(doc subseq)

13:57 clojurebot: "([sc test key] [sc start-test start-key end-test end-key]); sc must be a sorted collection, test(s) one of <, <=, > or >=. Returns a seq of those entries with keys ek for which (test (.. sc comparator (compare ek key)) 0) is true"

13:58 gfredericks: bacon1989: you shouldn't need an inner loop for what you're doing

13:59 bacon1989: gfredericks: if the entire buffer isn't consumed, won't it conj crap at the end of my output?

13:59 justin_smith: ,(java.util.Arrays/copyOfRange (byte-array (map byte (range 8))) 3 7) bacon1989

13:59 clojurebot: #<byte[] [B@3a8544>

13:59 bacon1989: right... so there is no easy way to grab a range...

14:00 justin_smith: bacon1989: look above, that's an easy way to grab a range

14:00 most of that code is just generating a byte array, for exampling purposes

14:00 sm0ke: if i knew how to get :classifier for the current profile. we can patch it to (if uberjar? :standalone (classifer))

14:00 bacon1989: ah

14:01 technomancy: sm0ke: don't think in terms of profiles; at that point all you have is a project map.

14:01 justin_smith: ,(into [] (java.util.Arrays/copyOfRange (byte-array (map byte (range 8))) 3 7)) bacon1989: for clarity

14:01 clojurebot: [3 4 5 6]

14:01 sm0ke: yes? (:classifer project-map)

14:01 how do i get project map?

14:01 :P

14:02 or may be not so simple

14:02 if its nested in a profile?

14:02 technomancy: sm0ke: it's passed as an argument to the task function

14:02 sm0ke: during task execution, profiles don't exist

14:03 sm0ke: aha

14:03 technomancy: only the project map exists meaningfully

14:03 sm0ke: technomancy: does the project map is as is? i mean are profiles merged in it?

14:04 if merged we can just do (:classifier project) right?

14:04 technomancy: sm0ke: yeah, the profile merge has happened upstream, but tasks shouldn't be aware of it

14:04 bacon1989: justin_smith: if I had an array of length 8, would I need to copyRange 0 7 to grab the entire thing?

14:04 i'm assuming it's zero-indexed

14:04 technomancy: tasks must operate just based on the map they're given, which will have everything they need

14:04 justin_smith: bacon1989: you could just use into to get it as a vector

14:04 bacon1989: or seq to get it as a seq

14:04 etc.

14:04 bacon1989: yeah, maybe I should just do that

14:04 justin_smith: ,(seq (byte-array (map byte (range 8))))

14:04 clojurebot: (0 1 2 3 4 ...)

14:05 justin_smith: that example shows both halves of the monad (from seq to byte-array back to seq)

14:05 I thought you wanted some subsequence

14:06 ok, now that I read that paste less myopically, you just want the whole array, and calling seq will just do the right thing there

14:06 sm0ke: ok got to sleep now.. i will try my hands on this and will send a pr for review by tomorrow..nobody else wants this anyways

14:07 justin_smith: (and less verbosely, since seq already checks the size etc.)

14:07 bacon1989: justin_smith: as in, it will truncate any garbage for me?

14:07 justin_smith: bacon1989: hmm, that may be a "try and see" type thing actually

14:07 bacon1989: I don't think it will

14:07 justin_smith: but (take n s) is the solution if you get garbage

14:08 bacon1989: ah

14:12 I got an out of memory exception

14:12 i'm on the right track

14:13 is a string just a character sequence

14:14 justin_smith: well, it does implement the CharacterSequence class

14:14 *interface

14:14 *CharSequence that is

14:15 http://docs.oracle.com/javase/6/docs/api/java/lang/CharSequence.html

14:15 it isn't just that, because it does stuff with interning, and immutibility, and hashcodes etc.

14:15 so it is more than just an Array of characters

14:21 bacon1989: I actually need a string of the output, so this is what i'm going to try after a reboot http://pastebin.com/LGHVkpRL

14:23 still getting out of memory, i'm doing something wrong here

14:27 screw it, i'm using slurp

14:31 justin_smith: ,(String. (byte-array (map byte "hello"))) bacon1989:

14:31 clojurebot: "hello"

14:42 alloyed: 18:21 < bacon1989> still getting out of memory, i'm doing something wrong here

14:42 18:25 < bacon1989> screw it, i'm using slurp

14:42 18:30 < justin_smith> ,(String. (byte-array (map byte "hello"))) bacon1989:

14:42 lol oops

14:43 cespare: Is there a reason the ->R record constructor cannot/does not attach a type hint to the result?

14:45 oh, because it's a function.

14:56 gfredericks: cespare: I think it still could

14:57 ,(defrecord R [^String s])

14:57 clojurebot: sandbox.R

14:57 gfredericks: ,(meta #'->R)

14:57 clojurebot: {:ns #<Namespace sandbox>, :name ->R, :file "NO_SOURCE_PATH", :column 0, :line 0, ...}

14:57 gfredericks: ,(:tag (meta #'->R))

14:57 clojurebot: nil

15:00 TEttinger: ,(:args (meta #'->R))

15:00 clojurebot: nil

15:00 TEttinger: ,(:arglist (meta #'->R))

15:00 clojurebot: nil

15:00 TEttinger: ,(:arglists (meta #'->R))

15:00 clojurebot: ([s])

15:00 TEttinger: ,(meta (:arglists (meta #'->R)))

15:00 clojurebot: nil

15:01 TEttinger: ,(map meta (:arglists (meta #'->R)))

15:01 clojurebot: (nil)

15:01 TEttinger: hm

15:08 gfredericks: I'm surprised the metadata doesn't make it there even accidentally

15:08 seems like the natural impl would have to go out of its way to suppress it

15:08 * gfredericks looks at defrecord source

15:11 gfredericks: cannot figure out where that gets lost

15:11 ,(defn thing [^:foo a])

15:11 clojurebot: #'sandbox/thing

15:11 gfredericks: ,(-> #'thing meta :arglists ffirst meta)

15:11 clojurebot: {:foo true}

15:12 TEttinger: ,(-> #'->R meta :arglists ffirst meta)

15:12 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve var: ->R in this context, compiling:(NO_SOURCE_PATH:0:0)>

15:12 TEttinger: ,(defrecord R [^String s])

15:12 clojurebot: sandbox.R

15:12 TEttinger: ,(-> #'->R meta :arglists ffirst meta)

15:12 clojurebot: nil

15:13 TEttinger: ,(class R)

15:13 clojurebot: java.lang.Class

15:13 Bronsa: gfredericks: https://github.com/clojure/clojure/blob/master/src/clj/clojure/core_deftype.clj#L360

15:13 TEttinger: ,(class thing)

15:13 clojurebot: sandbox$thing

15:13 gfredericks: Bronsa: oh geez I missed that since it's shadowing

15:14 WELL GREAT

15:14 avgerino_: hello everyone

15:14 Bronsa: gfredericks: there's no particular reason why this https://github.com/clojure/clojure/blob/master/src/clj/clojure/core_deftype.clj#L366 uses fields rather than hinted-fields though

15:14 silasdavis: gfredericks, earlier you mentioned that not everything that satisfies a protocol implements the interface

15:14 couild you expand on that

15:14 Bronsa: sounds like that would be a reasonable improvement

15:14 silasdavis: what doesn't for instance?

15:15 gfredericks: silasdavis: anything you extend via extend-{protocol,type}

15:15 also nil

15:15 I guess that fits under the prior definition

15:15 silasdavis: what about within defrecord?

15:15 arrdem: Bronsa: er... do hinted fields make any sense except in the case of propagating the hint to (.foo my-record) cases?

15:16 Bronsa: in which case you take a cast check anyway..

15:16 cespare: I'm sure I'm being dense, but when I've got something like (let [s ^String (...)] (mymacro s)) why doesn't mymacro see the type hint on s?

15:16 gfredericks: silasdavis: inline impls are via the interface

15:17 Bronsa: arrdem: gfredericks was wondering why the :arglists for ->record ctor doesn't preserve the hints

15:17 arrdem: Bronsa: ah

15:17 gfredericks: silasdavis: but inline isn't always possible, e.g. if two protocols have a function with the same name

15:17 arrdem: yeah it's not a big deal since the basis vector has them

15:18 arrdem: devn: dare I ask what you're using git-bump for? :P

15:19 silasdavis: gfredericks, ah I had wondered about that

15:19 so I am controlling the record definitions, and I am extending the interface of the protocol with another protocol

15:19 really it's a convenience to not have to repeat it

15:20 and I guess has some speed benefits

15:20 if I needed to I could copy the implementation into an (extend ...) macro

15:21 Is it possible to share implementation between and extend form and a defrecord form?

15:21 as a map

15:21 could I splice it in, so I don't have repeat the defintion?

15:21 gfredericks: extend takes a map I think

15:22 I think doing a bunch of stuff programmatically via extend is the most flexible thing you could come up with

15:23 cespare: and same thing with functions. mymacro only seems to get hints that are given directly to its arg

15:24 Vfe: How can I ensure sequential execution of seveal functions? I’m having an issue where I have a let statement, and one of my assignments has to pull from a DB, and sometimes the functions afterwards executes before that assignment completes, and it ends up with a null value.

15:24 silasdavis: looking at the source, emit-defrecord is called by defrecord and is marked private

15:25 so I suppose if you want to share implementations you can't easily include them inline

15:25 Bronsa: silasdavis: extend takes a map of functions, defrecord does not

15:26 silasdavis: Bronsa, yep I was aware of that, I was just wondering if I could use a macro or something to get the benefit of sharing implementations and the speed benefit of implementing inline

15:26 Jaood: Vfe: use an atom

15:27 Bronsa: silasdavis: I wrote https://github.com/Bronsa/neurotic which allows you to share implementation between deftypes/defrecord

15:27 not between a deftype and an extend though

15:30 silasdavis: Bronsa, bonkers

15:30 really cool

15:30 gfredericks: ,(->> (repeat 10000 ['(3) [4]]) (apply concat) (apply concat) (reduce +))

15:30 silasdavis: just what I had in mind

15:30 clojurebot: #<StackOverflowError java.lang.StackOverflowError>

15:30 Vfe: Jaood: On what exactly? each element of the let? Here’s what’s going on, https://gist.github.com/VFe/3c8fe2f088301c931339 . I just want to make sure all let assignments complete before anything that will come after the let.

15:30 silasdavis: how much have you had to modify the implementations of defrecord*

15:30 I couldn't tell by inspection

15:30 Bronsa: gfredericks: IIRC there's already a ticket w/ patch for that

15:31 silasdavis: I really don't remember

15:31 gfredericks: Bronsa: yeah that was mine I just sometimes feel this insatiable urge to make the bot do something

15:31 it's a personal shortcoming.

15:31 Bronsa: ah ok :)

15:31 silasdavis: Bronsa, is it possible it could have diverged from functionality in 1.6?

15:32 Bronsa: silasdavis: let me check one sec

15:33 silasdavis: no there hasn't been any changes to defrecord/deftype since I wrote neurotic

15:33 cespare: If I have (let [s ^String (...)] (mymacro s)) why doesn't mymacro see the type hint on s?

15:35 Jaood: Vfe: on the data you are receiving from the DB, atoms will block until modifications on them are complete

15:36 silasdavis: Bronsa, great thanks for checking I think I'll find this useful :)

15:36 Vfe: Jaood: Thanks!, I’ll give it a try.

15:37 Jaood: Vfe: so your function after the let will run after the modification of the atom (retrieving the data from the DB) is complete

15:40 Janiczek: Is there a way for `cljsbuild test my-test-profile` not to run ALL cljsbuild tasks beforehand? I'd like it to not run any, or to at least run one, specified by me. This way testing takes too long because it compiles dev, prod, test, just about every cljsbuild build I have.

15:55 borkdude: Are microservices a chance to smuggle more clojure into production?

15:58 whodidthis: maybe modestservices, jvm to big for micro

16:06 gfixler: does clojure have a thing which I'm tempted to call juxtcat?

16:10 borkdude: probably not

16:11 gfixler but mapcat can be used thusly:

16:12 ,(mapcat #(% 1) [vector vector vector])

16:12 clojurebot: (1 1 1)

16:12 borkdude: which looks kinf of like ((juxt vector vector vector) 1)

16:13 gfixler: hmmm

16:13 ,(map (juxt #(apply vector %) #(apply (comp reverse vector) %)) ["foo" "bar" "baz"])

16:13 clojurebot: ([[\f \o \o] (\o \o \f)] [[\b \a \r] (\r \a \b)] [[\b \a \z] (\z \a \b)])

16:13 gfixler: juxtcat would just merge those subcollections

16:14 ([[\f \o \o \o \o \f] [\b \a \r \r \a \b] etc...])

16:14 borkdude: gfixler what is the exact result you want. [\f \o \o \o \o \f ...], or a nested nested thing?

16:14 gfixler: it's actually for 3-space stuff

16:15 (map (juxtcat pos rot) ["node1" "node2" "node3"])

16:15 pos and rot would both give back [x y z] triples

16:15 borkdude: I think a for comprehension might be better here

16:15 llasram: gfixler: So (comp (partial apply concat) (juxt ...)) ?

16:15 gfixler: I suppose

16:15 I can make it happen a few ways, but clojure has so many of these little tools, I figured I'd ask :)

16:16 llasram: ,(defn juxtcat [& args] (comp (partial apply concat) (apply juxt args)))

16:16 clojurebot: #'sandbox/juxtcat

16:16 gfixler: llasram: yep, that would do it

16:17 borkdude: ,(for [word ["node1" "node2" "node3"]] (concat word (reverse word)))

16:17 clojurebot: ((\n \o \d \e \1 ...) (\n \o \d \e \2 ...) (\n \o \d \e \3 ...))

16:17 gfixler: ,(map (juxtcat #(apply vector %) #(apply (comp reverse vector) %)) ["foo" "bar" "baz"])

16:17 clojurebot: ((\f \o \o \o \o ...) (\b \a \r \r \a ...) (\b \a \z \z \a ...))

16:17 gfixler: clojurebot abbreviates?

16:18 ,(map (juxtcat #(apply vector %) #(apply (comp reverse vector) %)) ["foo" "bar"])

16:18 clojurebot: ((\f \o \o \o \o ...) (\b \a \r \r \a ...))

16:18 gfixler: interesting

16:18 borkdude: also a good idea

16:18 llasram: gfixler: (apply vector ...) is pretty much just vec, and in this context is pretty much just seq

16:19 gfixler: ,(map (juxtcat #(seq %) #(apply (comp reverse vector) %)) ["foo" "bar"])

16:19 clojurebot: ((\f \o \o \o \o ...) (\b \a \r \r \a ...))

16:19 gfixler: yep

16:20 moea: I have a pretty simple macro which, for debugging, is doing this: (println (into {} (map (fn [[k v]] [(name k) (mapv str v)]) output-spec))), where output-spec is a literal map which is one of the macro's parameters

16:21 it collapses three keys with distinct keyword names into nil - i.e. (name) is returning nil

16:22 (class k) is Keyword

16:22 and doing (str k) results in ":keyword-name"

16:22 so i have no idea why name would be returning nil

16:23 borkdude: moea because of the println

16:23 oh wait sorry, misread

16:24 edw: moea: Could you re-post your paste?

16:26 devn: arrdem: RE: git-bump. i was stalking your github profile last night and thought it looked like it might be a good idea (maybe :)

16:27 arrdem: I was thinking the hook could prompt me or something

16:27 arrdem: another thought i had was to use rewrite-clj to auto-update my project.clj at the same time

16:27 technomancy: devn: ahem

16:27 devn: technomancy: yessir?

16:27 moea: edw: https://gist.github.com/moea/09f5465acec4f3333014

16:28 technomancy: devn: https://github.com/technomancy/leiningen/blob/master/src/leiningen/change.clj

16:28 moea: oops

16:28 edw: Thanks.

16:28 devn: technomancy: :) oops

16:29 edw: There's a lot wrong going on there, moea.

16:29 technomancy: well it is brand new functionality =)

16:30 devn: also the release task

16:30 devn: technomancy: that's really nice to have. i may try and co-opt some of that for hoplon

16:30 edw: moea: Do you know that you can use `macroexpand-1` to see what a macro will expand into?

16:30 moea: edw: yeah, i figured spitting it out would make it easier to talk about the about output

16:30 technomancy: man

16:31 every time I read Papert, I'm all "this guy knows where his towel is"

16:31 http://www.papert.org/articles/ACritiqueofTechnocentrism.html

16:31 amalloy: moea: your macro only takes one parameter, but you're passing it four? that breaks long before this "collapsing different keywords" thing you're talking about

16:32 edw: moea: Is this closer to what you were looking for?

16:32 https://gist.github.com/moea/09f5465acec4f3333014#comment-1259965

16:32 moea: yeah, i screwed up paste, sorry :(

16:32 amalloy: edw: that would be a silly macro definition

16:33 even if you fixed it to compile, by adding the gensyms, you've just defined something that a function could do

16:33 edw: amalloy: Yeah, obviously.

16:33 amalloy: I'm more of a "make it work, then explain why it was the wrong solution in the first place" kind of person.

16:33 amalloy: well, you missed step 1, then :P

16:34 his defmacro compiles and then fails when used; yours doesn't even compile

16:34 edw: I don't have a REPL open right now, and it might be half-written in Scheme.

16:35 amalloy: his definition looks fine to me, honestly, as long as he only calls it with one argument which is a literal map

16:35 gfixler: edw: can confirm, it runs in (partial clojure scheme)

16:35 I mean (comp clojure scheme)

16:35 amalloy: which is what he said was happening

16:35 gfixler: that's what I want someday - composable languages

16:36 TEttinger: can't racket kinda do that?

16:36 gfixler: I don't know. I haven't used it

16:36 edw: gfixler: I've been writing some nasty `comb` templates that generate JavaScript inside HTML. It's not fun.

16:37 TEttinger: and wouldn't it end up with a JS/CSS/HTML hybrid monstrosity like web dev has?

16:37 edw: TEttinger: Yeah, good luck getting Emacs to indent that shit correctly.

16:38 TEttinger: haha

16:38 Frozenlock: edw: Emacs can already indent many different codes in org-mode babel

16:39 edw: Frozenlock: So to edit HTML with embedded CSS and JS, I should use…org-mode?

16:39 Frozenlock: clearly the superior solution :-p

16:39 org-html-css-js, the future of the web

16:39 moea: never mind, i'm a moron. part of me screwing up the paste was me removing a "name" parameter to the macro. so dumb.

16:39 Frozenlock: be afraid, very afraid

16:40 moea: i also removed the body, which couldn't be accomplished in a function, FWIW

16:41 edw: moea: In general 99% percent of what you want a macro to do *can* be done in a function, so make the macro nothing more than the syntactic glue-sugar to make that happen.

16:43 cespare: If I have (let [s ^String (...)] (mymacro s)) why doesn't mymacro see the type hint on s? It seems like the compiler consumes the tag and the macro doesn't get to see it.

16:43 unless (...) yields something that is not a string.

16:45 shiranaihito: off-topic, but educational: https://www.youtube.com/watch?v=5IJeemTQ7Vk

16:48 edw: shiranaihito: Troll elsewhere please.

16:49 shiranaihito: edw: please remain calm :) you might want to watch the video anyway

16:49 edw: I don't think I'm ready to handle the Ron Paul Revolution.

16:49 shiranaihito: i'm inclined to agree :P

16:51 but instead of objecting to seeing a video because it's got a controversial title, it might be more sensible to just watch it a bit further and see if it makes any sense etc

16:52 bbloom: shiranaihito: not appropriate for this channel.

16:54 shiranaihito: yes, i was expecting a hostile reaction, but that's alright

16:55 Frozenlock: That's even less related to clojure than my Carl Sagan videos.

16:58 shiranaihito: obviously, the idea here was just to post a link hoping that someone would see it without having a fit, watch it and learn about the world we all live in.. i was well aware that it would be frowned upon, but linked it anyway.. on the other hand, i'd expect a bunch of people as smart as Clojure programmers to be reasonably well equipped to process new information

16:58 amalloy: cespare: what do you mean, the macro doesn't get to see it? do you know how metadata works? try posting some compilable code, its actual results, and what you expected to see instead

16:59 technomancy: ,(= "equipped to process new information" "appreciates political propaganda spam")

16:59 gfredericks: amalloy: I think he means the symbol passed to the macro doesn't have metadata

16:59 clojurebot: false

17:00 amalloy: gfredericks: that would be one reasonable interpretation, but i'm not going to explain what's going on until i know that's the question

17:01 TimMc: technomancy: If spam, why not kick?

17:02 technomancy: TimMc: I save kicks for repeat offenders =)

17:02 TimMc: *nod*

17:02 gfredericks: clojurebot: why is <reply> because that's not how macros work

17:02 clojurebot: Roger.

17:03 TimMc: I am a bit more of a hard-ass^W^W^Wproactive.

17:03 Frozenlock: and that's why we prefer technomancy :-p

17:04 verma: whe I reify a java interface, do I have to implement all methods?

17:04 TimMc: I mod some subreddits and it would be really nice to have a /kick option to complement bans -- something where the offender has to take a small action to start participating again.

17:04 Frozenlock: seancorfield: I'm loading my database into into tokumx, I should be able to test congomongo with it very shortly.

17:05 gfredericks: ,(reify clojure.lang.ISeq (first [_] 42))

17:05 clojurebot: #<AbstractMethodError java.lang.AbstractMethodError>

17:05 gfredericks: ,(let [x (reify clojure.lang.ISeq (first [_] 42))] (instance? Object x))

17:05 clojurebot: true

17:05 gfredericks: verma: I don't think you do?

17:07 amalloy: you don't have to, but if anyone tries to call one of those methods they'll get an unpleasant surprise (and you're "supposed" to implement them all)

17:07 stuartsierra: AbstractMethodError is what you get, I think

17:08 amalloy: yeah, but only if someone calls it, not when you actually reify it

17:08 stuartsierra: yes

17:08 gfredericks: you're supposed to? we're held to a higher standard than vectors implementing java.util.List?

17:08 amalloy: gfredericks: they implement all of it

17:08 as far as i know

17:08 gfredericks: wat

17:08 amalloy: they throw UnsupportedOperation for the mutating methods

17:08 * gfredericks pulls out his clojure bible

17:09 amalloy: i mean, vector is written in java. it's impossible to not implement all of an interface in java

17:09 gfredericks: amalloy: oh is the exact exception type the relevant difference?

17:09 seancorfield: Frozenlock: cool, i look forward to any tickets you raise to add full support! :)

17:09 amalloy: errrr

17:09 well, AbstractMethodError is kinda different

17:09 it's not even an exception, it's an error

17:09 gfredericks: I'm just wondering where this supposing comes from since there seem to be a plethora of java interfaces that have sane partial implementations

17:10 amalloy: it's like a linker error

17:10 gfredericks: okay so that *is* the difference you're after then

17:10 and if there was a helper macro that threw the UnsupportedOperation then that'd be better?

17:10 amalloy: gfredericks: the java.util.* interfaces explicitly say "if you don't support mutation, you can throw UnsupportedOperationException for those methods"

17:11 gfredericks: oh are they checked?

17:11 amalloy: throwing it for arbitrary other methods in other interfaces would be wrong

17:11 no, it's just a sentence in the javadoc

17:12 related: this is the minimum you have to implement for the clojure printer to be willing to print you as a sequence: ##(take 10 (reify clojure.lang.ISeq (first [this] 1) (more [this] this) clojure.lang.Seqable (seq [this] this) clojure.lang.Sequential))

17:12 lazybot: ⇒ (1 1 1 1 1 1 1 1 1 1)

17:14 gfredericks: amalloy: TIL.

17:15 amalloy: gfredericks: Error is supposed to be an indication that something is seriously wrong with the vm and you generally shouldn't attempt to recover

17:15 gfredericks: amalloy: that bit I was aware of

17:16 amalloy: it's always seemed wrong to me that clojure and/or the jvm let you define partial implementations of an interface that throw an Error when you try to use them

17:17 gfredericks: you'd prefer the jvm abort when loading the class?

17:17 and/or the spec disallow it?

17:19 amalloy: that seems reasonable to me

17:19 otherwise you can get a disastrous Error literally anywhere in your code, where you don't have any catch blocks set up to handle it because it's an Error

17:21 gfredericks: I think the biggest bug I've caught in clojureland was java.jdbc catching Exception around transactions

17:25 cespare: amalloy: gfredericks came up with several different questions: http://pastie.org/9369240

17:25 please correct my misunderstandings

17:26 amalloy: cespare: yes, reader metadata is for the compiler,not for you to work with at runtime

17:27 if you want your m macro to work, you can/should write (let [^String s (str "1")] (m s))

17:28 gfredericks: amalloy: I don't think that works

17:29 amalloy_: well at least not the stricter thing I thought you meant, but you probably didn't

17:32 ,(defmacro sym-meta [sym] (meta sym))

17:32 clojurebot: #'sandbox/sym-meta

17:33 gfredericks: ,(sym-meta ^:foo ^:bar x)

17:33 clojurebot: {:bar true, :foo true}

17:33 gfredericks: ,(let [^String s (str "1")] (sym-meta s))

17:33 clojurebot: nil

17:34 Bronsa: gfredericks: you could always (ab)use &env

17:34 gfredericks: ,(defmacro sym-meta [sym] (-> &env (find sym) key meta))

17:34 clojurebot: #'sandbox/sym-meta

17:34 gfredericks: ,(sym-meta ^:foo ^:bar x)

17:35 clojurebot: #<NullPointerException java.lang.NullPointerException>

17:35 gfredericks: ,(let [^String s (str "1")] (sym-meta s))

17:35 clojurebot: {:tag java.lang.String}

17:35 gfredericks: HUH.

17:35 (inc Bronsa)

17:35 lazybot: ⇒ 27

17:35 gfredericks: I woulda declared that impossible

17:35 Bronsa: that's just horrible though never do that again

17:35 TEttinger: (inc Bronsa)

17:35 lazybot: ⇒ 28

17:35 Bronsa: a puppy dies every time you use &env etc

17:36 gfredericks: ,(defmacro sym-meta "Despite Bronsa" [sym] (-> &env (find sym) (some-> key) (or sym) meta))

17:36 clojurebot: #'sandbox/sym-meta

17:36 gfredericks: ,(sym-meta ^:foo ^:bar x)

17:36 clojurebot: {:bar true, :foo true}

17:36 gfredericks: ,(let [^String s (str "1")] (sym-meta s))

17:36 clojurebot: {:tag java.lang.String}

17:37 gfredericks: there now it is more robust and production-ready

17:37 eh it should probably merge the two eh?

17:37 we're already on version 0.2.0 of this

17:38 ,(defmacro sym-meta "Despite Bronsa" [sym] (let [immediate (meta sym), env (-> &env (find sym) (some-> key) meta)] (merge env immediate)))

17:38 clojurebot: #'sandbox/sym-meta

17:38 gfredericks: ,(sym-meta ^:foo ^:bar x)

17:38 clojurebot: {:bar true, :foo true}

17:38 gfredericks: ,(let [^String s (str "1")] (sym-meta ^:immediate s))

17:38 clojurebot: {:tag java.lang.String, :immediate true}

17:41 iamdustan: Total noob question here. I'm learning clojure right now and decided to do some codeeval's. Only problem is I cannot find any way to read from stdin like codeeval requires that works.

17:42 Frozenlock: seancorfield: Everything (except the geo thingy) is working for me... and the DB is indeed 90% smaller. o_O

17:42 iamdustan: it's example code looks like:

17:42 (doseq [line (remove empty? (line-seq rdr))] (do-something-with line)))

17:42 which throws an error about rdr

17:43 and another think I found on stackoverflow looked like the following:

17:43 (defn -main

17:43 [& args]

17:43 (with-open [rdr (clojure.java.io/reader (first args))]

17:43 (doseq [line (remove empty? (line-seq rdr))]

17:43 (println (solve line)))))

17:43 which also throws an error.

17:43 Frozenlock: seancorfield: the congomongo test returns 4 errors however. (on 52 tests / 180 assertions)

17:44 Still, I'd say it's pretty impressive.

17:44 iamdustan: wait. that one doesn't error, it just doesn't ever print anything...

17:45 seancorfield: Frozenlock: not bad!

17:45 aperiodic: iamdustan: is ##(doc read-line) what you're looking for?

17:45 lazybot: ⇒ "([]); Reads the next line from stream that is the current value of *in* ."

17:45 seancorfield: feel free to open an issue with the test failure details and i'll take a look

17:45 can't promise anything, but i'll take a look :)

17:45 Frozenlock: understood :-p

17:47 iamdustan: aperiodic: trying that now. thanks

17:47 aperiodic: iamdustan: you probably would've found it by looking at http://clojure.org/cheatsheet

17:48 iamdustan: bookmarked!

17:56 cespare: amalloy_: oh jeez, thanks.

17:57 amalloy: man. my isp's field tech cannot fix my internet soon enough. it's frustrating getting dropped out of #clojure in the middle of explaining something

18:00 huh. i just got emacs to ask me if i want to abort and dump core

18:01 but C-h l doesn't show me typing anything out of the ordinary. just a bunch of movement commands and then C-g

18:02 but when i said "no thanks" it just went back to working as usual, so i guess i don't get to say i crashed emacs

18:05 gfredericks: amalloy: it asks me that almost every day

18:05 usually after I've been mashing the keyboard for a couple seconds

18:06 amalloy: really???????

18:06 gfredericks: actually it's after accidentally backgrounding

18:06 amalloy: i've been using emacs for like four years, never seen that in my life. i feel like emacs is willing to do things with you it never does for me

18:06 gfredericks: keyboard mashing -> in the background -> `fg` -> "abort and dump core?"

18:06 it's like this married routine we have

18:07 amalloy: and yes, i think it's backgrounding related. i discovered that i can't background it (C-z gets ignored) when i'm running it via `ssh some-host -t emacs`

18:07 gfredericks: z is my tmux hotkey so this stuff is complicated for me

18:07 amalloy: so i was smashing on keys to see what would happen

18:07 gfredericks: every month or so I end up crashing my whole tmux session somehow

18:08 arrdem: Bronsa: tejvm will only emit .invoke for {:op :fn-method}, right? I can't force a different method name without forking to my own emitter?

18:14 Bronsa: arrdem: yeah that's not really configurable

18:15 arrdem: Bronsa: kay. thanks.

18:15 Bronsa: arrdem: but well, you could provide your own -emit multimethod that defaults to c.t.e.j.emit/-emit and provides different compilation methods for the op you need

18:16 arrdem: Bronsa: I think that's what I'm gonna do, the question is whether the common set of emit operations is large enough to justify not just writing my own from scratch due to other differences.

18:17 Bronsa: that's up to you :)

18:18 arrdem: :P

18:31 technomancy: amalloy: spamming C-g will let you dump core at any point with emacs

18:32 if you tip some threshhold

18:32 amalloy: for real? nice

18:32 technomancy: presumably for debugging the lisp engine

18:32 amalloy: huh, so it will

18:32 technomancy: I've only ever seen it over SSH

18:42 gfredericks: (inc technomancy)

18:42 lazybot: ⇒ 117

18:42 gfredericks: that explains a lot

18:42 spamming C-g is my primary debugging tactic

18:42 Janiczek: (inc gfredericks)

18:43 lazybot: ⇒ 74

18:43 gfredericks: I'll assume I just got inc'd because I inc'd somebody

18:43 somebody inc Janiczek plz

18:44 Janiczek: gfredericks: haha no, I liked the "spamming C-g" line. :)

18:44 gfredericks: can we turn this into a pyramid scheme somehow?

18:44 amalloy: i'll never reveal the secret of my scheme, gfredericks

18:44 gfredericks: if anybody figures out how make sure that everybody involved inc's me for coming up with the idea

18:44 seangrove: (* -1 amalloy)

18:45 amalloy: seangrove: ITYM (- amalloy)

18:45 seangrove: (inc amalloy)

18:45 lazybot: ⇒ 144

18:45 technomancy: I've upgraded to pyramid rackets.

18:46 gfredericks: you guys had me suspecting I had missspelt something

18:48 is pyramid scheme the name of an interpreter?

18:49 if not I offer $10 to anybody who starts one and takes over the google search results for that phrase

18:49 I'll be willing to go up to $11 but that's my best offer

18:50 j0ni: win 2

19:06 noncom: how do i make this work : https://www.refheap.com/87991

19:06 it does not accept "pres" there

19:06 Shayanjm: Given a lazyseq in the form of (("thing1" "thing2") ("thing3" "thing4")...) - what would be the most efficient way to iterate over each sub-seq, determine if "thing2" and "thing4" are equivalent - and merge the adjacent elements together if they are (i.e: (("thing1 thing3" "thing2 thing4")))

19:07 The hard part is preserving the rest of the lazyseq as is

19:08 noncom: split in two lazyseqs ?

19:08 a lazyseq built from a lazyseq preserves laziness i guesss.. ?

19:09 but plitting them, you will have two seqs of equal length..

19:09 if that helps..

19:37 Shayanjm: yeah I'm drawing a blank here. Any help would be much appreciated

19:37 I have a lazy-seq in this format: https://gist.github.com/shayanjm/51b19051fead468158a5

19:37 clojurebot: No entiendo

19:38 Shayanjm: each element of the lazy-seq has two values. I'd like to compare the second value of the element to the second value of the next element. If both are the same, I'd like to merge both elements together in the form ("thing1 thing2" "thing3 thing4")

19:39 I'm just unsure as to how to iterate over the lazy-sequence, merge the elements and insert while still preserving the rest of the sequence

19:39 arrdem: well that's a trivial reduce operation...

19:39 I think there's a clojure core function for it

19:39 Shayanjm: seriously? :o

19:40 amalloy: mapcat

19:40 arrdem: I was thinking for partition-by, which won't do this job

19:41 Shayanjm: My issue is selecting a 'current element' and a 'next element'

19:41 probably just a mental block

19:42 arrdem: (reduce (fn [[previous-hunks this-hunk prev] this] (when (= (second prev) (second this))...)))

19:42 amalloy: are you sure you actually mean pairs of elements? it looks like your example wants to combine all the things whose second element is "O" together, or something

19:42 which is just partition-by

19:42 Shayanjm: amalloy: it's not. It must be adjacent elements

19:42 amalloy: arrdem: gross. not lazy enough

19:42 right right, all the adjacent ones with the same second element

19:43 Shayanjm: Yeah. I'm basically scraping for tags inside article content

19:43 amalloy: as opposed to each pair, which sounds very different: the number 2 is not special to you at all, so pair is wrong

19:43 Shayanjm: if two words next to each other are tagged the same (i.e: "Gaza" and "Strip" are both tagged as locations)

19:43 amalloy: you just want (partition-by second xs)

19:43 Shayanjm: they should be concat'd so it becomes "Gaza Strip"

19:43 arrdem: amalloy: you could partition-by over (map vec seq (rest seq))

19:44 amalloy: arrdem: there's no reason to do that. he doesn't care about pairs. he's just trying to partition-by. observe: Shayanjm, should '(("has" "O") ("launched" "O") ("what" "O")) all three be merged into one thing?

19:44 Shayanjm: They could be. It doesn't really matter at that point

19:45 but if "launched" had something other than O attributed to it, they shouldn't be.

19:45 It probably would simplify things if the O's were merged as well

19:45 arrdem: amalloy: amaze me, I don't think that's possible with a single partition-by.

19:46 seangrove: Just to be sure, (doseq [s (doall (map :name some-seq))] ...) - the doseq isn't lazy, so the doall is unnecessary, right?

19:46 amalloy: arrdem: it is literally (partition-by second xs). that is is all that's being requested. then you map over that

19:46 Shayanjm: amalloy: xs?

19:46 amalloy: your input seq

19:46 Shayanjm: oic

19:46 interesting. Let me try

19:47 gfixler: Shayanjm: (map #(apply str (map first %)) (partition-by second '(("Israel" etc...?

19:47 all: critiques of this approach?

19:47 not lazy?

19:47 amalloy: but, as always, i'd like to repeat the general rule: if you want help writing a function to turn X into Y...include an exact, specific value for X and Y

19:47 verma: hey you guys think there's a better way of doing this: https://gist.github.com/verma/6cf76edffd91a93bac3e

19:48 amalloy: it dramatically cuts down on the pointless guessing and back-and-forth everyone has to do to figure out what you want to do

19:48 Shayanjm: amalloy: that's fair. The partition-by didn't work. I'll rewrite my gist so its more clear

19:48 gfixler: Shayanjm: partition-by works fine for me

19:48 amalloy: Shayanjm: the partition-by gets things grouped together. then you map over the seq and format them however you want

19:48 as in gfixler's example

19:49 which in fact is perfectly lazy

19:49 gfixler: my apply str doesn't put in spaces, but that's simple enough to add in

19:49 arrdem: (inc amalloy)

19:49 lazybot: ⇒ 145

19:49 amalloy: gfixler: (clojure.string/join " " (...))

19:49 Shayanjm: oh you're right

19:49 much appreciated amalloy gfixler

19:49 gfixler: arrdem: is that a clojurecoin?

19:50 amalloy: but, really, combining the strings with spaces - are you *sure* you want to do that? having a list of strings instead of one string with spaces in it doesn't lose any information, and is easier to chew on later

19:50 arrdem: gfixler: I mean.. I'd dogetipbot amalloy but apparently I'm on thin ice as a channel nusance according to hiredman so I refrain

19:51 gfixler: arrdem: I see. It's about day 4 for me on freenode, and day 1 for me on irssi; still learning

19:51 arrdem: gfixler: welcome then. yeah inc is for in-channel karma.

19:52 note that it's not really a function. code is , or & prefixed whereas inc is just a bot command.

19:53 Shayanjm: amalloy: I'm mining keywords from an article. It actually fuzzes the results by quite a bit if I'm returning multiple adjacent 'similar' elements

19:54 amalloy: Shayanjm: feel free to combine them, but make it a list

19:54 Shayanjm: That's fair

19:54 amalloy: '((gaza strip) (has whatever blah foo) (west bank))

19:59 arrdem: Bronsa: is it safe to say that your bytecode AST is AST :- (Seq Op); Op :- [icode :- Keyword [ method :- Keyword . args :- (Seq Object)] ret-type :- Class]

20:02 ttasterisco: (karma amalloy)

20:02 ; how do I check the karma of someone?

20:02 amalloy: $karma ttasterisco

20:02 lazybot: ttasterisco has karma 0.

20:02 ttasterisco: $karma amalloy

20:02 lazybot: amalloy has karma 145.

20:03 ttasterisco: $karma lazybot

20:03 lazybot: lazybot has karma 28.

20:03 ttasterisco: $karma clojurebot

20:03 lazybot: clojurebot has karma 40.

20:05 Bronsa: arrdem: uhm, not really, only a small part of the bytecode represent calls

20:06 arrdem: Bronsa: yeah I see that as I'm reading more of this. disregard the above :P

20:06 Bronsa: arrdem: and besides, symbols/strings/classes/keywords can be used interchangeably right now

20:07 arrdem: also -emit doesn't return [bc*] for :method and :fn-method, which is something that'll probbaly need to change

20:07 arrdem: Bronsa: yeah it doesn't, which is something I'm gonna have to change

20:08 Bronsa: I was just too lazy to think of another function name for that so I implemented it with -emit

20:08 arrdem: I have my own -emit fork that handles only the AST elements involved in my hello world test. I'm going through transform.clj trying to get a handle on it so I can either use it or yak shave it into something I will use.

20:09 I kinda feel like transform.clj is general purpose enough that it could be its own objectweb ASM wrapper lib..

20:09 Bronsa: arrdem: yeah it's easier to figure out all the allowed bc representations by reading transform.clj

20:09 it's really straightforward

20:10 arrdem: Bronsa: yah. probably a documentation patch headed your way once I'm done :P

20:11 Bronsa: arrdem: when I was moving CinC to the contrib infrastructure Rich proposed to pull transform.clj into its own library to manipulate bytecode

20:11 the reason why I didn't think it was a good idea is because as it is, it's pretty much just a POC

20:12 before putting any considerable amount of work into making it more than just that I'd like to assess if it's reasonable to keep using this approach, performance wise

20:13 arrdem: yeah... I'm tempted to yak shave a pure clojure JVM class emitter but that's just a waste of time. a better objectweb ASM wrapper would be nice tho.

20:14 Bronsa: arrdem: I havent done any specific benchmark to see how much impact that little interpreter has on the compilation speed but I fear that all that destructuring + multimethod dispatching for EACH bytecode op might be too much

20:14 arrdem: Bronsa: I doubt that's a problem. I'd expect that all the vector mashing you do in emit.clj is the primary roadblock.

20:14 Bronsa: I think that cleaning that up with a better bytecode DSL should solve most of our woes

20:15 * arrdem has not yet tried to profile loading clojure.core or anything else huge

20:16 atyz: Does anyone have an opinion on the following om libraries: Devcards, om-tools or would you rather just use om?

20:16 Bronsa: arrdem: I talked with bbloom a while ago what the alternatives could be for avoiding all that unquote-splicing and he pointed me to his transduce library which he uses for flipp

20:18 arrdem: I looked into it and it looks like a reasonable approach but I haven't had the time to work extensively on tej yet, dunno if you'll have before me but feel free to experiment if that's the case

20:18 arrdem: Bronsa: I'll check it out. I was just thinking that at an architectural level we don't really care about the sequence _type_ of bytecode so long as the _order_ is preserved. This means that if we represent a single op as an obvious {:op ..} map ala the rest of TANAL it's trivial to detect nested subsequences of bytecode that need to be inlined. This would let us make all bytecode generation lazy and soforth until it hits the emitter which is strict anyway.

20:19 but it may be worth sweating the memory overhead of a crapload of small maps compared to some vectors....

20:19 bbloom: Bronsa: i forget the details, but i'm not sure what i suggested transduce for..... i think i just suggested you do like fipp does prior to the transduce stage: where it does it's own serialization

20:19 er linearization/flattening/whatever you wanna call it

20:20 the slow part being this:

20:20 '`[~x ~@y ~z]

20:20 ,'`[~x ~@y ~z]

20:20 clojurebot: (clojure.core/apply clojure.core/vector (clojure.core/seq (clojure.core/concat (clojure.core/list x) y (clojure.core/list z))))

20:21 bbloom: notice all the extra vector constructios, applies, concats, etc

20:21 if instead you flattened seqs as part of the traversal, hiccup style, then you'd save a lot of construction/garbage costs

20:21 arrdem: Yep.

20:23 bbloom: oh, and then there's metadata:

20:23 '`^{:omg "this" :is "nuts"} x

20:23 ,'`^{:omg "this" :is "nuts"} x

20:23 clojurebot: (clojure.core/with-meta (quote sandbox/x) (clojure.core/apply clojure.core/hash-map (clojure.core/seq (clojure.core/concat (clojure.core/list :is) (clojure.core/list "nuts") (clojure.core/list :omg) (clojure.core/list "this")))))

20:23 bbloom: lol

20:24 arrdem: heh

20:24 bbloom: syntax quote is killing your perf :-P

20:24 Bronsa: bbloom: yeah right, I actually profiled that quite a while ago and I remember tej spending close to ~60% of the time flattening the bytecode

20:25 getting rid of that would be a good performance win

20:25 bbloom: that's why i do this: https://github.com/brandonbloom/fipp/blob/master/src/fipp/printer.clj#L28

20:25 Bronsa: bbloom: have you actually looked at how other lisps implement syntax-quote while writing backtick?

20:26 bbloom: where seqs are treated the same as a :span node: https://github.com/brandonbloom/fipp/blob/master/src/fipp/printer.clj#L43-L44

20:26 arrdem: &(seq? {})

20:26 lazybot: ⇒ false

20:26 bbloom: Bronsa: clojure's syntax-quote is pretty standard, but has some oddities regarding 1) metadata and 2) namespaces & symbol qualification

20:26 and 3) the pretty standard gensym unification extension

20:27 Bronsa: 2 and 3 shouldn't cause any performance problem here

20:27 1 probably does since it's operating on read-time literals that will have line/column/file metadata

20:27 bbloom: yeah, both of those happen statically

20:28 yup :-/

20:28 but good news is that you can just remove the `, ~, and ~@s and put a little flattening recursive walk around the whole thing, and the code basically doesn't need to change beyond that

20:28 should just be faster AND prettier

20:29 Bronsa: I belive you on faster, not sure about the prettier ;P

20:29 bbloom: Bronsa: how is simply removing some sigils not prettier?

20:29 arrdem: bbloom: I don't think it's that trivial... remember the single op representation is [:keyword [] ..] and (seq? []) is definitely true.

20:29 bbloom: ,(seq? []) ;nope

20:29 clojurebot: false

20:30 arrdem: why do I even bother..

20:30 shrug. not the way I would have expected that to work. okay.

20:31 bbloom: ~colls

20:31 clojurebot: colls is http://www.brainonfire.net/files/seqs-and-colls/main.html

20:32 Bronsa: arrdem: you're thinking of seqable? which is not even in core unfortunately

20:32 bbloom: ah nevermind I get what you're saying now

20:33 bbloom: so the way it would work is, -emit would output nested bytecode and then flatten it before passing it to the bytecode interpreter

20:33 bbloom: Bronsa: yup

20:33 and as a bonus, the whole thing becomes lazy

20:34 Bronsa: bbloom: not too sure if that'd be a feature we'd care about

20:35 bytecode always needs to be emitted, being it generated lazily only adds overhead

20:35 bbloom: Bronsa: won't hurt anything

20:37 Bronsa: https://github.com/clojure/core.async/commit/4b06327455d993930a121db7ecfadc6359a23e95 looks like Rich forgot to commit this `transformer` function

20:40 arrdem: Bronsa: hum... I guess this means (emit) should be AST -> (Seq Class) and then do (doseq [c classes] (load-class! (class->bytecode c)))

20:40 which coincidentally is what I was looking at for Oxcart :D

20:40 rather than just injecting classes in-place when they are generated..

20:43 Bronsa: ;; (The hairier macro-character definitions, for #\# and #\`, are

20:43 ;; defined elsewhere, in their own source files.)

20:43 great I love searching for files

20:44 arrdem: Class being java.lang.Class or "class"?

20:44 arrdem: Bronsa: class AST

20:45 bbloom: Bronsa: where's that comment :-)

20:45 Bronsa: bbloom: sbcl/src/code/reader.lisp

20:45 backq.lisp is where ` is defined btw

20:45 * bbloom brandon is ashamed he doesn't have that source on his box :-P

20:46 Bronsa: arrdem: sounds reasonable, but I'm not 100% sure it's going to be that easy

20:46 arrdem: I'm worried about nested functions for example

20:47 arrdem: Bronsa: state monad or just a thread local atom. I'm kicking off a branch aimed at the latter.

20:47 Bronsa: bbloom: it's never been a very pleasant read

20:47 * arrdem needs to play with sbcl and haskell seriously

20:48 Bronsa: bbloom: reading through bits of the compiler made me realize how much not having implicit forward deps in clojure helps

20:49 brehaut: Bronsa: i believe F# explicitly forbids almost all forward deps they consider it so advantageous

20:50 bbloom: Bronsa: define before use is the only sane thing for non-mutually exclusive functions

20:50 brehaut: (theres a mutually recursive thing for stuff within the same module, and via interfacse with objects)

20:55 Bronsa: bbloom: so it looks like sbcl actually transforms `(~@'(1 2)) into `(1 2) at read time

20:56 being able to do that could help us for metadata at least

20:56 I could try doing something like that in tools.reader

20:57 bbloom: Bronsa: seriously, just get rid of the use of backquote in emit

20:57 Bronsa: it should be a very straightforward change

20:58 Bronsa: bbloom: yeah yeah that was unrelated to tej, I'm already sold on getting rid of ` there

20:59 bbloom: Bronsa: i don't think it pays to complicate the reader with a very simple partial evaluation scheme

20:59 arrdem: bbloom: agreed. let the compiler do the partial evaluation.

21:00 Bronsa: bbloom: I've always had an issue with ` as it makes the output of macroexpand-1 barely readable

21:02 sbcl also uses backq-cons and friends rather than cons so that the printer can output using `,@ rather than printing the expansion

21:03 bbloom: huh?

21:03 Bronsa: bbloom: * '`(,@x y) ;=> `(,@X Y)

21:04 backq-cons is just defined as (def back-cons cons)

21:04 it's only as a hint for the printer

21:05 bbloom: i get it, but seems weird that it would print that way as if nothing happened

21:05 ,'`(~@x y)

21:05 clojurebot: (clojure.core/seq (clojure.core/concat x (clojure.core/list (quote sandbox/y))))

21:06 Bronsa: bbloom: you'd really rather read a macroexpand output consisting of nested calls to seq/concat/list rather than some ~ and ~@ thrown here and there?

21:06 tuft: tried to have the OOP/FP debate with a new colleague today -- need to sharpen up my arguments =)

21:06 bbloom: no i just don't understand what cons has to do with it

21:07 tuft: doing a lot of FP here, but it's a hybrid language (Python), so it's a discussion every time someone new comes

21:07 Bronsa: bbloom: oh suppose ` in clojure wasn't emitting (clojure.core/seq ..) but (backtick-seq ..) with backtick-seq defined as seq

21:07 evaluation is the same but when the form gets printed, the printer can check whether op is one of the backtick ops and pretty print it

21:07 bbloom: yeah, i get that, but then the printer is lying to you... it's telling you that it's got syntax-quote, but it's really got backtick-seq

21:08 two different expressions shouldn't have the same printed representation

21:08 although i guess that happens plenty

21:08 ,(int 5)

21:08 clojurebot: 5

21:08 bbloom: ,(long 5)

21:08 clojurebot: 5

21:08 Bronsa: ,(symbol "String")

21:08 clojurebot: String

21:08 bbloom: grumble grumble

21:09 can't trust the damn printer at all

21:09 Bronsa: ^that caused me&Andy a lot of troubles while debugging t.a.j once

21:09 bbloom: I suppose there is a flag on the cl printer to turn off the backtick pretty printer

21:10 * bbloom mutters something about mathematica's FullForm

21:10 Bronsa: yes the printer is lying to me, but I really don't care about what ` expands to

21:10 that's an implementation detail to me, I just want to see how the expression is shaped

21:11 bbloom: until you have some piece of code that tries to deconstruct a backtick form, and you're pulling your hair out b/c testing if the symbol = 'syntax-quote doesn't work b/c you should be testing for back-cons

21:12 speaking of silly things like that

21:12 ,`syntax-quote

21:12 clojurebot: sandbox/syntax-quote

21:12 bbloom: ,`unquote

21:12 clojurebot: clojure.core/unquote

21:12 bbloom: ,(let [x 1] `(clojure.core/unquote x))

21:12 clojurebot: 1

21:12 Bronsa: bbloom: well we have metadata, just output ^:backtick clojure.core/seq rather than clojure.core/seq :P

21:12 bbloom: that's more reasonable...

21:13 still, damn lying reader :-P

21:13 Shayanjm: hmm

21:19 I'm trying to do the following data transformation but having serious troubles constructing my reduce function...

21:19 https://gist.github.com/shayanjm/054cdeb380bf2daf4b2b

21:19 any pointers would be very helpful

21:23 arrdem: Shayanjm: (for [tokens token-sequence] [(->> tokens (map first) (interpose " ") (reduce str)) (first (second tokens))])

21:23 oops. flip the first and second

21:24 there may be something faster than the (reduce str), but I don't know it offhand.

21:27 mange: I think (apply str ...) is a bit faster than (reduce str ...).

21:28 bbloom: apply str is definitely faster

21:28 reduce str will be quadratic

21:28 arrdem: bbloom: StringBuilder backed?

21:28 bbloom: variadic str uses a string builder, and will be amortized linear

21:28 arrdem: yep.

21:28 do that then.

21:29 bbloom: it's kinda a shame that (into "" ...) doesn't work :-)

21:29 arrdem: :P

21:29 Shayanjm: so (for [tokens token-sequence] [(->> tokens (map first) (interpose " ") (apply str)) (first (second tokens))])?

21:30 arrdem: Shayanjm: flip the first and second. it needs to be (second (first))

21:30 Shayanjm: right, because that's pulling the first (token, value) pair and taking the value of it.

21:30 Shayanjm: Right right

21:30 so I guess a follow up question: is there a way to do this in a single reduce function?

21:31 instead of using a for loop, etc.

21:31 arrdem: well... for isn't a loop. it's a sequence comprehension that's lazy.

21:31 so it's better than reduce :P

21:31 Shayanjm: :o

21:31 you just blew my mind

21:31 arrdem: :D

21:31 Shayanjm: I've been avoiding using for this whole time for that reason

21:31 "nah for's probably not lazy. Probably would be way less performant than reduce"

21:31 lol thank you so much

21:31 arrdem: http://grimoire.arrdem.com/1.6.0/clojure.core/for/

21:31 amalloy: Shayanjm: it's pretty easy to test that theory

21:32 Frozenlock: 'for' is awesome http://programming-puzzler.blogspot.ca/2013/03/logic-programming-is-overrated.html

21:32 amalloy: ,(first (for [x (range)] (+ 100 x)))

21:32 clojurebot: 100

21:32 arrdem: Frozenlock: haha love that post

21:32 amalloy: tada, must be lazy!

21:33 Frozenlock: It took me a while to notice the (range) in there

21:34 ... which is why it must be lazy.... for those even slower than me :-p

21:57 cespare: If I change from plain jetty to http-kit, does that change/break usage of dynamic vars?

21:57 given that dynamic vars are thread-local and http-kit is presumably multiplexing multiple requests onto a single thread?

22:41 justin_smith: cespare: yeah, you'll have to avoid using dynamic vars mostly with http-kit

22:41 which is for the best, I think

22:42 you can just put whatever data you need for that request into the request map intself

22:42 (if it is not localized in lifetime enough to be a local in one let block, of course)

22:45 you already have the request map as a per-request data store, you don't need to also assume that a per-thread data store will also map seamlessly to per-request (this is ugly even if you aren't using http-kit)

22:51 bsima: Are there any API docs for the enlive library? I'm doing some web scraping…

23:02 ddellacosta: bsima: you're probably best of digging through the code itself, in my experience. Other than that there is just the main README and tutorials linked to from there (https://github.com/cgrand/enlive)

23:02 *best off

23:03 bsima: Yeah I've decided that's what I'll do. The code is a tiny bit messy though… maybe api docs will be a future pull request of mine…

23:13 hellofunk: is there a more idiomatic/efficient way to write (or (= t 2) (= t 33) (= t 56)) for checking if a value is one of three possibilities?

23:13 technomancy: ,(#{2 33 56} 2)

23:13 clojurebot: 2

23:13 Frozenlock: nooooo, I wanted to be the one to answer that!

23:13 hellofunk: well now how about that

23:14 technomancy: Frozenlock: learn dvorak and type fast like meeeeee

23:14 (never mind that none of those were letters)

23:15 hellofunk: technomancy are you referring to the new world symphony?

23:15 Frozenlock: Is there a difference in speed for (some #{2} [2 33 56])?

23:15 amalloy: Frozenlock: well, do you think there should be?

23:16 Frozenlock: no...

23:16 * Frozenlock looks to see if it's a trap

23:17 amalloy: of course, if they're both literals it's O(0), because you could just reduce to either true or false

23:17 but try making the set of numbers to compare against larger, say a million elements, and imagine someone passed it to you

23:17 * hellofunk is imagining

23:18 hellofunk: (some.. ) will bail on the first match, right? so out of a million, if the 10th matches, only 10 were looked at

23:18 does the set as function behave that way as well?

23:19 Frozenlock: ,(time ((set (range 1000000)) 2))

23:19 clojurebot: eval service is offline

23:19 amalloy: like, i'm imagining (let [candidates (vec (range 1e6))] (fn [x] (some #{x} candidates))) vs (let [candidates (set (range 1e6))] (fn [x] (candidates x)))

23:20 hellofunk: amalloy my *guess* is that the some.. operation is better performant

23:20 amalloy: hellofunk: no, it is terrible

23:20 Frozenlock: Really? In my repl the 'some' is much, much faster

23:20 amalloy: if the thing you're looking for is the last element, you have to look at every possible item in the seq

23:21 hellofunk: amalloy so how does the set-as-function do it, not also looking at every possible item?

23:21 amalloy: sets are hashtables

23:21 it hashes the input, looks in the place it should be, and returns true if it was there

23:21 hellofunk: amalloy ah, there like an optimized tree behind the scenes and handled thusly rather than sequentially

23:21 amalloy: (the algorithm is more complicated than that because of persistent data structures, but that's an idea)

23:21 Frozenlock: (time (some #{1000000} (range 1000000))) ---> 166ms

23:22 (time ((set (range 1000000)) 2)) ----> 1109ms

23:22 amalloy: Frozenlock: you're timing the wrong thing

23:22 Frozenlock: the time to make the set?

23:22 hellofunk: should time something late in the sequence, not early

23:22 amalloy: yes

23:22 take the two functions i defined above

23:22 def them to via-set and via-vec

23:22 and time them on looking up (dec 1e6)

23:23 Frozenlock: okay... but why would we already have the set ready?

23:24 amalloy: Frozenlock: because you're planning to compare against it often, in some app that loves to check whether x is either 1 or 5 or 22 or whatever

23:24 the original example was (or (= t 2) (= t 33) (= t 56))

23:24 it you want to look up against that often, of course you'll define a set #{2 33 56} once, and then use it over and over

23:24 ddellacosta_: ,(println "test")

23:24 clojurebot: test\n

23:24 amalloy: and of course if you only want to look up once, who cares what's fast

23:25 Frozenlock: Makes sense.

23:25 ddellacosta: ,(println "test")

23:25 clojurebot: eval service is offline

23:25 ddellacosta: Frozenlock: you can't use clojurebot either?

23:25 amalloy: ,1

23:25 clojurebot: 1

23:26 Frozenlock: Tho I might have taken for granted that (#{...} x) is faster than 'some' for all cases, but it really depends if you are always doing the same comparison.

23:26 ddellacosta: no. Clojurebot hates us I suppose.

23:26 ddellacosta: Frozenlock: well, for me it rather seems that hiredman hates me: https://github.com/hiredman/clojurebot/blob/master/clojurebot-facts/src/clojurebot/facts.clj#L72

23:26 amalloy: Frozenlock: using a literal set is never going to be fast

23:27 ddellacosta: Frozenlock: but not sure why that's true for you. Maybe he has blocked you too randomly and hasn't committed it. Ridiculous.

23:27 amalloy: because you have to build the set before using it each time, which takes linear time

23:27 Frozenlock: ddellacosta: loool

23:27 hellofunk: amalloy unless you build it just once

23:27 amalloy: hellofunk: right, i meant a literal set inline

23:27 obviously if you let it, as in my example, and use it often, that's fast

23:28 hellofunk: there's nothing like a good let over lambda

23:28 * hellofunk cracks himself up

23:29 hellofunk: ddellacosta aren't you getting hit by a major typhoon like right now?

23:29 ddellacosta: hellofunk: yeah, supposedly...we'll see!

23:29 hellofunk: saw it on the news

23:30 seems like every year they say "the biggest one yet!"

23:31 amalloy where did you find your prowess, were you born programming?

23:35 i suppose that sounded rhetorical yet it was not.

23:37 if there was an equivalent to practicing musical scales for programming, i'd think a few of you did it for many hours a day for many years, from the insight that's shared in here

23:38 Shayanjm: No kidding

23:40 amalloy: hanging out in irc and on stackoverflow and answering questions is a big help. even if you get all the answers wrong for months, doing the research to formulate a plausible answer, and then being corrected by someone who knows more, is a great way to expand your knowledge

23:40 arrdem: TL;DR while getting corrected by amalloy may be bad for the ego, it's good for the code :P

23:40 hellofunk: amalloy it's hard for me to imagine you getting all the answers wrong for months :)

23:42 amalloy: here's a short article about eric lippert - the advice made a big impact on me: http://www.informit.com/articles/article.aspx?p=1919436

23:42 arrdem: the tldr is actually that i started learning clojure by: learning the absolute basics, then hanging out in #clojure and listening, and trying to repeat answers i'd heard already

23:42 technomancy: hanging out on IRC you just get exposed to ambient information

23:43 amalloy: there's nothing magical about it

23:43 technomancy: for instance I've never done cljs but I can still tell when people make certain common mistakes

23:43 same with vim

23:43 amalloy: right, same here

23:43 arrdem: amalloy: funny to hear you say that. I'd say the same with you, technomancy and the rest of the lurkers as primary sources

23:44 amalloy: sure. technomancy has been around longer than i have, of course - i was learning especially from him, hiredman, and chouser, iirc

23:44 hellofunk: inspiring

23:45 amalloy: plus i learned some fun tricks by reading others' 4clojure solutions

23:45 technomancy: true fact: when we hired hiredman there was some reluctance because we were afraid he'd have less time to help people on IRC

23:45 hellofunk: 4clojure is amazing stuff man. i think it's the single best tool in becoming good at clojure (and I have a long way to go)

23:46 amalloy: i'm glad it's still finding new people to help

23:46 hellofunk: amalloy i hope that site doesn't go anywhere (and its database of answers)

23:46 amalloy: hellofunk: i don't have any plans to take it down

23:47 hellofunk: amalloy i'd love to see just an athology of sorts of all the questions and the answers by the top 100 users for each question. that is better than any book.

23:48 technomancy: someone should do machine learning on the logs

23:48 amalloy: hmmm

23:48 technomancy: maybe ... someone who is looking to learn clojure

23:48 amalloy: technomancy: devn did that, or something like it

23:48 * technomancy glances at hellofunk

23:48 technomancy: oh, that's right

23:48 amalloy: http://getclojure.com/

23:48 technomancy: did it classify the questions and rank them?

23:48 hellofunk: as I've gone through the site, i've taken pdf exports of certain questions answers that were thought provoking, but it's time-consuming to do that for all of them

23:48 arrdem: (inc technomancy) ;; I had the link to getclojure months ago and lost it

23:48 lazybot: ⇒ 118

23:49 technomancy: appears to be borked

23:49 arrdem: hork and bork.. totally technical terms

23:49 hellofunk: i cannot tell what getclojure is supposed to be/do

23:49 amalloy: huh, that's a shame. he should have written it in a more stable language, like php

23:49 arrdem: amalloy: but then his immutable dates would have a modify method...

23:50 amalloy: hellofunk: you were supposed to enter functions you're interested in, and it would search the #clojure logs for example uses of it

23:50 hellofunk: ah

Logging service provided by n01se.net