#clojure log - Jul 17 2015

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

1:25 crocket: Is it possible to embed clojure plugins or python plugins in a clojure program?

1:25 Is it simple?

1:42 sm0ke: goog.require could not find: cljs.core

1:43 anyone else saw this

1:43 pretty vague question i know

2:08 jyu1: I have a func (defn a ([x] x)),how to add a new branch in runtime, become (defn a ([x] x) ([x y] (+ x y))

2:09 thanks at advanced

2:11 sm0ke: i am not sure if that is possible

2:12 a macro can do it though by overwriting the function

2:19 jyu1: a macro used currently, `(def ~name (~name ~@p)) . it is used to curry, but I want to keep the original def

2:20 and another problem is that the macro must be used in the same namespace with the func

2:24 sm0ke: sounds tricky, i guess you can use multimethods to add new dispatch at runtime

2:24 not sure if it would work

2:25 jyu1: the background like this

2:25 (defcurrable piece-name->id "get the mapped id from the piece name" [entity-name piece-name] [piece-name-ids] (-> (piece-name-ids) (get-in [entity-name piece-name])))

2:26 a macro is defined , defcurrable

2:26 it has 2 parameter vector [entity-name piece-name] [piece-name-ids]

2:27 the former is the params, and the later is that dependencies

2:28 and curry the func with dependencies at the top level function.

2:30 (cur piece-name->id sc/piece-name->id #(b/get-state :piece-name-ids))

2:30 so i need not pass the dependencies everywhere

2:31 sm0ke: jyu1: are you aware of `partial` in clojure?

2:31 jyu1: i see

2:31 sm0ke: seems like you want that

2:31 ,((partial + 2) 3)

2:31 clojurebot: 5

2:32 jyu1: i use closure to do this instead.

2:32 (defmacro defcurrable "define the currable function, p is the params to be curried" [name doc p p1 body] `(defn ~name ~doc ~p1 (fn ~p ~body)))

2:35 actually it is the problem how to inject dependencies.

2:36 sm0ke: it sounds very fragile to change function definition at runtime

2:36 i mean you do it all the time in repl

2:36 but thats for dev

2:36 i wouldnt try that stunt in production

2:36 but ymmv of course

2:38 jyu1: https://github.com/weejulius/imdb/blob/master/src/imdb/core.clj, https://github.com/weejulius/imdb/blob/master/src/imdb/schema.clj, you will see I have to inject lots of dependencies to the functions.

2:38 sorry, it is hard for me to state well. thanks for your advice.

2:39 sm0ke: wow that is something

2:39 is still dont understand, why can you use something like (def new-fun (partial old-fun some-val)) ?

2:40 (def new-new-fun (partial new-fun other-val))

2:40 and so on

2:42 jyu1: I understand partial. but that is not the key. no matter partial or curry, or others, i just want to inject dependencies a better way.

2:45 i find a useful article, http://ekosz.github.io/2012/08/22/overriding-functions-in-clojure.

2:50 you see the format of all my functions, a->b, for example entity-id->entity, it is used to get entity by id, but actually this func will depend on lots of others, I use defcurrable macro to seperate them in the parameter list, and inject the dependencies in the top level function.

2:51 i am thinking a way to simpify the injection.

3:07 Phoh4ang: Can somebody explain me why we have clojure.test and cljs.test? Why can't it be a single namespace?

3:14 crocket: If I invoke '(assoc config :appenders (get-default-appenders (:log-file config)))', (:log-file config) becomes nil in get-default-appenders.

3:14 Why?

3:14 clojurebot: http://clojure.org/rationale

3:15 crocket: Is it a bug in assoc?

3:16 No, it's not.

3:16 The bug is somewhere else.

3:17 It was my bug.

3:18 kungi: crocket: of course it was :-) The First Rule of Programming: It's Always Your Fault

3:21 crocket: It seems every bug is stupid.

3:21 kungi, not always.

3:21 That assumes everyone else doesn't make bugs.

3:21 H4ns: crocket: the more experienced you are, the more likely it becomes that you run into bugs made by others

3:21 kungi: crocket: it assumes that standard library functions which everyone uses every day are not broken.

3:22 H4ns: crocket: the likeliness that you discover a bug in some piece of code is inversely proportional to its number of users

3:22 crocket: the likeliness that the bug is your own is always much larger than the likeliness of a bug in someone elses code.

3:24 crocket: Mutations introduce bugs.

3:24 I mean code mutations done by a coder.

3:33 How do I package a leiningen project with an executable?

3:33 I wish a shell script was generated that delegates to an uberjar.

3:37 H4ns: crocket: chmod +x uber.jar; ./uber.jar

3:38 crocket: H4ns, does that really work?

3:38 kungi: H4ns: really?

3:38 H4ns: folks. why don't you just give it a try?

3:39 kungi: H4ns: It sounds to easy to be true :-)

3:39 dstockton: superh4ns

3:39 crocket: H4ns, It doesn't work.

3:39 H4ns: dstockton: i hope you know the reference :)

3:40 crocket: then your operating system does not support it. it works on linux.

3:40 kungi: I get an exec format error when I try this

3:40 dstockton: peep show ;)

3:40 H4ns: dstockton: +1

3:40 reminds me, they were supposed to release another season.

3:41 crocket: Why does leiningen raise my CPU temperature when it start up?

3:41 H4ns: kungi/crocket: it is possible that you need to install something so that the exec handler for jar files is installed in your distribution. i tried this on centos 7 and there it worked.

3:41 oddcully: s/linux/some &/

3:41 dstockton: yes, end of the year i think H4ns

3:42 H4ns: dstockton: so looking forward to it :)

3:42 dstockton: me too, will probably be the last

3:42 Phoh4ang: crocket: because java is slow and greedy for your cpu and memory

3:42 H4ns: dstockton: even the longest adolescence has to end at some point.

3:43 Phoh4ang: I actually hope someday we will have lein running in a nodejs. Not sure if it's eve possible though

3:43 TEttinger: $google lein-bin

3:43 lazybot: [Raynes/lein-bin · GitHub] https://github.com/Raynes/lein-bin

3:43 crocket: For some people, adolescence ends in 30s.

3:43 H4ns: (inc TEttinger)

3:43 lazybot: ⇒ 62

3:43 TEttinger: thanks!

3:44 kungi: (inc TEttinger)

3:44 TEttinger: lein-bin only will work if java is on your path though

3:44 lazybot: ⇒ 63

3:45 TEttinger: if you want to work around that (java isn't put on the path by default on windows with the JRE installer), you may need a openjdk bundler.

3:45 $google lein-packr

3:45 lazybot: [Packr-generated exe prints nothing, does nothing #33 - GitHub] https://github.com/libgdx/packr/issues/33

3:45 TEttinger: gah

3:46 oddcully: hehe

3:46 crocket: lein-bin

3:46 TEttinger: https://github.com/tommyettinger/lein-packr

3:47 lein-bin is pretty cool, it just appends the jar contents as a big string into a combination .bat and .sh file (it's valid syntax for both)

3:47 so it's less than 1K larger than the uberjar I think

3:53 H4ns: i'd still like to know why ./uber.jar works for me

3:53 oddcully: because you have configured in your kernel, that you allow alternative exec to happen

3:54 H4ns: oddcully: that much i gather - but as i have not done that explicitly, i'd like to know what needs to be done if it does not work.

3:55 oddcully: yeah, i guess your distribution has done that for you

3:55 H4ns: oddcully: yes, that much i had guessed.

3:55 oddcully: you could look, what files get installed with your jdk or the supporting package

3:55 wasamasa: echo '#!/bin/bash' > uber.sh; echo 'java -jar uber.jar' >> uber.sh; chmod +x uber.sh; ./uber.sh

3:55 lazybot: '#!/bin/bash' > uber.sh; echo 'java -jar uber.jar' >> uber.sh; chmod +x uber.sh; ./uber.sh

3:55 wasamasa: ...

3:56 not lazy enough

3:58 oddcully: wasn't there even a a target in lein for that shebank version? or is the openjdk shipping a tool for it?

4:01 H4ns: couldn't for the life not remember the name... looked it up in kernel config: binfmt_misc is the module for it

4:01 H4ns: oddcully: right at this moment i found that binfmt must be the keyword for searching, thanks! :)

4:02 oddcully: H4ns: in your kernel source: Documentation/java.txt

4:03 wasamasa: awesome: https://github.com/Raynes/lein-bin/blob/master/src/leiningen/bin.clj#L20-L24

4:15 crocket: Is anyone interested in writing a DDNS client in clojure?

4:15 I wrote a simple one.

4:15 https://github.com/crocket/clj-ddns-client

4:18 kwladyka: What do you think about Clojure doesn't have types for data. What with big projects with many programmers. How they know what function will return if it doesn't have type. And what if somebody will change "id" to "uid", it need to change all code which use that functions, but how to find it in code without types.

4:20 Fuivash7: kwladyka: see core.typed or prismatic/schema

4:21 kwladyka: Fuivash7, thx.

4:21 So it is additional library

4:21 but what about idea?

4:22 idea of Clojure without types

4:22 is it good or not when project has many programmers

4:22 and code is changing, what functions return is changing

4:22 and other program has to know what function return

4:23 H4ns: kwladyka: please design your sentences before you type and send them to the channel.

4:23 kwladyka: it is hard to explain :P

4:23 H4ns: kwladyka: there are languages which support strong static typing, and those cater for those that believe that strong types are the only way to write reliable software.

4:24 Fuivash7: kwladyka: personally, I would like to see a clojure with a rich type system. Today's type systems are still pretty restrictive though, so it's hard to get it right. As for "code is changing, how do programmers stay sane" question, I believe it's somewhat more of an organizational problem.

4:25 kwladyka: H4ns, but how it looks in Clojure? I don't have experience like that in Clojure and i was talking about that with my friend yesterday. I couldn't explain him how Clojure programmers deal with changes what function return.

4:26 H4ns: kwladyka: one good approach is not to change the contract of a function without making sure that all uses are updated. another good approach is documentation. also preconditions, tests, code inspection, discipline.

4:26 Fuivash7: microservices

4:27 Right?

4:27 kwladyka: Fuivash7, yes but for example with strong types when you change "id" to "uid" for User you can easy find all places in code which use User and check it. What will you do in Clojure?

4:27 H4ns: Fuivash7: microservices are a way to contain the mess in smaller units :)

4:27 crocket: kwladyka, Clojure has other measures to enforce interface integrity.

4:28 H4ns: kwladyka: i will do textual replacements. i've done that for many years, and while it sometimes sucks, it is by no means a chore.

4:28 crocket: However, haskell has better guarantees of interface integrity.

4:28 Fuivash7: H4ns: yep, that's what we programmers do, lol

4:28 H4ns: kwladyka: i see how people love the convenience of their integrated type safe refactoring, but i've been living without that forever, so i'm not missing it.

4:29 kwladyka: but maybe the topic what i am talking about it is not problem in reality? My Clojure programmers don't have problem with changes like that. I don't know.

4:29 crocket: Clojure's immutable data structures help you reason about code a lot more than usual static typing techniques.

4:29 H4ns: kwladyka: besides, smarter refactoring tools for clojure are available, i just don't feel that i need them.

4:29 crocket: kwladyka, ^^

4:30 Fuivash7: kwladyka: you will feel pain. It's just my opinion though.

4:30 kwladyka: Fuivash7, feel pain if/when what? :)

