#clojure log - Jan 07 2015

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

0:03 luxbock: yeah I'm talking about writing data to a file

0:04 I have a transducer that does a series of transformations on a datastructure, and I want to save the end result to file

0:04 or it's a bit more complicated than that

0:07 I have a list of nodes which I encode to binary via ztellman's Gloss library, and I want to write these to a file

0:08 but I also need to create a header that tells me at what byte count is each item located in that file

0:09 so was planning on creating a transducer that takes an element, encodes it as a bytebuffer, checks how many bytes it has and then saves that into a file, returning the byte-count

0:09 and then I can create the header from those byte-counts afterwards

0:10 but I wasn't sure if this is a good idea or not, so I thought to ask here first

0:10 ztellman: luxbock: you're encoding it with 'gloss.io/encode'?

0:11 luxbock: ztellman: yes

0:12 ztellman: luxbock: no need to use a transducer, just use (->> bufs (map #(.remaining %)) (reductions +))

0:12 and potentially add a side-effect to the .remaining call if you want to do I/O as you're iterating

0:14 luxbock: ztellman: the Clojure datastructures that I'm encoding are coming from a C API call, and they represent results of simulation that takes up a lot of memory, so one of my goals is to try to save the results of the simulation without running out of it

0:14 so I'm trying to think of a way to process each of the nodes in my list individually

0:15 ztellman: luxbock: so #(let [size (.remaining %)] (append-to-file %) size)

0:15 same basic deal

0:15 luxbock: ztellman: cool I'll give that a try

0:16 ztellman: that'll have to be a scratch file you're appending to, though

0:16 if you want to have the header be at the front of the file

0:16 or put a fake header in your file and then overwrite it

0:17 luxbock: ztellman: yeah I was considering doing the latter

0:17 thanks for all of your libraries btw, with this project I've been using byte-streams, vertigo, potemkin and Gloss :)

0:17 ztellman: haha

0:17 vertigo!

0:17 glad someone's using it

0:17 luxbock: I'm using it with clj-native to perform the C API calls

0:18 ztellman: cool, let me know if you have any issues there

0:18 that's a use case it was designed for, but I never actually used it for that myself

0:19 luxbock: ztellman: there was someone on the Clojure ML asking a Gloss question a few days ago

0:19 https://groups.google.com/forum/#!topic/clojure/NxsCPBk12mE

0:19 ztellman: oh, thanks

0:19 luxbock: I didn't know how to do what he wanted and I suspect it might be imposible

0:19 ztellman: I need to create some central place for questions

0:20 luxbock: ohh, actually I misread what he was asking

0:48 ztellman: any reason why `defcodec` shouldn't take the same pre and post-decoder functions as its arguments as `compile-fram` does?

0:49 I find myself using (def foo (gc/compile-frame X Y Z)) a lot because I usually want to clean up the data a bit

0:49 ztellman: luxbock: that would be atypical for a def form

0:49 but I dunno, I'm currently scoping out a ground-up rewrite, maybe I'll rethink that

0:52 yeah, I think I prefer that to having a complex set of arguments to a def-form

0:53 luxbock: ztellman: when I searched for examples of people using Gloss I noticed a lot of them use defcodec around compile-frame

0:53 ztellman: fair enough

0:54 luxbock: think I might do that as well, just because it makes the code a bit easier to read, and I assume there's no drawbacks

1:00 ddellacosta: not exactly Clojure related, but does anyone have good reading suggestions for getting a good understanding of the JVM?

1:02 rs0: ddellacosta: that's a pretty huge topic

1:02 mfikes: ddellacosta: I like Goetz JCiP for the JVM's memory model.

1:02 rs0: ddellacosta: there's performance, bytecode, the JIT compiler, the garbage collector... even the JVM spec only covers a small fraction of the functionality in a typical JVM

1:03 ddellacosta: mfikes: this one, right? http://www.amazon.com/Java-Concurrency-Practice-Brian-Goetz/dp/0321349601/ref=sr_1_1?ie=UTF8&qid=1420610526&sr=8-1&keywords=brian+goetz

1:04 mfikes: ddellacosta: Yep.

1:04 ddellacosta: mfikes: gotcha, thanks

1:05 rs0: speaking of which, http://docs.oracle.com/javase/specs/jls/se8/html/index.html

1:05 or rather http://docs.oracle.com/javase/specs/jvms/se8/html/index.html

1:07 mfikes: ddellacosta: But that only really covers one aspect of the JVM, as rs0 is saying. (But, it seemed be the part of the JVM that cost me the most cognitive load.)

1:08 ddellacosta: mfikes: yeah, I was just interested in getting a kind of open-ended response to see what folk recommended. I'm interested in all sorts of topics surrounding the JVM, in particular what Clojure developers would care about.

1:09 what folks*

1:10 but otherwise, I'm also very much interested in just simply understanding basics about the JVM, like how memory is structured and how to use visualvm effectively, for example.

1:11 mfikes: ddellacosta: Then there's things like value types :)

1:11 ddellacosta: for example, this kind of information: http://blog.jamesdbloom.com/JVMInternals.html

1:12 mfikes: Are you talking about these? http://martinfowler.com/eaaCatalog/valueObject.html

1:13 rs0: ddellacosta: http://www.amazon.com/dp/1449358454 and http://www.amazon.com/dp/0137142528

1:13 ddellacosta: rs0: have you read both of those? Which do you prefer, they seem to cover the same topics?

1:13 rs0: ddellacosta: maybe http://cr.openjdk.java.net/~jrose/values/values-0.html ?

1:14 ddellacosta: the first book is more recent, but i haven't read as much of it as the second one

1:14 mfikes: ddellacosta: If you have large array Point objects, those Point objects could be all over the heap, and expensive to touch.

1:14 ddellacosta: Yes, the John Rose stuff

1:14 rs0: mfikes: have you played with the Valhalla prototypes yet?

1:14 ddellacosta: rs0, mfikes: okay, thanks

1:16 mfikes: rs0: No, what is that?

1:16 ddellacosta: but sounds like value types are not presently a part of the JVM?

1:16 rs0: mfikes: the prototype implementation of specialization, e.g. Box<int> instead of Box<Integer>

1:16 mfikes: http://cr.openjdk.java.net/~briangoetz/valhalla/specialization.html

1:17 mfikes: rs0: Cool stuff. :)

1:17 ddellacosta: Right, value types are a hopeful future, an aspect of the JVM that Clojure programmers may care deeply about :)

1:18 ddellacosta: mfikes: got it, thanks for the clarification

2:22 irctc: (defmacro abc [name] (println name ", hello!"))

2:22 why (macroexpand '(abc "John")) return nil?

2:22 luxbock: irctc: println returns nil

2:22 irctc: you probably want macroexpand-1

3:27 macdice: total newbie used to other lisps: shouldn't that be (defmacro abc [name] `(println ,name ", hello!")) ?

3:28 luxbock: macdice: yeah, except in Clojure it's ~name

3:29 macdice: ah. thanks

3:48 dysfun: naming things is hard. especially protocols

3:52 rritoch: dysfun: Did you get my message about lein-sablecc?

3:53 dysfun: I've tested the generated AST and even been able to create a functional hello world from a custom interpreted language with it so it looks like 1.1.0 is fully functional.

3:56 dysfun: rritoch: yes, but every time i've come back to my screen you've logged out by the time i come to reply :)

3:56 good work was mostly what i wanted to say

3:56 i didn't think i'd have a need for it, but i found a new yak

3:58 then again, it might be sufficiently complex i just use parse-ez and to hell with performance

3:58 rritoch: dysfun: hehe, SableCC is it's own yak farm collective... It takes about 5 minutes to code the grammar and hours to resolve conflicts.

3:58 dysfun: haha, yes

3:58 imagine me and my friend poring over what's wrong with our perl 5 grammar

4:02 rritoch: dysfun: The most helpful article I've found so far is @ http://www.sable.mcgill.ca/listarchives/sablecc-list/msg00241.html

4:03 dysfun: I almost missed it in the google search results because it doesn't seem related, but it has some very helpful tips which has helped me resolve most conflicts in less time.

4:03 dysfun: oh yes, java is so simple

4:03 we just need a naming convention!

4:03 but the tips look good

4:04 you sort of get into the swing of resolving it after a while though, it's almost fun

4:04 a bit like mod_rewrite rules, with similar levels of stockholm syndrome

4:06 rritoch: As for your naming issue, I usually just name things by the first thing I can think of, and eventually change the name to whatever I accidentally type most often instead of the assigned name.

4:06 dysfun: heh, i do that too

4:07 programming's a strange game sometimes

4:07 hellofunk: dysfun: yes. and sometimes, after doing it every day, all day, for many days, you just feel like you've gotten into a strange loop

4:08 dysfun: ah, someone else lives in groundhog day

4:08 deathmarch projects are the worst

4:08 hellofunk: https://thestrangeloop.com/

4:08 dysfun: clojure seems the most generally fun time i spend programming, which is why i keep doing it

4:10 i'm still looking for a good language for systems programming though. every time i think i've found something i realise it's crap and just use c

4:10 ocaml seems the least broken, but it's hardly unbroken. the syntax is the first sign something is very wrong.

4:10 hellofunk: dysfun: have you considered just using assembly. it's great for systems.

4:12 dysfun: if i never have to program assembly language again it'll still be too much for one life in what i've already done

4:12 it's been so many years since i could do a better job at assembly than a compiler

4:13 technology is pretty awesome

4:13 rritoch: dysfun: C is really the best language for systems programming. If you compare the generated C code to generated C++ code you'll see C++ code produces a lot of junk symbols that aren't really part of the solution to the given problem.

4:14 dysfun: well it doesn't have a choice because of the language

4:14 but in the general case, i find my c++ tends to be "c with classes" anyway, because c++ is hateful

4:15 i finally found myself having to deal with utf8 data in c++ and by the end of discovering how the standard library mangles it i was ready to cry about the state of systems programming in 2014

4:17 in the end i was relieved to find that somebody managed to implement the same thing i actually wanted already in C and i was happy

4:19 rritoch: dysfun: Hmm, I think I dealt with that issue already but I don't have a clue where I the code is. I was trying to make a plugin to metatrader to publish and export metatrader features via web services so it could be controlled from Java.

4:21 SagiCZ1: rritoch: metatrader as in the forex/futures client?

4:21 rritoch: dysfun: If I recall correctly I ended up converting UTF-8 to UTF-16 internally and used widechars

4:21 SagiCZ1: Yeah.

4:22 dysfun: rritoch: bingo!

4:22 SagiCZ1: rritoch: I found that thing so ugly and buggy that i am currently in the state of writing my own trading platform in clojure.. note that i dont aim to trade in high frequencies so i dont need extremely low latency

4:22 dysfun: rritoch: actually it's all pluggable of course (and why wouldn't it be when you only ever want a handful of things and it could all be made so much easier with a different api?)

4:24 rritoch: SagiCZ1: Yes, and their internal data types are horrible and inconsistent. After about the millionth segfault I gave up on the project.

4:24 SagiCZ1: Their string length was just to small to do anything of value.

4:24 SagiCZ1: rritoch: i was trying to learn and use that MQL that they want you to write the plugins/experts in.. i cried

4:25 dysfun: oh, another domain specific extension language! just what the world needed!

4:25 SagiCZ1: dysfun: yup!

4:25 i coudlnt trust my money with that thing.. so i noped out

4:26 rritoch: SagiCZ1: Yes, it is the MQL strings and arrays that are the problem, passing them to and from .dll plugins is a nightmare, but the strings themselves are just too small and the system usually segfaults randomly when you change the string length from a plugin.

4:26 dysfun: did you see gary bernhardt tweet the homepage of mathematica yesterday? nice comment on how the mess of code on the first page produced a pretty graph and how it's all so easy and understandable that dear god has wolfram ever programmed a thing before?

4:27 https://twitter.com/garybernhardt/status/552224807664644096

4:28 SagiCZ1: rritoch: sounds really bad.. btw people in the past sometimes used Common Lisp for trading platforms.. it is actually what brought me to clojure. The rapid prototyping is very handy

4:28 dysfun: SagiCZ1: you mean the repl? or the fact everything is pretty easy to do?

4:29 SagiCZ1: dysfun: both actually

4:29 dysfun: the latter i think lends clojure to being a good maintenance programming language as well as good for prototyping

4:29 and since most programming is maintenance...

4:29 SagiCZ1: the only disadvantage is the garbage collection which could throw of some microsecond transactions.. one just has to keep that in mind

4:30 dysfun: coming from perl, where they like to keep things simple too, clojure libraries have felt comfortable

4:30 SagiCZ1: i see

4:30 dysfun: they're the minority. don't worry about it

4:30 you should be making it up in numbers

4:30 SagiCZ1: i am aiming at that

4:30 rritoch: SagiCZ1: Well most trading systems use MT4 so it is a neccissary evil, unfortunatly they never published their protocol to allow third parties to develop functional trading platforms that are compatible with it. Developing a functional trading platform shouldn't be that difficult of a task, the hard part will be getting the brokers to use it.

4:31 SagiCZ1: i also cant not mention that testing pure functions is a pure bliss compared to testing mutable mess of c++ or java..

4:31 rritoch: actually you dont need to force the brokers to do anything.. most brokers offer platform independent api

4:31 dysfun: yes, testing is brilliant in clojure

4:31 i like midje

4:31 SagiCZ1: most of them offer something called FIX

4:32 or some web based streaming such as REST

4:32 i am already trading my demo through clojure with no problems

