#clojure log - Feb 08 2016

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

0:01 * tolstoy prays he doesn't actually have to build this on windows.

0:25 tolstoy: Is there a concept of too many file descriptors on Windows? Hm.

0:36 slester: sorry for asking 'is this idiomatic?' over and over, but I want to have good programming habits in clojure heh

0:37 (count (filter #(:active %) (:players state))) ;; is that idiomatic for counting the number of active players?

0:37 tolstoy: You can (filter :active (:players state)).

0:38 slester: amazing :D

0:38 tolstoy: These days, I like: (->> state :players (filter :active) count), but YMMV. I wouldn't argue that's preferred.

0:39 slester: is there a specific reason?

0:39 tolstoy: That I like it? It seems clearer to me when I return the the code, and feels kinda like X-path, easier to see the underlying structure.

0:39 rhg135: (->> (:players state) (filter :active) (count))

0:39 slester: yeah

0:39 understandable

0:40 rhg135: that's my pick

0:40 it emphasizes the facts you're working on the players

0:41 slester: is that more prevalent amongst clojurians than (count (filter :active (:players state)))?

0:41 I mean I guess they're both fine

0:41 rhg135: not in the code I've read

0:42 tolstoy: Yeah, I don't think they're clearly un-idiomatic.

0:43 rhg135: I for one like the threading macro, but I also love to (ab)use comp and partial ;)

0:46 ,(((comp (partial apply juxt) (partial (comp (fnil conj []) (partial apply vector)) 1)) 2 3 4) 0)

0:46 clojurebot: #error {\n :cause "Don't know how to create ISeq from: java.lang.Long"\n :via\n [{:type java.lang.IllegalArgumentException\n :message "Don't know how to create ISeq from: java.lang.Long"\n :at [clojure.lang.RT seqFrom "RT.java" 542]}]\n :trace\n [[clojure.lang.RT seqFrom "RT.java" 542]\n [clojure.lang.RT seq "RT.java" 523]\n [clojure.lang.RT cons "RT.java" 662]\n [clojure.core$cons__4331 in...

0:46 rhg135: no wonder it wasn't working

0:48 amalloy: i would write (count (filter :active (:players state))) ("count the active players"), but (->> (:players state) (filter :active) (count)) is fine i guess. the only one i hate is (->> state :players (filter :active) count)

0:49 rhg135: my validation is more than 2 ) in a row moake my brain hurt when reading in a non-rainbowparens environment

0:56 I also like keeping the () around a function call even if unnecessary. reminds you it's a function call

0:57 unlike python were you can have properties call code D:

0:58 slester: ok so! I have a list of active players, want to get the next player's turn... (second (drop-while #(not= % current) (into active-players active-players))) seems wordy haha

0:59 ignore the into stuff, it has to be in order, so using a vector

0:59 justin_smith: why (into active-players active-players) ?

0:59 oh

0:59 slester: rotating around

1:00 [0 1 2 0 1 2] so it goes from 2 to 0