4:30 H4ns: kwladyka: programming is making trade-offs all the time. use one thing, you'll not get what the other one supplies.

4:31 crocket: H4ns, Rich Hickey would say microservices do not necessarily pull apart components.

4:31 H4ns: also, programming is not about "being right", but about "getting stuff done" mostly.

4:31 crocket: getting stuff done and maintaining

4:31 Fuivash7: kwladyka: if you have a zillion klocs of clojure code and you *have to* change all :id to :uid but only for Users. It seems like a stupid task for me though, not something you'll do in a real-world application.

4:31 crocket: When it comes to maintaining, code integrity matters.

4:32 That's where clojure comes in.

4:32 H4ns: that's where tests come in much more than any language choice.

4:32 kwladyka: Fuivash7, yeah example is maybe not the best

4:33 Fuivash7, but the problem in that situation is to find all places which use Users data.

4:34 Fuivash7: H4ns: everytime I hear something like 'programming is not about "being right", but about "getting stuff done"' I get that strange sad painful feeling in my stomach.

4:34 kwladyka: Fuivash7, and GUI support for that operation

4:35 H4ns: Fuivash7: life becomes much easier when you accept that.

4:35 kwladyka: Fuivash7, but the true is programming is for business.

4:36 programming and programmers without business don't exist

4:36 Fuivash7: kwladyka: well, after all you can use namespaced keywords, datomic-style. I don't know about GUI; cursive and ccw probably support such refactorings.

4:37 H4ns: I guess so, but for me it sounds like "life becomes much easier when you don't think about morals or ethics of your decisions". It's kinda true, but still feels wrong.

4:39 H4ns: Fuivash7: it is not wrong. programming is not a science, it is an art form. it is highly dependent on fads and on technology available at a certain point. the programmer always makes tradeoffs, some deliberately, some unconscious.

4:40 kwladyka: Fuivash7, on the end of rational thinking you have to care about how people feel and about they morale so even if you don't think about your inner morals or ethics rational thinking still win. So like in coding when you think about deliver product and maintenance still you have to care about quality and do thinks right :)

4:41 i think it is more about which thinks in head should come first, about priority :)

4:42 crocket: Is it safe to execute "java -Xmx20m -XX:MaxMetaspaceSize=40m -jar target/uberjar/clj-ddns-client-0.1.2-standalone.jar"?

4:42 I'm not sure how small clojure programs could handle 20 megabytes of heap.

4:43 The program is at java -Xmx20m -XX:MaxMetaspaceSize=40m -jar target/uberjar/clj-ddns-client-0.1.2-standalone.jar

4:43 oops

4:43 The program is at https://github.com/crocket/clj-ddns-client

4:44 Fuivash7: H4ns: I can't say I don't agree with you. On the other hand, something inside me keeps telling me that it is exactly this point of view which leads us to crappy industry standards, flash-player, the 12309 bug still popping out on some linux boxes and people who still write desktop applications in C. I'm just grumbling though.

4:44 crocket: It seems a small clojure program is stable with 20MB of heap and 40MB of metaspace for a while.

4:45 Would it throw an OutOfMemory exception anytime soon?

4:45 H4ns: Fuivash7: i envision a future in which programming will no longer be an art form, but a standardized activity that people can actually rely on. we're not there yet, by any means, though.

4:45 Fuivash7: kwladyka: yeah, you right about priority, that's the point.

4:47 crocket: It currently consumes 146MB of memory despite 20MB of heap and 40MB of metaspace.

4:47 What am I missing?

4:47 Fuivash7: H4ns: in order to make it possible we human probably have to replace our natural language with an artificial, totally precise one, so that requirements can be communicated effeciently. I kinda like the idea, you know.

4:47 H4ns: Fuivash7: either we become robots or the robots become us.

4:49 kwladyka: Fuivash7, if i know the true reason why software looks like a mess inside in many cases are managers not programmers and not assertive programmers. Managers push managers and they push lower managers and... ... and they push programmers to deliver more and more in shorter time.

4:50 programmers do mess job, and month by month they do more mess and write slower and slower and all doesn't make sense :)

4:51 Fuivash7: H4ns: GLORY TO ROBOTS! KILL ALL HUMAN! I'm not sure though whether this phrase is used outside russian language or not, lol.

4:53 kwladyka: the other side of problem is that in order to become a surgeon you have to study for almost a ten years, and in order to become a programmer, you know, you have to write code, that's all. Anyway, I think we are a little off-topic here, and people actually have question about clojure and jvm...

4:55 kwladyka: Fuivash7, yeah but only one reason why people let programmer without experience write code is... not so big consequence like in surgery :) ok then end off-topic. Unfortunately i can't help with this question about clojure and jvm...

4:58 Fuivash7: kwladyka: well when the robots will finally take out the consequences will be exactly the same, if not worse, lol. as for jvm memory consumption, I'm not sure either but I suspect there is a minimum allowed value for the maxmetasize.

4:58 crocket: ^^^ can't find a proof though

5:07 Pupeno_: So, in Clojure I cannot call a function unless it was defined *above* in the file?

5:08 H4ns: Pupeno_: you can use "declare" if you want to use a symbol before defining it.

5:08 crocket: Fuivash7, 40MB was about the minimal metaspace size.

5:11 Fuivash7: Pupeno_: clojure evaluates your files just like you would input the forms in the REPL, so it's by design, not "lazy programmers don't care enough to write multipass compiler" or whatever.

5:12 crocket: maybe it's the jvm itself eating the other memory.

5:14 jaen: Quick question, when you use schema & coercions the order is coerce -> validate, which is useful if you, say, have incoming JSON data you want to hydrate into Clojure datastructures. But I couldn't find any way to switch the order to validate -> coerce, which would be useful to validate the shape of an API request before turning it into JSON. Is anyone aware of such a feature in schema offhand?

5:33 crocket: How can I deamonize a clojure app without jsvc?

5:33 Without apache commons daemon.

6:11 wasamasa: why not let your init handle that

6:11 it's been specifically engineered for that task!

6:15 kwladyka: is any function which turn [x y] into x y?

6:16 TEttinger: kwladyka: sorta, not really

6:16 ,`(~@[+ 1 2])

6:16 clojurebot: (#object[clojure.core$_PLUS_ 0x67a5eb90 "clojure.core$_PLUS_@67a5eb90"] 1 2)

6:16 TEttinger: ,`(~@[3 1 2])

6:16 clojurebot: (3 1 2)

6:17 kwladyka: so is any better way to write https://www.refheap.com/344128913896a0746f47df8e4 ?

6:17 TEttinger: ~@ only works in a syntax-quote, and there is no multiple return in clojure

6:17 clojurebot: Roger.

6:17 TEttinger: apply

6:18 wasamasa: kwladyka: why not destructure judiciously?

6:18 oddcully: kwladyka: why not destrcuture?

6:18 lerl