4:32 as far as the trading systems go, i would have to rewrite them to use them, thats true

4:33 rritoch: SagiCZ1: Well the companies I went through only provided MT4 services. If they had provided REST services I would probably still be trading.

4:33 SagiCZ1: these have rest, java, fix http://developer.oanda.com/

4:33 rritoch: Lol, My account was with Oanda

4:34 SagiCZ1: i guess you just wasnt looking hard enough mate! haha

4:34 rritoch: That must be new, I've never seen it before

4:35 Anyhow, they suspended my account, aparently new U.S. laws don't allow expats to utilize foreign trading systems, and I was using Oanda/Singapore

4:35 It was the only way I could legally trade gold/silver/platinum

4:36 SagiCZ1: rritoch: that sounds super odd

4:36 TMA: SagiCZ1: FIX is _the_ sane protocol for trading [considering the alternatives, like polling tables via JDBC -- each table row basically contains two columns -- message type and encoded message string]

4:37 rritoch: SagiCZ1: They gave me an option to re-open my account under Oanda US, I just wasn't interested at the time it happened.

4:37 hellofunk: rritoch: why would you need a foreign account to trade gold or silver?

4:38 SagiCZ1: TMA: yeah well i started with the REST API, since i heard that FIX is the grandfather of trading protocols

4:38 rritoch: hellofunk: The U.S. made it illegal to trade gold and silver.

4:38 hellofunk: rritoch: what? people trade gold and silver all the time, what are you referring to?

4:38 rritoch: hellofunk: At least within the U.S.

4:39 hellofunk: rritoch: that is completely false. the gold and silver market is huge in U.S.

4:39 rritoch: you must be referring to something very specific and unusual

4:39 rritoch: hellofunk: Well maybe they revoked the law

4:40 hellofunk: rritoch: it has been completely legal to trade gold and silver in the U.S. for many decades, there has never been a time when you couldn't

4:40 rritoch: hellofunk: The law caused most brokers to deny and cancel the accounts of U.S. customers

4:40 hellofunk: That isn't true

4:40 SagiCZ1: gold/silver is very vague.. it depends if it was CFD or currency/silver or something else

4:40 hellofunk: rritoch: you must be talking about a very specific instrument, because general gold and silver trading has always been available

4:41 Gold futures, gold ETFs, physical bars of gold, they are all an active market and have been at least during my entire career

4:42 SagiCZ1: so many traders around here

4:42 rritoch: https://gold-forum.kitco.com/showthread.php?86011-It-is-illegal-to-trade-currencies-against-precious-metals-now

4:43 This was another con-game by the current administration

4:43 hellofunk: rritoch: you are talking about Forex trading, not metal trading? big difference

4:44 rritoch: it is true that Forex laws have changed a lot in recent years, but trading metals has never been illegal

4:44 rritoch: hellofunk: As far as I know it is still illegal to trade any precious metal in the U.S., the only way around it is to trade ETF's

4:45 hellofunk: Any metal trading your doing is probably only backed by ETF's.

4:45 hellofunk: rritoch: that is completely false.

4:45 rritoch: heck no. the futures industry?

4:47 nonuby: most idiomatic way to test if a parameter is a function?

4:47 grr. fn? was trying to find a function?

4:48 rritoch: http://www.financialsense.com/contributors/james-bibbings/2011/07/19/dodd-frank-restrictions-on-gold-and-silver-derivatives-market-now-in-effect

4:48 hellofunk: Per that article the law is in effect, but parts of it arn't yet being enforced.

4:49 hellofunk: But until the law is changed, it is technically illegal to trade precious metals in the U.S.

4:50 hellofunk: rritoch: wrong. that article is about OTC and Forex.

4:50 rritoch: hellofunk: I'm not a lawyer, if you want to take the risk that's your decision

4:51 hellofunk: My lawyer assured me that it's illegal and the only way I could do it legally was by utilizing foreign brokers

4:51 hellofunk: rritoch: it's not a risk. the futures market is vast and legal. I work for an American broker. it is a pillar of the economy to allow metal trading

4:51 rritoch: check out the futures industry, it's traded by the billions every day

4:52 but OTC and Forex are different markets and those have changed recently. if all you had was a Forex account, then this would have affected you, yes

4:55 rritoch: hellofunk: I wasn't involved in futures trading, and I'm not willing to risk any SEC involvement in my business. The airfare alone would bankrupt me.

4:57 Speaking of "illegals" exporting new cryptography technologies is also illegal, which is one benefit of being an expat since I'm never exporting cryptography technology from the U.S. but importing it into the U.S.

4:58 They're all a bunch of ignorant laws limiting technology development, and the politicians that wrote those laws should all be fired.

4:59 I'm not sure if the precious metal laws effect software development though, but I wouldn't want to find out the hard way.

5:01 hellofunk: rritoch: the primary mechanism for trading metals in the world is the futures industry, which is gigantic and legal. if you were talking about unregulated markets like OTC and Forex, then of course those markets are in jeopardy. de-centralized financial markets can be a fragile spot for any economy, hence the laws you mentioned.

5:02 rritoch: feel free to join me in #clojure-offtopic if you want to discuss further

5:06 rritoch: hellofunk: No thanks. I need to get back to work, but to bring it back on topic, clojure based trading libraries would certainly be a useful addition to clojars.

5:08 hellofunk: There is a disproportional overlap between the financial industry and clojure developers, so it is likely a good niche for clojure dominance.

5:08 hellofunk: rritoch: i have found that any programming language has a large number of traders among its developers.

5:08 clgv: Happy New Year to all Clojurians ;)

5:09 rritoch: hellofunk: I'll pm you

5:09 hellofunk: This is delving into propriatary issues

5:11 zarkone: hello all! i have list of vectors, how can i use mapv with it without macro?