1:02 justin_smith: (second (drop-while (complement #{current}) (cycle active-players)))

1:02 is an option

1:02 as compared to into, cycle probably does less

1:02 and then it still works with a list too

1:03 rhg135: ,(cycle [0 1])

1:03 clojurebot: (0 1 0 1 0 ...)

1:03 slester: ,(cycle '(0 1))

1:03 clojurebot: (0 1 0 1 0 ...)

1:03 slester: yeah

1:03 :D

1:04 rhg135: (inc justin_smith) ; in spirit as lazybot is no longer with us

1:11 slester: seriously would be struggling with clojure a lot more sans justin_smith

1:13 amalloy: there are machinations afoot to bundle a justin_smith with each jar in the next release

1:13 slester: +1

1:14 hfaafb: ,(inc amalloy)

1:14 clojurebot: #error {\n :cause "Unable to resolve symbol: amalloy in this context"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Unable to resolve symbol: amalloy in this context, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6688]}\n {:type java.lang.RuntimeException\n :message "Unable to resolve symbol: amalloy i...

1:40 BRODUS: why doesn't this work? (map #(clojure.test/function? (first %)) (ns-map *ns*))

1:41 justin_smith: BRODUS: the ns-map has symbols as keys, and vars as values

1:42 I recommend using key instead of first there (it will work the same way), but if testing for functions, use (map #(clojure.test/function? @(val %)) (ns-map *ns*))

1:42 you need to deref the var to get the actual current binding

1:44 BRODUS: ok I didn't realize that the var needed to be derefed

1:45 justin_smith: oh and there are also classes in that map... so you need to only deref the vars

1:47 (map (comp clojure.test/function? deref val) (remove (comp class? val) (ns-map *ns*))) ; one way to approach this

1:47 BRODUS: I'm a bit confused whythe var needs to be dereffed, when I do (clojure.test/function? take) , is it derefed implicitly?

1:47 justin_smith: ,(= + @#'+)

1:47 clojurebot: true

1:47 justin_smith: ,(= '+ #'+)

1:48 clojurebot: false

1:48 justin_smith: ,(= '+ @#'+)

1:48 clojurebot: false

1:48 justin_smith: that's why

1:48 BRODUS: got it

1:49 justin_smith: BRODUS: take is the equivalent of @#'take, if you are getting #'take from a list, you need @ in order to make it = take

1:53 BRODUS: ok so #' is for quoting vars which I guess is the same as referencing. Do you know why a normal quote isn't used instead? So that symbol can potentially be used for something else?

1:53 *that the symbol

1:54 justin_smith: #'v is var-quote, it prevents the symbol from being resolved from the var in the current context, and instead stops with the var itself

1:54 normally v is looked up in the current compilation context, and then looked up as either a local or a var

1:55 and 'v stops even before any lookup

1:55 so it's stopping at different steps in a multi-step lookup

1:57 BRODUS: ok I think I get it. Thanks! that was informative

2:05 ambrosebs: eg. (let [v 1] v) is 1, (let [v 1] #'v) is the global var called v

2:16 rhg135: , (with-local-vars [+ 1] @#'+)

2:16 clojurebot: #object[clojure.core$_PLUS_ 0x4299b045 "clojure.core$_PLUS_@4299b045"]

2:16 rhg135: Hmm

2:17 ,(with-local-vars [+ 1] +)

2:17 clojurebot: #<Var: --unnamed-->

2:17 justin_smith: I like how unnamed is impaled on an arrow there

2:19 rhg135: Impalation!

2:20 ridcully: with-local-vars the impaler

2:21 rhg135: Is there ever a good reason to use it?

2:22 justin_smith: I think now you'd probably want a volatile instead usually

2:23 rhg135: I've seen people use atoms for locally scoped stuff, but unlike atoms vars don't do retries when you do a compare-and-swap thingy to them

2:24 so I could consider using with-local-vars for a local mutable, where I might have threads, and the modifications should not retry... but that's awfully specific

2:26 rhg135: I don't think a locally scoped atom will ever retry if not shared

2:26 justin_smith: fair point

2:27 but if you are only in one thread, using an atom seems a little silly too

2:27 rhg135: And if you do share it then you can't use a var

2:27 justin_smith: or maybe that's just me

2:27 rhg135: why can't you use a var? vars are thread safe.

2:28 rhg135: Well, you could but it seems iffy

2:33 amalloy: local vars are super sketchy. being single-threaded is no reason to not use an atom

2:33 rhg135: https://github.com/ztellman/proteus is what I'd use before volatiles existed

2:33 amalloy: or volatile, these days

2:34 justin_smith: amalloy: what's sketchy about them?

2:35 amalloy: they're for dynamic scope, not lexical scope

2:35 (doc with-local-vars)

2:35 clojurebot: "([name-vals-vec & body]); varbinding=> symbol init-expr Executes the exprs in a context in which the symbols are bound to vars with per-thread bindings to the init-exprs. The symbols refer to the var objects themselves, and must be accessed with var-get and var-set"

2:36 amalloy: it creates an object that ceases to work outside of its lexical scope

2:36 ,@(with-local-vars [v 1] v)

2:36 clojurebot: #object[clojure.lang.Var$Unbound 0x1e5f1c12 "Unbound: #<Var: --unnamed-->"]

2:37 amalloy: ,@(let [v (atom 1)] v)

2:37 clojurebot: 1

2:37 rhg135: That's a new one for me

2:38 amalloy: what is?

2:38 rhg135: I thought dereffing an unbound var threw

2:39 justin_smith: ,(declare a)

2:39 clojurebot: #'sandbox/a

2:39 justin_smith: ,@#'a

2:39 clojurebot: #object[clojure.lang.Var$Unbound 0x7e9c09a5 "Unbound: #'sandbox/a"]

2:40 rhg135: Apparently unbound vars are only a delusion.

2:40 They're bound to Var$Unbound

2:41 justin_smith: so undefined, unbound, nil, none, and NaN walk into a bar...

2:41 rhg135: They don't actually exist

2:42 amalloy: what about false and 0?

2:43 justin_smith: amalloy: off having fun with the empty set

2:43 rhg135: Don't forget ''

2:45 I once saw a language that treated ' ' as falsey

2:46 justin_smith: is that the string or the char?

2:46 rhg135: Both

2:47 A string consisting of only whitespace

2:52 justin_smith: would it be possible to make a vector or lazy-seq that implemented CharSequence?

2:53 seems like you could pretty easily (answering myself)

2:55 ,(instance? CharSequence (vector-of :char \a))

2:55 clojurebot: false

2:56 rhg135: That could be useful if not for the dependence on String in java

2:56 justin_smith: rhg135: but there's at least a few places where you can use CharSequence instead of needing string

2:56 rhg135: Very few

3:28 TomTheBOM: oh yes.

3:28 clojurebot: 1

3:28 1

3:29 TomTheBOM: at least in the webchat, \u2029 does not print

3:29 it also counts as whitespace

3:47 clojurebot: 6

7:46 qsys: Just saw https://www.youtube.com/watch?v=zp0OEDcAro0 and it looks pretty powerful... just wondering if anyone has some experience with condition systems in Clojure?

7:47 so, well, is anyone using ribol, slingshot, ...? or anyone using dynamic bindings for this kind of condition systems?

7:49 MasseR: qsys: can't watch videos atm, can you tl;dr what's a condition system

8:11 ashnur: must ask it here too, although probably even less chance for success. how to parse/generate edn from javascript, any ideas? anyone did something like this in the past 3 years? there are 2 modules, one is unusable for anyone than the author and the other is broken

9:20 amoe: has "C-c ," stopped working in a recent cider version? It now seems to wait for another keystroke, before it ran all tests for the namespace

9:21 dysfun: you probably want #clojure-emacs

9:24 amoe: dysfun: thanks

9:24 dysfun: yw

9:25 i-blis1: run-ns-tests is (now) bound to C-c , n

9:26 C-c , C-n

9:27 amoe: i-blis: thanks!

9:27 i-blis: yw

10:42 jonathanj: what's the easiest way to retrieve the content of an element in an XML document with Clojure?

10:43 an element at a particular path, i mean

10:43 phorse: Is there a way to reload changes to server code with reagent? Right now I'm quitting and restarting, but I don't like that.

10:53 jonathanj: why does (clojure.xml/parse (clojure.java.io/file "foo.xml")) never return in my repl but (clojure.xml/parse (slurp (clojure.java.io/file "foo.xml"))) immediately parses the data?

10:56 oh, slurp doesn't actually succeed, it just fails immediately:

10:56 CompilerException java.net.MalformedURLException: no protocol

10:59 gryyy: Try using (clojure.java.io/file (clojure.java.io/resource "foo.xml")) instead

11:00 https://clojuredocs.org/clojure.java.io/resource

11:00 First example

11:00 jonathanj: that seems mostly irrelevant

11:01 the file is not a resource, it's just a file somewhere on disk

11:01 it seems like the slowness here is that parse fetches the DTD to perform validation

11:01 is it possible to use clojure.xml/parse without validating the DTD?

11:05 i-blis: jonathanj: are you using the fullpath name?

11:06 jonathanj: what JVM do you run? >= 1.6?

11:20 jonathanj: it turns out this has nothing to do with the filesystem path

11:20 it's about clojure.xml/parse trying to download the DTD in order to validate it

11:20 i don't know how to not do that

11:21 dysfun: it doesn't look like that's an option

11:21 if only there were literally hundreds of options

11:22 wow. clojure-toolbox is a bit short in the xml department

11:22 has weavejester given up?

11:24 i-blis: jonathanj: you could pass your custom instance of the saxparser

11:25 jonathanj: looks like you have to set http://apache.org/xml/features/nonvalidating/load-external-dtd to false on the SAXParserFactory instance

11:25 i-blis: and do setValidating false to SAXParserFactory

11:26 yeap, exactly

11:26 jonathanj: setting "setValidating" to false doesn't actually do anything by itself

11:26 you have to turn both features off

11:26 SAXParserFactory is just abstract though, what happens if on some system somewhere you get an implementation that is not xerces?

11:27 and that particular feature is hidden under some other name

11:30 dysfun: then you're fucked? :)

11:31 (or you might have to bear it in mind when deploying)

11:33 jonathanj: this seems ridiculously complicated

11:36 https://github.com/kyleburton/clj-xpath

11:36 this is new since i last looked for xpath clojure stuff

11:37 i-blis: jonathanj: also have a look at data.xml

11:38 jonathanj: the thing with data.xml is that i couldn't find out how to turn it into a zipper or query it

11:38 i-blis: you can pass options to the underlying javax.xml.stream.XMLInputFactory

11:39 even if you force the realization of the lazy-seq

11:40 jonathanj: so how do i query the result of parsing with data.xmL/

11:40 data.xml?

11:42 dysfun: doesn't it give you back a data structure representing the structure of the document?

11:42 you have tons of collection functions at your disposal

11:48 jonathanj: oh, you can actually use xml-zip to turn it into a zipper

11:49 none of the documentation actually mentions this

11:49 dysfun: heh, zippers are kept separately, but they include an xml zipper

11:49 but it depends if you want the zipper abstraction

11:49 there are many valid ways of getting data out of data structures

11:54 kwladyka: i am looking symetric encryption algorithm (clojure module) to encrypt id from database. id like 12356 to alphanumerical r2ifdrfwi and back. Can you recommend something?

11:55 The purpose is to hide id numbers in database

11:55 so algorithm has to consume as less CPU as possible

11:58 eventually it doesn't make sense and i will use uuid instead of id in database

11:59 i am not sure what is the best solution. Better will be use encryption in Clojure not uuid in DB, but i am afraid about performance.

12:00 or symetric encryption with cash... but it start to be complex

12:01 Maybe somebody can say something about encryption and performance in Clojure?

12:03 dysfun: sorry, why are you hiding id numbers in the database?

12:05 kwladyka: because inform your competition about so important data like number of orders every month, new users etc. is stupid :)

12:06 dysfun: use a uuid, be happy, stop encrypting the wrong thing

12:06 postgres has native uuid support

12:07 kwladyka: i know, but still i feel better is to have common database and hide id in app. But there is a performance problem. I don't know how to pass that.

12:08 If i wouldn't find any solution to hide id in app i will uuid in DB

12:08 *will use

12:08 dysfun: just use a uuid and get on with your day

12:09 kwladyka: ;)

12:09 dysfun: your other idea was not a good one

12:11 kwladyka: there are also other pros using uuid as id in DB. Separated app can generate data without id conflict

12:11 dysfun: in theory, certainly. in practice, i still have a unique constraint on my postgres tables keyed by uuid

12:12 kwladyka: dysfun how many rows?

12:12 dysfun: oh, we haven't launched yet

12:12 it's just defense in depth, in case it happens

12:12 kwladyka: dysfun mmm it is "impossible" if you use uuid v4

12:13 dysfun: yeah yeah, down to more atoms than there are in the universe. and yet every so often i still read about clashes happening

12:13 it matters less on a server, but if you let clients generate ids, they might have a shitty randomness source

12:14 and in the very many 9s case, it imposes almost no overhead

12:15 in the rare event of a collision, the transaction fails and i generate a new uuid

12:15 kwladyka: oh if client can generate it with other version then v4 that is bad desgined i guess

12:15 dysfun: how can you possibly enforce it in my case? it's a REST API with an open source client

12:16 kwladyka: dysfun i don't know details of your project. No idea :)

12:16 dysfun: well, the short answer is that you're fighting a losing battle

12:17 gganley: hello, how can i look at the "shape" of a datastructure, namely a HTML document pulled from a website using enlive.

12:17 dysfun: because somsone will port it to javascript and then wonder why it clashes a lot

12:17 prn ?

12:18 kwladyka: dysfun but it is not the purpose of your tool so i guess it is ok

12:18 gganley: I'm very new to all things web and relearning clojure. but I'm a pretty decent programmer

12:18 dysfun: yes, but given that i run the (also open source) webservice, it becomes my problem one way or another

12:19 anyway, better safe than sorry

12:22 kwladyka: dysfun i don't what you are doing, but i guess you should demand user to register and save the data under his authorisation id, if he is stupid and using javascript random string generator to generate uuid or something like that... what to do, he will lean to use the tool like is write in the documentation.

12:28 dysfun: kwladyka: or i could stop fighting the world and do sensible things instead

12:29 kwladyka: dysfun but what you can do with that? nothing. (if i understand what you are doing ;) )

12:30 Mokuso: kwladyka, I really like your nick

12:30 kwladyka: Mokuso why?

12:30 dysfun: what can i do with what?

12:30 Mokuso: in greeklish it's how the plural form of lapdance bars would be written

12:31 dysfun: i try and abstract it from a user as much as possible

12:31 Mokuso: *lapdance bar

12:31 dysfun: and i catch it if it fails

12:31 Mokuso: in Greek it's κωλάδικα

12:31 which literally means "a place with asses"

12:31 *"places with asses"

12:32 anyways, please continue

12:32 kwladyka: Mokuso lapdance bar?

12:32 dysfun: that is accidentally hilarious

12:32 quotefiled

12:33 kwladyka: Mokuso what to do, it happens all the time with all nicks :)

12:34 Mokuso even word mokuso exist ;)

12:34 dysfun: a few years ago a brand of indian sauces and things had to pull out because they found out their brand name was something rude in punjabi or some other language

12:34 Mokuso: kwladyka, yeh, for both comments ;)

12:35 been to Poland btw, years ago, it was nice

12:35 good beer

12:35 dysfun: beer and sausage

12:35 Mokuso: beer and soups :>

12:35 dysfun: hunter stew!

12:35 and lots of meat

12:35 kwladyka: Mokuso Where do you live?

12:36 Mokuso: kwladyka, in GR

12:36 dysfun: i don't imagine there are too many clojure jobs in GR

12:36 kwladyka: Mokuso oh you have problem with immigrants now?

12:37 dysfun like in PL....

12:37 Mokuso: dysfun, actually there's a company at Thessaloniki who's looking for clojure programmers :>

12:37 but yeah, not many companies around

12:37 kwladyka, the islands have huge problem

12:37 Athens too

12:37 dysfun: i saw a maltese company looking for clojure devs the other day

12:38 seems clojure is mostly breaking out in places you don't normally associate with development because they see it's great and they're not burdened with it being new like enterprise is

12:38 kwladyka: Mokuso whole Europe is so stupid and naive... i am watching this and... that is sad

12:39 Mokuso: kwladyka, yeah...

12:39 dysfun: i think perhaps that's quite strong, quite a lot of european people are really quite open minded

12:39 their leaders less so

12:40 kwladyka: yeah there are too open minded to get so stupid ideas...

12:41 Mokuso: I don't think Europeans can ever be too open minded, 'cos our freedom of thought is bounded by our history

12:42 kwladyka: the next world war coming and i believe it is the spark

12:42 Mokuso: the Americans are most likely the most open minded folk, but then they might be way too open minded sometimes, which turns against them in the end

12:42 kwladyka: it will takes years, but history will repeat like always

12:45 and other countries (also USA and Russia) will help with this fire. But of course it is my opinion. When economical fundament is in dangerous people always go to war.

12:48 hyPiRion: ugh

12:48 ,(binding [*print-dup* true] (println "hello" "world"))

12:48 clojurebot: "hello" "world"\n

12:49 TMA: you have reminded me of an anecdote from mathematical analysis: "open set is like a closed party -- nobody can get in"

12:49 hyPiRion: ^ is that intentional?

12:49 I thought it would only matter for pr and friends

12:52 kwladyka: dysfun what do you think about uuid_generate_v1mc() vs v4? v1mc based on time, v4 is totally random.

12:52 dysfun: i use v4 because there are even greater issues with v1

12:54 kwladyka: dysfun but in theory (practice?) it mean v1mc will never have conflict because of time based?

12:54 dysfun: haha, if you think that, you're going to have to some surprises

12:55 kwladyka: dysfun i don't know, there is didn't find clear information about that

12:55 dysfun: okay, well let's take out the mathematical security and go back to the example where your random source isn't very good

12:56 how many transactions a second do you think you have to get to with the reduced number of bits before the same node starts clashing? :)

12:56 kwladyka: hmmm i have to press something on keyboard and it changes my words when i am writing.... it happen too often when i write something with no sense :)

