#clojure log - Mar 22 2015

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

4:41 ane: is there a shorter way around this: (map (fn [sym] ((resolve sym) a b)) symbols)

4:42 opqdonut: well you can always say (map #((resolve %) a b) symbols)

4:42 but that's it I guess

4:47 ane: hm, yes. so there's no handy "anti-quote" macrothing to do what resolve does?

4:50 amalloy: how could it be a macro? you're asking it to operate on data the exists at runtime

4:52 ane: oh, not a macro

4:53 opqdonut: if you use quote, you'd have to couple it with eval

6:41 dysfun: what's the easiest way to deal with temporary file generation in clojure?

6:42 hrm, me.raynes.fs looks easy enough

8:24 spinningarrow: The docstring for empty? says to use seq instead of (not (empty? ...)) but seq doesn't return a boolean. So is that still the right approach when writing a predicate?

8:25 Bronsa: spinningarrow: clojure generally doesn't care about true/false, truthy/falsy is usually enough

8:25 spinningarrow: Bronsa: so if a function returns truthy/falsy, it is still considered a predicate, I suppose?

8:26 gfredericks: yeah people do it all the time

8:26 Bronsa: spinningarrow: eh, no it's not strictly a predicate but we use it as a predicate all the time

8:27 gfredericks: hello Bronsa

8:27 hyPiRion: It sort-of depends – I tend to be a bit careful about that

8:27 get and nth may return nil, for instance

8:27 spinningarrow: ah cool. Sorry if that was a stupid question, but I was doing a clojure course and the midje tests were explicitly checking if the predicate returned `true` or `false`. Was just wondering if that's common :)

8:27 Bronsa: gfredericks: o/

8:27 gfredericks: \o

8:27 hyPiRion: (for correct lookups)

8:27 s/correct/successful/

8:28 spinningarrow: hyPiRion: yeah, that's a good point too!

8:31 sahil: exit

8:31 spinningarrow: so I guess that generally it's fine, but something to be careful about

8:45 hyPiRion: yeah, it depends on what the function can return

8:45 you might get false negatives

8:47 gfredericks: (defn does-has? "Returns :nope if m contains k and :yep otherwise." [m k] ...)

8:47 I think I got that backwards

8:49 spinningarrow: gfredericks: haha

8:50 well, thank you guys very much for all the clarification! I shall mess around some more in clojure-land gfredericks hyPiRion Bronsa

8:51 hyPiRion: gfredericks: just do (alter-var-root #'does-has? complement)

8:55 gfredericks: hyPiRion: no we're pretty much stuck with it; don't want to make breaking changes

8:55 bcm: spinningarrow: what clojure course is that?

8:55 hyPiRion: gfredericks: oh okay then

8:56 spinningarrow: It's this one - 'Functional programming with Clojure' (http://mooc.fi/courses/2014/clojure/)

8:58 bcm: Clojure is listed as an intermediate language. There isn't that much more to setup is there?

8:59 This course looks pretty cool

8:59 really well done use of bootstrap, too

9:49 edeferia: hi. question for the group: i would like know the most idiomatic way of doing the following: i have a list of functions (literaly as a list) and would like to use the thread macro on it. how?

9:50 justin_smith: edeferia: macros work before the compilation stage, they are not a runtime thing

9:51 if the list is known before runtime, you can make a macro that injects that list into a threading macro

9:51 otherwise, you can use reduce

9:51 (to get most of the same functionality, but at runtime)

9:51 edeferia: ah, got it. understand. so basically unroll the list in a macro that uses ->

9:51 justin_smith: `(-> ~x ~@fs)

9:52 inside a macro

9:52 but only works if fs are known when compiling

9:52 edeferia: they are.

9:52 hyPiRion: Well, if you have the list at compile time, why not write (-> x f-1 f-2 f-3) ?

9:53 gfredericks: yeah -> is more for readability; not so useful with macros

9:53 hyPiRion: Otherwise you can just use (defn thrush [x fs] (reduce #(%2 %1) x fs))

9:53 edeferia: hyPiRion: because although the list of functions is known, their sequence can change from call to call

9:54 justin_smith: hyPiRion: yeah, that was the reduce version I was suggesting above

9:54 gfredericks: can't use -> then

9:54 or

9:54 um

9:54 depends on what "call to call" means

9:55 edeferia: multiple invocations of the equivalent of (-> init (…)) would have different ordered set of functions in (…)

9:56 hyPiRion: edeferia: I'd say to go with a function first (thrush), as justin_smith originally suggested.

9:56 A macro won't give you any notable benefits here, at least not initially

9:56 gfredericks: and has drawbacks

9:56 like it's tricky to reason about

9:56 case in point, I still can't tell even with your last clarification whether this would work

9:57 justin_smith: right. The macro is helpful for readability, and using it programmatically like that avoids that benefit.

9:57 edeferia: agree. thank you all for the assistance. i will try justin_smith’s suggestion. thanks again.

11:06 Manaphy91: Hi! Is there a way to create a non mutable tree, where nodes have parents and childs, with deftype?

11:07 justin_smith: Manaphy91: doubly linked and immutable doesn't work

11:08 Manaphy91: if you don't need parent links from the children, then yeah, you can do that with deftype

11:08 Manaphy91: mmmh, I suppose it but I would like to ask it for a confirm... I dont linke to use loking manually but I think it's what I will do...

11:08 justin_smith: loking?

11:08 gfredericks: locking

11:08 justin_smith: why would you need to lock anything?

11:10 Manaphy91: I would like to use this structure concurrently.... I can use atom for a race safe access...

11:10 justin_smith: Manaphy91: I thought you said it would be immutable

11:11 Manaphy91: Yes!!

11:11 justin_smith: OK, atoms don't use locking at all, and they wrap an immutable datatype

11:12 Manaphy91: Ok, thanks, I will try something!!

11:13 hyPiRion: Manaphy91: bbloom had a talk on immutable graphs in Clojure: https://www.youtube.com/watch?v=YgvJqWiyMRY

11:14 Manaphy91: hyPiRion: Thanks!!

11:14 hyPiRion: at 6:10 specifically

12:22 justin_smith: hyPiRion: that bbloom talk is great, it makes me want to make an adjacency-list based follow up

12:23 (adjacency lists being a way to get a super general reification of traversal context, even handling cycles and cross references)

12:25 hyPiRion: yeah, it's good

12:34 spradnyesh: why do i see ***[org.clojure/tools.nrepl "0.2.6" :scope "test" :exclusions [[org.clojure/clojure]]]*** in "lein deps :tree" even though my project.clj explicitly lists ***[org.clojure/tools.nrepl "0.2.8"]*** as a dependency?

12:34 justin_smith: spradnyesh: put the tools.nrepl dep under :dev

12:35 spradnyesh: justin_smith: thanks for the pointer, let me check that

12:35 hyPiRion: spradnyesh: because bugs

12:38 spradnyesh: justin_smith: worked. thanks :)

13:15 mmg: I’m having some basic macro behavior that I don’t get and I’m trying to understand why. I started with a macro I didn’t expect to work but it’s failing in a way I wouldn’t have guessed:

13:15 (defmacro macro-foo

13:15 [should-run arg]

13:15 (when should-run arg))

13:15 => (macroexpand '(macro-foo bar baz))

13:15 baz

13:16 why does that just expand to baz when it can’t resolve bar at compile time?

13:16 justin_smith: because to the macro code, bar is a symbol

13:16 and symbols are truthy

13:16 mmg: oh....

13:16 thank you!

13:16 justin_smith: ,(when 'ok :go)

13:17 clojurebot: :go

13:17 mmg: yeah I was thinking (when nil :go) => nil

13:17 I see what I did wrong now

13:17 thanks a ton

13:17 justin_smith: remember that a macro should return the form that you want to run

13:17 mmg: yeah, no I get that this was a dumb macro, I was just expecting failure to look different (shrug)

13:17 now I get why ;)

13:17 thanks again

13:18 justin_smith: np

13:19 amalloy: on the subject of bad commit histories, I have discovered that the combination of "git merge --no-commit" followed by cycles of "git add -p" and "git commit -m" is like magic

13:20 amalloy: hm. what is -m?

13:20 something merge-related, but...

13:20 justin_smith: amalloy: oh, sorry, just supplying a message on the command line

13:20 amalloy: oh haha

13:21 so, i do cycles of add -p, commit -m all the time. how does it interact with merge no-commit?

13:21 justin_smith: so I run git add -p, and select a "themed" group of changes, then commit them together

13:21 it's like a retroactive cure for add

13:21 amalloy: merge --no-commit means you get all the changes from the other branch, but not its history

13:22 amalloy: ah, i see now

13:22 justin_smith: so it's a way of rewriting the history of a series of messy changes because I have no attention span / focus

13:22 into an alternate, coherent history

13:23 amalloy: i'm still not quite sure how you end up with those changes on an alternate branch that you want to merge

13:24 justin_smith: amalloy: getting mixed up in the development process, and when it comes time to make a pr I realize the history is a total mess

13:24 amalloy: justin_smith: so you create another branch, and merge no-commit your disjointed changes?

13:25 justin_smith: right

13:25 then I turn them into sensible commit history

13:25 amalloy: i would usually just git reset before-dumb-changes, rather than git checkout -b some-branch before-dumb-changes

13:25 justin_smith: aha, yeah I think as usual git has multiple paths to glory

13:25 amalloy: yeah

13:27 justin_smith: oh, yeah, there was actually a reset step in there anyway (between the merge --no-commit and the add-p)

13:27 because even without the commits, it still stages things, so I need to reset to unstage so I can do selective staging

13:28 oh wow, there is a "reset -p", combine that with "add -p" and you have a nice little choose your own adventure

13:30 amalloy: justin_smith: also checkout -p

13:30 justin_smith: oh wow, nice

13:33 Glenjamin: i really like "git cola" for that sort of stuff - Qt based gui around staging/unstaging/comitting

13:35 oddcully: i use tig fiddling togetter proper commits. but i didn't knew about -p

13:35 justin_smith: magit does some of that stuff too, but I end up preferring to just use the terminal

13:35 yeah, -p is like a repl for building commits

13:36 Glenjamin: i dislike the linear nature of add -p

13:36 justin_smith: Glenjamin: like the way it gives you things in a predetermined order?

13:36 Glenjamin: guis are a bit better for random access, and easier to split hunks

13:36 yes

13:37 kwladyka: hello, i am learning clojure, can you tell me why in this function http://pastebin.com/zTzhVfUy is "when pred"? What is the prupose of this line?

13:37 justin_smith: kwladyka: if pred is nil or false, the next line does not run

13:37 Glenjamin: kwladyka: in that scenario, (when) is equivalent to (if)

13:37 justin_smith: when is like if but only one branch

13:38 kwladyka: justin_smith yes i understand that but why is that necessary? It is example form book, it is index-of-any

13:38 justin_smith: kwladyka: if pred was nil or false, the next line would throw an exception

13:38 kwladyka: justin_smith i uderstand technical aspect "when pred" but i don't undrestand why author wrote this line

13:38 justin_smith: you'd have to look at the rest of the code to know why pred would be nil or false

13:39 I suspect index-filter is being called in a recursive context where pred might be updated on each loop, and might eventually be nil?

13:39 just a guess

13:39 kwladyka: hmm so in clojure there is no exception like try{} catch{} or something like that? Should i write in all places code prevent to exception?

13:39 justin_smith: kwladyka: there is

13:39 kwladyka: but that author is not using it

13:40 kwladyka: so it wouldnt be miskate if i dont write (when pred) in function like that? What is best pracice in clojure?

13:40 justin_smith: in general, exceptions (in any language) should be used for exceptional cases, not for control flow

13:41 we also have things like some-> that do chaining that short circuits if you hit nil

13:41 Glenjamin: kwladyka: many core functions are written to behave without exception when they receive nil

13:41 justin_smith: (doc some)

13:41 clojurebot: "([pred coll]); Returns the first logical true value of (pred x) for any x in coll, else nil. One common idiom is to use a set as pred, for example this will return :fred if :fred is in the sequence, otherwise nil: (some #{:fred} coll)"

13:41 justin_smith: (doc some->)

13:41 Glenjamin: ,(get nil)

13:41 clojurebot: "([expr & forms]); When expr is not nil, threads it into the first form (via ->), and when that result is not nil, through the next etc"

13:41 #error{:cause "Wrong number of args (1) passed to: core/get", :via [{:type clojure.lang.ArityException, :message "Wrong number of args (1) passed to: core/get", :at [clojure.lang.AFn throwArity "AFn.java" 429]}], :trace [[clojure.lang.AFn throwArity "AFn.java" 429] [clojure.lang.AFn invoke "AFn.java" 32] [sandbox$eval69 invoke "NO_SOURCE_FILE" -1] [clojure.lang.Compiler eval "Compiler.java" 6784] ...

13:41 jdeisenberg: Is there a way to specify the version of a template that you want to use in Leiningen?

13:41 Glenjamin: oh, whoops - bad example

13:42 justin_smith: jdeisenberg: no, a real peeve of mine actually

13:42 ,(get nil :anything)

13:42 clojurebot: nil

13:42 Glenjamin: that's what i meant :)

13:42 clojure mostly gives you back nil instead of throwing null pointer exceptions

13:43 jdeisenberg: justin_smith: Thanks. Maybe I should look at Leiningen and see if I can figure out how to add that. In my copious spare time, of course :)

13:43 justin_smith: haha, of course

13:44 kwladyka: ok so if i undrestand best practice in clojure is: if function can do what should do return value, in other case return nil?

13:44 justin_smith: that's the usual thing, yeah

13:45 jjttjj: what are people's preferred clojure dynamoDB clients these days?

13:46 I guess I prefer operating on a higher level than having more fine tuned control, if that's a factor

13:46 kwladyka: thx!

14:09 geekyvin_: Hey Guys, I've created a simple web-app in Clojure and deployed it in a remote server. but the problem is my application doesnt seem to serve resource files such as css/javascripts...etc. I couldnt figure out why.

14:09 I tried jetty with nginx and tomcat7 with nginx

14:09 this is my project.clj

14:09 (defproject test_web_app "0.1.0-SNAPSHOT"

14:09 :description "FIXME: write description"

14:09 :url "http://example.com/FIXME"

14:09 :dependencies [[org.clojure/clojure "1.6.0"]

14:09 [compojure "1.1.6"]

14:09 [hiccup "1.0.5"]

14:09 clojurebot: It's greek to me.

14:09 geekyvin_: [ring-server "0.3.1"]]

14:09 :plugins [[lein-ring "0.8.12"]]

14:10 :ring {:handler test_web_app.handler/app

14:10 justin_smith: geekyvin_: don't do that

14:10 geekyvin_: :init test_web_app.handler/init

14:10 :destroy test_web_app.handler/destroy}

14:10 justin_smith: geekyvin_: stop

14:10 geekyvin_: :profiles

14:10 {:uberjar {:aot :all}

14:10 :production

14:10 {:ring

14:10 {:open-browser? false, :stacktraces? false, :auto-reload? false}}

14:10 :dev

14:10 {:dependencies [[ring-mock "0.1.5"] [ring/ring-devel "1.3.1"]]}})

14:10 Opps...sry

14:10 Opps...

14:10 Oops..

14:10 andyf: Gist or paste please

14:10 justin_smith: geekyvin_: how are you accessing the resource files?

14:11 geekyvin_: its a simple web-app created with the command lein new compojure-app <web-app-name>

14:12 justin_smith: geekyvin_: that didn't answer my question

14:12 geekyvin_: the statics files are called from html

14:12 justin_smith: what specifically is being done to fetch those resources

14:12 are you using wrap-resource?

14:12 wrap-file?

14:13 geekyvin_: right, I found then but couldnt really find how to use them.

14:14 shld the :wrap-resource be in project.clj or in my handler?

14:14 justin_smith: wrap-resource is a function, and it should be in your handler

14:18 geekyvin_: ok let me try that.

14:18 thank Justin.

14:19 justin_smith: np

14:20 gfredericks: "in your handler" in the sense that it's a middleware you should use

14:20 justin_smith: right, "around" would be the better preposition there

15:39 michaelr`: anyone here uses bidi?

15:39 err

15:42 i have one handler which handles both :post and :delete requests, the url of the first is /something and the second is /something/1. is there any way that I can unmatch for both urls from the same handler?

15:45 both routes are guarded with request methods, essentially I'd like to parametrize url generation with the request method

15:49 arrdem: Anyone messed with Racket and care to comment on it?

16:02 justin_smith: arrdem: very clean, a great language for pedagogy, not a huge library ecosystem (like most schemes)

16:02 gfredericks: technomancy likes it

16:02 for...kids

16:03 justin_smith: also, the way you can explicitly choose a language dialect in your source code is kind of cool

16:04 andyf: I find its mob associations make it scary to use. License enforcement by limb mangling?

16:05 * arrdem chuckles

16:06 justin_smith: andyf: it follows a proud tradition of "scheme" dialect names. See also gambit, larceny, guile

16:06 and some of them get a bit more conceptual, like stalin

16:06 andyf: Holy cow. We may have unearthed a conspiracy here

16:19 ben_vulpes: i've been away from clojure webapp development for a while (9 mos? feels like eternity...). is chestnut awesome or will it be really painful in novel ways after six months?

16:21 _2_Mini: Hola a todos

17:00 tolstoy: Is there any way to avoid this thing: 'Reflection warning, clojure/data/priority_map.clj:215:19 - call to method equiv on java.lang.Object can't be resolved (no such method).'

17:00 Not sure why it's showing up all of a sudden.

17:01 Maybe some interaction with 'aleph'? Hm.

17:01 gfredericks: that's interesting

17:01 tolstoy: Using :global-vars {*warn-on-reflection* false} doesn't help.

17:02 Also: 'Reflection warning, clojure/core/memoize.clj:72:23 - reference to field cache can't be resolved.'

17:02 gfredericks: tolstoy: are you using priority-map directly? or is aleph requiring it?

17:03 it looks like there's a "fix reflection" commit in their history included in the latest release

17:03 tolstoy: I'm not.

17:03 If it's a lib, I don't see it in "lein deps :tree".

17:04 gfredericks: what version of aleph are you using?

17:04 tolstoy: "0.4.0-beta3"

17:06 Related: http://permalink.gmane.org/gmane.comp.java.clojure.aleph/693

17:14 Ah, I see it now. core.async is indeed using priority_map.

17:15 What's puzzling is that the latest release is from Sep 2014.

17:16 Ah. Update to the latest priority map, and that goes away.

17:17 No newer core.memoize, so out of luck there.

17:25 http://dev.clojure.org/jira/browse/CMEMOIZE-13

18:17 _1_Andrz8766: hey

18:21 hello?

18:21 clojurebot: BUENOS DING DONG DIDDLY DIOS, fRaUline _1_Andrz8766

18:21 _1_Andrz8766: how do you use this thinh

18:24 justin_smith: _1_Andrz8766: are you new to IRC?

18:26 Bronsa: (inc clojurebot)

18:26 lazybot: ⇒ 48

19:53 gfredericks: (inc lojurebot)

19:53 lazybot: ⇒ 1

20:01 justin_smith: I may have done something silly. I am working on a data structure lib that represents graphs natively as adjacency lists, and I have functions that attempt to turn a graph into a tree or list

20:01 and the list one is just a lazy list that follows a random outgoing edge at teach step until there are no more outgoing edges left

20:02 so running it twice will give you two different outputs for any graph that can't be represented as a singly linked list

20:02 maybe that's useful?

20:02 if the graph has no non-cyclic paths, you get an infinite lazy-seq

20:10 gfredericks: has anybody made an arithmetic lib for dealing with pretend unsigned bytes/ints/longs?

20:10 presumably by using primitives but doing the arithmetic differently

20:10 justin_smith: gfredericks: that seems like a natural thing, like in some java lib that asists in jni stuff or something

20:11 gfredericks: I think java 8 might have related things

20:11 but that doesn't help for writing fluent clojure

20:12 I was also thinking that anybody who intentionally uses bigdecimal might find a set of arithmetic functions restricted to bigdecimal useful

20:12 to ensure they never accidentally degrade to doubles

20:13 justin_smith: gfredericks: hmm, maybe you could even keep the arithmetic the same (but only do unchecked operations) and just override like >, <, and the print method

20:13 because with twos compliment the rest should just work until you hit over / under flow

20:13 gfredericks: gotta be careful with shifting too

20:14 justin_smith: ahh, yeah

20:19 gfredericks: justin_smith: multiplication wouldn't work right would it?

20:20 without a separate impl I mean

20:28 justin_smith: "The two's-complement system has the advantage that the fundamental arithmetic operations of addition, subtraction, and multiplication are identical to those for unsigned binary numbers (as long as the inputs are represented in the same number of bits and any overflow beyond those bits is discarded from the result)."

20:28 that's why I was thinking it would be elegant

20:28 basic ops just stay the same (and thus also remain as efficient)

20:29 gfredericks: oh wow I didn't know it worked for multiplication as well

20:29 the more I think about it the more skeptical I am

20:30 thinking about the highest bit, and what determines it in an unsigned mult

20:30 justin_smith: gfredericks: I think overflow would just "accidentally" do the right thing

20:31 but that's easy to test with some unchecked math, or even by hand

20:32 gfredericks: where did you get this quote

20:32 justin_smith: wikipedia

20:32 gfredericks: you can't trust that did you know anybody can edit it

20:32 justin_smith: I've heard

20:32 gfredericks: it's like a button on there; *you can make it say whatever you want!*

20:33 justin_smith: gfredericks: but that wasn't my original source, it was just easier to look up :)

20:34 gfredericks: in multiplication the highest bit in the result is dependent on like every bit of the inputs

20:34 but in signed multiplication that bit has to be the correct sign of the result

20:35 but if it's also dependent on every bit of the inputs I should be able to twiddle the bits of the inputs (without changing their sign) to manipulate the sign of the outputs

20:35 s/outputs/output/

20:36 justin_smith: gfredericks: the two's complement signed multiply and the unsigned multiply, when applied two to numbers with the same bit representation, are guaranteed to result in the same bits in the output

20:36 it's the same operation on the bit level

20:36 gfredericks: you're just stating the position I'm arguing against, right?

20:37 justin_smith: I'm telling you a fact about how two's complement multiply works

20:37 gfredericks: yes I believe you that it's true but it's also totally impossible and I'm trying to explain why

20:38 justin_smith: gfredericks: it's because what is overflow on one side, is a correct multiply on the other

20:38 it's a lot easier to overflow with signed multiply

20:38 gfredericks: sure, but I'm focusing on the value of the highest bit

20:38 after truncating overflow

20:39 which is a bit that must be determined by virtually every bit of the inputs I think

20:40 justin_smith: OK - they are identical for non-overflowing operations, and are respectively correct for ops that don't overflow (there are some signed results that are overflows, that are not overflows in the unsigned version)

20:40 gfredericks: huh?

20:41 justin_smith: I'm going to try to work this out in a simplified model, like with a three bit number

20:41 ok, maybe four bit

20:41 gfredericks: wikipedia says something about having to double the precision beforehand

20:44 justin_smith: if you want to guarantee you don't overflow, sure - double precision and extend the sign bit

20:47 gfredericks: so what you said earlier is that multiplication doesn't work if the ops are large enough to overflow, right?

20:47 which means the sentence in the wikipedia intro is misleading?

20:49 I just did 7+(-3) and got -5

20:49 er 7*(-3)

20:49 which is the correct sign actually

20:50 now that I think about it I don't know what you're supposed to expect semantically from overflow of signed multiplication

20:50 is it equivalent to multiplication mod something somehow?

20:51 this must be my problem I don't actually know what I think it's supposed to do; I just assumed that signs should be well-behaved, but maybe not

20:59 justin_smith: gfredericks: so I just wrote out all the five bit numbers in standard / 2's complement, and picked a random multiplication to show that once you truncate overflowed bits, the output is the same

20:59 http://i.imgur.com/tZX9uuI.jpg

20:59 sorry it's a little sloppy - on the left is bits - unsigned / signed

20:59 on the right is signed on top, then bits, then unsigned

21:00 with the two truncated bits bracketed

21:02 gfredericks: justin_smith: but what happens when the signed op result is semantically out of range?

21:02 e.g., -5 * 7

21:03 justin_smith: one second, scribbling

21:03 gfredericks: I demand moar photo graphs

21:04 faxed to me

21:04 justin_smith: haha

21:05 john2x: there's no date generator in test.check?

21:06 gfredericks: nope

21:07 what kind of distribution would you want on that?

21:07 john2x: just completely random dates. hmm I guess a constant date would work just as well for my current purposes.

21:07 gfredericks: is 19487917373191-02-28 a date?

21:08 john2x: heh yeah.. that could get tricky

21:08 gfredericks: we've got a lot of design work to do on good numeric generators

21:08 which would probably help with what you're wanting

21:09 in the meantime if you think of something obviously generally useful I can probably put it in test.chuck

21:13 justin_smith: gfredericks: with 27*7, / -5*7 they still match for the last five bits (which is all the matters since I was doing five bit two's complement) and they only diverge where they overflow

21:13 both end in 11101

21:14 if cl-format wasn't a filthy liar when it comes to binary, I could show you that easily

21:14 *signed binary that is

21:16 gfredericks: ,(mod (* 27 7) 32)

21:17 clojurebot: 29

21:17 gfredericks: ,(mod (* -5 7) 32)

21:17 clojurebot: 29

21:17 gfredericks: which is -3 I think?

21:17 justin_smith: gfredericks: if you refer back to my jpg, it says yes

21:18 gfredericks: so I guess the semantics are multiplication mod 2^n and then wrapped around to negative as appropriate

21:19 and therefore the sign is chaotic

21:19 which is what I was intuiting before, but assumed that meant it wasn't working right

21:19 justin_smith: yeah, that sounds about right, and it is intuitive because multiplication is repeated addition

21:19 it's just that there are so many overflowing results you get overflowed overflow etc. :)

21:20 gfredericks: right, a chaotic sign

21:20 justin_smith: gfredericks: are you coming to clojure/west?

21:20 gfredericks: yep

21:21 booked my flights yesterday

21:21 justin_smith: cool

21:21 gfredericks: I've always lived closer to the east coast but I've attended clojure/west a lot more reliably

21:25 now I'm curious how you detect multiplication overflow

21:25 justin_smith: this will be my first clojure conference, and it will be crazy seeing all these people I know online in person

21:25 gfredericks: to the Numbers.javamobile!

21:25 justin_smith: gfredericks: you put the result in a double-sized result, then you check for any set bits

21:25 (in the extra sized side, of course)

21:26 gfredericks: but this is why I was saying before that it would be easy if you do unchecked ops :)

21:26 heh

21:26 because the unchecked results will match (while likely being useless to the application code)

21:26 gfredericks: you're just describing how to do it on a chip, no?

21:26 justin_smith: not *just*

21:27 you can do the same thing in an algorithm

21:27 gfredericks: Numbers.java is doing something clever

21:27 justin_smith: though I guess you would use a bigint instead of like a 128 bit int

21:27 interesting

21:27 gfredericks: omg there's a whole check for x == Long.MIN_VALUE && y < 0

21:27 maybe that's an edge case you can't detect otherwise

21:28 but then after multiplying it does a divide to see what happened

21:28 if (x&y)/y != x then overflow

21:28 x*y rather

21:28 justin_smith: fascinating, nobody's using those overflow bits on hardware more's the shame

21:29 s/bits/flags

21:29 I wonder if there are like experimental languages that use that feature

21:29 or if everybody's like "c doesn't support it, so we don't"

21:34 rksm: What's the most idiomatic way to read in a project.clj from a jar? I need the project map normally returned from leiningen.core.project/read.

21:34 gfredericks: is it normally in the jar at all?

21:35 you can probably get it into the jar with some :filespecs thing and then just read it with clojure.java.io/resource

21:36 might be a plugin that does this kind of thing already

21:37 justin_smith: gfredericks: rksm: checking a random jar, yeah I find a project.clj

21:37 now how do you get a specific version of a resource that is on the class path multiple times again? I always forget

21:38 gfredericks: a random jar? is it a lib?

21:38 justin_smith: yeah

21:39 gfredericks: yeah, I see them in each clojure lib I check

21:40 gfredericks: huh. well what do you know.

21:40 seems a little bit weird

21:40 rksm: Dealing with the classpath and getting content from a jar I managed to do. However, I want to duplicate none (or at least as little as possible) from leiningen.core.project/read (https://github.com/technomancy/leiningen/blob/master/leiningen-core/src/leiningen/core/project.clj#L950)

21:41 As read only accepts a file (not a jar URI or jar entry reader).

21:41 Hmm... how can I convert a buffered reader to a pushback reader?

21:41 tomjack: (java.io.PushbackReader. buffered-reader)

21:42 justin_smith: rksm: so how do I get a resource from a specific jar?

21:43 rksm: tomjack: yep, that works, thanks. now I can use read-raw :)

21:43 Draggor: Is there a tutorial to start with on clojure.test?

21:44 justin_smith: Draggor: the clojuredocs page for it is decent. It's a small library.

21:44 tomjack: justin_smith: (-> (Thread/currentThread) (.getContextClassLoader) (.getResources "foo") (enumeration-seq)) will give you a seq of URLs

21:44 rksm: justin_smith: I use jar files + jar entries for it: https://github.com/cloxp/clj-system-files/blob/master/src/main/clojure/rksm/system_files.clj#L100

21:44 justin_smith: tomjack: oh, nice

21:44 tomjack: I guess you can figure out which one is from which jar from there

21:44 I stole that from the stuff in core.clj for data_readers.clj

21:45 justin_smith: tomjack: nice

21:46 tomjack: thank java that is possible..

21:46 Draggor: justin_smith: in particular looking to read about doing setup/teardown and setting a variable for tests

21:46 if I were to not use fixtures I'd just do a let form I suppose

21:47 justin_smith: Draggor: typically there is very little setup/ teardown - with pure functions you do stubbing instead of mocking

21:47 and the stubbing can just be data literals and the occasional function literal

21:48 Draggor: justin_smith: sure, anywhere I can see an example of that?

21:48 justin_smith: Draggor: and my preferred approach is to have all my complex logic in pure functions (as much as possible), because stubbing to test all the logic is pretty trivial, then making the side effecting stuff as simple as possible so I can avoid / minimize stubbing

21:48 Draggor: hmm...

21:49 it would be good to have a go to example for that approach

21:55 rksm: Draggor: Take a look at how authentication in leiningen itself is tested. There is a credentials function that returns the content of ~/.lein/credentials.clj.gpg: https://github.com/technomancy/leiningen/blob/master/leiningen-core/src/leiningen/core/user.clj#L122 In order to test that without creating an actual file the var leiningen.core.user/credentials is re-defined at test time: https://github.com/technomancy/leiningen/blo

21:55 b/master/leiningen-core/test/leiningen/core/test/user.clj

21:55 Draggor: Take a look at how authentication in leiningen itself is tested. There is a credentials function that returns the content of ~/.lein/credentials.clj.gpg: https://github.com/technomancy/leiningen/blob/master/leiningen-core/src/leiningen/core/user.clj#L122 In order to test that without creating an actual file the var leiningen.core.user/credentials is re-defined at test time:

21:55 https://github.com/technomancy/leiningen/blob/master/leiningen-core/test/leiningen/core/test/user.clj

21:56 Most of the time you are best of with directly passing dependencies to your functions, though.

22:00 Draggor: I still feel like I'm missing something simple. I want a fixture that as setup, calls a pure function that returns an immutable object I'm then going to use in my tests. What does that look like?

22:02 justin_smith: Draggor: why does the fixture need to do that?

22:03 fixtures are for things with side effects, they don't pass anything to the tests

22:03 if it's immutable, can't it be a top level def or a let binding?

22:03 Draggor: Good point

22:03 gfredericks: ,(def my-test-data 42)

22:03 clojurebot: #'sandbox/my-test-data

22:04 justin_smith: one moment, I'll upload what I am working on right now

22:04 gfredericks: I just made a computer somewhere on the internet keep the number 42 around for a little while just in case

22:07 justin_smith: https://github.com/noisesmith/adj/blob/master/test/org/noisesmith/adj_test.clj

22:07 I define some data structures, and do various things with them in each test

22:08 Draggor: Ahh, yes, it is that simple, thanks!

22:09 justin_smith: sadly, nothing in this project does side effects

22:09 though I guess I may add a db backed ns for persistent graph stuff eventually...

22:09 Draggor: What I'm doing, the side effect is user input which I can fake out in tests, the functions themselves are pure for doing the real work

22:10 justin_smith: right, and that's very simple to test

22:11 rksm: Draggor: And in case your input needs to change you can use dynamic scoping, however, be aware that this creates an indirect dependency between the dynamic state and your tests/code. https://gist.github.com/rksm/4a6c0116b32046290af3

22:12 And to just have a "template" test the are macro is useful: https://clojure.github.io/clojure/clojure.test-api.html#clojure.test/are

22:30 underplank: Hi all. Im using the fantastic clj-http lib, and I’ve been able to find the {:throw-exception false} parameter for the get function. But im using the request function to do arbitrary requests. Is there a way to pass the :throw-exception keyword in?

22:32 hmm thats wierd. it seems that the get is actually using request under the covers.

22:32 gfredericks: do (clojure.repl/source clj-http.core/request)

22:32 you can see a lot of opts there

22:32 last I checked they weren't otherwise documented

22:36 underplank: thanks i’ll take a look

22:47 ben_vulpes: man i am baffled. where does react.js come from in the chestnut/cljs templates?

22:49 tolstoy: ben_vulpes: I think it's pulled in as a dependency of [org.omcljs/om "0.8.8"].

22:49 It's in a jar file, if that helps.

22:49 ben_vulpes: hm.

22:50 tolstoy: [cljsjs/react "0.12.2-5"]

22:51 Last I remember (it's been a while) there's a deps.cljs in the jar and other such conventions.

22:51 ben_vulpes: i was using an ancient version of om, apparently.

22:52 spinningarrow: Which text editor or IDE do most people use for Clojure? (hope I'm not starting a war - just genuinely curious)

22:53 srid: Emacs

22:53 justin_smith: spinningarrow: emacs, though cursive (an intellij idea plugin) likely has the best tooling

22:54 srid: but I'm open to learn of better IDEs for Clojure

22:54 ben_vulpes: i know a guy who uses vim/fireplace

22:55 srid: Cursive will be available as an IntelliJ plugin for use with the Community or Ultimate editions, as well as a standalone Clojure-focused IDE. It will be a commercial product, at a similar price point to PyCharm or RubyMine.

22:55 - https://cursiveclojure.com

22:55 justin_smith: srid: yes, but it is available for free right now

22:55 srid: so it is not production ready

22:55 justin_smith: srid: it's more complete than any of the other options

22:57 ben_vulpes: is emacs even production ready?

22:58 justin_smith: ben_vulpes: cider sure the hell isn't, it still changes the abi all the time

22:58 ben_vulpes: tolstoy: i should expect to see react.js get compiled onto my clojurescript path, right?

22:58 just by virtue of using org.omcljs/om "0.8.0"

22:58 or am i missing something here.

22:59 tolstoy: ben_vulpes: I think (depending on cljs compiler configuration), it gets merged into your main.js file.

22:59 ben_vulpes: hm.

22:59 tolstoy: ben_vulpes: For me, it so often "just works" that I've forgotten about it. ;)

23:00 ben_vulpes: fwiw, i get out/goog/base.js

23:00 "works on my machine..."

23:01 tolstoy: Building a project to see where it goes.

23:01 I have a "dev" task which does the source map and optimizations :none thing.

23:02 goog.addDependency("../react.inc.js", ['cljsjs.react'], []);

23:02 It's in my "out" directory.

23:02 ben_vulpes: when you say "dev" task, are you referring to a :dev key in your :builds vector?

23:02 er

23:02 tolstoy: Yes.

23:03 ben_vulpes: a build in the build vector with a "dev" value for the :id key, more accurately.

23:03 Draggor: rksm: are looks perfect, thanks

23:03 tolstoy: Yeah: {:builds [{:id "dev" ;; but I get what you mean.

23:03 I've defined an output dir as resources/public/out and react.js gets put in there.

23:04 Extracts from the jar, I imagine.

23:06 ben_vulpes: is it possible that the clojurescript compiler thinks it already copied the react file?

23:06 tolstoy: When I do a "release" build (:optimizations :whitespace), react.js is embedded at close to the top of the resulting "single" main.js file.

23:06 Are you using 0.8.8?

23:07 ben_vulpes: [org.omcljs/om "0.8.8"]

23:09 tolstoy: Oh. You're experiencing an issue or something?

23:09 ben_vulpes: it looks like om etc aren't terribly willing to compile.

23:10 tolstoy: Here's my extremely minimal build config, if that helps.

23:10 ben_vulpes: i just blew away my resources/public/out directory by hand, reran lein cljsbuild auto, and it did not drop goog/**

23:10 tolstoy: https://www.refheap.com/98782

23:11 ben_vulpes: looks pretty identical to mine.

23:11 tolstoy: You have the most recent cljs?

23:11 Yeah, I'm not exploiting a whole lot on CLJS. ;)

23:11 ben_vulpes: yeah, let me restart my jvm

23:12 tolstoy: Actually, I don't have the most recent stuff (this is an EOL project).

23:13 ben_vulpes: hrm.

23:14 well i'm rolling back to 0.8.0 rc1 to see if it'll compile google closures etc

23:14 underplank: Ok, so I have a ring server that is being run. I want to se a break point in a handler and use a debug repl to have a look around and step in and out of functions. What is the best way to do this?

23:15 tolstoy: Does "lein deps :tree" reveal anything troubling?

23:16 Latest lib updates produce some interesting warnings, but it all works with regard to react.js.

23:17 ben_vulpes: lein figwheel screamed about misconfigured output-dir path, interestingly.

23:18 tolstoy: Ah, figwheel. Maybe comment that out and see?

23:19 ben_vulpes: now that i think about it, figwheel was how i compiled assets first.

23:19 but from inside a repl. i was working to shoehorn figwheel-from-repl into a component

23:20 tolstoy: There's been a lot of repl thrash lately. I think bhauman has been keeping up, but I've given up on it for the duration.

23:20 ben_vulpes: *sigh*

23:20 good to know, thanks.

23:20 tolstoy: According to dnolen, all the repls work great (from Emacs) using an inferior-lisp mode, but not cider.

23:20 ben_vulpes: (classic me, though: "this workflow isn't right! as part of spinning this project up i will make it do the RIGHT THING")

23:21 mk, that did it.

23:21 :output-dir "resources/public/js/out/"

23:22 tolstoy: Heh. For me, it's, "Surely I need to get a handle on line numbers properly formatted and dimmed rather than my actual hobby project I love working on."

23:22 ben_vulpes: okay, commit.

23:24 tolstoy: The QuickStart guide might interest you, if you're into back-to-basics on a path to building up again.

23:29 ben_vulpes: clojurescript quickstart?

23:38 tolstoy: Yeah.

23:39 https://github.com/clojure/clojurescript/wiki/Quick-Start

23:42 ben_vulpes: yeah, i'm like 80% competent with all of that

23:42 lol okay i got figwheel running awesome

23:42 now i'm just going to let go of it not being integrated in my component workflow for now, and see if i can hammer out a few om buttons or something

23:42 woo

23:42 thanks tolstoy

23:43 tolstoy: Excellent! Nah, I just mention it because cljs dev has been improving a lot lately, and it's always nice to go back to take stock. (Like re-reading clojure.core API every once in a while.)

23:48 ben_vulpes: definitely good ideas.

Logging service provided by n01se.net