5:13 with mcaro i would do `(mapv f ~@elems)

5:14 clgv: zarkone: `apply`

5:14 (apply mapv f elems)

5:14 zarkone: clgv

5:14 i'm idiot

5:14 thanks

5:15 clgv: ,(apply mapv vector '([1 2] [3 4]))

5:15 clojurebot: [[1 3] [2 4]]

5:30 TEttinger: ,(apply mapv identity '([1 2] [3 4]))

5:30 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (2) passed to: core/identity>

5:30 TEttinger: ah

5:40 CookedGryphon: does anyone have any good hints for better git merging with clojure?

5:41 I find I get far fewer merge conflicts in general with clojure code, but when I do get them they're often a bit annoying or not really conflicts

5:43 martinklepsch: I'm using an atom in tests to count some requests made to a httpkit-fake thing: https://gist.github.com/6cdb6ee4c5516b6186ae

5:43 rritoch: CookedGryphon: I use tortoisemerge which I believe came automatically when I installed tortoisesvn

5:44 martinklepsch: for some wierd reason these atoms sometimes have values that are not plausible except under the assumption that an old atom with an old value is recycled

5:45 zot: is there a way to use lein to generate a jar of all dependencies, so that i can separate out the building (and uploading) of a large dependency set, from the actual project code?

5:46 martinklepsch: is there anything wrong with how I use atoms there? should I use something different?

5:46 zot: how do you mean? if there are separate dependencies as jars you must have gotten them from somewhere no?

5:47 zot: martinklepsch: "i" didn't get them per se; leiningen downloaded them on my behalf, and i have no idea of what the entire chain is, and i don't want to. uberjar already does this part — i just haven't found the deps part split out (so far)

5:47 rritoch: zot: I believe it would be possible to do it using a custom profile while doing a lein uberjar, just have that custom profile use an empty directory for it's :source-paths. I don't know for a fact it would work, but it should.

5:48 zot: rritoch: clever. i may try this :)

5:49 rritoch: zot: Also put all your deps in the :dev profile, that will keep them from being included in your generated uberjar for the actual application.

5:50 zot: The final part, of linking your uberjar to the single dependency jar would be the hard part, and I'm not sure how to do it.

5:51 zot: classpath isn't enough?

5:53 rritoch: zot: I suppose you can add it to your classpath, I was just thinking of something more elegant, like modifying the manifest https://github.com/technomancy/leiningen/blob/master/sample.project.clj#L417-L427

5:54 zot: ah. that is definitely more elegant :)

5:55 sm0ke: hello all

5:56 i have this toy usecase https://www.refheap.com/95825

5:56 can somebody explain how is this not vulnerable to head holding?

6:18 clgv: CookedGryphon: "BeyondCompare" as merge tool is an option though you have to buy it. usually, "meld" under linux suffices for me

6:18 hellofunk: sm0ke: this type of example confused me when I first started learning the language. maybe it still does. but if you switch the two count forms, do you see why it *would* retain the head?

6:19 sm0ke: hellofunk: chaning order is ok, it makes sense

6:20 but in the example let [lazy ..] reference is there throughout!

6:20 clgv: sm0ke: I suppose "locals clearing" avoids to hold the head of the sequence

6:20 hellofunk: sm0ke: actually your take while doesn't make sense to me. it is nil, no?

6:21 ,(take-while #(< 10 %) (range 20))

6:21 clojurebot: ()

6:22 sm0ke: oops (< % 10)

6:22 hellofunk: sm0ke: did you mean #(< % 400) instead if you are trying to chop the seq into 2 seqs

6:22 sm0ke: but i think that wont make a difference?

6:22 or would it?

6:22 clgv: sm0ke: https://www.refheap.com/95826

6:23 sm0ke: clgv: how the hell you get that so fast?

6:23 clgv: sm0ke: huh? what exactly do you mean?

6:23 sm0ke: the byte code?

6:23 makes sense

6:23 clgv: sm0ke: double click on a class file starts the decompiler GUI I use

6:23 sm0ke: (inc clgv)

6:23 lazybot: ⇒ 41

6:24 sm0ke: so clojure is setting it to nil just before function call

6:24 hellofunk: sm0ke: if you wait for the second count to count the beginning of the lazy seq, then the first count cannot throw away the head since the head is used in the second count, that comes after

6:25 sm0ke: but when you switch them, the head is no longer needed as it counts the rest of the seq

6:25 sm0ke: but there is still a problem what if i do .. alazy (take-while #(< 100000000 %) lazy)

6:26 i mean #(< % 100000000)

6:26 ugh

6:27 hellofunk: sm0ke: it would still depend on which end of the range you are counting first, right?

6:27 clgv: sm0ke: I'd say the original gist definitely keeps the first 400 realized elements in memory

6:28 sm0ke: yep

6:28 i think making alazy large would render localclearing useless

6:29 https://www.refheap.com/95827

6:30 is there a way around this?

6:30 clgv: sm0ke: partition + (map count)

6:30 hellofunk: just try this to see the issue: (count (range 100000000)) it takes a while but it completes for me

6:31 clgv: sm0ke: or more like something similar to partition-by

6:31 hellofunk: but if you count from teh head of the lazy seq before you count the send partition, then the head would not be retained

6:31 *second

6:32 switching them, and counting the second first, means the head is retained since it is used by the second count form

6:32 clgv: sm0ke: if you can transform it to pipeline style (->> lazy (clever-partition #(< % 400)) (map count)) - you'll be sure that it is not holding on to the head of the seq

6:33 sm0ke: let me try partitioning

6:33 hellofunk: sm0ke: your example is more or less the same as the one in the Oreilly book: (let [[t d] (split-with #(< % 12) (range 1e8))] [(count t) (count d)]) completes fine. but if you switch the counts, it is a memory erryr

6:34 *error

6:34 you can read the explanation on page 99 if you have the book :)

6:34 sm0ke: hellofunk: no its more than that, what if you substitute 12 with 1e8?

6:34 hellofunk: sm0ke: now you are talking about a different issue unrelated to head retention, no?

6:35 sm0ke: is it unrelated?

6:35 i just changed a value!

6:35 clgv: split-with sounds good

6:36 sm0ke: ,(doc split-with)

6:36 clojurebot: "([pred coll]); Returns a vector of [(take-while pred coll) (drop-while pred coll)]"

6:36 clgv: I totally forgot about that function ^^

6:36 sm0ke: i didnt even knew it exists

6:36 clgv: $source split-with

6:36 lazybot: split-with is http://is.gd/QsZ10c

6:36 hellofunk: sm0ke: well, count by itself does not hold onto the head, so i guess it is a head retention issue because you are asking it to hold onto the head when you put the count of the first partition *after* the count of the second

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

6:37 clgv: well, that implementation is about the same as your code - so I'd guess that'll be no solution

6:37 sm0ke: i have no luck with partition either

6:37 (let [[alazy blazy] (partition-by #(< % 100000000) lazy)]

6:38 hellofunk: the solution is to arrange your non-head-retaining actions in a way that their combination doesn't force head retention

6:38 which is the point of the Oreilly example

6:44 clgv: hellofunk: but that's tricky if you don't know which is the larger part (maybe that does not occur in practical problems)

6:45 hellofunk: i'm running this example right now, taking a few minutes for me: (let [[t d] (split-with #(< % 1e8) (range 1e8))] [(count t) (count d)])

6:45 clgv: it's not about which is larger, it's about which contains the head, which you would always know

6:46 clgv: ok the head of the original seq, right

6:46 hellofunk: yes

6:47 so actually in my most recent example, the ordering doesn't matter at all. both are memory errors.

6:49 the example made my computer sound like it was ready for liftoff

6:49 the ultimate "side effect"

6:49 clgv: :P

6:51 martinklepsch: ,(merge-with merge {:a {:b 1 :c 2} :x "test"} {:a {:c 3} :x "foo"})

6:51 clojurebot: #<ClassCastException java.lang.ClassCastException: java.lang.String cannot be cast to clojure.lang.IPersistentCollection>

6:52 martinklepsch: I kind of see why this breaks but is there a way to write this without a custom `merge` function?

6:52 clgv: martinklepsch: no. but some libs probably include a deep-merge already

6:53 the question reappeared here multiple times already

6:55 hellofunk: martinklepsch: i'd be more inclined to change the map and make x a key for a map so all "levels" of the map have similar types of values

6:55 ,(merge-with merge {:a {:b 1 :c 2} :x {:v "test"}} {:a {:c 3} :x {:v "foo"}})

6:55 clojurebot: {:x {:v "foo"}, :a {:c 3, :b 1}}

6:58 clgv: old contrib seemed to have a deep-merge-with

6:59 martinklepsch: you can use crossclj.info to look for those

7:07 dysfun: does core.async have a 'stop the world' mechanism such as might be required for a garbage collector to work properly?

7:08 clgv: dysfun: to get a consistent snapshot of all channels?

7:08 dysfun: to get a consistent snapshot of all refs in the world

7:08 if you have many thousands of refs

7:08 clgv: "refs" as in Clojure's `ref`?

7:08 dysfun: yes

7:09 clgv: Why is just using a transaction to read all of those not acceptable?

7:09 dysfun: can transactions scale to millions of refs?

7:10 clgv: dysfun: depends on what is done with them

7:11 dysfun: well, in this case, garbage collection

7:11 clgv: huh?

7:11 you can certainly run into problems with many short running transactions and some few long running transactions

7:12 dysfun: i want to have data that is generally manipulable as a map stored in a vector, like you have with a columnar store like hbase as a column primitive

7:12 clgv: dysfun: garbage collection is vm level, not really the level of your application

7:12 dysfun: i want to go through pruning data that i consider to be now unimportant

7:12 clgv: ah ok

7:13 dysfun: so how would you model that?

7:13 clgv: good question.

7:13 dysfun: heh :)

7:15 clgv: dysfun: are you sure you cant use one of the database options?

7:15 dysfun: it's a hobby thing, so i can't be bothered to faff around, it gets boring

7:15 clgv: dysfun: I still regret not having use a proper database for a certain use case. but I wont be able to change because of time constraints

7:16 dysfun: heh

7:18 i'm hoping all of my data will fit in memory for some time to come

7:18 clgv: dysfun: that was my starting assumption ;)

7:18 dysfun: hahaha

7:18 yeah, there's a point at which hadoop starts to appeal and then you know you're stuffed :)

7:18 clgv: the problem for me has been that clojure's persistent datastructure add quite some overhead

7:19 dysfun: really?

7:19 i thought they were reasonably space-efficient

7:19 clgv: my last quick work around has been to implement a map-alike that supports only the reading interfaces via a deftype

7:21 so I got something that works like a map with respect to reading - that worked since the data is read-only

7:21 just some analysis stuff. but an ordinary sql database would have been the best choice to start with...

7:21 dysfun: ooh, that's quite interesting. in my use case they're 99.9999% read-only

7:22 (famous last words!)

7:23 justin_smith: martinklepsch: for your atom issue, would retries account for the states you are talking about?

7:23 clgv: dysfun: CollReduce, Indexed, ILookup, Counted, IKVReduce are the interfaces/protocols I implemented

7:23 justin_smith: martinklepsch: remember that they don't lock, if two concurrent changes happen, the one which observes an inconsistency between what it first sees, and the value when it attempts to update, retries with the new value

7:24 dysfun: clgv: thanks

7:24 clgv: dysfun: if you got those, you can access the data in idiomatic clojure

7:25 dysfun: interesting. thanks.

7:25 clgv: dysfun: I have two deftypes Dataset and Row, to represent the data

7:27 dysfun: *nod*

7:30 clgv: dysfun: next time I'll use some kind of embedded sql database for that usecase

7:30 dysfun: heh. sqlite is pretty great

7:31 clgv: or even H2 or HSQLDB

7:31 dysfun: *nod*

7:36 hellofunk: sqlite offers some neat features that many other dbs don't have or are harder to use, like an all in-memory database

7:45 luxbock: I want to write X amount of zero-bytes to a file first, fill it with some other stuff, and then finally replace those zero-bytes with something meaningful in the end

7:45 I need to use RandomAccessFile for this right?

7:57 AeroNotix: luxbock: why do you need to write them to the file before determining what you need to write in the X bytes?

7:57 for efficiency?

7:58 luxbock: AeroNotix: I know the size of the header before but not the contents it has

7:58 header being the part of zero-bytes I want to re-write later

7:58 AeroNotix: Gotcha, still, omitting efficiency woes, I'd probably use an in-memory stream first and then copy it to disk later.

7:59 luxbock: AeroNotix: I'm trying to avoid running out of memory when reading the results of a large computation which I'm reading via API calls to a C program that performs it

8:00 the more efficient I'm with memory, the larger simulations I can run

8:00 AeroNotix: ok, so use a random access file then. I was just trying to save latency rather than memory.

8:00 but we're just pulling numbers out of our collective arses here.

8:01 Write the simplest thing and benchmark :)

8:01 luxbock: AeroNotix: thanks. latency is not an issue since this is run once and store for a long time type of operation

8:01 AeroNotix: oke doke

8:46 hellofunk: in Cursive keymaps anyone know what a diagonal arrow represents? left/right/up/down are obvious, but what is the diagonal arrow key?

8:47 and also, an arrow with a double dash intersecting it

8:51 jonathanj: hellofunk: does this help you: http://www.danrodney.com/mac/

8:52 (I don't use Cursive, so I'm not sure exactly what arrows you're seeing, but I think you're describing Home/End and PgUp/PgDn)

8:55 hellofunk: jonathanj: excellent, thank you!

9:03 H4ns: does apply realize its last argument? in other words, if a function has signature [ & foo] and i invoke it with a lazy seq using apply, would foo be a realization of that seq or would it be lazy as well?

9:05 justin_smith: &(apply (fn [x y & _] (+ x y)) (range))

9:05 lazybot: ⇒ 1

9:05 justin_smith: that would have been an infinite loop if apply realized any args past the first two

9:06 opqdonut: &(apply (fn [x y & _] (+ x y)) (range))

9:06 lazybot: ⇒ 1

9:06 justin_smith: well, if it realized the "last" arg at least (chunking, d'oh)

9:06 opqdonut: oh, that was already what you did, erm

9:06 &(apply (fn [x y & _] (+ x y)) 1 2 3 (range))

9:06 lazybot: ⇒ 3

9:06 justin_smith: yeah, that was like my exact code

9:06 opqdonut: that was what I meant to do

9:08 H4ns: interesting, thanks!\

9:08 Ninerian: Hello, i have a beginner question. When I use another namespace with require, I cannot access the methods which are defined the. But a predefined refer works. Is there something to notice?

9:09 opqdonut: if you require, you need to use a prefix

9:09 i.e. (require 'foo) (foo/function 1 2 3)

9:09 Ninerian: ‚(ns xml-to-plist.handler

9:09 (:require [xml-to-plist.dev :refer [browser-repl start-figwheel]] <— works

9:09 [xml-to-plist.util :refer [foo-cljx]] <— doesnt work

9:09 opqdonut: (refer 'foo) "mirrors" the definitions from foo to the current namespace

9:10 oh, you were talking about something different

9:11 Ninerian: i cannot call foo-cljx

9:11 but browser-repl

9:11 opqdonut: are you sure foo-cljx exists in xml-to-plist.util?

9:12 justin_smith: Ninerian: using a prefix is good style by the way, and on a pedantic note, functions are not methods

9:13 Ninerian: Yes it is. When I copy the function into xml-to-plist.dev and include into the refer vector it is available

9:18 Using the namespace with (require 'xml-to-plist.util) and calling it with the prefix works. What is the difference between (require) an (ns .. (:require)) ?

9:20 justin_smith: there is none

9:20 the best approach generally is (:require [foo.bar :as bar]) and then call foo.bar/baz as bar/baz

9:21 well, actually there is the difference that (ns ...) is a macro, so you don't need to quote things inside it

9:21 but require can do everything that :require in an ns form can do, and visa versa

9:29 yazirian: In the cljs case, the difference is where and when it's executed; you mention browser-repl so I assume that the real difference here is that (ns .. (:require)) is taking place in a file, whereas you may be typing (require ..) into a browser repl.

9:29 cljs, unlike clj, does not have access to its compiler

9:29 (if that isn't what you were doing -- i can't really tell from the question -- then nevermind :)

11:06 thheller: @dnolen_ what do you mean if you say :foreign-libs? is that non-closure compliant JS, or closure compliant but not in deps.js?

11:06 dnolen_: thheller: non-closure compliant JS

11:07 thheller: it's been there since the beginning so you can at least load foreign libs

11:07 thheller: but it was never that useful because it predated preamble

11:07 thheller: but if foreign libs supply their :requires and we preamble them - everything will just work

11:07 thheller: you mean provides?

11:08 dnolen_: thheller: no, foreign already have to say what they provide

11:08 thheller: that's how goog.require can work w/ them

11:08 thheller: ah but they may require CLJS code

11:08 got ya

11:08 dnolen_: thheller: foreign libs requiring CLJS code doesn't seem likely

11:09 foreign libs are exactly that, foreign JS stuff that Closure can't understand

11:09 thheller: ok, but one foreign lib may depend on another

11:09 dnolen_: thheller: so foreign libs should alway supply {:provide ... :requires ... :externs ...}

11:09 thheller: are you skipping over what I am saying? :) *:requires*

11:10 thheller: actual dependency resolution happens via Maven as usual

11:10 thheller: well, I meant to sort the preamble

11:12 foreign jquery, provides jquery, requires []

11:12 dnolen_: thheller: sorting the preamble is solve via :requires just like everything else

11:12 thheller: foreigh jquery-ui, provides jquery-ui, require jquery

11:12 something like that

11:12 dnolen_: thheller: how is this in conflict w/ what I just described?

11:13 {:provides "jquery.ui" :requires ["jquery"] :externs ["jquery.ui.externs.js"]}

11:13 thheller: no conflict, just making sure I understand correctly ;)

11:15 just thinking it is a bit tricky on the integration side

11:16 the CLJS code must somehow express that it depends on something foreign

11:16 otherwise the JS file will ALWAYS be preamble'd

11:17 but (ns my-ns (:require [jquery-ui])) won't work unless we do special tricks

11:17 cause goog.require('jquery-ui') doesn't work

11:17 dnolen_: thheller: yeah ok, I think you just don't understand that already works :foreign-libs is not well understood

11:17 thheller: http://lukevanderhart.com/2011/09/30/using-javascript-and-clojurescript.html

11:18 thheller: always being preambled is what you want for release builds anyway

11:18 thheller: anyways think about it some more, after you have a solid sense of what I'm talking about feel free to chime on ticket about issues

11:19 thheller: I'm pretty sure I got it, we just misunderstand each other

11:19 I'm talking about :foreign-libs in JARS via deps.clj

11:19 dnolen_: thheller: no tricks required for the require to work, it already works

11:20 thheller: just scan the classpath for deps.clj that matches

11:20 bbiab

11:55 thheller: dnolen_: I don't see how this is working with :advanced right now. if deps/-foreign? create a javascript file, prepend goog.provide statements and slurp the source of the foreign file. which we then treat like any JS file and pipe it into Closure Compiler which would then optimize it?

11:55 created a demo but that just fails with a nullpointerexception

11:56 maybe I'm doing it wrong

11:58 martinklepsch: thheller: I think you'd still need some combination deps.clj with an :externs key to do that

12:01 thheller: no I mean the process, we can't pipe a react.min.js into the Closure Compiler which the code is doing

12:01 unless I'm totally wrong

12:01 sure it all works in :none

12:01 dnolen_: thheller: read the ticket updated, you don't need to supply goog.provide because we will sort and insert between :preamble and the build

12:01 thheller: yes that the part that just broken anyway if it's doing that, foreign libs can't go into Closure

12:04 thheller: yeah thats what confusing me

12:04 dnolen_: thheller: just a bug

12:04 thheller: can't even get a simple example to compile

12:04 not even :none because of some weird path

12:05 well ok, anyways just wanted to make sure I understand correctly before I add something like that to shadow-build

12:06 sdegutis: On the "benchmark game" website it appears Java is only marginally faster than Clojure, but in here I've hear it's significantly faster. What accounts for this discrepancy?

12:12 Bronsa: ,((fn [& args] (apply (fn [a & b] (apply list b)) args)) 1 2 3)

12:12 &((fn [& args] (apply (fn [a & b] (apply list b)) args)) 1 2 3)

12:12 lazybot: ⇒ (1 2 3)

12:15 sdegutis: Thanks in advance.

12:17 justin_smith: sdegutis: reading the benchmarked code should offer a hint - fast clojure is not always the same pretty immutable clojure we know and love

12:18 clgv: justin_smith: but efficient clojure can be pretty idiomatic clojure as zach tellmans libraries can show you ;)

12:20 thheller: sdegutis: all things being equal clojure cannot be faster than java since it runs on the same jvm

12:20 justin_smith: can be, yes - but it's easy to sacrifice speed for beauty, or visa versa

12:22 sdegutis: thheller: that seems incorrect, since both Java and Clojure compile to JVM bytecode

12:22 thheller: "all things beeing equal" ...

12:22 if the clojure impl of the benchmark uses a different algo than the java version

12:23 the better one wins

12:24 nuwanda__: well, I don't see how "all things" will ever be equal :)

12:25 thheller: that's why benchmarks like that are pretty useless ;)

12:25 sdegutis: ∞ == ∞

12:29 thheller: dnolen_: should I open an issue or comment on CLJS-965? :foreign-libs definitly does not work correctly with :advanced. well you might get lucky if the file actually survives :advanced compilation ;)

12:30 dnolen_: thheller: lol might as well open a separate actionable ticket, it's something I've been meaning to fix for a while now

12:31 thheller: https://github.com/thheller/cljs-foreign-bug

12:31 tbaldridge: sdegutis: even the benchmark game site admits that their benchmarks really don't mean anything

12:32 thheller: maybe I configure it wrong but the source of js/sample.js ends up in the output, advanced optimized

12:33 EvanR-work: know what a cool benchmark game would be, measure the time it takes people develop the "benchmark application" using that language (implementation irrelevant!)

12:33 i think most will not complete

12:36 seangrove: dnolen_: Wanted to ping you here before I open an issue on Mori - was going to propse 2 things for Mori

12:37 dnolen_: seangrove: l'm listening

12:37 seangrove: 1. A mori.chainable ns, that looks like the snippet I posted the other day. Has obvious perf implications, but it's a nice way of onboarding js devs by making it looks like underscore or immutable, just with a much more mature implementation and broader set of functionality

12:38 2. A set of sweetjs macros... somewhere in the repo that would add a -> like macro, and literals for vectors, hashmaps, and sets

12:39 #2 would obviously be much nicer in terms of both perf, syntax, and return semantics. Not everyone is going to use it, but it would be nice to have out of the box

12:41 soulman_: hi

12:42 => (javax.swing.KeyStroke/getKeyStroke (int java.awt.event.KeyEvent/VK_UP))

12:42 IllegalArgumentException No matching method found: getKeyStroke clojure.lang.Reflector.invokeMatchingMethod (Reflector.java:80)

12:42 seangrove: Both are pretty small, and since mori moves pretty slowly, I should be able to maintain them if it's too much hassle for you

12:42 soulman_: => (javax.swing.KeyStroke/getKeyStroke java.awt.event.KeyEvent/VK_UP)

12:42 IllegalArgumentException No matching method found: getKeyStroke clojure.lang.Reflector.invokeMatchingMethod (Reflector.java:80)

12:43 any ideas why the KeyStroke.getKeyStroke(int) method is not found?

12:44 hiredman: have you checked the java docs?

12:44 soulman_: hmm, because there is only a KeyStroke.getKeyStroke(char) method

12:45 classical case of rubber ducking :-(

12:51 EvanR-work: soulman_: 🐥

13:06 seangrove: dnolen_: Wanted to get your thoughts before I did it in the Mori repo vs a separate wrapper project

13:09 dnolen_: seangrove: 1) is fine, 2) is not hardly anyone uses sweet.js from what I can tell and it's not properly maintained

13:11 seangrove: dnolen_: Ah, bummer re #2. Was just hoping to bring Mori as close to possible to JS devs

13:12 dnolen_: seangrove: I don't see how it's going to bring it closer to JS people - they don't use sweet.js

13:12 seangrove: dnolen_: Thought some might. I'd like to see it in JSX as well, tbh

13:13 dnolen_: seangrove: if JS people use anything it's ES6 transpilers, that has some traction

13:13 macros do not

13:18 seangrove: dnolen_: Fair enough. JS is the perfect example of being between a rock and a hard place with its limitations and choices, so that you have to choose between expression, elegance, performance, and sanity

13:22 andyf: sdegutis: Re: benchmarks game, my 2 cents. Anyone who relies only on those results to compare languages is ignoring facts. Anyone who says the results are meaningless is, I think, also ignoring facts. Those are measurements of *something*, but they are not necessarily relative time measurements you will get if you implement application A in language B and C.

13:22 Typical Clojure code allocates a lot more memory that is then garbage collected than the Clojure programs in the benchmarks, which are often written to use mutable data specifically to help make them faster.

13:23 sdegutis: andyf: that sucks

13:23 They should use idiomatic code only.

13:23 dnolen_: seangrove: this is not our problem ;)

13:24 andyf: sdegutis: Web site owners get to decide what is published.

13:24 sdegutis: fæir

13:24 seangrove: dnolen_: Only when trying to bring some of the pleasantries to JS-land...

13:24 andyf: New web sites are simple to create a domain name for, but time consuming to maintain over time.

13:25 dnolen_: seangrove: this is assuming they will even accept them

13:25 seangrove: Mori was out there for 2 years - only React.js made people pay attention

13:26 seangrove: dnolen_: It is, yeah. But projects like immutable.js and underscore make me slightly sad

13:26 dnolen_: seangrove: JS people still cannot grok the utllity of macros

13:26 seangrove: thus stupid crap like AtScript (puke)

13:26 * seangrove googles AtScript

13:27 dnolen_: seangrove: bask in the abomination http://eisenbergeffect.bluespire.com/all-about-angular-2-0/

13:30 andyf: sdegutis: Also, finding a set of people that can decide what is idiomatic in 20 different programming languages and what is not, when comparative measurements between languages is on the line, would turn into a big time sink on mediating arguments of what is idiomatic. If a web site purported to publish such findings, many would likely dismiss it as ?well, my favorite language could be much better, but they judged language featu

13:30 as non-idiomatic for that problem, so we are hamstrung?

13:31 hiredman: idioms are also domain dependent not just language dependent

13:31 sdegutis: ok

13:33 * andyf went way over his 2 cents worth there.

13:36 tbaldridge: sdegutis: that's the problem with the benchmark games in general. Take all the pi-digits programs. Almost all of them just do FFI to libgmp. So that benchmark is a benchmark of libgmp not of the languages.

13:37 Notice how both the Java and Clojure version of that program to directly emit JVM bytecode.. So yeah, if you ever need to calculate pi-digits really fast, that might be the way to do it.

13:37 But you're not really measuring anything of worth there.

13:38 andyf: tbaldridge: That is the one that all critics focus on first :)

13:38 and I would agree with that criticism

13:38 stuartsierra: There are lies, damned lies, statistics, and then there are benchmarks.

13:38 andyf: I wouldn't say it applies equally well to the other problems.

13:38 TimMc: :-)

13:42 tbaldridge: I think something like the Om benchmark numbers are a good example of the big wins that can come by re-thinking an approach to a problem. That's the issue I have with the benchmark game, it's too restrictive.

13:43 seangrove: tbaldridge: Or has a lot of expectations baked in, certainly

13:43 tbaldridge: The game may say something like "how fast can your language make 100,000 updates to the DOM"? But if you use something like React with Om, you may not ever need to do something like that in real life.

13:43 seangrove: expectations/assumptions

13:48 puredanger: the only reason (at this point) for pi-digits to be doing bytecode gen rather than deftype is lack of marking native methods

13:49 sorry, not deftype, gen-class

13:49 which is logged here http://dev.clojure.org/jira/browse/CLJ-1409

13:50 but I agree with the original point that these benchmarks are all doing effectively the same thing in different forms

13:50 stuartsierra: Let's just find wherever they keep the Java code and call it.

13:51 :P

13:51 csd_: Is there any way to use clojure's mrn (e.g. 2r16) representation of numbers where the, for example, 16 is an input from a function

13:51 puredanger: yes, works same

13:52 or rather the literal form works the same - what do you mean as input?

13:52 ,2r16

13:52 clojurebot: #<NumberFormatException java.lang.NumberFormatException: For input string: "16">

13:52 csd_: I want a (fn [n] 2rn)

13:53 puredanger: so you want to interpret a decimal number as if it was a binary number?

13:53 csd_: yeah

13:53 puredanger: do you want the result as a string?

13:54 csd_: i want ultimately to compute the hamming distance, where the bits differing between two strings of bits are counted. so, yeah string is fine

13:54 Ninerian: Hello

13:54 puredanger: oh, well there are better ways to do that probably

13:55 stuartsierra: XOR and count the 1 bits, or something like that

13:55 Ninerian: How can I filter a list by using contains? '(filter #(.contains % ".xml") "asdasd.xml")

13:55 csd_: more just looking for an easy way to cast to binary

13:56 puredanger: Ninerian: try .indexOf instead of .contains

13:56 csd_: Integer/toString seems my best bet

13:56 puredanger: csd_: there's toHexString

13:56 sorry toBinarySting

13:56 Ninerian: puredanger No matching method found: indexOf for class java.lang.Character

13:56 puredanger: http://docs.oracle.com/javase/7/docs/api/java/lang/Long.html#toBinaryString(long)

13:57 Ninerian: puredanger: No matching method found: indexOf for class java.lang.Character

13:57 puredanger: Ninerian: just (>= (.indexOf "asdas.xml" ".xml") 0)

13:58 godd2: Ninerian you need to filter over a collection

13:58 lasergoat: what's wrong with contains? i feel like the problem is the collection

13:58 ,(some #(.contains % ".xml") ["asdasd.xml"])

13:58 godd2: &'(filter #(.contains % ".xml") '("asdasd.xml"))

13:58 clojurebot: true

13:58 lazybot: ⇒ (filter (fn* [p1__45387#] (.contains p1__45387# ".xml")) (quote ("asdasd.xml")))

13:59 godd2: &(filter #(.contains % ".xml") '("asdasd.xml"))

13:59 lazybot: ⇒ ("asdasd.xml")

13:59 puredanger: that's fine, you're right

14:00 ,(Long/toBinaryString 42)

14:00 clojurebot: "101010"

14:00 Ninerian: Okay, thank you

14:01 lasergoat: what are the relative advantages of lazybot vs clojurebot?

14:02 sdegutis: none

14:02 ~guards

14:02 clojurebot: SEIZE HIM!

14:02 sdegutis: clojurebot can do that, lazybot cant

14:02 puredanger: they're both surly

14:02 sdegutis: but that's not an advantage

14:03 noonian: its nice having two bots when one of them stops working

14:03 puredanger: ,2r101010

14:03 clojurebot: 42

14:03 lasergoat: got it

14:03 puredanger: plus you can make them fight for your amusement

14:05 lasergoat: the little arrow in front of the lazybot results doesn't prevent that

14:05 ?

14:05 mdrogalis: puredanger: Same with your children.

14:05 Bad parenting advice brought to you by Mike.

14:05 * TimMc takes notes

14:05 puredanger: they just do that automatically :)

14:06 mdrogalis: :)

14:06 lasergoat: ,(str "&(+ 1 1)")

14:06 clojurebot: "&(+ 1 1)"

14:06 lasergoat: yeah, see, i don't know how to make them fight

14:06 puredanger: I was just kidding :)

14:07 it was an AI joke - enjoy 'em now before the singularity

14:08 SagiCZ1: does java save anywhere how much memory do primitive types? is it even consistent? across platforms or JVMs?

14:08 yazirian: you suggest the singularity hasn't already happened -- personally, i feel like it explains a lot about where tv programming has gone in the last decade

14:08 SagiCZ1: or is there a way to find out how many bits for example takes up?

14:09 OscarZ: with java interop you can do (.myMethod some-object), how could i pass object and method to some generic function and call method inside the function ?

14:09 puredanger: SagiCZ1: it's defined to some degree by the JVM spec

14:09 SagiCZ1: jesus my english tonight.. -.- sorry

14:09 OscarZ: i tried passing .myMethod directly but i guess its some special form

14:09 mdrogalis: puredanger: Really nice stuff on your new blog btw. Enjoying it.

14:09 lasergoat: if there's a tech singularity out there controlling tv and its output is "the bachelor", consider me worried

14:09 puredanger: mdrogalis: thx :)

14:10 yazirian: five dozen cop procedurals? sounds like neural net learning to me

14:10 puredanger: OscarZ: method in the form of what? a String? a java.lang.reflect.Method?

14:10 yazirian: iterating on the perfect CSI

14:10 SagiCZ1: OscarZ: you can wrap the interop call like this #(.myMethod %) and then use it as any other clojure function

14:10 puredanger: or use a macro

14:10 OscarZ: cool, thanks guys.. i guess string is fine

14:11 out of curiosity, would it possible to pass it in form .myMethod somehow ? i also tried '.myMethod

14:11 yazirian: OscarZ: also . itself is callable

14:11 puredanger: . is a special form

14:11 yazirian: ,(. 1 toString)

14:11 clojurebot: "1"

14:12 OscarZ: cool

14:12 puredanger: .method is sugar over the special form

14:12 http://clojure.org/java_interop#dot

14:15 SagiCZ1: the primitive types are defined here: https://docs.oracle.com/javase/specs/jvms/se5.0/html/Overview.doc.html#22239

14:15 stuartsierra: And no, you can't do (fn [method] (. object method))

14:16 SagiCZ1: puredanger: thanks!

14:16 OscarZ: stuartsierra, i was just tryin :)

14:19 puredanger: you can use a macro though with something like this (defmacro call [o method] (list '. o (symbol method))) (prob not the best way to say that)

14:19 lasergoat: SagiCZ1: this might be useful: https://github.com/twall/jna/blob/1e071d9ca139245b9c2ecf557010aac588732e04/src/com/sun/jna/Native.java#L1102

14:20 SagiCZ1: lasergoat: thanks! i was just writing something like this

14:20 OscarZ: puredanger, yes i thought maybe i'd need to use macro here but havent looked at macros yet.. maybe this is simple enough to learn some macros :)

14:21 puredanger: with that one you could do (call 5 toString) for example. not sure what you want exactly, but it's totally possible. really, you're just ultimately tapping into the bytecode generating capabilities of the Clojure compiler in the end

14:23 stuartsierra: That's still not going to let you do (fn [method] (call 5 method))

14:23 OscarZ: im trying to make a simple helper function that would wrap the usage of to-java and from-java .. so i could do something like (call obj method {:id 303 :name "fooo"})

14:24 and it would convert the map to object before the call

14:24 puredanger: OscarZ: you might want to look at what I did at http://stackoverflow.com/questions/27308061/whats-the-idiomatic-way-to-do-this-java-function-in-clojure/27308254#27308254

14:24 takes a map of vals and calls appropriate setters on an obj

14:25 kind of the inverse of bean

14:27 yazirian: OscarZ: memfn might also help you here, if you can wrap your method name it becomes a normal callable fn

14:28 OscarZ: cool, whats the gensym thingy? is that something you often use with macros?

14:30 puredanger: https://clojuredocs.org/clojure.core/gensym

14:30 yes

14:32 OscarZ: why cant you work on options and obj directly but you need to create new symbols and assign options and obj to them ?

14:35 noonian: i think in his example he is just doing that so he has a more concise name to use in the body of the macro but still takes an argument with a name that conveys what is should be

14:35 OscarZ: ok

14:36 i better read up on macros anyway :)

14:37 puredanger: no, it's more important than naming - it has to do with what runs at compile time vs in the generated code

14:37 I am not an expert macrologist btw - there are far better people for that on this channel

14:37 OscarZ: do you have any recommendations for some good articles on that black magic?

14:38 noonian: ah right, since obj could be an expression that returns an object and you wouldnt want that to run more tahn once

14:38 puredanger: there's a new prag press book

14:38 sdegutis: Would a Clojure file that only uses Java objects and Java method calls have the same performance as the equivalent Java file?

14:38 puredanger: sdegutis: the generated bytecode is not identical, but it's very similar

14:38 sdegutis: My theory is that, since it would only use Java classes and no Clojure (clojure.core or anything else) constructs, it should be equivalent to the Java code in terms of performance.

14:38 stuartsierra: sdegutis: In a contrived microbenchmark, no. In real-world application code, yes.

14:39 puredanger: it's similar

14:39 sdegutis: I suppose the main problem is in using Clojure literals that have a Java box instead of a Java scalar.

14:39 (Which would thus rely on some of the Clojure runtime)

14:39 amalloy: you can use primitives if you're careful

14:39 as long as you only want long and double

14:39 csd_: puredanger: thx Long/toBinaryString made things a lot easier

14:40 puredanger: amalloy: which can be particularly challenging in interop with Java apis that rely on int (like String, collections, etc)

14:40 I have even seen the number of checkcast bytecode calls make a difference in a hot loop, and I think in some cases the Clojure compiler overdoes that

14:42 I ran into that on Alioth comparing effectively the same bytecode generated from Java, Scala, and Clojure

14:42 amalloy: yeah, it casts every time it needs to call a method instead of once at the beginning of a loop or whatever

14:42 clojurebot: Pardon?

14:44 amalloy: puredanger: i always forget, you can actually even get a lot done with primitive ints if you don't mind a lot of extra typing

14:44 puredanger: if you're careful, yes :)

14:44 if you happen to let an (int …) the compiler will really make an int and use it inside the let iirc

14:45 stuartsierra: I thought that stopped working after invokePrim was added?

14:45 puredanger: stuartsierra: it works in a very narrow scope of cases

14:46 might even be accidental for all I know

14:46 stuartsierra: :)

14:46 amalloy: puredanger: you can definitely do it, but in that case the compiler still emits calls to Numbers/addInt or whatever

14:46 but if you're very nice, you can get primitive bytecode ops like iadd: (fn [] (unchecked-multiply-int (unchecked-add-int (unchecked-int 1) (unchecked-int 1)) (unchecked-int 1)))

14:47 disassembles to https://www.refheap.com/36dd6bcd14ac1e257f399c702

14:47 puredanger: yeah, I'm talking about making a call into a Java method

14:47 yes, I've done some of that too :)

14:47 stuartsierra: (no-really-clojure-i-want-an-int 42)

14:47 amalloy: (inc stuartsierra)

14:47 lazybot: ⇒ 15

14:48 stuartsierra: Array indices, that was the one that I ran into.

14:52 puredanger: yeah, calling into the string, array, and collection apis are the ones I see all the time

14:52 and really, the jvm does a super job of optimizing away l2i. but it's not free.

14:53 I fought this byte-related one and lost in alioth - http://dev.clojure.org/jira/browse/CLJ-1342

14:55 seangrove: dnolen_: First pass at chainable in cljs - works nicely, probably some bugs but have to run https://www.refheap.com/95854

15:37 dagda1_: can anyone improve this syntax for me (apply str (vec (re-seq #"[A-Z]" s)))

15:38 what I have works but using apply str and vec seems verbose

15:39 justin_smith: why do you need vec?

15:39 SagiCZ1: dagda1_: you can do str/join

15:39 instead of apply str

15:40 dagda1_: SagiCZ1 great, thanks and I don't need the vec

15:40 hiredman: what is that supposed to do?

15:40 dagda1_: hiredman: return a string with only capitals

15:40 hiredman: filtering?

15:40 dagda1_: hiredman: you could use filter

15:41 justin_smith: &(apply str (re-seq #"[A-Z]" "This Is A Test"))

15:41 lazybot: ⇒ "TIAT"

15:41 Muonic: is anyone familiar with paredit.vim? I am wondering if it it is possible to type array classes like [B?

15:41 i can't get rid of the closing square bracket

15:42 justin_smith: Muonic: it does that even inside a string?

15:42 Muonic: but then its inside a string

15:42 justin_smith: it should be

15:42 does [B work as a type hint outside a string?

15:43 I would think the reader would choke on it

15:43 I know it works as a string as a type hint

15:43 amalloy: justin_smith: you can't use it outside of a string

15:43 Muonic: I actually want to use type as a multimethod switch

15:43 on type

15:43 justin_smith: amalloy: yeah, that's what I thought

15:43 Muonic: then you need ##(Class/forName "[B")

15:43 lazybot: ⇒ [B

15:44 Muonic: k, thx

15:44 justin_smith: but case won't like that, as it's not a literal, but cond will still work

15:44 also, if you are switching on class, consider using a multimethod instead

15:45 amalloy: justin_smith: Muonic said multimethod already

15:48 justin_smith: amalloy: d'oh

15:49 * justin_smith puts the dunce cap on and goes to sit in the corner

15:52 celwell: Hi, can't figure out why I'm able to run fine with 'lein ring server', but 'lein ring uberwar' is throwing a NullPointerException. I've narrowed it down to a particular dependency (clj-facebook-graph), but I'm at a loss to correct the issue. Any thoughts?

15:54 gfredericks: celwell: do you have a stacktrace?

15:55 celwell: gfredericks: https://gist.github.com/celwell/807005f39cd15ae20be5

15:57 justin_smith: celwell: what is "purple" ?

15:57 celwell: project name

15:58 this is that namespace that is listed in the trace: (ns purple.users

15:58 (:use clj-facebook-graph.auth

15:58 gapi.core)

16:01 hiredman: dagda1_: I don't think I would do that with a regex, I would likely do something like (apply str (filter #(Character/is %) "..."))

16:01 Character/isUpperCase or whatever the static method is

16:02 not that there is anything wrong with the regex

16:08 celwell: justin_smith: I can paypal/venmo you some $ if you can fix it today/tomorrow. Whatever you think is fair. I'll give you repo access. Not sure if appropriate to solicit on irc?

16:11 justin_smith: well, usually that would be done via /msg

16:11 celwell: I'm not experienced in irc, whoops

16:15 amalloy: i've never heard of venmo. am i an old person now, out of touch with the newfangled hophip gizmos?

16:15 hellofunk: justin_smith: that shipment of powder you asked for came in but Sally said she wasn't feeling well and the cops were everywhere, so we are delaying

16:16 justin_smith: whoops, sorry. supposed to be a /msg

16:16 celwell: amalloy: it's great for small transfers no fee

16:16 hellofunk: hey don't make fun of me ;)

16:17 hellofunk: celwell: ;)

16:26 puredanger: lol

16:30 justin_smith: celwell: did you see my reply to your /msg or are you having continued unfamiliarity with your irc client?

16:31 celwell: justin_smith: ha, apparently I am. maybe M-x irc is bad or i am. can you email me at elwell dot christopher on gmail?

16:33 justin_smith: I'll get in touch, sure thing

16:42 sdegutis: What's a reasonable way to make state implicit in Clojure?

16:43 weavejester: sdegutis: should state be implicit?

16:43 hellofunk: sdegutis: what does that mean?

16:43 mi6x3m-alt: sdegutis: don't say implicit state in this channel :)

16:43 tbaldridge: ~gourds!

16:43 clojurebot: No entiendo

16:44 SagiCZ1: ~guards!

16:44 clojurebot: excusez-moi

16:44 hellofunk: ~gorbachev!

16:44 clojurebot: No entiendo

16:44 mi6x3m-alt: sdegutis: http://clojure.org/transients

16:45 sdegutis: There are many times when I want to write a convenience layer around some functionality, and in more OOP-focused languages, I would put the shared state in an immutable instance variable that can be given in the constructor.

16:45 hiredman: ~gourds

16:45 clojurebot: SQUEEZE HIM!

16:45 amalloy: hiredman: ~guards excited people so much they remember it with an exclamation point, it seems

16:45 SagiCZ1: you can keep state in some atom

16:45 sdegutis: For an example, I want to operate on a database from within many related functions, and in Clojure, I must add an extra database parameter to them all. Whereas I would typically put that in an instance variable on a class for the related functions, and make these into methods.

16:46 stuartsierra: sdegutis: Function arguments are good for you. https://github.com/stuartsierra/component

16:46 SagiCZ1: sdegutis: you could also utilise closure..

16:46 tbaldridge: sdegutis: that's why I like stuartsierra's component lib, you get "implicit" state in a natural way

16:46 sdegutis: stuartsierra: Thank you for the advice. I have been using Clojure very idiomatically for a few years now, and have not found the popular style to be a good one in my experience.

16:46 hiredman: it is exciting

16:46 sdegutis: SagiCZ1: Ah, that is a reasonable idea, thank you very much.

16:47 tbaldridge: sdegutis: with something like component you get polymorphism combined with "implicit state". It ends up being quite natural and easy to extend.

16:48 sdegutis: It looks like defrecord may even possibly be what I'm after.

16:48 But I'll check out component nonetheless.

16:49 justin_smith: defrecord defines an immutable record datatype, I don't see what would be so stateful about that on its own

16:49 sdegutis: I am usually skeptical of using third party libraries however, as they can become discontinued and unsupported at any given time.

16:49 justin_smith: I don't care about mutating its state, only making it accessible while generally implicit.

16:49 hellofunk: sdegutis: libraries do not disappear from clojars, even if authors don't do anything with them any more.

16:50 amalloy: hellofunk: that's generally my opinion too, but being supported is not nothing: future bugs being fixed is nice

16:50 sdegutis: hellofunk: but they will not receive potential bugfixes and upgrades for future Clojure compatibility and other such things they may need; thus by adopting one, I make my employer have full but implicit ownership of it

16:50 justin_smith: sdegutis: if it never mutates, just put it in a var, but I don't know why you'd even call that state

16:50 sdegutis: justin_smith: I mean per-instance

16:51 SagiCZ1: i have a big java project and i want to build gui for it in clojure.. the project is managed by maven.. what is the best way to put clojure there? i would probably try to stick with calling java from clojure as the gui is the entry point of the application

16:51 hellofunk: amalloy: of course, but i'd be much more concerned if a library that served important functionality had the possiblity of just evaporating and no longer being available in lein builds

16:51 sdegutis: justin_smith: Think of an immutable property on a class instance which is only set in the initializer/constructor but can be used in instance methods -- this is what I want in Clojure.

16:51 tbaldridge: sdegutis: component is like 100 lines of code...it's not that hard to maintain.

16:51 justin_smith: sdegutis: yeah, defrecord

16:51 or just a map

16:52 sdegutis: tbaldridge: ah I see; then I may simply incorporate it wholesale into our application, if its license permits

16:52 hellofunk: SagiCZ1: these days i'm convinced that all GUIs should be cljs front ends :)

16:52 SagiCZ1: hellofunk: not sure what you mean.. i was thinking seesaw.. i liked it in my last project

16:52 sveri: hellofunk: +1

16:53 tbaldridge: sdegutis: or just don't worry about it at all, if someday it becomes a problem it's not going to be hard to rewrite it from scratch or maintain it on your own.

16:53 hellofunk: SagiCZ1: i mean, your clojure code runs on the web server, even if it is a local server on your laptop or whatever. your GUI runs in a web browser and communicates with it. you get much better GUIs with the web these days then you will ever get with seesaw

16:54 SagiCZ1: hellofunk: wow that sounds bizzare.. so it would run in a browser<

16:54 hellofunk: SagiCZ1: the question: would you rather write Java for your GUI in yucky seesaw, or write awesome clojurescript for a much better GUI ?

16:54 SagiCZ1: you realize that many of the apps you are probably using these days are actually web technologies. there is nothing bizarre about it.

16:54 tbaldridge: I'd take swing/javafx any day over the crap that is HTML/CSS </rant>

16:55 hellofunk: SagiCZ1: take Light Table for instance. or many other code editors now. they are shallow web shells that are really just browsers

16:55 sveri: SagiCZ1: hellofunk maybe you know this one? http://www.kalzumeus.com/2009/09/05/desktop-aps-versus-web-apps/ its pretty convincing

16:55 hellofunk: tbaldridge: Om and cljs changed my opinion real fast on that

16:55 tbaldridge: Om and cljs have nothing to do with HTML and CSS

16:55 SagiCZ1: hellofunk: but lighttable does not run in a browser!.. the main portion of the app will be a viewport window with javas LWGJL 3d engine.. is that a problem?

16:55 tbaldridge: The layout and page oriented nature of HTML is what's horrible.

16:55 hellofunk: tbaldridge: my point is that you can write solely in cljs and get a great GUI experience

16:56 mi6x3m-alt: sveri: just one side of the story

16:56 hellofunk: SagiCZ1: whether it is in a real browser or a shell like LT is up to you, but it's a concept worth exploring before you give yourself whole hog to seesaw

16:56 tbaldridge: I spent quite a lot of time doing Silverlight/WPF programming (close to JavaFX), and the layout, and rapid development that those platforms offer blows HTML/CSS away.

16:57 sveri: mi6x3m-alt: of course

16:57 hellofunk: tbaldridge: naw, single-page apps that emulate desktop apps even though there is no real page switching is the way many of us work now.

16:57 SagiCZ1: hellofunk: thanks for the ideas, sounds great.. what should i google to learn more?

16:57 tbaldridge: SagiCZ1: I'd take a look at JavaFX2 if you want a desktop app, it's pretty fast, and comes standard with Java8

16:57 hellofunk: SagiCZ1: clojurescript

16:58 sdegutis: At the top of its introduction page, [component] says it is "for managing the lifecycle of software components" -- this sounds like it has nothing to do with accessing state, and I'm very confused why it would label itself this way if that is what it's good at.

16:58 mi6x3m-alt: sveri: for instance a desktop app is a desktop app, it requires no connection, you leave no trace and you do not need to fire up a password manager to use it first

16:58 you also own it

16:58 SagiCZ1: tbaldridge: javafx has no clojure wrapper :(

16:58 mi6x3m-alt: SagiCZ1: seesaw then

16:58 SagiCZ1: yeah thats my plan

16:58 mi6x3m-alt: seesaw is great

16:59 sveri: mi6x3m-alt: thats true, but thats only value for the customer, and tbh, most people are accustomed to enter a password somewhere

16:59 tbaldridge: SagiCZ1: and I built a wrapper in about a week. But yeah seesaw is good

16:59 sdegutis: component lifecycles and implicit state are very closely linked.

16:59 mi6x3m-alt: tbaldridge: usable wrapper around javafx in a week? interesting...

17:00 SagiCZ1: how can cljs run outside of browser?

17:00 tbaldridge: if you have state you need a way to create/destroy that state, that's called lifecycle management

17:00 sveri: OTOH an autoupdate solves some of the problems desktop apps have

17:00 sdegutis: The "A component is similar in spirit" paragraph should be *way* higher.

17:01 mi6x3m-alt: sveri: you cannot convince me but I'm on the other extreme. I do not use web apps

17:01 hellofunk: SagiCZ1: look at how LT does it if you want. LT is basically a web browser that is running standalone so it doesn't "looK" like a browser

17:01 mi6x3m-alt: I understand the point though

17:01 SagiCZ1: hellofunk: so is it a modified firefox or whatnot?

17:01 sveri: mi6x3m-alt: it's ok, I don't want to convince you, just showing the positive sides of web apps

17:01 mi6x3m-alt: SagiCZ1: you want a browser component?

17:01 hellofunk: SagiCZ1: Adobe's new Brackets editor, which i LOVE for HTML/CSS stuff is also another example, open source, of a browser that looks like a desktop app, running standalone

17:02 SagiCZ1: mi6x3m-alt: no i dont.. i just want a regular offline desktop app.. but hellofunk is suggesting that writing the GUI in clojurescript would be better

17:02 sdegutis: /cc stuartsierra

17:03 hellofunk: SagiCZ1: i'm just saying, consider your options. cljs is really amazing these days, and Om and the billions of industry dollars taht have been spent to make browsers powerful runtimes is not trivial

17:03 sveri: And, as always, it depends, I would not want to build a full stack IDE like intellij in the browser

17:03 dagda1_: why is this false (seq? [4 [5 6]])

17:03 SagiCZ1: hellofunk: yeah it sounds interesting, i am just trying to grasp the idea, because i would never think of something like that possible.. as in running an app in a browser that looks like regular desktop app

17:03 hellofunk: sveri: yet, you could!

17:04 SagiCZ1: , (seq? [4 [5 6]])

17:04 dagda1_: coll? works but I'm confused as to what seq? is

17:04 mi6x3m-alt: just embed a browser in a desktop app, have the page available in the resources, DONE

17:04 clojurebot: false

17:04 hellofunk: SagiCZ1: oh man there are sooo many appos these days that are developed that way

17:04 sveri: hellofunk: true, someone wants to work on it? :D

17:04 SagiCZ1: hellofunk: sounds like living under a rock I have been

17:05 whats the learning curve though? i kinda know about seesaw a little.. would it delay my project a lot?

17:05 sveri: SagiCZ1: did you code javascript before?

17:05 SagiCZ1: sveri: a little bit of js with jquery, yeah

17:05 amalloy: dagda1_: seq? tests, basically, whether something would print with ()s

17:06 hellofunk: sveri: SagiCZ1: i know very little JS. you don't need JS. cljs is all you need. cljs is totally amazing

17:07 SagiCZ1: hellofunk: YOU EXCITE ME! LETS DO THIS! haha

17:07 hellofunk: you know how amazing cljs is? i started a huge project a year ago with the intention that cljs would be my front end, clj on server my back end. guess what? turns out cljs is so great, i've got nearly ALL of it running in the browser instead!

17:07 sveri: SagiCZ1: ĥellofunk but you might need some js interop, It took me quite some time to integrate some js libraries like a calendar for instance, I mean, if you know how to do it, it's easy, but there is not much docs about this out there

17:07 hellofunk: sveri: interop is not big deal. once you learn the little techniques, it's easy. #clojurescript is there to help

17:08 sveri: hellofunk: that's what I basically said, still, there will be some delay in the beginning

17:08 SagiCZ1: but can i call my ugly java from cljs?

17:08 tbaldridge: hellofunk: you're missing the big problem though. To write a good GUI with cljs you need to know CSS and HTML as well.

17:08 hellofunk: SagiCZ1: well, you can call down to the server, which is clj, and that can run Java if you need it.

17:09 tbaldridge: If you don't know those, or don't know them well, that can be a problem.

17:09 hellofunk: tbaldridge: any GUI requires some help from someone who knows how to make things look pretty.

17:09 SagiCZ1: hellofunk: what about browser compatiblity? is that not an issue?

17:09 tbaldridge: hellofunk: not if layout has sane defaults, hence why I recommend stuff like seesaw for quick and dirty client GUIs

17:09 hellofunk: SagiCZ1: if you are looking for a standalone desktop-like app, then compatibility is no issue at all because no one will ever run your app in an actual browser like Chrome, Firefox, etc

17:09 tbaldridge: no need for all the complexity of a "browser acting like a desktop app"

17:10 hellofunk: tbaldridge: you can learn the basics of HTML layout in 1 day that will cover nearly any interface of moderate complexity

17:10 tbaldridge: HAH!

17:10 SagiCZ1: hellofunk: and would it be possible to run that 3d viewport in it and interact with it?

17:10 tbaldridge: you jest

17:10 amalloy: <table>

17:10 hellofunk: tbaldridge: no i don't, BUT you have to actually want to learn it

17:10 noonian: i believe cljs is compiled to js that runs fine on older browsers

17:10 hellofunk: SagiCZ1: have you seen all the 3d games using WebGL on the web today?

17:11 sdegutis: Why does the docs for "clojure.core/defrecord" say "Alpha - subject to change" ?

17:11 hellofunk: you get hardware accelerated graphics now in the browser!!

17:11 noonian: but i agree that if you just want a simple gui then seesaw is probably a quicker route

17:11 SagiCZ1: hellofunk: they look nothing like desktop apps with 3d viewports such as 3dsMax and the like..

17:11 and anything more demanding requires unity plugin

17:12 hellofunk: SagiCZ1: all the good WebGL demos I've seen are quite high quality and stand up close to lots of desktop apps. are they like a game console? not quite yet, but getting there

17:12 tbaldridge: hellofunk: name me one commercial game written in WebGL

17:12 amalloy: $google one commercial game written in WebGL

17:12 lazybot: [30 amazing examples of WebGL in action | 3D | Creative Bloq] http://www.creativebloq.com/3d/30-amazing-examples-webgl-action-6142954

17:12 hellofunk: tbaldridge: commercial? i don't know, i'm not a big gamer. i think that's missing the point though

17:12 SagiCZ1: hellofunk: but the 3d part and rendering is already done and it is using java's LWGJL engine.. i am not sure i can display that viewport using browser.. i think the server would have to send every frame to cljs

17:13 hellofunk: SagiCZ1: well loooook, i'm not trying to tell you how to write your app. you haven't paid me for that. but i'm just saying, people need to be aware of what is happening right now with browser and cljs, because it warrants serious consideration

17:13 SagiCZ1: LWGJL is using OpenGL can I run that in a browser? but maybe there is a WebGL alternative.. i dunno

17:14 tbaldridge: SagiCZ1: and I'm saying that if all you want is a GUI, and you already know Clojure on the JVM, minimize your risk, keep it all on the JVM.

17:14 hellofunk: SagiCZ1: just do your research if you are interested. something to think about.

17:14 SagiCZ1: hellofunk: ok sorry

17:14 tbaldridge: thanks for your opinion.. i will have to do some research

17:15 tbaldridge: yep, in the end you're the only one who can answer these questions

17:15 hellofunk: btw dnolen has been tearing it up with cljs over the last couple weeks. it is a true platform for the future!

17:16 tbaldridge: (for a certain sub-set of all computing problems)

17:18 sdegutis: The [component] lib doesn't seem to hide any state within the functions you use it in -- you still have to pass the component around.

17:18 tbaldridge: sdegutis: hidden state is invisible (and un-debuggable) state. Also you get polymorphism for free with component. It's trivial to swap in a new DB because everything goes through a component.

17:19 sdegutis: I have a ton of functions that take "db" as the first parameter, and I'd like to get rid of this parameter while still being able to access the "db" from each of them.

17:19 noonian: yes, but using the dependency injection system it provides you will just need to pass in a single argument that has all the state you need

17:19 dnolen_: SagiCZ1: atom-shell might get there eventually wrt doing traditional UI work w/ CLJS, https://github.com/daveray/seesaw might be better a safe bet

17:19 sdegutis: The two solutions I can think of are closures and currying.

17:19 tbaldridge: both hide state...you really don't want to do that

17:19 dnolen_: SagiCZ1: mfikes work w/ JavaScriptCore & Objective-C demonstrate for OS X stuff can def be productive w/ CLJS, esp. if Java isn't an option and you're OK w/ just OS X

17:19 amalloy: i don't think currying is relevant here

17:19 sdegutis: But currying (i.e. partial functions) seems to work in the reverse, giving convenience to the function's caller, not the function definitino.

17:19 amalloy: it's just another word to say closure

17:20 sdegutis: tbaldridge: Why do you insist that I don't want to do this?

17:20 noonian: could also write a with-db macro which is basically thread-first

17:20 tbaldridge: sdegutis: because when you hide state it's super, super hard to debug/maintain code.

17:20 Would you rather have this:

17:21 , {:state 42}

17:21 or this:

17:21 clojurebot: {:state 42}

17:21 SagiCZ1: dnolen_: who is OK with just OS X? I am not ok with that at all haha.. thanks for suggestions though

17:21 tbaldridge: ,(fn [] {:state 42})

17:21 clojurebot: #<sandbox$eval49$fn__50 sandbox$eval49$fn__50@5a9f8e82>

17:21 noonian: its just so much easier to reason about and compose pure functions than ones that rely on some sort of stateful context

17:21 dnolen_: SagiCZ1: lots of people are, no idea what your goals are - just free suggestions

17:22 amalloy: tbaldridge: by the way, you can evaluate things in the middle of a message, eg ##(fn [] {:state 42})

17:22 lazybot: ⇒ #<sandbox11388$eval45518$fn__45519 sandbox11388$eval45518$fn__45519@467f4f6f>

17:22 sdegutis: tbaldridge: that anonymous function seems irrelevant

17:22 SagiCZ1: dnolen_: thank you

17:22 tbaldridge: but that's exactly what you are trying to do with talk about closures, you're hiding state inside functions.

17:22 sdegutis: noonian: I'll have to respectfully disagree.

17:23 tbaldridge: sdegutis: you can disagree, that doesn't make you right.

17:23 sdegutis: tbaldridge: Right. But I see no problem with that. We have a comprehensive test suite that gives us full assurance of our code.

17:24 tbaldridge: I have reasons behind my opinion just like you have reasons behind yours. Neither of us is right or wrong.

17:24 tbaldridge: http://s2.quickmeme.com/img/67/671256e55e7b94c478f77c4dd2aa2641afb98ec711bc9be66307aab25cd881fe.jpg

17:24 SagiCZ1: i think that sdegutis is right in that passing the "state" around in every function can be become very tedious

17:24 sdegutis: Not only tedious, but it precludes certain patterns.

17:25 noonian: tests can only prove the existence of bugs, not prove that they don

17:25 sdegutis: If I have a "db" argument in the beginning of my function, I can't idiomatically use that function with certain other clojure.core functions.

17:25 noonian: don't exist

17:25 tbaldridge: "we have a comprehensive test suite for that..." that's called guard-rails programming...

17:25 sdegutis: How long have I been in #clojure?

17:25 tbaldridge: sure you can, you just use (partial foo db) whenever you need to do that.

17:25 sdegutis: To how many people have I said the very same things you're now saying to me?

17:26 Am I ignorant of this philosophy you're trying to explain to me?

17:26 tbaldridge: apparently :-)

17:26 sdegutis: It's clear that I'm not. So there must be some other reason I've changed my mind about it.

17:26 So just give me the benefit of the doubt.

17:27 tbaldridge: I'm well aware that you've decided to throw out certain aspects of FP. So I guess I'll exit the conversation now as it's pretty pointless.

17:27 noonian: i agree that explicitly passing arguments can get out of hand if each dependency is an argument, but the component lib addresses that so that you never will need more than one argument with all the stateful deps in it

17:28 SagiCZ1: noonian: cant you achieve the same thing simply by having a simple state map that has all the state variables in it?

17:28 tbaldridge: You're programming in a functional language. So perhaps try to just stick with pure functions. It's worked out quite well on all the (rather large) codebases I've worked on for some time.

17:29 Some people like stuartsierra have invested years of their lives into research and development of libraries that address these exact issues, and component is the result. Now it's a free country and you're free to reject all this research after only reading up on it for about half an hour. But I'll say its foolish to do so.

17:29 And I'm done.

17:29 noonian: SagiCZ1: yeah, thats basically what component is doing; the protocols and lib functions allow you to create and manage the lifecycle of your state without having to use clojure reference types except once at the top level in your app where you hold the entire state of your system. and don't even need mutability there if you start it and never stop it

17:30 SagiCZ1: noonian: that actually does sound pretty handy, glad i bookmarked it

17:30 sdegutis: noonian: I see how that can be helpful, but it requires monolithic adoption which makes it a very unlikely choice for my situation, plus it does not get rid of the function argument itself, it merely combines several parameters into one, and that's all.

17:31 SagiCZ1: does clojure's map implement java.util.Map?

17:31 tbaldridge: yes

17:31 SagiCZ1: so cool

17:31 arohner: ,(ancestors (class {}))

17:31 clojurebot: #{clojure.lang.IPersistentMap java.lang.Iterable clojure.lang.APersistentMap clojure.lang.MapEquivalence clojure.lang.IObj ...}

17:32 sdegutis: tbaldridge: You're apparently taking great offense at my philosophy and I have no idea why. This isn't religion, it's just programming.

17:32 poppingtonic: dnolen_: I'm reading your article http://swannodette.github.io/2015/01/02/the-essence-of-clojurescript-redux/ but whenever I start a repl with ./scripts/repl I run into a "java.net.ConnectException, Connection refused".

17:32 dbacar: Hi, did anyone here encounter a FilenotfoundException during (refresh) while using tools.namespace? Any ideas why?

17:32 noonian: sdegutis: you're right; if you really can't stand an extra argument for your functions stateful dependencies then you will need to use another solution

17:33 stuartsierra: dbacar: Known issue, use `refresh-all` to fix.

17:33 noonian: it sounds like you want dynamic vars, but then you start having the problems that component and functional programming strive to avoid

17:33 SagiCZ1: sdegutis: you mentioned you could do something like this via constructor in java.. couldnt you imitate classes with namespaces? and use maybe multimethod dispatching and things like that?

17:34 sdegutis: SagiCZ1: hmm maybe, good idea

17:34 Right now I'm mostly leaning towards building closures.

17:34 _KryDos_: Hi guys. I'm trying to learn Clojure and at the moment I'm trying to rewrite socket server, which was written in Node.JS, to Clojure. In Nodejs' socket server I had a special array where I'm storing all active connections. My question is how can I implement it using Clojure? I thought, in Clojure, I have no ability have global array with all connections

17:35 And how can I change it? Of course I can't. Can I use Actors for this? This is good solution?

17:35 exaptic: _KryDos_: well, you do but global state is generally a bad idea

17:36 _KryDos_: exaptic: exactly... and I just can't understand how should I solve this problem using Clojure

17:36 exaptic: _KryDos_: these are web sockets or the old school kind?

17:36 poppingtonic: _KryDos_: what do you want to use Actors for?

17:37 _KryDos_: exaptic: old school kind

17:37 SagiCZ1: ,(byte 0xFF)

17:37 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: Value out of range for byte: 255>

17:37 exaptic: _KryDos_: only just googled this up, but could be useful: https://github.com/tonsky/net.async

17:37 poppingtonic: what particular subproblem of 'writing a socket server' would you solve with them?

17:38 SagiCZ1: (byte) 0xAC works in java but (byte 0xAC) does not work in clojure, what am i doing wrong?

17:39 amalloy: ,(unchecked-byte 0xac)

17:39 clojurebot: -84

17:39 amalloy: the byte function does bounds checking

17:39 noonian: _KryDos_: you could use an atom to store the global connections if you can't figure out how to do it without global state

17:39 _KryDos_: exaptic: thank you. I'm already have a library for sockets. In my application I have many connections. And one of them can send message to the socket server with a special parameters. I want read these parameters and send a message to the particular socket-connection (which I'm going to get from list/map/vector)

17:39 noonian: thank you so much. I will try

17:39 SagiCZ1: amalloy: thanks

17:39 sdegutis: tbaldridge: and I never meant to show any lack of respect to stuartsierra and his work, I'm sure it's very valuable to those who have use for it, so I don't know where that part of your rant came from

17:40 justin_smith: _KryDos_: in many cases, keeping a list of active connections is a workaround for the fact that you can't simply have a separate asynchronous task handling each connection

17:40 SagiCZ1: cfleming: are you around by any chance?

17:40 _KryDos_: justin_smith: hm... sound reasonable...

17:40 justin_smith: _KryDos_: we have actual threads, so often we can skip the global list of things that are active, and just spawn something that handles it as long as it is active

17:41 dbacar: stuartsierra: In repl I executed (require '[clojure.tools.namespace.repl :refer [refresh refresh-all]]) and then (refresh-all) without restarting repl, but i get the same error.

17:41 justin_smith: which doesn't have to mean one thread per request - there can be a thread pool or something like core.async

17:41 _KryDos_: justin_smith: but how can I organise messaging between connections? (sorry I'm just keeping think OOP way)

17:42 noonian: i'm not sure if that would fix his problem since he will need the list of active connections in order to route the incomming messages to the correct open sockets

17:42 justin_smith: _KryDos_: core.async uses channels

17:42 sdegutis: Is it possible to bind a name in a macro, like so? (defmacro foo [& body] `(let [f 3] ~@body)) (foo (println f))