12:57 dysfun i don't know, but i guess a huge number

12:57 dysfun: v4 uuids are the only ones i'm inclinded to trust, and i'm only inclined to trust them to the point where i expect that in some cases clashes may happen

12:57 well that depends on how bad your randomness source is. if you're using glibc rand() equivalent, it's actually quite a small number

12:57 and you'd be surprised how often that happens

12:58 kwladyka: dysfun i will use of course solution like http://www.postgresql.org/docs/9.4/static/uuid-ossp.html or similar

12:59 dysfun: yeah there are two options for uuids in postgres. one of them only supports v4

12:59 kwladyka: so i guess it is good source

12:59 just not sure use v4 or v1mc

12:59 dysfun: but i still think it's worth putting a unique constraint on if the data is supposed to be uniquely identified

12:59 kwladyka: also found this article https://blog.starkandwayne.com/2015/05/23/uuid-primary-keys-in-postgresql/

13:00 dysfun: use v4

13:34 holy crap my tests finally pass in clojurescript

13:34 (they previously only supported clojure)

13:34 oh yeah i commented half of them out

13:36 macrolicious: I'm looking at the cider doc's at https://github.com/clojure-emacs/cider, and it mentions invoking C-c C-e with a 'prefix argument' to insert the result into the current buffer… what is the prefix argument (it's not specified)?