6:18 wasamasa: kwladyka: return a vector and let the function dealing with it do the work

6:18 TEttinger: ,(apply str [1 2])

6:18 clojurebot: "12"

6:18 TEttinger: if that's a two-element collection, apply will work fine

6:20 kwladyka: so how it should looks, i am a little confuse

6:21 oddcully: kwladyka: use [r c] instead of size, then replace your first/last calls with r and c

6:22 ,(let [[c r] '(:a :b)] (str c r))

6:22 clojurebot: ":a:b"

6:22 kwladyka: oh... but is there a way to not use "let"?

6:22 oddcully: or go with the apply

6:23 but you already use `let`?

6:23 or do what TEttinger suggested: (apply handle-resize (t/get-size term))

6:23 kwladyka: yes, but i am thinking is it a way to not use let, do this in one line

6:24 hmm

6:25 tgoossens: if (def b [a 2]) why does (let b a) gives "IllegalArgumentException let requires a vector for its binding in com.ooliba.tablescript.processor:1"

6:26 oddcully: maybe (let [b a]) ?

6:27 tgoossens: it should return 2

6:27 interesting

6:27 kwladyka: apply looks good, thank you

6:27 oddcully: the error is about the let not getting a [] as first argument

6:29 kwladyka: tgoossens, did you read https://gist.github.com/john2x/e1dca953548bfdfb9844 ?

6:30 tgoossens: kwladyka, nope thanks

6:30 i'll take a look at it

6:30 because i don't understand why it doesn't work oddcully

6:30 kwladyka: tgoossens, it is good, i learned from that site

6:32 tgoossens: if (def b [(symbol "a") 2])

6:32 then b is a vector

6:32 then why

6:32 (let b a)

6:32 says the first argument is not a vector

6:33 kwladyka: tgoossens, because let [x 1 y 2] not let x 1 y 2

6:34 tgoossens, read this site which i linked, this is precise describe

6:34 tgoossens: kwladyka, ok :)

6:34 kwladyka: and of feel free to ask :)

6:34 *of course

6:34 tgoossens: thanks

6:39 crocket: hi

6:39 How do I make a comment? ';' or ';;'?

6:40 tgoossens: kwladyka, i think i will be needing macros

6:40 of course it doesn't work

6:40 namra: crocket: one ';' is enough for a comment

6:41 crocket: but you might use multiple to distinguish between code sections etc, for that you can take a look at that style guide -> https://github.com/bbatsov/clojure-style-guide#comments

6:41 H4ns: ; for comments on the same line as code, ;; for comments interspersed with code, ;;; for top-level block comments

6:42 crocket: namra, emacs clojure-mode indents ';' incorrectly.

6:42 Thus, I just use ';;' in emacs clojure-mode.

6:45 H4ns, Where do I find the guide line?

6:46 H4ns: crocket: what do you mean? https://github.com/bbatsov/clojure-style-guide#comments ?

6:48 kwladyka: tgoossens, i don't know what are your trying to do

6:52 (t/move-cursor term (first @terminal-size) (last @terminal-size)) <- how to write more readable? only with "let [[cols rows] @terminal-size]"? (t/move-cursor term #([%1 %2])@terminal-size) doesn't work because of ClassCastException chess_challenge.console_draw$pause$fn__2040 cannot be cast to java.lang.Number lanterna.terminal/move-cursor (terminal.clj:155)

6:54 oddcully: (let [[cols rows] @terminal-size] (t/move-cursor term cols rows))

6:58 kwladyka: oddcully, but is it possible without let?

6:58 hmm but it is good enough i think

7:44 tgoossens: kwladyka, are you still here?

7:50 kwladyka: tgoossens, yes

7:55 tgoossens: kwladyka, this illustrates what I want https://gist.github.com/tgoossens/9e4f6237d06ecbb0ceed

8:02 kwladyka: tgoossens, hmm still i am not sure what you want achieve

8:03 tgoossens: kwladyka, basically a list containing symbols and i want to replace certain symbols by a value after which I eval the list

8:03 i could convert it to string and replace

8:03 kwladyka: tgoossens, you did def var with char "a" and "b" and you did def quation with char '+ '1 'a 'b and i dont understand why and what you want to do with that

8:03 tgoossens: but that seems not ideal

8:04 kwladyka: tgoossens, if i understand you want replace one element of list with another value?

8:05 tgoossens, let is for something else

8:05 tgoossens: '(+ a b a )

8:05 replace a by 1

8:05 b by 2

8:07 kwladyka: tgoossens, hmm anyway why do you need that change? where you use that?

8:09 tgoossens: kwladyka, basically: the user gives an expression string "a+b", by a parser converted to '(+ a b) Then I want to assign valuesto a and b

8:10 kwladyka, important to know i'm not making a calculator

8:10 the user gives me "a+b" and expects to get a clojure function with two inputs that returns the sum

8:12 kwladyka: tgoossens, you could find the position of a and b and use http://clojuredocs.org/clojure.core/replace

8:12 tgoossens, i guess maybe there is shorter way, but i don't know now

8:12 tgoossens: i was trying with macro's

8:12 but i don't understand them well enough yet

8:13 kwladyka: (replace '{0 ZERO, 1 ONE, 2 TWO} '(This is the code 0 1 2 0))

8:13 (This is the code ZERO ONE TWO ZERO)

8:13 ,(This is the code ZERO ONE TWO ZERO)

8:13 clojurebot: #error {\n :cause "Unable to resolve symbol: This in this context"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Unable to resolve symbol: This in this context, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6543]}\n {:type java.lang.RuntimeException\n :message "Unable to resolve symbol: This in this co...

8:13 kwladyka: ,(replace '{0 ZERO, 1 ONE, 2 TWO} '(This is the code 0 1 2 0))

8:13 clojurebot: (This is the code ZERO ...)

8:13 ticking: tgoossens: if you want to write a user facing programming language, translation to clojure is not a good idea

8:14 tgoossens: if it doesn't have to be expandable not making it expandable is generally a good idea

8:14 tgoossens: especially if the alternative means, being able to inject arbitrary clojure code

8:14 tgoossens: kwladyka, seems to work :)

8:16 ticking, basically what I have to do is to process some SQL like query given by the user: "SELECT age+1 FROM people". Where people will be a "table" in memory (no database involved)

8:16 and i need to convert 'age +1' to a clojure function in order to apply it to the data structure in memory

8:17 ticking, but your point seems valid

8:18 ticking: I'd create a ast with instaparse and than evaluate that with a treewalker

8:26 kwladyka: tgoossens, why no use sql memory database?

8:27 noncom: ,(map #([%]) [1 2 3])

8:27 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (0) passed to: PersistentVector>

8:27 noncom: why? ^

8:28 ,(map (fn[a] [a]) [1 2 3])

8:28 clojurebot: ([1] [2] [3])

8:29 crocket: ,(println "bitch")

8:29 clojurebot: bitch\n

8:29 crocket: ,(print "bitch")

8:29 clojurebot: bitch

8:30 snowell: ,(map vector [1 2 3])

8:30 clojurebot: ([1] [2] [3])

8:30 snowell: noncom: ^

8:30 crocket: (into [] '(1 2 3))

8:30 snowell: I mean…that doesn't really answer your question, but it's at least nicer than defining a new fn :D

8:31 crocket: ,(into [] '(1 2 3))

8:31 clojurebot: [1 2 3]

8:31 crocket: ,(into "" \b \i)

8:31 clojurebot: #error {\n :cause "java.lang.Character cannot be cast to clojure.lang.IFn"\n :via\n [{:type java.lang.ClassCastException\n :message "java.lang.Character cannot be cast to clojure.lang.IFn"\n :at [clojure.core$transduce invoke "core.clj" 6583]}]\n :trace\n [[clojure.core$transduce invoke "core.clj" 6583]\n [clojure.core$into invoke "core.clj" 6601]\n [sandbox$eval174 invoke "NO_SOURCE_FILE" 0...

8:31 crocket: ,(join "" \b \i)

8:31 clojurebot: #error {\n :cause "Unable to resolve symbol: join in this context"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Unable to resolve symbol: join in this context, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6543]}\n {:type java.lang.RuntimeException\n :message "Unable to resolve symbol: join in this co...

8:31 crocket: ,(clojure.string/join "" \b \i)

8:31 clojurebot: #error {\n :cause "Wrong number of args (3) passed to: string/join"\n :via\n [{:type clojure.lang.ArityException\n :message "Wrong number of args (3) passed to: string/join"\n :at [clojure.lang.AFn throwArity "AFn.java" 429]}]\n :trace\n [[clojure.lang.AFn throwArity "AFn.java" 429]\n [clojure.lang.AFn invoke "AFn.java" 40]\n [sandbox$eval221 invoke "NO_SOURCE_FILE" 0]\n [clojure.lang.Compi...

8:31 crocket: ,(doc clojure.string/join)

8:31 clojurebot: "([coll] [separator coll]); Returns a string of all elements in coll, as returned by (seq coll), separated by an optional separator."

8:31 crocket: ,(clojure.string/join [\b \i])

8:31 clojurebot: "bi"

8:32 crocket: ,(clojure.string/join [\b \i \t \c \h])

8:32 clojurebot: "bitch"

8:33 kwladyka: is it possible to clearn repl console?

8:33 *clean

8:33 and i mean about chars on console not vars and namespace

8:34 gfredericks: C-a C-k?

8:34 kwladyka: nope, i am using intellij repl

8:34 noncom: kwladyka: there is a tiny button on the console

8:34 don't remember how it looks

8:34 kwladyka: oh there iss a button!

8:34 noncom: probably something with an "x"

8:35 kwladyka: it is icon of trash :)

8:35 noncom: oh ok :)

8:35 kwladyka: should be rubber

8:36 noncom: kwladyka: in eclipse it is http://joxi.ru/DrlavXzIXoqWmP

10:09 tgoossens: Using instaparse (example from readme) i convert infix "2+2" to AST and with instaparse/transform to (+ 2 2) which then gets evaluated. However i'm interested in getting '(+ 2 2) instead of 4. How do i do that

10:14 crocket: Can I put (* 3 1000) in an .edn file?

10:23 TimMc: tgoossens: Just don't eval it? I'm confused about where eval is happening automatically. Perhaps a link?

10:26 tgoossens: I edited the source code of instaparse transform

10:26 TimMc,

10:27 The eval seems to happen in the recursion step

10:27 (apply ... ...)

10:27 (apply x y) i replaced that by (cons x y)

10:27 I'll propose in the project to include such a thing in apiµ

10:34 TimMc: I'm not familiar with instaparse, so this is all very mysterious to me.

10:35 I don't know why a parsing lib would include eval.

10:35 tgoossens: TimMc, it should be decomplected :)