17:42 stuartsierra: dbacar: Try restarting the REPL. The state-tracker isn't perfect. If there's still an error after a clean REPL restart, there's something wrong with your file names or ns declarations.

17:42 exaptic: _KryDos_: yeah what justin_smith is saying -- that way you don't need to manually juggle which state goes with which connection

17:42 justin_smith: _KryDos_: which are an abstraction over queues, there are a few options using queues directly as well

17:42 _KryDos_: exaptic, justin_smith you guys are awesome

17:42 noonian: sdegutis: yes but it is frowned upon unless the macro consumer supplies the name

17:42 amalloy: sdegutis: ~'f, but of course be careful, this sort of thing leads to muddy code

17:42 _KryDos_: thank you so much. I will try your solutions

17:43 sdegutis: Good points. I'm not likely to use it, mostly just curious.

17:43 justin_smith: _KryDos_: mind you, with threads or async blocks or whatever, there is still per-client state, it's just that there is an abstraction in place (the thread pool, the worker group, whatever) that handles the bookkeeping and details for you

17:45 _KryDos_: I'd compare talking about per-connection state and callbacks in clojure to talking about goto and labels in any modern language: we have good abstractions that make it so you usually don't need to think at that level

17:46 sometimes you need to mess with it, but usually you can think in simpler terms (functions, thread pool, async tasks, channels)