13:37 dysfun: C-u

13:37 C-c C-c C-e

13:37 (yes, it's the same mechanism you use to repeat actions)

13:38 justin_smith: macrolicious: all emacs commands can take a numeric prefix, C-u is 1 (see also Meta+num-key)

13:38 and yeah, the number is usually interpreted as a count, but that's up to the function

13:39 dysfun: also it needn't be a number

13:39 justin_smith: dysfun: there's no mechanism for a non-numeric prefix

13:39 dysfun: all prefix keys provide numbers

13:39 dysfun: there isn't an interactive means of doing it

13:39 but it's possible in code :)

13:39 justin_smith: right, and when you are non-interactive it's not a prefix, it's an argument

13:40 so like I said, prefixes are numbers

13:40 dysfun: actually this is emacs, there almost certainly *is* a means of providing a non-numeric argument

13:40 it's just we don't know what it is

13:41 macrolicious: oh man, this is awesome… thanks!

13:41 dysfun: but it would be very handy to know

13:41 justin_smith: dysfun: no, this is base level emacs impl stuff, any "non-numeric prefix" would not be a true command prefix in this sense https://www.gnu.org/software/emacs/manual/html_node/elisp/Prefix-Command-Arguments.html

13:41 dysfun: okay, fair enough

13:42 justin_smith: dysfun: lolemacs "numerous commands make a distinction between nil and the integer 1"

13:42 hahahaa

13:42 dysfun: nice

13:42 emacs lisp has always seemed so utterly backwards to me

13:42 justin_smith: it's some crufty old time stuff

13:43 dysfun: i like the keybindings and having a programming language in my editor and everything, but i wish it were a decent programming language

13:43 justin_smith: it's like meeting someone that still worships one of the ancient Phoenician gods or something

13:43 dysfun: true that

13:43 dysfun: i saw someone tried to make an emacs in clojure, but it stalled because elisp support

13:43 obviously if you have to throw away you entire life of emacs config, it's a problem

13:44 justin_smith: dysfun: see also emacs in ocaml, emacs in scheme, emacs in haskell, emacs in c, emacs in perl...

13:44 actually "emacs in scheme" is still ongoing and they still think it's gonna work

13:44 dysfun: oh, i thought those just stalled because there was no point

13:44 Morgawr: Okay.. maybe I'm missing something, I'm developing a library and a project that uses that library, I found a bug in the lib, I fixed it, I pushed it to clojar (upped the version), I recompile my project with the new version, I run it and the bug is still there

13:44 justin_smith: haha I'm sure they think the same thing of "emacs in clojure"

13:44 Morgawr: sourcemaps (it's clojurescripts) shows that the cljs file for that library still has the old line in

13:44 dysfun: i wouldn't actually develop an emacs, i would develop something significantly less batshit

13:45 Morgawr: what am I doing wrong?

13:45 it's like my bugfix isn't being pushed to clojars

13:45 dysfun: what did the output of pushing to clojars say?

13:45 justin_smith: Morgawr: you can open a jar file, it's just a zip

13:45 dysfun: did it take the update?

13:45 justin_smith: Morgawr: download the one from clojars, check the code in the jar

13:45 Morgawr: dysfun: Yes it did

13:45 justin_smith: I'll try

13:46 dysfun: ah okay, it's not duplicate version then

13:46 unzip -l jar.jar

13:46 (*very* useful as a boot user, because boot is batshit crazy insane)

13:46 justin_smith: or just navigate to it in editor, if your editor is smart enough

13:46 eg. emacs can open jars, vim, idea

13:46 dysfun: i hadn't honestly conidered that emacs would just open a zip, but i bet it does

13:47 justin_smith: dysfun: yup, zips or tars, like directories

13:47 and then you can get at the files, sometimes saving even works

13:47 dysfun: oh ace

13:47 it just works

13:47 this isn't the emacs i know ;)

13:48 justin_smith: dysfun: another nice one - if you name a file foo.gpg, on first save emacs will prompt for whose public key to encrypt to, and when re-opening it will prompt for the password and decrypt

13:48 dysfun: amazingly some things in emacs are really nice and simple to use

13:48 haha

13:48 dysfun: yeah, a stuck clock is right twice a day

13:49 Morgawr: Okay looks like the line for the bugfix is in the .jar pushed to clojar, now I need to check the .jar that is actually used by my project, where can I find it again?

13:49 dysfun: i wish being an emacs user weren't quite so stockholm syndrome-y

13:49 justin_smith: dysfun: I have not actually used any other general-purpose software that integrates with gpg / pgp as nicely as emacs does

13:49 Morgawr: ~/.m2/... I'd delete the version you have locally and force a re-download

13:50 Morgawr: justin_smith: trying that, thanks

13:51 justin_smith: Morgawr: path under .m2 should be easy to find based on package / project

13:51 Morgawr: Yeah, I found it :)

13:51 just rm -rf'd its directory so it forces a redownload

13:51 (not the whole .m2)

13:52 Nope, looks like that didn't fix it... wtf

13:52 justin_smith: Morgawr: lein clean /

13:52 you might also need to restart figwheel if you are running it/ or use clean-build etc.

13:57 Morgawr: justin_smith: Okay this is weird, I cleaned the whole project, checked the locally-downloaded (and the only version) library, the bugfix is there, but the project still has the bug and the sourcemaps point to an old line which still has the bug

13:58 dysfun: #object[Error Error: No protocol method IWithMeta.-with-meta defined for type cljs.core/IndexedSeq: (123)]

13:58 let's start with 'what is an indexedseq'?

13:58 and why is it not one of the meta-supporting datastructures in clojurescript?

14:00 sounds like you didn't manage to clean out the cljs

14:00 and you haven't rebuilt it since

14:00 justin_smith: Morgawr: did your clean remove the source map? could be your clean targets are off

14:00 dysfun: or you're referring to the wrong version in your project.clj

14:00 Morgawr: dysfun: I doubt that's the case since there's only one version downloaded at all in the current offline repo

14:01 justin_smith: that could be the problem, where do I find the source maps?

14:01 justin_smith: Morgawr: running clean should be removing the source map and all js files that are not external libs

14:01 Morgawr: your cljs config tells the compiler where to put those things, :output-to

14:01 Morgawr: yeah then they should be cleaned

14:02 dysfun: there is a leiningen setting to tell it what to clean

14:02 justin_smith: Morgawr: try verifying by running clean and seeing if any of those files exist afterward

14:02 yeah, your cljs config doesn't inform the clean task

14:02 you have to manually configure it usually

14:02 unless you tell cljs to output to a place like target that gets cleaned

14:03 dysfun: it would be lovely if we had a silver bullet, but we don't

14:03 so we just play with our build configs until they work

14:03 or at least appear to

14:07 Morgawr: Okay... I fixed it it seems. Thanks for the help! looks like I was erroneously looking in the wrong folder when cleaning some targets

14:07 now it works as intended :D

14:12 BRODUS: does clojure or java provide a built-in for unescaping a string?

14:12 dysfun: which type of escaping?

14:12 BRODUS: backslash escaping

14:13 justin_smith: ,(print-str "\"OK\"")

14:13 clojurebot: "\"OK\""

14:14 Glenjamin: what are you going to do with the escaped string?

14:15 BRODUS: hmm, I tried that already, I'm trying to use it on the result of clojure.repl/source-fn

14:16 Glenjamin: it sounds like the string isn't escape

14:16 justin_smith: BRODUS: since clojure throws an error for "unknown escape sequences", I don't know what unescaping would be...

14:16 Glenjamin: *escaped

14:16 you're just displaying it in a place which escapes for you

14:16 if you just want to see the source, try (source) instead of (source-fn) ?

14:17 BRODUS: yeah im using source-fn because I need the string

14:18 Glenjamin: the string you get back isn't escaped

14:18 well, the repl escapes the string when displaying it

14:18 justin_smith: ,(count "\\")

14:18 clojurebot: 1

14:18 Glenjamin: unless i'm missing what you're asking still

14:19 justin_smith: exactly, the escaping is a detail of the repl / printing mechanism, not a property of the string itself

14:19 clojure doesn't have any such thing as an "escaped string" as an actual thing

14:19 except as used in printing, and that's a property of printing, not the string

14:20 BRODUS: Glenjamin: you're right. I was using the repl to examine it and the escaping threw me off.

15:14 kwrooijen: Hey guys, I'm having a bit of trouble with the choices in the concurrency field (still very new to Clojure). Basically I want to spawn a lot of "worker" processes which can do a variety of tasks, and have unpredictable lifetimes.

15:14 From what I understand, go blocks would be a bad choice since you can only have a limited amount? And I don't think spawning a new native thread for each job is a good idea either.

15:15 Would futures be a good candidate for a large amount of tasks?

15:15 Hansen-Pansen: Futures are also handled by an internal, kinda fixed thread pool.

15:16 To have more control over the number of threads in a pool, I can recommend https://github.com/TheClimateCorporation/claypoole

15:16 kwrooijen: I see, so the concurrency tools that Clojure provides by default might not be suitable for this problem?

15:17 I'm a bit used to Erlang's concurrency model, since that's my primary language. But I've been wanting to try out Clojure for a long time

15:19 Hansen-Pansen: I dabbled with Erlang a little bit. Clojure's core.async channels come close to Erlangs agents.

15:20 justin_smith: kwrooijen: you can use core.async to manage concurrent tasks, and use the thread macro in core.async for things that are meant to be long-running

15:20 kwrooijen: for thread pools and parallel stuff claypoole is handy (it has it's own configurable-pool-using version of pmap)

15:20 kwrooijen: Hansen-Pansen: I assume you meant Erlang's actors? From what I understood about core.async chans is that you can't spawn too many go blocks

15:21 justin_smith: Hansen-Pansen: future thread pool is not fixed

15:21 Hansen-Pansen: it expands indefinitely (and I know this because I needed to stop using futures and use a fixed pool instead :P)

15:21 Hansen-Pansen: kwrooijen: Yes, of course you are right: ACTORS.

15:21 justin_smith: kwrooijen: go blocks don't map to threads

15:22 kwrooijen: Doesn't core.async's "thread" macro spawn a native (unix) thread?

15:22 justin_smith: kwrooijen: you can have more go blocks than threads, that's fine. What isn't good is long running computation heavy tasks inside go blocks - that steals threads from core.async, and that is where you should use the core.async/thread macro which is much like go but uses its own thread

15:22 kwrooijen: Or am I misunderstanding you?

15:23 Hansen-Pansen: justin_smith: oh, thanks.

15:23 justin_smith: kwrooijen: yes, and that's what it is for

15:24 kwrooijen: so use go when the primary task in the block is passing messages and coordination, use thread when you expect a long blocking task (io) or heavy CPU usage that will last a long time

15:24 (if using core.async)

15:24 kwrooijen: justin_smith: Does that also count for a large amount of threads though? I can't imagine spawning 50-100k native threads

15:25 justin_smith: kwrooijen: I've done it, it isn't a good idea :P

15:25 kwrooijen: Haha ok then that isn't what I need sadly

15:25 justin_smith: kwrooijen: if you also need to manage large numbers of heavy cpu usage or long blocking tasks, you want something like claypoole

15:26 core.async can have many blocks and use fewer threads, but that is fundamentally incompatible with heavy cpu usage or long blocking io. it isn't magic and can't upgrade your hardware.

15:27 kwrooijen: Yeah I thought that, seems that when I look at the default concurrency tools provided by Clojure, that Erlang would be a better candidate for *this* case

15:27 justin_smith: kwrooijen: maybe you could do something fancy with aws lambda

15:28 kwrooijen: clojure's going to get much more work done per CPU cycle. Or do you just mean erlang's better at running a program on multiple boxes at once?

15:29 kwrooijen: No I meant more by managing a large amount of long running jobs, not in terms of number crunching

15:29 Hansen-Pansen: kwrooijen: If you are really trying to match Erlang's model in Clojure, maybe take a look at https://github.com/puniverse/pulsar

15:30 justin_smith: kwrooijen: large amount / long running are both fine in core.async. What isn't fine is blocking a thread.

15:30 clojurebot: c'est bon!

15:31 Hansen-Pansen: kwrooijen: As justin_smith said, blocking will be bad. But the same applies to Erlang's actors.

15:32 kwrooijen: Isn't the whole point of concurrency to not block any thread? And I'm still a bit confused about core.async

15:32 Since before you said it's bad to spawn too many native threads and go blocks are not good for long running jobs

15:33 Sorry if my questions are bit still, I'm only familiar with Erlangs concurrency model which is pretty dead simple

15:34 And thank you for bearing with me on this until now

15:34 Hansen-Pansen: At a Berlin conference, Joe Armstrong said that an actor shouldn't do work for more than 100 .. 200 ms worth.

15:35 kwrooijen: Some tasks can't be done within 100 ms though

15:35 dysfun: yes, and it's a rule of thumb

15:35 the sorts of systems he works on are relatively low latency

15:35 not like machine intelligence or something

15:36 kwrooijen: I completely agree on that, if it can be avoided

15:36 But if you you need to invoke a low latency task you might not have a choice

15:37 And then still, you could have 1 line of execution creating 100 ms tasks, you're still with that one long lasting line

15:37 dysfun: low latency isn't all that difficult to program for in the general case, fsvo 'low latency

15:38 Hansen-Pansen: kwrooijen: Then you have to ship that task off to a new thread. And if threads on that box are limited, ship it off to a different machine.

15:40 kwrooijen: Yeah, if course machines have their limits

15:40 s/if/of

15:41 But thank you for helping me on this, I'll be taking a look at the libraries you've linked. And possible rethink my strategy :)

16:06 amalloy: lein pro tips: you can add any number of `do` to your lein command line, to emphasize how important you consider the task: $ lein do do do do help

16:07 dysfun: :)