10:36 justin_smith: crocket: yes, but it would be a list

10:36 TimMc: tgoossens: Can you show me where it does this?

10:36 tgoossens: yes

10:36 one moment

10:36 TimMc, https://github.com/Engelberg/instaparse/blob/master/src/instaparse/transform.clj line 36

10:37 replace 'apply' by 'cons' and problem is solved

10:38 TimMc: Oh, that's not eval -- that's just tree transform stuff.

10:39 Instead of passing :add + to insta/transform, why not pass :add (partial list '+)?

10:40 tgoossens: interesting

10:40 TimMc: (There's probably a nicer way of writing that.)

10:41 tgoossens: TimMc, Hey man. thanks a lot! :)

10:41 justin_smith: TimMc: you probably want (partial cons '+) to get the right output, but same idea

10:41 tgoossens: Nevertheless

10:41 I did not expect my tree to be evalutated

10:44 crocket: justin_smith, An unevaluated list

10:44 '(* 3 1000)

10:44 Shit, it's difficult to pronounce "an unevaluated list"

10:44 justin_smith: crocket: right

10:45 ,'(* 3 1000)

10:45 clojurebot: (* 3 1000)

10:54 TimMc: tgoossens: Hmm, I think the readme is pretty clear in that example that transform is being used for evaluation.

10:55 tgoossens: TimMc, i noticed now :p

10:55 TimMc: OK :-)

10:57 tgoossens: TimMc, A common error of mine. Assuming too quickly what it (should) does

11:01 crocket: Is there a way to string a value through a dynamic set of functions?

11:01 If the set was static, I could use '->' macro.

11:01 justin_smith: crocket: comp

11:02 ,((comp :c :b :a} {:a {:b {:c 42}}})

11:02 clojurebot: #<RuntimeException java.lang.RuntimeException: Unmatched delimiter: }>

11:02 justin_smith: err

11:02 crocket: ok!!!

11:02 That is it!!!

11:02 justin_smith: ,((comp :c :b :a) {:a {:b {:c 42}}})

11:02 clojurebot: 42

11:02 justin_smith: crocket: yeah, it's like -> but backward, and doesn't do things like macros

11:04 crocket: maybe you want ##(((comp (partial apply comp) #(reverse %&)) :a :b :c) {:a {:b {:c 42}}})

11:04 lazybot: ⇒ 42

11:04 crocket: Is there an equivalent of (apply comp (reverse x))?

11:05 justin_smith: ,(def (comp (partial apply comp) #(reverse %&)) pmoc)

11:05 clojurebot: #error {\n :cause "First argument to def must be a Symbol"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: First argument to def must be a Symbol, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyzeSeq "Compiler.java" 6740]}\n {:type java.lang.RuntimeException\n :message "First argument to def must be a Symbol"\n :at [cloju...

11:05 justin_smith: err

11:05 ,(def pmoc (comp (partial apply comp) #(reverse %&)))

11:05 clojurebot: #'sandbox/pmoc

11:05 justin_smith: crocket: pmoc, of course!

11:06 in all seriousness, nothing built in as far as I know

11:07 probably better as (defn pmoc [& fs] (apply comp (reverse fs)))

11:10 also, thrush might be a better name than pmoc for it

11:14 crocket: How do I string a value through a series of functions that only touch the value under a certain condition?

11:14 justin_smith: sounds kind of like cond->

11:15 but you need a non-macro version, right?

11:15 crocket: maybe?

11:15 No

11:15 I don't care

11:15 justin_smith: cond-> might be your thing then

11:15 (doc cond->)

11:15 clojurebot: "([expr & clauses]); Takes an expression and a set of test/form pairs. Threads expr (via ->) through each form for which the corresponding test expression is true. Note that, unlike cond branching, cond-> threading does not short circuit after the first true test expression."

11:16 MattWest: If the conditional depends on the value of your threaded value, you may rather use a function which has the conditional built in, since cond-> doesn't use the threaded value.

11:16 crocket: justin_smith, However, I need when-let!!

11:16 cond-> doesn't emulate when-let

11:18 justin_smith: some-> stops at the first nil result (if any)

11:18 ,(-> {} :a inc)

11:18 clojurebot: #error {\n :cause nil\n :via\n [{:type java.lang.NullPointerException\n :message nil\n :at [clojure.lang.Numbers ops "Numbers.java" 1013]}]\n :trace\n [[clojure.lang.Numbers ops "Numbers.java" 1013]\n [clojure.lang.Numbers inc "Numbers.java" 112]\n [sandbox$eval47 invoke "NO_SOURCE_FILE" 0]\n [clojure.lang.Compiler eval "Compiler.java" 6792]\n [clojure.lang.Compiler eval "Compiler.java" 67...

11:18 justin_smith: ,(some-> {} :a inc)

11:18 clojurebot: nil

11:18 justin_smith: ,(some-> {:a 1} :a inc)

11:18 clojurebot: 2

11:18 crocket: Does some-> help me?

11:19 justin_smith: crocket: well, when-let doesn't proceed if a value is nil

11:19 that's how they are similar

11:19 crocket: I don't test for the value in the middle.

11:19 I test for another value

11:20 justin_smith: sounds like you want a plain old function

11:20 or maybe a few functions

11:20 crocket: (cond-> value (cond a) (action a) (:key value2) (action b))

11:21 (cond-> value (cond a) (action a) (:key value2) (action-b (:key value2))

11:21 I want to remove duplication of (:key value2)

11:21 (cond-> value (cond a) (action a) (:key value2) (action-b (:key value2)))

11:21 justin_smith, ^^

11:23 The second condition's value could be used in the second form.

11:25 justin_smith: for the (:key value2) part, how is that related to a / (action a) ?

11:25 in that it only gets executed if the first part was?

11:26 crocket: justin_smith, The actual code is https://www.refheap.com/106665

11:26 justin_smith: oh, so this works?

11:27 crocket: justin_smith, I haven't tested yet.

11:28 justin_smith: OK, looks like that should work

11:28 since your conditions don't use the threaded value, as MattWest mentions

11:29 crocket: justin_smith, How would you remove duplication of (:logfile options)?

11:29 justin_smith: crocket: I would do that in the destructuring on line 2

11:30 crocket: So brilliant

11:30 justin_smith: [{logfile :logfile verbose :verbose :as options} :options log-config :log-config}]

11:30 something like this

11:30 in fact you likely don't need the :as options part

11:35 crocket: justin_smith, [{{:keys [verbose log-file]} :options arguments :arguments} log-config]

11:36 This compiles.

11:36 justin_smith: yeah, that works too

11:36 danielpcox: Hey All, what does it mean when proxy throws "Exception Incompatible return types clojure.core/most-specific (core_proxy.clj:23)"?

11:36 justin_smith: crocket: usually, as soon as I do any nesting I stop using :keys altogether, for better or worse

11:37 danielpcox: sounds like you are trying to proxy something but you got one of its method signatures wrong

11:38 danielpcox: justin_smith: i did this: (proxy [App] [])

11:38 justin_smith: so a proxy that implements no methods and takes no constructor args?

11:39 danielpcox: justin_smith: well, i was originally trying to proxy a scala abstract class that extends this one, and got the same error, so i just started cutting things out of the scala class until i figured out which one of its parents was causing the trouble

11:40 justin_smith: oh, scala

11:40 interop with scala is... not easy

11:40 danielpcox: justin_smith: does this look like it should be proxyable with no constructor args? https://twitter.github.io/util/docs/index.html#com.twitter.app.App

11:41 justin_smith: i'm sort of earning the right to work with Clojure by implementing a framework my company has already developed in Scala :)

11:41 justin_smith: danielpcox: OK< but scala has some extra "stuff" that isn't part of the vm, and in order to extend it you have to satisfy it and it's weird and hard to interact with outside the scala language

11:42 you're much better off accessing clojure stuff from scala, that's much simpler, because clojure is much more "vanilla" in its usage of the jvm

11:44 danielpcox: justin_smith: i feel you. it has been pretty frustrating so far. but if i can figure out how to use this Scala framework they wrote from Clojure, I get to program in Clojure.

11:44 justin_smith: danielpcox: another options would be to make a small adaptor in scala, that can have an instance of a vanilla jvm interface injected, and then you could inject something written in clojure

11:45 danielpcox: hmmm… that might be a possibility

11:45 justin_smith: danielpcox: I'm not saying it's bad to use scala from clojure, just that scala does a great job of making it much more difficult than it should be

11:46 whereas clojure stays "closer to the metal", so one direction of interop is much easier than the other

11:46 danielpcox: thanks justin_smith, i'll try going the adaptor route

11:47 justin_smith: danielpcox: also, I hope your plot to integrate clojure succeeds!

11:48 danielpcox: justin_smith: :) so do i!

11:49 crocket: Let's assume I have {:appenders {:file-appender '(rotor/rotor-appender)}}

11:50 justin_smith: crocket: why a list with a symbol in it? that's really kind of weird

11:50 crocket: How do I associate :debug to :level in the map at the second position of the list?

11:50 The reulst would be {:appenders {:file-appender '(rotor/rotor-appender {:level :debug})}}

11:50 I'm constructing a function call.

11:51 justin_smith: crocket: does someone eval the list eventually? ahh

11:51 crocket: I'm constructing a function call in a nested map

11:52 justin_smith: ,(update-in {:appenders {:file-appender '(rotor/rotor-appender)}} [:appenders :file-appender] concat [{:level :debug}])

11:52 clojurebot: {:appenders {:file-appender (rotor/rotor-appender {:level :debug})}}

11:52 crocket: No

11:52 It could be either {:appenders {:file-appender '(rotor/rotor-appender)}} or {:appenders {:file-appender '(rotor/rotor-appender {:a :b)}}

11:52 So, I can't just concat.

11:54 justin_smith, Can you think of a clever trick?

11:56 justin_smith: ,(update-in {:appenders {:file-appender '(rotor/rotor-appender)}} [:appenders :file-appender] #(list (first %) (assoc (second %) :level :debug)))

11:56 clojurebot: {:appenders {:file-appender (rotor/rotor-appender {:level :debug})}}

11:56 justin_smith: ,(update-in {:appenders {:file-appender '(rotor/rotor-appender {:a :b)}} [:appenders :file-appender] #(list (first %) (assoc (second %) :level :debug)))

11:56 clojurebot: #<RuntimeException java.lang.RuntimeException: Unmatched delimiter: )>

11:56 justin_smith: oops

11:56 scriptor: so the idea is to add that map to the list?

11:56 justin_smith: ,(update-in {:appenders {:file-appender '(rotor/rotor-appender {:a :b})}} [:appenders :file-appender] #(list (first %) (assoc (second %) :level :debug)))

11:56 clojurebot: {:appenders {:file-appender (rotor/rotor-appender {:a :b, :level :debug})}}

11:56 justin_smith: scriptor: update if present, create if not

11:57 second / assoc have that behavior when combined

11:57 ,(assoc nil :a 0)

11:57 clojurebot: {:a 0}

11:57 justin_smith: (second [])

11:57 ,(second [])

11:57 clojurebot: nil

11:57 scriptor: justin_smith: and by update you mean append?

11:57 justin_smith: what?

11:57 clojurebot: what is short for ,(doc ...)

11:57 scriptor: sorry, that was for crocket ^

11:58 justin_smith: scriptor: by update I mean add keys if there is a map

11:58 scriptor: there is no appending there

11:58 crocket: justin_smith, I think you could use deconstructuring.

11:58 clojurebot: No entiendo

11:58 justin_smith: crocket: sure, any usage of first/second can likely be replaced with a destructure

11:59 scriptor: well, there is appending if you need to create the map, right?

11:59 from '(rotor/rotor-appender) to '(rotor/rotor-appender {:a :b})

11:59 justin_smith: scriptor: it unconditionally creates a two element list

11:59 no matter what the input was

12:00 ,(update-in {:appenders {:file-appender '(rotor/rotor-appender {:a :b})}} [:appenders :file-appender] (fn [[h t]] (list h (assoc t :level :debug)))

12:00 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

12:00 justin_smith: ,(update-in {:appenders {:file-appender '(rotor/rotor-appender {:a :b})}} [:appenders :file-appender] (fn [[h t]] (list h (assoc t :level :debug))))

12:00 clojurebot: {:appenders {:file-appender (rotor/rotor-appender {:a :b, :level :debug})}}

12:01 justin_smith: ,(update-in {:appenders {:file-appender '(rotor/rotor-appender)}} [:appenders :file-appender] (fn [[h t]] (list h (assoc t :level :debug))))

12:01 clojurebot: {:appenders {:file-appender (rotor/rotor-appender {:level :debug})}}

12:02 crocket: justin_smith, https://www.refheap.com/106666

12:03 This is some dirty trick.

12:03 No one is going to understand this except me.

12:03 justin_smith: crocket: you'll get better performance if instead of (eval '(rotor/rotor-appender {})) you do (#(apply (first %) (rest %)) [rotor/rotor-appender {}])

12:04 crocket: also, that won't work, because '(+) doesn't have the callable function + inside, it has the callable symbol '+ inside

12:04 ,('+ 42 1)

12:04 clojurebot: 1

12:04 justin_smith: LOLOL

12:04 symbols invoke get, and the second arg acts as the "default value" if they are not found in the first arg

12:05 so you really don't want '(rotor/rotor-appender), unless you also plan to use resolve, which is silly and slow

12:05 crocket: justin_smith, I don't care about performance much.

12:05 justin_smith: ,((resolve '+) 42 1)

12:05 clojurebot: 43

12:05 crocket: fast enough

12:06 justin_smith: crocket: but seriously, I gave you an alternative above that isn't slow

12:06 that does the same thing

12:06 ,(#(apply (first %) (rest %)) [+ 41 1])

12:06 clojurebot: 42

12:06 justin_smith: skip the quoting part, then you don't need the resolve part

12:07 crocket: I'm so stupid

12:08 justin_smith: you're just new to the language, and to this style of coding

12:08 crocket: in general, avoid using the symbol for something if all you plan on doing is looking it up later

12:09 unless you think it should have a diferent value later...

12:14 crocket: justin_smith, I'm trying to build a function call.

12:14 So, it's like macro

12:14 I'm going macro.

12:14 justin_smith: crocket: why? why do it that way when you can just pass in a function then call it?

12:15 crocket: I want to build a data structure that I can call later in a one swoop.

12:15 It is built dynamically and sequentially.

12:15 justin_smith: crocket: sure, my apply example above does that

12:15 crocket: I realized that I could just build a function call..

12:16 It is simpler.

12:17 justin_smith: the thing you pasted won't actually work, because `() will just return the fully qualified symbols, you'd still need eval, or the marginally better resolve, but you don't need either if you pass in the actual funciton then use apply

12:17 crocket: justin_smith, https://www.refheap.com/106667

12:18 justin_smith: OK, but that still doesn't do the part where the appender gets called, that's what I'm talking about

12:19 crocket: justin_smith, Will it not work?

12:20 justin_smith: crocket: what you have now will return a list starting with a symbol. to invoke rotor/rotor-appender you either need to use eval, or resolve + apply, or (my preferred option) pass in the function itself and just use apply

12:21 crocket: The function could be anything.

12:21 justin_smith: crocket: sure it courld. eval and resolve are usually signs there is a problem with your design, unless you are building a compiler or interpreter of some sort.

12:22 *could

12:23 crocket: So

12:23 What do you recommend?

12:23 justin_smith: crocket: cleanest option, pass the function that constructs your logger, and your config, each under their own key in the map, and use apply to create the logger

12:23 crocket: There is only one argument.

12:24 actually

12:24 justin_smith: ,((fn [{:keys [f arg]}] (f arg)) {:f inc :arg 41}) ; if you know the arg count, that's even better

12:24 clojurebot: 42

12:25 crocket: Do you mean it's better to have {:appenders {:file-appender {:fn #'rotor/rotor-appender :arg {:path "ok.log" :maxsize 500}}}}?

12:25 justin_smith: right

12:25 then you can do a clean update-in to add keys to the arg

12:25 crocket: Damn

12:25 I originally went for that design.

12:25 justin_smith: and then call the fn with the arg later

12:25 haha

12:25 crocket: And, I wanted to remove :fn and :arg.

12:25 justin_smith: it's the best option

12:25 crocket: They looked dirty.

12:25 justin_smith: resolve and eval are dirtier

12:54 kwladyka: ,(key {[1 1] :king})

12:54 clojurebot: #error {\n :cause "clojure.lang.PersistentArrayMap cannot be cast to java.util.Map$Entry"\n :via\n [{:type java.lang.ClassCastException\n :message "clojure.lang.PersistentArrayMap cannot be cast to java.util.Map$Entry"\n :at [clojure.core$key invoke "core.clj" 1494]}]\n :trace\n [[clojure.core$key invoke "core.clj" 1494]\n [sandbox$eval25 invoke "NO_SOURCE_FILE" 0]\n [clojure.lang.Compiler e...

12:54 kwladyka: why?

12:54 clojurebot: why is Why

12:54 snowell: Because {[1 1] :king} is a Map, not a Map entry

12:55 What are you expecting it to return?

12:55 kwladyka: [1 1]

12:55 ,(key (first {[1 1] :king}))

12:55 clojurebot: [1 1]

12:55 kwladyka: but this works

12:55 snowell: Because (first <map>) returns its first map entry

12:56 kwladyka: what is difference between map an map entry?

12:56 snowell: A map is a collection of (key, value) entries

12:56 You can use keys and vals to get all the keys/vals in a map

12:56 kwladyka: oh because is one position map and i didn't see the point

12:56 ok i got it

12:57 snowell: Or you can get an individual entry (like with first) and find its key or val with… key or val

12:58 kwladyka: thx

12:58 snowell: np

13:11 justin_smith: ,(key (find {[1 1] :king}) [1 1])

13:11 clojurebot: #error {\n :cause "Wrong number of args (1) passed to: core/find"\n :via\n [{:type clojure.lang.ArityException\n :message "Wrong number of args (1) passed to: core/find"\n :at [clojure.lang.AFn throwArity "AFn.java" 429]}]\n :trace\n [[clojure.lang.AFn throwArity "AFn.java" 429]\n [clojure.lang.AFn invoke "AFn.java" 32]\n [sandbox$eval25 invoke "NO_SOURCE_FILE" 0]\n [clojure.lang.Compiler e...

13:11 justin_smith: ,(key (find {[1 1] :king} [1 1]))

13:11 clojurebot: [1 1]

13:12 justin_smith: kwladyka: you may want something more like {:position [1 1] :piece :king} unless you expect the one hash map to represent the whole board

13:12 and you could use group-by or map to go from the one representation to the other

13:17 crocket: Does :or in a map destructuring form lead to detection of nil values?

13:18 justin_smith: crocket: it doesn't test for nil/false, just whether the key is present

13:19 ,(let [{x :x :or {x 2}} {:x nil}] x)

13:19 clojurebot: nil

13:19 justin_smith: ,(let [{x :x :or {x 2}} {}] x)

13:19 clojurebot: 2

13:20 crocket: It seems :or detects presence of a key.

13:20 justin_smith: crocket: that's exactly what I just said

13:40 xonev: Hi there, I was just reading this http://swannodette.github.io/2013/07/12/communicating-sequential-processes/. And this caught my interest: "JavaScript promises don't solve the inversion of control problem - callback hell is unnested but it's still callback hell." Does anyone know of additional articles that explain that assertion?

13:41 justin_smith: xonev: I know swannodette hangs out here and on #clojurescript as dnolen if you have a specific question.

13:41 xonev: the alternative being offered is surely core.async (which uses channels to replace callbacks)

13:42 any good core.async intro should compare the channel using version with the ugly callback based alternative

13:42 xonev: thanks justin_smith, I will ask in #clojurescript, since it would be more on-topic there. I'm just trying to understand the problem better; I already like the solution

13:43 justin_smith: xonev: well, core.async is definitely on topic here too (just 'cause we have threads doesn't make it not useful)

13:45 xonev: ok, well I think my main question is how do promises not solve the inversion of control problem? For example, this article claims otherwise: http://blog.getify.com/promises-part-2/

13:46 crocket: ok

13:46 justin_smith, https://github.com/crocket/clj-ddns-client

13:47 is the product of the hard work I did today.

13:48 Is it possible to load a .clj file dynamically on the run?

13:48 If it was, then I could load clojure plugins on the run.

13:48 Hot plug in

13:48 amalloy: his section about loss of trust is just bizarre. if you write someAsyncFunction(function () {runMyProgram;}), then it's true you're at the mercy of someAsyncFunction. but...that's true even for someSyncFunction(10);! you never know, maybe it chooses not to return at all, just hijack the thread forever, or print a bunch of alerts

13:53 TimMc: amalloy: Yeah, from my quick read, it's a misplaced argument.

13:53 I'd be *much* more concerned about someone forgetting to call a callback or something like that.

13:54 justin_smith: crocket: load-file

13:56 TimMc: amalloy: I find any talk of "trust" in the context of pervasively mutable languages hilarious

13:57 "you passed a collection to this function, this is a loss-of-trust situation"

14:00 TimMc: window.undefined = 4

14:01 if (undefined = foo()) { ... }

14:01 bja: err, undefined is a singleton in js?

14:02 reminds me of `True = 0` in python

14:02 TimMc: Hmm, this used to wreak havoc with websites, but I guess now you can't actually write to window.undefined.

14:04 Ah well, you can still set JSON = 11

14:05 justin_smith: haha, I like that one

14:57 sm0ke: with new cljs upgrade i see a weird problem in my application

14:58 with advanced optimization intergration with a js library seems to break

14:58 which is working fine with no optimization!

14:59 dnolen: Bronsa: http://dev.clojure.org/jira/browse/TRDR-28 perf patch for cljs.tools.reader

15:00 sm0ke: js library is codemirror, and specifically the (.getValue codemirror) now returns nil/empty

15:01 amalloy: sm0ke: advanced optimization renames all members to short names, so it's renamed getValue to something like q, but the library you're including hasn't participated in that optimization

15:02 you need to provide some kind of externs or whatever, so that it knows that cna't be optimized away, or use aget to get out the property via a string

15:02 dnolen: amalloy: goog.object/get recommended now, trying to get everyone off aget for Object stuff

15:03 sm0ke: amalloy: i am using the library as extern itself so names are not mangled

15:03 it used to work fine before upgrade

15:04 i double checked that by searching for getValue in the compiled js

15:06 I am kind of clueless on this, specially since i am not able to get brepl working for advanced as well

15:12 Bronsa: dnolen: thanks, can you also take a look at https://github.com/clojure/tools.reader/commit/8330f773e6ecdab0edeaca824a4724ff75433304 and see if there are type-hints missing?

15:13 dnolen: Bronsa: the performance enhancements really don't come down to type hints

15:13 Bronsa: that commit looks non-trivial wrt perf implications

15:14 would need to rebase and rerun benchmarks & profiles, and likely rewrite that code

15:15 Bronsa: dnolen: ouch. those changes on resolve-ns and resolve-symbol are needed to support auto-qualifying on of symbols and keywords in syntax-quote

15:16 dnolen: Bronsa: makes sense but if you want the perf patch you'll just have to leave cljs.tools.reader alone for the time being.

15:17 Bronsa: dnolen: I already applied the perf patch, that commit is on top of that. I can revert it if you think it'll cause performance issues but that code (or a different impl of it) will eventually need to be committed

15:18 dnolen: Bronsa: oh ok!

15:18 Bronsa: dnolen: I'm fine with letting you take over cljs.tools.reader btw if that works best for you

15:18 dnolen: Bronsa: I think we should add a simple benchmark hardness to track regressions

15:19 Bronsa: no happy for you to lead but I think we should have a benchmark - like parsing cljs.core

15:19 Then you know the implication of a commit

15:20 s/hardness/harness

15:56 Bronsa: dnolen: yeah definitely. I'll take a look at how cljs benchmarks stuff and add some -- I don't have time to do any work until late Monday though so if you were planning on cutting a cljs release depending on the new t.r release I'm sorry but you'll have to wait a until early next week

15:57 dnolen: Bronsa: nah no plans yet, still working through bootstrapping stuff

15:57 Bronsa: ok cool

15:57 dnolen: Bronsa: I think a simple script that does before & after patch would be better than what ClojureScript currently does

15:57 reading cjls.core is sufficiently non-trivial

15:58 Bronsa: are you OK with this being a bash script? I don't mind putting it together since it would be useful to me too

15:58 Bronsa: yeah consuming the core ns is how I always benchmarked tools.reader/tools.analyzer & tools.emitter :)

15:58 dnolen: sure

15:58 dnolen: Bronsa: ok I will put something together

16:01 celwell: Hello, how could I get all the arguments passed to a function? Particulary, I need retrieve them while in a macro.

16:08 justin_smith: ,(defmacro psychic [& args] (println &form))

16:08 clojurebot: #'sandbox/psychic

16:09 justin_smith: ,(psychic :weird, :how :did :you :know?)

16:09 clojurebot: (psychic :weird :how :did :you ...)\n

16:09 justin_smith: celwell: does that give you what you need?

16:12 celwell: or do you mean you have a function, then you want to access its args in a macro call inside that function? because that would be very hygeinic and I wouldn't recommend it even if it was possible

16:12 celwell: Yeah the latter

16:13 I have macro "catch-notify" that is basically: `(try ~@body (catch Exception e (send-email (str e))))

16:13 justin_smith: I think clojure's scoping rules are too strict to do that without explicitly passing the args in

16:13 celwell: I would like to include all the args of parent function in teh email

16:14 a bad idea then?

16:14 justin_smith: yeah, I think that would involve some implementation defails if it is possible at all

16:14 celwell: ah ok

16:14 thanks

16:15 justin_smith: I mean I understand that's a reasonable functionality to want but I don't think clojure offers a good way to do it, because that would also allow a bunch of stupid things we don't want

16:15 spoopy action at a distance

16:15 celwell: Yeah, now that I think about it, it would need a secondary macro or something to cover the original function and that would be bad

16:15 amalloy: you can't distinguish between args to the parent function and locals introduced by something else

16:16 justin_smith: celwell: you could do like prismatic/schema and make your own version of defn wrapping the original

16:16 amalloy: but it is not too hard to look at &env if you want to include all the locals

16:16 justin_smith: amalloy: is there even a way to get at that stuff without relying on implementation details?

16:16 amalloy: justin_smith: you only need the keys of &env

16:16 which is fine

16:16 justin_smith: intersting

16:17 amalloy: the problem is that then you're holding onto the head of all locals, which can change behavior; and even if that doesn't break things, trying to print one of them might, because it could be infinite

16:17 justin_smith: ,(defmacro psychic [& args] (println &env))

16:17 clojurebot: #'sandbox/psychic

16:17 amalloy: ,(defmacro locals [] (into {} (for [k (keys &env)] [`'~k k])))

16:17 clojurebot: #'sandbox/locals

16:17 justin_smith: ,(let [x 1] (weird))

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

16:17 amalloy: ,(let [x 1] ((fn [y] (env)) 2))

16:17 clojurebot: #error {\n :cause "Unable to resolve symbol: env in this context"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Unable to resolve symbol: env in this context, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6543]}\n {:type java.lang.RuntimeException\n :message "Unable to resolve symbol: env in this conte...

16:17 justin_smith: ,(let [x 1] (psychic))

16:17 clojurebot: {x #object[clojure.lang.Compiler$LocalBinding 0x76d03c52 clojure.lang.Compiler$LocalBinding@76d03c52]}\n

16:18 amalloy: ,(let [x 1] ((fn [y] (locals)) 2))

16:18 clojurebot: {x 1, y 2}

16:18 justin_smith: fascinating

16:19 celwell: But if you're saying it might cause unexpected issues, I'm probably going to not use it. The point of this macro is to notify of problems, not create them... ha

16:20 justin_smith: celwell: I don't think it will cause unexpected issues actually, I'm glad people aren't doing complicated tricks using &env, but your usage and getting some data from &env sounds fine

16:20 I think I knee-jerked a bit on it

16:23 amalloy: i think it will cause unexpected issues, for the reasons i said

16:24 celwell: amalloy: Not sure if this is acceptable place to mention, but do you know of any Clojure developers looking for work? My Beverly Hills based startup is looking...

16:24 amalloy: me? just ask #clojure; this is the most likely place to find such people

16:25 celwell: Well I know you're in Santa Monica

16:26 justin_smith: that reminds me, I know about some contract work in the pdx area, simple stuff hitting APIs and cleaning up the data, if anyone in this area is looking.

16:35 blake_: I'm in the Valley. I hate the Beverly Hills commute. =P

16:36 celwell: blake_: hit me up when Elon's done with the Hyperloop

16:36 blake_: celwell: Ha! If they'd put some money into flying cars...

16:55 celwell: Sorry, I'm not able to retrieve those private messages sent to me. Emacs irc issues. My email: chris@purpledelivery.com

16:56 xemdetia: IT'S A RUSE

16:58 mk: blake_: what someone really needs is to put some money into developing a way to work on things without needing to commute

16:59 blake_: mk: Such a thing would require a massive NETwork, INTERconnecting people globally!

16:59 justin_smith: oddly I am not receiving any private messages regarding my job mention - it's legit, hit me up if you are looking

16:59 mk: blake_: haha. Let's just wait for your flying cars.

17:01 blake_: justin_smith: Well, but is it inside or outside the inundation zone? =P

17:30 elvis4526: What's the best way to execute a "timeout" in clojure? Like waiting 30 seconds and then proceed with some SEXP?

17:32 justin_smith: elvis4526: with core.async there's timeout, in regular clojure code you can use something like (let [cancel (delay :stop)] (future (Thread/sleep 30000) (when-not (realized? cancel) (do-it))) cancel) returning the "cancel" delay and doing the thing if nobody forces its value

17:32 (before 30 seconds pass, of course)

17:42 elvis4526: I don't mind using core.async - timeout seems to be the thing I'm looking for, thanks (again) !

17:44 kwladyka: if i am using one file only to test and this file doesn't have any test but it is to convert results to more human readable form should i put this file into test/app_name/file.clj or in another place?

17:44 what best practise say about that?

17:52 elvis4526: I think your test should be named file_test.clj, but otherwise yes its the "standard" place to put tests

17:56 kwladyka: elvis4526, but this file has 0 test

17:57 elvis4526, i use in only in repl to convert thing to more human readable when i am verify manually code

17:57 so it is something not common

18:00 ed-g: kwladyka, put it in a directory other than your src/ and include that dir using the :profiles { :dev ... } in project.clj

18:01 I use :profiles { :dev { :source-paths "dev" ...} ...}

18:01 if you call it user.clj it will automatically be in all your repls

18:02 kwladyka: ed-g, so it is better to put file in "dev" folder then "test" folder if purpose of this code is manual tests? :)

18:03 exactly this code draw solutions on screen in graphical form

18:07 ed-g, thx

18:23 roman_: quick question: is there is any easy way to test exceptions on macro expansion time?

18:28 nvm: found a way, eval and syntax quote for the win

20:56 reutermj: What ides do you guys use? Im getting fed up with light table

21:01 Bronsa: reutermj: give cursive a try

21:01 reutermj: Cool I love intellij. Ill try it

21:18 elvis4526: Cursive is probably the best thing next to CIDER.

21:20 my only complain would be the cljs support... the autocomplete and code analysis is pretty weird :4

21:25 reutermj: im a game developer so cljs doesnt excite me too much

21:26 TEttinger: reutermj: are you using play-clj by any chance?

21:26 it's a good one

21:31 reutermj: bits and pieces of it

21:32 but there are several parts of the api that it doesnt expose so Im having to write my own wrapper

21:50 viperati: I'm worried about investing more of my time in learning Clojure professionally. 6 years after 1.0 and there are only 11 jobs listed on indeed.co.uk for title:clojure compared with 321 for title:scala. I think Clojure is by far the best language out there but it seems destined to remain a niche player like Erlang. OK if you have job stability but as a freelancer looking for clients it's becoming a no-op for me.

21:52 Anyone else freelancing as a Clojure developer?

21:54 justin_smith: viperati: I was until pretty recently, I got a lead for a freelance job today actually, but had to turn it down

21:56 viperati: justin_smith: Which part of the world are you in?

21:56 justin_smith: viperati: portland, oregon

21:58 viperati: justin_smith: The London job scene is very much skewed towards Scala for some reason. Maybe due to all the financial companies who feel Scala is closer to their Java comfort zone. I dunno.

21:58 justin_smith: ~scala

21:58 clojurebot: Unfortunately the standard idiom of consuming an infinite/unbounded resource as a stream can be problematic unless you're really careful -- seen in #scala

21:59 justin_smith: clojurebot: that's a pretty dumb factoid

21:59 clojurebot: Gabh mo leithscéal?

21:59 viperati: :)

22:00 justin_smith: Do you think it's that most Java shops just can't cope with the parens or something?

22:00 justin_smith: he has better ones: 19:00 <clojurebot> scala uses UTF-17

22:00 viperati: no idea

22:00 TEttinger: clojurebot: scala is http://scalaz.github.io/scalaz/scalaz-2.9.0-1-6.0.1/doc.sxr/scalaz/Kleisli.scala.html

22:00 clojurebot: Ik begrijp

22:01 TEttinger: clojurebot: scala is http://nurkiewicz.github.io/talks/2014/scalar/img/list-scala.png

22:01 clojurebot: In Ordnung

22:01 TEttinger: ~scala

22:01 clojurebot: scala is http://scalaz.github.io/scalaz/scalaz-2.9.0-1-6.0.1/doc.sxr/scalaz/Kleisli.scala.html

22:04 TEttinger: viperati: I think Clojure has an unusually high usage amount in SF/Bay Area, and maybe Austin, TX. I could easily be wrong, I have never been to Austin.

22:05 I'm mostly judging by people here, there seems to be a high bay area presence

22:05 justin_smith: there's a decent amount of clojure stuff going on on the west coast US, all around

22:05 figures all the hip(ster|ie)s would be using it mostly

22:06 TEttinger: Tijuana has a great clojure job market too. did I say clojure, I meant drugs

22:07 justin_smith: TEttinger: as long as it isn't donkeys

22:07 TEttinger: heh

22:08 I'm glad the violence of the drug cartels seems to be going down in mexico. a distant relative of mine was killed when he went from his home in El Paso across the border for the day to buy a car for cheap. gunned down for looking out of place.

22:08 justin_smith: wow

22:08 TEttinger: (not sure his name, very very distant)

22:08 justin_smith: I'm sorry to hear that

22:08 TEttinger: yeah it was just shocking

22:08 reutermj: So, everyone who I know that uses java/scala is too afraid of leaving the comfort of oo

22:09 Also static types systems

22:09 justin_smith: I heard there was a flare up caused by the reduced marijuana sales (coming from the colarado, oregon, washington legalization), with less business there was more fighting over what was left supposedly

22:09 TEttinger: reutermj, it's interesting. I am moving fluidly between Clojure and Java these days

22:09 (same application, eventually, the Java's a lib)

22:09 justin_smith: they are afraid the clojure cartel is gonna put their heads on a LOGO turgle

22:10 *turtle

22:10 TEttinger: haha

22:10 better call Rich

22:11 reutermj: TEttinger yeah I feel like once youve done both for a while it's pretty easy

22:11 but going in is scary

22:12 TEttinger: reutermj: there's something you could show a javadev, not sure who in here made it... it's quite good

22:12 https://github.com/rschmitt/dynamic-object

22:12 https://github.com/rschmitt/collider

22:16 reutermj: TEttinger those are pretty cool.

22:17 But, arent they more targeted at clojure programmers that need to interface with clojure from java?

22:17 not getting java programmers into clojure?

22:17 TEttinger: the first is aimed at getting clojure techniques into java programming

22:17 immutable data, easy data construction, clojure-like API

22:18 the second I am not sure. it doesn't seem to use clojure's data structures verbatim

22:19 seems aimed at clojure style while programming java

22:20 reutermj: so right now I'm working on SquidLib, which a friend of mine originally made as a Java library for roguelikes (text-based, top-down, @ is the player, # is a wall, etc.). I'm realizing that Swing for rendering is going to cause problems if the rendering gets too complex (layered panels of chars, animations for things like water tiles that need to render more often)

22:21 reutermj: Swing is actually so bad if you want to make games

22:21 TEttinger: Swing was fine for 2 panels, but I'm working on something with 5 translucent panels...

22:21 yep

22:21 reutermj: it has super unpredictable performance between jvms and os

22:21 whomp: is it better to do (lazy-seq (cons 1 (f ...))) or (cons 1 (lazy-seq (f ...)))?

22:21 reutermj: like you have no clue what it will hardware accelerate

22:21 TEttinger: do you have any recommendations for hardware-accelerated truetype font rendering?

22:22 reutermj: I like cons l (lazy-seq

22:22 but I think they essentially do the same thing

22:22 whomp: what are the pros and cons?

22:22 ok, because 4clojure enforced the former in http://www.4clojure.com/problem/168

22:22 reutermj: libgdx has really good truetype fonts

22:22 TEttinger: yeah, gdx-freetype

22:23 squidlib at one point had a libgdx renderer but it was really hard to set up a project to use it

22:23 reutermj: Im a huge fanboy of Mario and his work, so I'm sorry if that isnt the answer youre looking for

22:24 I really dont know of any standalone ones, aside from using something like openc

22:24 TEttinger: ah, it's fine. if there's a good way to use libgdx without the project structure (as in, as a real library not a framework thing), I'd be very interested

22:24 reutermj: opencl

22:24 TEttinger: OpenCL? the compute language?

22:24 reutermj: yeah

22:25 you can do the calculations for the vector graphics on there and read them into a bytebuffer

22:25 TEttinger: ahhhh

22:25 reutermj: im sure you can find some kernels out there that do it, and just use something like lwjgl for access

22:26 TEttinger: I think all I really need is something like Cairo and/or Pango...

22:27 reutermj: but as for not using the whole libgdx framework. all you need is the gdx, gdx-lwjgl, and gdx-lwjgl-natives jars

22:27 and you should be golden

22:28 you could always look into lwjgl 3

22:28 it has multi window support

22:40 crocket: hi

22:40 Can anyone suggest better names for functions on https://www.refheap.com/106679 ?

22:44 assoc-in-cond2, assoc-in-cond3

22:50 justin_smith: ,(defn haha [] (->> 'clojure.core ns-publics keys shuffle (take 2) (#(str (first %) '-in- (second %))) symbol))

22:50 clojurebot: #'sandbox/haha

22:50 justin_smith: ,(haha0

22:50 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

22:51 justin_smith: ,(haha)

22:51 clojurebot: ratio?-in-remove-all-methods

22:51 justin_smith: ,(haha)

22:51 clojurebot: bit-and-not-in-delay?

22:51 justin_smith: ,(haha)

22:51 clojurebot: mapcat-in-<

22:51 justin_smith: ,(haha)

22:51 clojurebot: Throwable->map-in-bit-shift-left

22:51 justin_smith: ,(haha)

22:51 clojurebot: defonce-in-restart-agent

22:51 justin_smith: sorry, for some reason that name pattern just became really oddly comical to me

22:51 ,(haha)

22:51 clojurebot: when-in-keyword

22:51 justin_smith: ,(haha)

22:51 clojurebot: booleans-in-map-indexed

22:52 justin_smith: maybe nobody else finds it funny, but I am sure TEttinger understands

22:52 (this is what happens when I have tequila)

22:52 ,(haha)

22:52 clojurebot: seque-in-aset-double

22:53 reutermj: man I wish this is what happens when I have tequila

22:53 I just start crying when I have tequila

22:54 justin_smith: reutermj: it might be a dosage thing

22:54 ,(haha)

22:54 clojurebot: bigint-in-send-off

22:54 justin_smith: ,(haha)

22:54 clojurebot: some->>-in-var-set

22:54 reutermj: true my normal dosage is half a bottle of jose cuervo

22:54 justin_smith: ,(repeatedly 20 haha)

22:54 clojurebot: (find-keyword-in-re-seq pop-in-bit-and-not drop-in-find-var definline-in-* eval-in-rational? ...)

22:55 crocket: justin_smith, Do you mean assoc-in-cond2 and assoc-in-cond3?

22:55 TEttinger: that's great justin_smith

22:55 justin_smith: crocket: I'm just being silly, I'm sure those are totally sensible functions

22:55 ,(repeatedly 20 haha)

22:55 clojurebot: (get-thread-bindings-in-unchecked-short defn-in-*suppress-read* conj!-in-key unchecked-negate-int-in-map? sorted-map-by-in-identical? ...)

22:55 crocket: How do I make https://www.refheap.com/106680 simpler?

22:56 justin_smith: I could almost imagine seeing sorted-map-by-in-identical? in a real codebase

22:57 crocket: justin_smith, Does sorted-map-by-in-identical help advance my purpose?

22:57 justin_smith: not at all, it's a joke

22:57 crocket: justin_smith, How would you make https://www.refheap.com/106680 simple?

22:58 I want to convert {:appenders {:appender-id {:fn fn :arg-map arg-map}}} to {:appenders {:appender-id (fn arg-map)}} in a simple way.

22:58 justin_smith: for what it does, that looks just fine to me

22:58 TEttinger: crocket, I'm looking at it, and I think there's a way

22:58 justin_smith: perhaps reduce-kv

22:59 crocket: Replacing (fn) with #()

22:59 TEttinger: hm, that actually looks pretty straightforward now that I read it again

23:02 crocket: TEttinger, Can you write it simpler with reduce-kv?

23:04 justin_smith: ,(update {:appenders {:appender-id {:fn inc :arg-map 41}}} :appenders #(reduce-kv (fn [m k {:keys [fn arg-map]}] (assoc m k (fn arg-map))) % %))

23:04 clojurebot: {:appenders {:appender-id 42}}

23:04 TEttinger: assuming you're on clojure 1.7 :)

23:05 justin_smith: yes, otherwise update :appenders becomes update-in [:appenders] but the rest works

23:05 crocket: Damn

23:05 TEttinger: (inc justin_smith)

23:05 crocket: clojour 1.7

23:05 lazybot: ⇒ 277

23:05 TEttinger: climbing fast!

23:06 justin_smith: (karma amalloy)

23:06 (identity amalloy)

23:06 lazybot: amalloy has karma 287.

23:06 * justin_smith keeps his eyes on the prize.

23:13 crocket: https://www.refheap.com/106681 contains two versions of reify-appenders.

23:13 Which one do you think is better?

23:14 In my opinion, the latter has more beautiful shape.

23:14 I mean it has a better appearance.

23:14 reutermj: I have to agree, I think the latter is more pretty

23:15 justin_smith: also it does less work, by doing the repeated updates at one level, rather than repeated nested updates, if that matters

23:15 (that's a small difference here I am sure)

23:16 bbl reading a book

23:19 amalloy: justin_smith: sorry, i'm dictator for life. it's in the charter

23:19 crocket: justin_smith, With your help, I got https://github.com/crocket/clj-ddns-client/blob/master/src/clj_ddns_client/core.clj

23:21 I couldn't have written in in such an elegant fashion in java.

23:22 I couldn't have written it in such an elegant fashion in java.

23:22 reutermj: but could you have written it as concise in brainfuck?

23:22 TEttinger: haha

23:22 APL

23:22 reutermj: that's the real question

23:33 crocket: reutermj, I don't know brainfuck.

23:33 reutermj: be glad

Logging service provided by n01se.net