17:47 _KryDos_: sounds hard... but, I will definitely try

17:47 thank you so much

17:47 exaptic: gl =)

17:47 dbacar: stuartsierra:Same error, in exception message it says it cant find "hello_world/core/views_ordered.clj on classpath:" , in fact the file is named views-ordered.clj with dash not underscore, do you thnk it may be a problem with dashes in filenames?

17:47 stuartsierra: dbacar: Yes, that's a problem for Clojure generally, not tools.namespace.

17:49 dnolen_: poppingtonic: are you on a slower machine? There's an outstanding issue to remove the timeout

17:51 poppingtonic: dnolen_: yes my machine is a slow 1.33GHz Atom. Could you post a link to the issue, please?

17:53 andyf: dbacar: Clojure lint tool Eastwood can help quickly find file name / namespace mismatches like that, among other things. http://github.com/jonase/eastwood

17:53 dbacar: stuartsierra:Thanks a lot, "replace hyphens with underscores in filenames", thank you for tools.namespace, real lifesaver.

17:53 stuartsierra: dbacar: You're welcome, glad to hear it's helpful.

17:54 dbacar: andyf:Thanks a lot, I will certainly give it a try

18:05 dnolen_: poppingtonic: there might not be a ticket at the moment, the issue is we just use a timeout instead of reading from std out of node process to know it's ready to connect, please open ticket - patch also welcome