16:07 lein do do do do do do do do do do do do there's no limit

16:09 tcrayford_____: amalloy: unix protip: if you pipe `cat` into itself enough times it yells at you

16:34 justin_smith: kwrooijen: one distinction maybe missing here is the difference between blocking and parking

16:35 kwrooijen: long-running tasks are fine, but blocking ones (even if much much shorter) are not

16:35 as long as the long running tasks park.

16:35 there are certain actions like channel ops that park, and allow the block to be put aside until later based on channel activity

16:36 long-running tasks are fine in a go block as long as they park regularly

16:49 dysfun: justin_smith: what you mean they won't magically save us from infinite loops? ;)

16:50 justin_smith: dysfun: nor will they save us from deadlocks or resource starvation, sadly

16:50 dysfun: damnit i want a silver bullet

16:53 kwrooijen: Ah I see, so waiting for channel input within a go block is considered "parking" ?

17:05 I have to go now, but thank you for the help!

17:25 cortexman: flatten an arbitrarily nested sequence of various types...

17:29 dysfun: 'flatten'?

17:29 as in that is the name of a core function

17:32 cortexman: you didn't answer the question...

17:37 i've been trying that function and i'm pretty sure it doesn't do what it says it does

17:37 amalloy: you didn't ask the question, cortexman