18:19 justin_smith: when (.printStackTrace *e) ends with "... 25 more" - what is the most straightforward way to see the 25 more?

18:20 poppingtonic: dnolen_: doing that.

18:24 amalloy: justin_smith: scroll up. they're just the same stacktrace elemnts in one of the parent exceptinos

18:25 justin_smith: well that sucks

18:25 thanks

18:25 amalloy: like: Exception: foo at a\nb\nc\n Caused by: Exception: bar at x\ny\n... 2 more, the "2 more" there are uh...either a+b or b+c, i forget

18:25 justin_smith: got it

18:26 one of thse stack traces that refuses to map cleanly to my mental model of my code

18:26 andyf: justin_smith: If clojure.repl/pst's modifications are acceptable, you can call it with 2nd arg nil

18:26 justin_smith: now to track down when and where things are actually helping

18:27 yeah, pst is much worse than .printStackTrace was in this case

18:30 andyf: And I was wrong about nil, too. Long/MAX_VALUE is closer

18:30 justin_smith: aha

18:31 so it turns out I fed transaction data to datomic that makes it get an indexOutOfBoundsException

18:32 so now I guess I shrink the transaction until I can turn it into a bug report for datomic (at least suggesting they give a cogent error message rather than throwing an exception on my data)

18:37 poppingtonic: dnolen_: where do you set the timeout?

18:52 ghadishayban: andyf: Do you have any scripts I could look at that take patches from JIRA and apply them to a local git repo? There are several "clusters" of bugs around AOT and reducers, would be nice to run tests against the clusters

18:53 andyf: right now my process is manual

18:55 andyf: ghadishayban: I have a semi-hairy Clojure program that automates downloading all patches, and applying each one, one at a time, to a given Clojure source tree, trying to build and test each one, but it doesn't do sets of patches applied at once.

18:56 dnolen_: poppingtonic: https://github.com/clojure/clojurescript/blob/master/src/clj/cljs/repl/node.clj#L94

18:56 * andyf Running it to get a copy of all current JIRA patches only, then creating tiny bash scripts to pick ones to apply, might be useful to you

18:57 dnolen_: poppingtonic: you will need to change line 85 to redirect to a buffer and will want to wait on that buffer until you see the server started string produced by https://github.com/clojure/clojurescript/blob/master/src/clj/cljs/repl/node_repl.js

18:58 andyf: I can test and write a few instructions for the download-all-patches part, with one example bash script applying 2 or 3 of them, if that would be useful

19:00 ghadishayban: andyf: i feel like that would be useful beyond my purposes. being able to apply everything tagged 'aot' or 'reducers' could really help (speed up) testing

19:00 andyf: i bet puredanger would be interested

19:01 andyf: Gotta go now, but please send me an email at andy.fingerhut@gmail.com to remind me to look at that tonight

19:20 irctc: is there a function that acts as an inverse to partition? so that (--> orignal-seq (partition 4 1) (inverse-partition-func 4 1)) = original-seq?

19:23 I get that there is a flatten and take-nth but I'm running into those quite a bit