17:38 you just gave a sentence fragment followed by an ellipsis. nobody knows what you're asking, and dysfun is guessing

17:38 TEttinger: ,(flatten [1 2 (java.util.ArrayList. 5 6 '(a b c))])

17:38 clojurebot: #error {\n :cause "No matching ctor found for class java.util.ArrayList"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.IllegalArgumentException: No matching ctor found for class java.util.ArrayList, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyzeSeq "Compiler.java" 6875]}\n {:type java.lang.IllegalArgumentException\n :message "No matchin...

17:39 TEttinger: ,(flatten [1 2 (java.util.ArrayList. [5 6 '(a b c)])])

17:39 clojurebot: (1 2 [5 6 (a b c)])

17:39 TEttinger: that is not what I guessed

17:39 ,(flatten [1 2 [5 6 '(a b c)]])

17:39 clojurebot: (1 2 5 6 a ...)

17:42 cortexman: i think my problem is that hashmaps are collections, and flatten works on sequences

17:42 so if you have a vector of lists of hashmaps of blah blah blah... it doesn't work, because maps aren't sequences

17:42 TEttinger: source for flatten is https://github.com/clojure/clojure/blob/clojure-1.7.0/src/clj/clojure/core.clj#L6843

17:42 amalloy: you don't ever really want to flatten something like that anyway

17:42 ~flatten

17:43 clojurebot: flatten is rarely the right answer. Suppose you need to use a list as your "base type", for example. Usually you only want to flatten a single level, and in that case you're better off with concat. Or, better still, use mapcat to produce a sequence that's shaped right to begin with.

17:43 cortexman: i agree that you don't ever want to do that

17:43 but i'm not you.

17:46 kenrestivo: it's a blunt instrument, for sure.

17:46 cortexman: json can return messes

17:46 unpredictable messes

17:52 TEttinger: ,(do (defn seq-like? [x] (or (sequential? x) (map? x))) (defn map-flatten [x] (filter (complement seq-like?) (rest (tree-seq seq-like? seq x)))) (map-flatten [1 2 {:a 3} [10]]))

17:52 clojurebot: (1 2 :a 3 10)

17:52 TEttinger: ^ cortexman

17:53 cortexman: TEttinger: reading this now, thanks

17:53 writing it is beyond me

17:53 for now..:)

17:54 TEttinger: generally once you know enough to write flatten you realize it's a bad idea

17:54 apply concat is more surgical

17:54 cortexman: TEttinger: it totally works

17:55 TEttinger: woohoo

17:55 I totally don't know why it works!

17:55 tree-seq is weird and very common in the source of the standard lib

17:56 cortexman: you're just walking the tree, testing if it's a seq, and if not, seq'ing it

19:56 tolstoy: note to self: when dealing with something that has to run on windows, double your estimate.

19:57 amalloy: except your expected number of users. quintuple that

19:58 tolstoy: Yep. Most of 'em still on XP. ;)

19:59 I can't figure out why this cljs/node thing seems to cause 99% action when dealing with opening and closing a socket.

20:00 Er, 90% CPU running in Electron. So, start from scratch, on windows. I can't even figure out how to edit something! ;)

20:03 Malnormalulo: Is there an idiomatic way to reduce a seq with a function, but produce a seq of each incremental result?

20:04 Glenjamin: (doc reductions)

20:04 clojurebot: "([f coll] [f init coll]); Returns a lazy seq of the intermediate values of the reduction (as per reduce) of coll by f, starting with init."

20:04 Glenjamin: ,(doc reductions)

20:04 clojurebot: "([f coll] [f init coll]); Returns a lazy seq of the intermediate values of the reduction (as per reduce) of coll by f, starting with init."

20:04 Glenjamin: ah

20:04 Malnormalulo: I knew there had to be a function for that. Thanks!

20:08 georgeyj: hi

20:09 i followed this tutorial https://github.com/bhauman/lein-figwheel/wiki/Running-figwheel-in-a-Cursive-Clojure-REPL but i keep getting an error when i hit run: Exception in thread "main" java.io.FileNotFoundException: Could not locate figwheel_sidecar/repl_api__init.class or figwheel_sidecar/repl_api.clj on classpath.

20:15 neoncontrails: georgeyj: that's typically a namespace issue related to the structure of your project. You might double check the (ns ... ) declarations of your files to make sure they're consistent with the tutorial's

20:15 also, welcome to Clojure!

20:16 georgeyj: i just did lein new figwheel

20:16 and then opened it up

20:16 brand new project

20:16 thanks

20:23 so anyone know?

20:23 just installed intellij and cursive and trying to get figwheel working with intellij

20:33 ok it just started randomly working

20:33 but now when i save files it doesnt auto reload

20:33 i have to manually refresh still

20:43 neoncontrails: georgeyj: ah, yeah there is a reasonably simple fix for that, let me see if I can find it

20:43 georgeyj: ok neato

20:47 neoncontrails: georgeyj: stop me if you've read through this already https://github.com/bhauman/lein-figwheel

20:47 georgeyj: yeah i've read that

20:48 neoncontrails: And on-jsload is set to true?

20:49 georgeyj: this? (defn on-js-reload [] ;; optionally touch your app-state to force rerendering depending on ;; your application ;; (swap! app-state update-in [:__figwheel_counter] inc) )

20:49 i just left it as it was generated

20:51 neoncontrails: Go ahead and uncomment that, that's the one you're looking for

20:53 georgeyj: still not working

20:55 neoncontrails: there is a related flag you'll need to set in your project.clj if you haven't yet, which loads the function into the dev environment

20:55 georgeyj: ok what is the flag?

20:57 neoncontrails: I'd recommend the docs, just because there's a few different configuration options and it discusses the tradeoffs

21:00 georgeyj: ??

21:00 clojurebot: ? is !

21:00 georgeyj: i've been reading the docs it's not working though

21:00 i followed the tutorial exactly

21:02 neoncontrails: were you able to load the silly birds? that demo should have live code reloading enabled straight out of the box

21:05 georgeyj: well i want an empty project

21:05 ughhh why are clojure docs so incomplete...

21:08 justin_smith: georgeyj: "an empty project" as in you don't have a project and just want clojure? "java -jar clojure.jar"

21:08 neoncontrails: Figwheel's well-documented. It's just one of the many programs that's easier to learn by example

21:08 georgeyj: no i mean like

21:08 i'm trying to get this working for a friend

21:09 and it's very frustrating because we're following the docs exactly and it just isn't working

21:10 installed jdk, lein, intellij, cursive, then did lein new figwheel firstproject then followed that https://github.com/bhauman/lein-figwheel/wiki/Running-figwheel-in-a-Cursive-Clojure-REPL exactly and it just doesnt work

21:10 been messing around with the project.clj, googling stuff, etc. nothing

21:10 he tried it too and cant get it working

21:10 neoncontrails: Definitely sounds a lot more frustrating than "git clone https://github.com/bhauman/flappy-bird-demo.git" and getting a working environment up in about 60 seconds

21:11 georgeyj: ??

21:11 clojurebot: ? is !

21:11 georgeyj: thats how you have to do it?

21:11 why dont the docs work?

21:12 we've been on this for hours and i can tell he's about ready to give up

21:12 justin_smith: georgeyj: the tooling around cljs in particular is still kind of brittle

21:12 georgeyj: getting started just takes way too long and it just doesnt work

21:13 justin_smith: georgeyj: if you follow the official clojurescript intro, it makes a lot more sense. But people want to tell you to skip that and jump into figwheel because figwheel has all the features.

21:13 georgeyj: well i mean it wouldnt be that bad if anyone could help

21:13 justin_smith: georgeyj: we try to help

21:13 georgeyj: well it's not like im asking how to do something extremely specific

21:14 this is something that everyone has to go through to use figwheel and intellij

21:16 bleh

21:16 justin_smith: georgeyj: you're hitting multiple levels of stuff at once - lein, figwheel, clojurescript, cursive (I don't know how well you knew intellij before setting this up)... even if all are usable, the small issues when setting each up can have a multiplicative effect when you don't know which one is misconfigured

21:16 georgeyj: yeah im aware of that thats why i follow every step exactly

21:16 it still works if i manually refresh the page i just want to get autoreload working

21:17 justin_smith: georgeyj: not following steps is not the only source of misconfiguration though. Versions change, slight incompatibilities happen.

21:17 tutorials hold google juice past their time of relevance.

21:17 georgeyj: what is google juice

21:18 justin_smith: the magic sauce that makes your page be high on the page

21:18 when googled

21:18 georgeyj: https://www.google.com/search?q=intellij+figwheel+tutorial&ie=utf-8&oe=utf-8

21:18 i dont even see any other tutorials

21:20 neoncontrails: Why are you averse to demos?

21:20 georgeyj: because it doesnt matter if i can get that working

21:20 neoncontrails: There's nothing more illustrative of how something works than a working project

21:20 georgeyj: its not like im going to start every project in the future by cloning a flappy bird demo.. it's just ridiculous

21:20 neoncontrails: Right, so admire it, compare with yours, and iterate

21:21 georgeyj: also its not even the same

21:21 neoncontrails: I'll admit it's not always that easy in practice, but the flappy-birds demo is designed as more of a skeleton showing sane Figwheel defaults

21:22 And it just *poof* works

21:22 georgeyj: the intellij figwheel tutorial says to make a script file, remove lein-figwheel from :plugins, etc.

21:23 does no one else here use intellij and figwheel?

21:23 i looked at the clojure survey results and it says intellij was the second most popular and figwheel the most popular

21:24 id imagine this is a common problem??

21:24 neoncontrails: I use IntelliJ. It's the bee's knees

21:24 georgeyj: ok have u tried figwheel?

21:25 neoncontrails: Intermittently for the past few months. I'm no expert but I think it's a fine piece of software

21:26 georgeyj: ok can you do me a favor and try to get the two working?

21:27 marcfontaine: is it possible to do structural searches on clojure code with cursive ?

21:28 neoncontrails: I don't really know what else I can say that would be helpful to you. I learned by kicking the tires of the flappy-birds demo

21:29 georgeyj: sigh

21:29 the response to a newbie coming in asking how to get started with figwheel and intellij shouldn't be: clone this old demo and do a diff to see whats wrong

21:30 maybe ill just go back to js and wait a couple more years for docs to get better

21:32 justin_smith: for the record my answer was "the tooling ecosystem is full of brittle things that change quickly, and do the basic clojurescript intro before doing any figwheel or nrepl / cursive integration." https://github.com/clojure/clojurescript/wiki/Quick-Start

21:33 georgeyj: if things change quickly it's of extreme importance that there's a guide for the most common path or else beginners will never be able to get started and the language will die..

21:34 justin_smith: georgeyj: the quickstart is the common path. All other things are optionals or nice to haves.

21:34 (in terms of cljs usage)

21:35 georgeyj: huh?

21:35 http://blog.cognitect.com/blog/2016/1/28/state-of-clojure-2015-survey-results

21:35 it's 70% vs 20%

21:35 justin_smith: georgeyj: common as in "all users of cljs will use the tech described in the clojurescript quick start"

21:35 common as in 100% of cljs users need to understand those things

21:36 everything else just builds on that

21:36 georgeyj: ive read this before

21:36 the quickstart

21:36 i still have this figwheel problem though

21:42 oh well

21:42 back to javascript

21:43 ill be back in a couple years i still think clojure is the best language probably but god damn these docs are awful lol

21:43 jiegec: my use of cloiure is fluent...

21:44 i love clojure

22:02 rhg135: Being able to code reload is a nice to have technically, but a very nice to have

22:02 On web apps at least

Logging service provided by n01se.net