19:24 [blake|: I'm trying to figure out Compojure wrap-session middleware. I've got my user logging in, and in my main route file, I see the :user name set. But I don't see where this happens.

19:24 A refheap explaining: https://www.refheap.com/95861

19:26 weavejes_: [blake|: You might be running into problems because you apply the session middleware twice. Once directly, once via handler/site.

19:28 [blake|: weavejes_: Yeahhhhhh...so....huh.

19:30 weavejes_: Maybe I'm going about this the wrong way, then. I just wanted to see who the current user was at any point so I could update a value on screen.

19:31 weavejes_: [blake|: Your example doesn't really explain the problem... All I can see wrong with it is that you have two session middlewares, which will likely cause problems.

19:31 [blake|: I would've thought middleware would be the way to go, but if the session-wrap is occurring inside handler/site, I never see it.

19:32 weavejes_: Well, I've got all these routes in my app-routes routine, but no matter what, I want the current user to be updated/reflected on the page.

19:32 weavejes_: [blake|: Is "sesh/wrap-session" the Ring session middleware?

19:32 [blake|: Maybe I've misunderstood your example.

19:34 [blake|: weavejes_: Yes, sesh is ring.middleware.session.

19:34 I took it out and it made no difference, so I guess I didn't need it...

19:35 weavejes_: The handler/site function already includes the session middleware.

19:36 weavejester: [blake|: How are you setting the session?

19:37 [blake|: Like "(assoc (resp/redirect "/") :session {:user username})"

19:37 After a successful login with that username.

19:48 warz: new to clojure here. what's the best way to find clojure libraries? im looking for possible couchdb libs.

19:49 [blake|: I usually just google but there is...cross-clj?

19:50 bridgethillyer: And http://www.clojure-toolbox.com/

19:50 And https://clojars.org/

19:57 warz: so lets say my objective is to locate the most-used and actively maintained postgre clojure client library

19:57 where's the best place to do that

19:58 amalloy: clojure.java.jdbc

19:58 fin

19:59 warz: ok so clojure provides that, but what about my original one of couchdb or something? best place to find that?

19:59 hiredman: warz: I would just google clojure couchdb

19:59 then look through the hits for something good

20:02 if you don't know clojure well it may difficult to make a decision about what is good from a page of google results

20:02 you'll be able to make better solutions as you learn and use the language more

20:02 warz: so there's no go-to place to find the answer to "what are the top few most actively maintened and used libraries for X"?

20:02 hiredman: until then the best answer is to ask someone who you think knows more

20:03 amalloy: (inc hiredman)

20:03 lazybot: ⇒ 66

20:03 hiredman: warz: lots of people have made various websites and directories and what not

20:03 and I have never found them to useful at all

20:03 to be

20:04 bridgethillyer: Asking here is perfectly acceptable

20:04 bbloom: well there is http://www.clojuresphere.com/

20:05 but yeah, i dunno, arbitrary rankings aren't that useful

20:05 hiredman: ugh

20:05 midje, ye gawds

20:05 bbloom: yeah, popular means bad just as often as it means good

20:05 warz: they're useful imo. can see if a lib has like 1000 downloads versus another that has none.

20:06 bbloom: looks like clojuresphere was last indexed in feb 2013

20:06 sooo that's old

20:06 warz: ah, dang

20:06 bbloom: it's dead b/c it's not useful. more downloads doesn't mean good

20:06 and more "actively maintained" means "less stable"

20:07 you have to evaluate individual projects for your criteria and evaluate maintainers for yourself

20:07 warz: i know it doesnt mean good, but it does mean there might be more people who know about it, etc

20:07 bbloom: or ask ppl who know

20:07 most good clojure libs are small enough that you can help yourself

20:07 if you can't help yourself, the lib is no good :-)

20:18 joshua___: Anyone know where to find what happened to these? http://dosync.posterous.com/sudoku, http://dosync.posterous.com/friendlier-shorter ... I didn't see them in a list of articles on swans's github.io

20:20 amalloy: joshua___: dnolen_'s posterous articles are, as i understand it, irretrievably lost

20:21 TEttinger: archive.org?

20:21 amalloy: it's possible i misunderstood though, so of course dnolen_ is the final authority

20:22 hellofunk: amalloy: joshua___ i have heard the same, they were not backed up and they did not provide a backup to him

20:22 joshua___: that really sucks...

20:23 amalloy: but you're right, it's on archive.org

20:23 http://web.archive.org/web/20130511050735/http://dosync.posterous.com/sudoku

20:23 or some of it, at least. i don't know if that's the full article; seems pretty short

20:24 joshua___: Nevertheless, thanks. I probably should have checked archive.org myself, but I had expected him to have exported his stuff and thought I just was missing the right blog somehow.

20:27 hellofunk: joshua___: it was posterious fault.

20:43 kevinfish: I installed this in chrome on my chromebook and now I can't find how to start it. It seemed to me at one point I found it on the tools menu. Can anyone help me fix it?

20:43 https://chrome.google.com/webstore/detail/clojurescript-repl/lmjjlapjpjeodaadkljnmdfbjpfddchm?utm_source=chrome-app-launcher

20:43 I have a javascript console on the more tools menu and I think it was right there next to it.

20:47 gfredericks: amalloy_: it probably linked to a gist originally? just a guess

20:51 sdegutis: Is there any way to make a Clojure object that's callable by writing pure Clojure code?

20:52 gfredericks: ,((reify clojure.lang.IFn (invoke [_] :hey)))

20:52 clojurebot: :hey

20:54 sdegutis: Cool thanks.

20:57 justin_smith: $mail irctc use apply concat instead of flatten

20:57 lazybot: Message saved.

21:01 hellofunk: justin_smith: that mail business is not a standard irc feature, right? a feature of lazybot just in this room?

21:02 justin_smith: hellofunk: yes, it's a lazybot plugin, the bot tracks who shows up and sends /msg if you have mail

21:03 hellofunk: justin_smith: a while back on #emacs someone was telling me that irc has as mail feature in general

21:03 justin_smith: $mail hellofunk it's haandy

21:03 lazybot: Message saved.

21:04 justin_smith: oh does it? I don't know of it

21:04 hellofunk: i could be wrong

21:08 kenrestivo: $mail mail mail

21:08 lazybot: Message saved.

21:45 travisrodman: does 1.7 allow annotations on proxied classes?

21:52 justin_smith: travisrodman: out of curiosity, what do you need the annotations for?

21:52 travisrodman: i am writing a dsl, and the proxied classes are consumed by a system that is looking for class-level annotations

21:54 i am about to start writing the functionality into the proxy code, but before i started, i wanted to double-check that the functionality was not available somewhere, and i was just missing it

21:55 justin_smith: travisrodman: that system being some java lib I assume

21:55 travisrodman: yes...

21:57 justin_smith: and so you need to either use gen-class, which allows annotations (or a shim class or...) else you need to re-implement stuff that is already in the java lib

21:57 ?

21:59 travisrodman: yeah, I am avoiding gen-class, since I want the functionality to be repl-available, avoiding the fixed classloading behavior once a gen-class is constructed.

22:00 justin_smith: I have seen the behavior available there, but trying to maintain the availability of the code for repl modification

22:01 justin_smith: right - what about a gen-class shim thhat calls things you can redefine in the repl?

22:01 clearly not ideal, but maybe workable

22:03 travisrodman: justin_smith: hmm... that is possibly an idea, i had considered it previously from a class perspective, but annotations not being inheritable, that was a no-go, it is an interesting idea

22:04 justin_smith: i could see some issues with code bloat though...

22:04 the dsl produces a dag, and wrapping every class with another class to get annotation faciltiy would be pretty sub-optimal

22:05 justin_smith: i do appreciate the alternative perspective though...

22:08 justin_smith: yeah, fair enough

22:19 TimMc: $mail $mail $mail

22:19 lazybot: Message saved.

23:24 lodin: Anyone know of a library that provides a multimethod-like interface to core.match?

23:26 sdegutis: I have a recursive problem.

23:27 I want to merge a map with another map which references the new map after the merge within a partial function.

23:28 This is what I have so far: https://gist.github.com/sdegutis/06e73ca38f22c7e5673d

23:29 This is the one-line version of it: (let [self {:age 29}] (merge self (into {} (for [[nm func] imethods] [nm (partial func self)]))))

23:30 justin_smith: sdegutis: the easiest way to express a cyclic structure (ie. not a tree, has paths that lead to other parts of the same structure) is an adjacency list

23:30 sdegutis: Is there any way to somehow make the functions used within the merged map have a reference to "self" being the result of the merge?

23:30 justin_smith: Hmmm, thanks I'll look at that word in Google.

23:31 justin_smith: otherwise you could use promises that deref to other parts of the same structure

23:31 sdegutis: Another option I was thinking of was to make it a ref, and deref it at the time of calling the function (within an anonymous function)

23:31 justin_smith: but adjacency list form is much cleaner

23:31 sdegutis: justin_smith: What would be the benefit of a promise over a ref/atom?

23:31 justin_smith: also how is a.l. cleaner?

23:32 justin_smith: you knoww a promise is never reassigned

23:32 sdegutis: justin_smith: the main benefit of promise/ref/atom over using an adjacency list is that I don't know how to make or use an adjacency list.

23:33 justin_smith: an adjacency list can have arbitrary loops in its structure and does not need any derefs to represent it

23:34 you cann represent super complex networks without tying your code in a knot with recursive refs

23:34 sdegutis: Oh.

23:34 lodin: sdegutis: Think about how you would write the structure down on paper and draw arrows when a map points to another map. Then have one data structure for the maps, and another for the arrows between the maps.

23:34 sdegutis: Ooooh, I see: I would simply use several maps to represent things.

23:35 lodin: (Then you can effectively shove this into one structure.)

23:35 justin_smith: lodin: yeah, that is pretty close to what an adjacency list is, but they are super well descriibed in graph theory

23:36 sdegutis: This is the context I plan to use this within, btw: https://gist.github.com/sdegutis/a331db340c6cc3e94b67

23:36 lodin: justin_smith: I fear a monad sneaking up on us in this conversation. ;-)

23:36 justin_smith: sdegutis: adjacency list is one structure, each key is an id, each value contains at least aa list of ids of all children

23:36 and can contain any othher data you wish

23:37 lodin: no monads needed I hope

23:37 sdegutis: In short: I'm writing a small object-oriented system for Clojure.

23:37 justin_smith: rofl

23:37 have ffun

23:38 this bluetoooth keyboard attacheed to my phone keeps repeeating keys

23:38 sdegutis: The main goal is to be able to access the method from the object itself, that is, the object would be a map containing its own methods and state.

23:39 Another goal is to be able to allow you to access unbound methods from within the class map, and call them by passing an instance as the first parameter.

23:39 lodin: sdegutis: Prototype objects. Super easy in Clojure.

23:39 sdegutis: lodin: how do you recommend it?

23:39 justin_smith: standard solution is to always pass the obbject to the method as the first arg

23:39 sdegutis: justin_smith: right, that's what I'm out to fix

23:40 justin_smith: I want to be able to use "bound methods" as functions with an implicit self, so that I can pass them to other functions that take a 1-fewer arity

23:40 justin_smith: I doubt you will find anything simpler, more efficient,or easier to work wiith

23:40 sdegutis: Simpler or more efficient, you're right. Easier, I dunno.

23:41 justin_smith: typing lag: I mean that passing the instance is simpler, efficient, easier to be clear

23:42 lodin: sdegutis: I'm not sure I get the problem you're trying to fix.

23:42 sdegutis: lodin: One problem is that many of my functions take a first parameter of "db" which is noisy.

23:42 justin_smith: is it a yak disguised as

23:43 sdegutis: lodin: In an OOP language, I would make that an instance variable and only pass it during initialization.

23:43 justin_smith: "intuitive"?

23:43 sdegutis: justin_smith: I'm well aware that you think my idea is stupid and you think I don't have the faintest clue what I'm talking about. So let's move on.

23:43 lodin: sdegutis: You can store it in the map. No?

23:43 sdegutis: lodin: what do you mean? are you talking about within the context of plain Clojure, or using an OOP system built in Clojure, or what?

23:44 lodin: sdegutis: (let [obj {:db the-db-conn :a-method (fn [self] ...)}] ((:a-method obj)))

23:45 Err, missed to pass obj.

23:45 sdegutis: lodin: yeah that's basically my implementation right now

23:46 lodin: see https://gist.github.com/sdegutis/a331db340c6cc3e94b67

23:47 lodin: Ah. yes. In :new.

23:48 sdegutis: This code was *almost* working fine.

23:48 lodin: I'd add a (defn call [obj method & args] (apply (get obj method) obj args)), btw.

23:48 sdegutis: The problem came when I tried to access an instance method from within another instance method.

23:48 lodin: Huh?

23:48 sdegutis: It did not have a "self" that contained instance methods, because during the merge in :new, the partial took the plain version of self.

23:49 So line 4 failed since (:proper-name self) was nil.

23:49 I was hoping to find a way to do this without splitting it into multiple maps, one for state and one for methods. But I think that's impossible.

23:50 lodin: Why not just use (call bob :greet) everywhere?

23:50 sdegutis: Because I want to be able to pass (:greet bob) as a function that takes 0 arguments, into something else.

23:50 lodin: sdegutis: That's where you use partial.

23:51 sdegutis: But I am using partial on line 12 -- oh wait this version isn't.

23:51 Yeah I was using partial at first. No difference.

23:52 lodin: So you want to call an instance method from where you only have access to the zero-arity function?

23:52 sdegutis: I mean like (defn method->func [obj method] (partial (get obj method) obj)).

23:54 sdegutis: Right, basically.

23:55 Also I want access to the function from the object itself, as a field or map key.

23:55 lodin: So when you need to pass (:greet bob) as a function, you pass (method->func bob :greet) instead.

23:56 sdegutis: That's a good idea.

23:56 Although I'd prefer to have no need for external functions like method->func.

23:56 lodin: sdegutis: Yes you do. ;-)

23:56 sdegutis: hm?

23:57 I do have need you mean?

23:57 lodin: I would think so.

23:57 sdegutis: I am determined to figure out a way to allow (:greet bob) give me a partialed function.

23:58 (which includes itself as the first value)

23:58 lodin: I mean, you could get creative by defining your own type and implement IFn or whatever.

23:58 sdegutis: How? Using reify?

23:58 lodin: sdegutis: You can do it like (bob :greet) then.

23:58 sdegutis: That would be so cool.

23:59 lodin: The reason (:foo m) works is because clojure.lang.Keyword implements IFn or whichever interface it is.

23:59 And maps implement the function interface too, which is why (m :foo) works.

Logging service provided by n01se.net