#clojure log - May 19 2015

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

1:15 tmtwd: > foldl f z [a,b,c]

3:26 zot: I have the feeling that type hinting is shooting me in the foot: datascript.core.Datom cannot be cast to datascript.core.Datom — any ideas how to debug?

3:48 TEttinger: zot: I think you may have multiple different Datom types defined somehow.

3:48 I don't use datascript though, is it for CLJS?

3:48 zot: yeah, eventually realized it was defrecord + repl

3:48 TEttinger: ah good

3:48 zot: i'm working on the CLJ port of it

3:48 TEttinger: nice!

3:49 zot: it's been fun and … educational. lots of little annoying diffs between the two.

3:49 but still awesome that it's possible.

3:49 (can't blame the designers — sticking to the host language/vm creates roadblocks, and the need for detours.)

4:36 is there any magic to getting data_readers.clj to work w/in clojure.test? i'm failing miserably, and not finding an example

4:40 ordnungswidrig: zot: an example gist might help

4:40 zot: trudat. a moment, please.

4:43 https://gist.github.com/anonymous/282abf8448e5f1cca608

4:43 it mostly works in the REPL, as i can directly run the test, or simply type the check in the repl

4:44 mpenet: zot: odd, the data_readers.clj file is in src?

4:44 zot: yep

4:51 is there any way to confirm that it's being loaded properly? i see no errors at compile time (as I once did when there was a typo in data_readers.clj)

4:53 (reinserting typo confirms that compiler fails, but i see now way to assert that the target functions are … targeted.)

4:54 justin_smith: zot: a job for unit tests?

4:54 zot: justin_smith: that's what's failing. see the gist above.

4:59 justin_smith: any ideas? :)

5:12 justin_smith: sadly no, it looks like it should work

5:13 zot: should i take anything from the fact that it says "No reader function for tag Datom" instead of "datascript/Datom" ?

5:59 martinklepsch: how again can I refer to a symbol that is at compilation time not resolvable?

6:00 (but at runtime it will be)

6:05 zot: no clue, but does #'foo/bar work this way?

6:05 justin_smith: martinklepsch: resolve

6:06 ,(resolve 'this-does-not-exist)

6:06 clojurebot: nil

6:06 justin_smith: ,(resolve '+)

6:06 clojurebot: #'clojure.core/+

6:06 justin_smith: it returns the var, so sometimes you want @(resolve 'foo)

6:07 martinklepsch: justin_smith: thanks, that was what I've been looking for!

6:08 justin_smith: martinklepsch: I used resolve recently to construct a shim for jsvc, so that I would not need to aot compile any of my code

6:08 other than one very small file, that uses require inside a defn, plus resolve, to call my actual main ns

6:09 martinklepsch: justin_smith: neat. actually didn't know about jsvc until now :)

6:10 justin_smith: jsvc is a great way to make a proper daemon out of a clojure project

6:10 but you likely know that now

6:11 I may even make a project out of this jsvc shim. Just a macro where you supply the symbol of your real main ns, and it compiles to do the proper runtime resolution

6:14 martinklepsch: justin_smith: it does not handle classpath stuff for you does it?

6:14 justin_smith: or do you use uberjars with it?

6:15 justin_smith: yeah, it needs to be an uberjar

6:15 which is why the shim - so that only one tiny ns needs aot compilation

6:17 martinklepsch: another option would be to set up the -cp arg in a script, and let lein generate the classpath as a build step

6:17 but uberjar is convenient for deploy anyway

6:18 jonathanj: justin_smith: is any of that shim code published?

6:18 justin_smith: jonathanj: it's really small, I'll definitely publish the lib if I make it

6:19 basically (defn -start [& args] (require 'real-ns) ((resolve real-ns/-main)))

6:19 with similar for stop, init, destroy

6:19 inside an ns that has (:gen-class) extending the proper daemon class of course

6:20 oh wait

6:20 (defn -start [& args] (future (require 'real-ns) ((resolve real-ns/-main))))

6:20 -start needs to return quickly :)

6:20 jonathanj: what's with the -?

6:21 is that the default prefix for gen-class exports?

6:21 justin_smith: jonathanj: it's the default method implementation prefix for gen-class

6:21 right

6:21 jonathanj: nice

6:21 justin_smith: $google jsvc clojure

6:21 lazybot: [rkn.io - Clojure Cookbook: Daemonizing an Application] http://www.rkn.io/2014/02/06/clojure-cookbook-daemons/

6:21 justin_smith: that's a decent intro

6:21 jonathanj: justin_smith: ah, neat

6:21 justin_smith: thanks

6:21 justin_smith: np

6:22 jonathanj: the motivation for using a shim, is it means I don't need to pre-compile the entire app

6:22 jonathanj: next question, how do i rewire my brain to stop reading that as (js)(vc)?

6:22 justin_smith: haha

6:23 jonathanj: clearly it's true nature is to be a venture-capital firm for javascript

6:23 jonathanj: justin_smith: right, so presumably that reduces the amount of time required to produce an uberjar

6:23 probably quite significantly

6:23 justin_smith: and it avoids tools like cider compiling all your stuff every time you start the repl

6:24 oddcully: isnt there some hip way to pronounce it, that shows you really know you stuff (like wizdul). maybe jazvic?

6:24 jonathanj: justin_smith: ooh

6:24 justin_smith: oddcully: heh

6:24 jonathanj: oddcully: haha

6:24 justin_smith: so a big part of it is that this avoids slow repl startup

6:24 because otherwise you'd get that gen-class run, which would be transitive, and would hit all your code

6:25 and all your libs...

6:28 noncom: is clojure.edn included with the core clojure distribution?

6:28 justin_smith: since 1.5 iirc

6:28 noncom: hmmmm...

7:17 justin_smith: i cannot spot it in the jar.. where is it?

7:17 clojure.edn i mean...

7:18 neither it is present in the local maven repo..

7:48 sveri: Hi, I have a function that takes an argument and then adds or substracts something to that argument (defn foo [x] (+ x 1)) or (defn foo2 [x] (- x 2)). Now I want to have an edn file / map that provides the function that is executed inside foo or foo2, something like {:foo (+ x 1) :foo2 (- x 2)}. what is the idiomatic way to do that? just writing x and y inside the map does not work as it does not recognize the vars

8:14 dstockton: sveri: anonymous functions maybe? (fn [x] (+ x 1))

8:14 and then ((:foo my-map) x)

8:20 sveri: dstockton: sounds like an idea, I try that, thanks

8:21 dstockton: #(+ % 1) for shorter

8:28 noncom: sveri: also, if you will have many functions and will need good stack traces for debugging, consider naming the anonimous functions like (fn my-anon-fum [x] (+ 1 x)) ...

8:33 sveri: noncom: yea, nice hint, but I won't need it I think, but good to know :-)

8:34 noncom: yeah, i find it useful only occasionally

8:45 ,(re-find (re-pattern "(\\d+)") "refs #123456 hello!")

8:45 clojurebot: ["123456" "123456"]

8:45 noncom: ^^^ why there are 2 same results?

8:46 ,(re-find (re-pattern "#(\\d+)") "refs #123456 hello!")

8:46 clojurebot: ["#123456" "123456"]

8:46 noncom: what is that..

8:46 ?

8:47 dstockton: ,(re-find (re-pattern "#\\d+") "refs #123456 hello!")

8:47 clojurebot: "#123456"

8:48 dstockton: one is the captured result and one is the overall match

8:48 first one is the overall, second is the captured number

8:48 ( ) means remember this for later

8:50 noncom: ah..

8:53 crocket: re-think

8:54 (re-think #"your life")

8:57 oddcully: ,(re-find #"(\d)(\d)(\d)" "refs #123")

8:57 clojurebot: ["123" "1" "2" "3"]

9:16 TEttinger: noncom: also you can use ##(re-find (re-pattern "(?:\\d+)") "refs #123456 hello!")

9:16 lazybot: ⇒ "123456"

9:16 TEttinger: (?:whatever) will match whatever but not capture it

9:16 it's a pure grouping operator

9:17 http://www.regular-expressions.info/brackets.html is amazingly useful for the weirder regex stuff

9:27 crocket: ,(doc re-find)

9:27 clojurebot: "([m] [re s]); Returns the next regex match, if any, of string to pattern, using java.util.regex.Matcher.find(). Uses re-groups to return the groups."

9:39 CookedGryphon: does anyone know if/when test.check is going to support nested for-all?

9:44 noidi: CookedGryphon, could this help? http://blog.jessitron.com/2014/08/quick-reference-monads-and-testcheck.html

9:45 isn't that pretty much what a nested for-all would look like?

9:45 CookedGryphon: more or less, that's essentially what i'm doing manually

9:46 crocket: (let [sexy? #(true)] (if (sexy?) (println "yay") (println "woo")))

9:46 ,(let [sexy? #(true)] (if (sexy?) (println "yay") (println "woo")))

9:46 CookedGryphon: would be nice to have it as a part of the standard for-all macro though

9:46 clojurebot: #error {\n :cause "java.lang.Boolean cannot be cast to clojure.lang.IFn"\n :via\n [{:type java.lang.ClassCastException\n :message "java.lang.Boolean cannot be cast to clojure.lang.IFn"\n :at [sandbox$eval25$sexy_QMARK___26 invoke "NO_SOURCE_FILE" 0]}]\n :trace\n [[sandbox$eval25$sexy_QMARK___26 invoke "NO_SOURCE_FILE" 0]\n [sandbox$eval25 invoke "NO_SOURCE_FILE" 0]\n [clojure.lang.Compiler e...

9:47 crocket: ,(if true (println "go go go"))

9:47 clojurebot: go go go\n

9:50 oddcully: ,((constantly true))

9:50 clojurebot: true

9:57 crocket: Why does (defn- private-function "ohai" []) fail after executing (in-ns 'cheese.analysis)?

9:57 Bronsa: crocket: in-ns doesn't refer all of clojure.core

10:09 maio: anyone using clojure.test.check + core async code?

10:09 crocket: Project Euler

10:11 CookedGryphon: maio: I tried

10:11 testing core.async is hard

10:11 really want something like step.async but official so it covers everything

10:11 crocket: Testing?

10:11 It seems clojure books don't really focus on writing tests.

10:11 CookedGryphon: so you can do things like step through every combination of takes, puts nad timeouts

10:11 crocket: Like unit tests.

10:14 Ricardo-Arges: crocket: The one by yogthos does (Web development with Clojure).

10:15 crocket: Are tests not important in clojure?

10:15 pbx: crocket, Clojure Programming (O'Reilly) has a chapter on tests

10:16 crocket: pbx, Do you mean http://www.amazon.com/Clojure-Programming-Chas-Emerick/dp/1449394701/ref=sr_1_1?ie=UTF8&qid=1432044980&sr=8-1&keywords=clojure+programming&tag=donations09-20 ?

10:17 pbx: crocket, yes

10:18 aka http://amzn.com/dp/1449394701/ :)

10:20 crocket: pbx, How did you get the short link?

10:21 oddcully: clojure applied will also have a chapter about testing. but it is missing as of beta 2

10:24 pbx: crocket, i have a side project for generating non-redirect shortlinks like that. (it's broken right now so i'll skip the url)

10:40 cemerick: What are people doing to cope with the new default exception printing?

10:41 gfredericks: does anybody know if using cider with multiple projects might be buggy when one project is a subdir of another?

10:41 cemerick: "cope with" meaning "aah s-expressions are harder to read at a glance!"?

10:42 cemerick: gfredericks: that's putting it politely, yes

10:42 this is particularly painful w/ the prints of error :results in test.check, etc

10:42 [hhalp.fsm$eval125347$notification_generator__125348$fn__125352$iter__125354__125360$fn__125361 invoke "fsm.clj" 147]

10:43 gfredericks: oh I see there are docs about the cider thing

10:43 cemerick: um, yeah, that's an sexpr

10:43 my best idea so far is to restore the (saner) default via a print-method impl in user.clj for Throwable

10:43 gfredericks: cemerick: I'm trying to figure out what the main differences are here -- e.g., the old behavior would still print that long classname, or not?

10:44 surely it must

10:45 apparently cider has a "default connection" that all buffer evals go to regardless of project

10:46 so I'll just have to toggle that around a bunch

10:46 cemerick: gfredericks: yeah, the rotate-connection thing is the only option to control the direction of your evaluation

10:49 gfredericks: no, the old behaviour was that throwables were printed unreadably, e.g. #<ExceptionType message-string>

10:49 now they are printed readably by default

10:51 I guess the change was prompted by the (aborted, AFAICT) stream-socket REPL idea, but the result at this point is pretty painful

10:56 dnolen: cemerick: socket REPL is just postponed far as I know

10:57 cemerick: dnolen: "aborted for 1.7", is what I meant

10:57 puredanger: will be in 1.8

10:59 cemerick: puredanger: since you're here, I'll save my msg to clojure-dev; is the new printing defaults remaining in 1.7 given the delay? I find the new presentation pretty unhelpful as things stand (esp. w/ test.check results, at the moment)

10:59 puredanger: not sure what "is the new printing defaults remaining in 1.7 given the delay" means?

10:59 I guess I'm not sure exactly what you're asking

11:00 there are no more changes planned for 1.7

11:00 cemerick: I have my answer, then :-)

11:01 puredanger: was wondering if the new default printing for Throwables and Object were going to be reverted

11:01 puredanger: no, definitely not

11:01 cemerick: ok; I can fix that for myself in user.clj or something

11:02 puredanger: I'm curious what's unhelpful about it though

11:02 and in particular what you're seeing with test.check

11:03 gfredericks: yeah I was trying to figure that out too

11:03 cemerick: you're saying you didn't get the stacktrace at all before and you liked it better that way?

11:03 noncom: if clojure.edn is shippen with the main clojure distribution, then where is it in the jar? i cannot find it..

11:03 *shipped

11:04 puredanger: test.check (or whatever) can use the new Throwable->map function to get the data as a map and do whatever you want with it re printing

11:05 noncom: yes, it's in the clojure jar

11:07 noncom: found it! sorry, somehow missed it.. heh :)

11:07 cemerick: puredanger: the return value of `quick-check` includes :result slot that can be a thrown exception; this used to print concisely, now prints the full readable representation of the error, including the stack, etc.

11:08 puredanger: yeah, I'd say that's up to test.check to customize as desired

11:08 cemerick: puredanger: but the exception is part of the return value; I don't think anyone would want test.check messing with that

11:10 puredanger: is the contract to return that data or as a string representation of the data

11:10 cemerick: Anyway, the unhelpful part is that exceptions (and other Objects to a much lesser extent) now make default REPL prints far noisier

11:10 puredanger: I'm guessing the former?

11:10 gfredericks: yeah that's an interesting use case

11:10 I thought of the new behavior as mainly replacing unreadable stack traces

11:11 puredanger: cemerick: there is no difference in the repl behavior when an exception is thrown

11:11 gfredericks: this is a different kind of situation

11:11 cemerick: puredanger: The exception, or the value that failed the test, yes

11:11 puredanger: only when the REPL catches the exception

11:12 puredanger: there are competing use cases here

11:12 cemerick: gfredericks: there's no accounting for taste, but I think it'd be rare to find someone that'd claim that the new readable printing of throwables is better for humans

11:12 gfredericks: cemerick: do you often use t.c/quick-check instead of t.c.c-t/defspec?

11:12 puredanger: having the ability to represent the Throwable as data and print as data enables you to leverage tools you have to make what you want

11:13 cemerick: gfredericks: fairly rarely, but the latter just passes along the results of the former

11:14 puredanger: yeah, I'm +100 on a readable representation of throwables being available. Being the default for any exception printed @ the REPL? Not so much.

11:15 puredanger: we had an explicit function available in the socket repl ticket for printing with the prior string form

11:16 that didn't end up making it in

11:16 gfredericks: #error-summary {:msg "..."}

11:16 puredanger: and it seems unlikely it will the way things are going for the socket repl stuff

11:17 but a separate ticket for a Throwable summary printer might be a useful clojure.repl enhancement

11:18 cemerick: puredanger: Having to be explicit about recovering a concise representation in an interactive context sort of defeats the point?

11:18 The socket REPL is another topic IMO; this is strictly a question of default REPL UI for me

11:19 I very vaguely recall hiredman making a similar point when this was being batted around in connection w/ the socket stream REPL, but I wouldn't dare try to find his msg in that thread now :-)

11:20 puredanger: just to reiterate this - if an exception is thrown and caught by the repl, there has been no behavior

11:20 zot: i have a map {:a [1 2], :b [2 3]} … and want to invert it (and convert to sets), a la {1 #{:a}, 2 #{:a :b}, 3 #{:b}} — is there a concise way to pull this off? my solution is a bit ugly w/ reduce and for loops together

11:20 puredanger: ^change in

11:20 cemerick: puredanger: yes, but that's not the only scenario when an exception is part of a value printed at the REPL

11:20 mmeix: sorry for basic question: what's wrong with https://www.refheap.com/101288 ?

11:21 cemerick: Anyway, if things are as they are to be, that's cool, I'll just re-def the necessary print-methods to their previous default

11:21 puredanger: cemerick: I understand, but I think that's the majority use case

11:21 cemerick: puredanger: depends on how much one uses test.check :-)

11:21 xeqi: mmeix: your using v inside the loop body instead of in

11:21 mmeix: doh ...

11:21 thanx (ashamed)

11:22 puredanger: cemerick: that's unfortunate for sure and that's why I'm trying to understand more

11:23 xeqi: mmeix: no ashamed, no sorry for basic questions. You're free to ask those here. Everyone starts somewhere

11:23 I've done that same thing before

11:24 mmeix: lesson: be consistent, when renaming vars

11:24 gfredericks: puredanger: the use case of printing a repl-caught exception is irrelevant to cemerick's point I think -- he's saying that *assuming you're already trying to print an exception as a normal value* the verbose way is probably too noisy

11:24 for repls

11:24 puredanger: yeah, but it didn't print as a "normal value", it just printed some string gunk

11:25 cemerick: puredanger: Understand that I'm not advocating per se, just feedback: the REPL is my primary UI when programming, so everything presented there should be suitable for human, not machine consumption.

11:25 gfredericks: puredanger: but it was short and it did have *some* information

11:25 puredanger: cemerick: again bringing up the socket repl ticket just b/c that's where I worked on it the most... we had the ability in that patch to use a dynvar to set the error printer which is an idea that would help you

11:25 and I can see that being a reasonable thing to set to a concise printed form when using the repl

11:26 cemerick: puredanger: that sounds cool. I don't think its presence would impact my opinion on defaults, tho.

11:26 puredanger: I'm saying it could be the default when in the repl

11:26 cemerick: ah

11:27 puredanger: this is helpful and it can feed into where the socket repl stuff is going

11:27 gfredericks: #error-summary [some.ClassName "the msg"]

11:27 cemerick: well, then I'm confused as to why the default changed at all, since we seem to be in violent agreement about what it should be

11:28 puredanger: I think the major issue was in it not being data

11:29 I don't know Rich's thinking on why verbose vs summary

11:29 cemerick: puredanger: I'm getting the distinct impression that I'm the first person to raise this?

11:33 puredanger: this aspect, yes

11:33 cemerick: cemerick, the princess and the pea of the clojure world

11:35 anyway, I upgraded to 1.7.0, and my test output was suddenly completely dominated by machine-readable stack traces. Probably a 10:1 ratio on the screen. So, I'm surprised.

11:35 puredanger: yeah, no one's mentioned that :)

11:35 andyf_: Just heard about this today. Wonderful: http://friendda.org

11:37 gfredericks: How do we teach Clojurebot that cemerick is a princess? :)

11:40 puredanger: cemerick: so you have these in results like {:result true, :num-tests 100, :seed 1431522180984, :test-var longrange-equals-range} where :result is a Throwable?

11:41 cemerick: puredanger: exactly

11:41 puredanger: isn't this potentially an issue for any result that is "large"?

11:42 cemerick: puredanger: I have a couple of library projects that do funny things with exceptions as well, which return multiple exceptions in various data structures here and there

11:42 puredanger: I'm just trying to figure out if you're just a weird user :)

11:42 cemerick: puredanger: not insofar as :result is otherwise an instance of a type or other data structure that I've constructed, is domain-relevant, and is printed using very familiar/useful notations

11:43 meanwhile, the readable stack traces has things like [hhalp.fsm$eval125347$notification_generator__125348$fn__125352$iter__125354__125360$fn__125361 invoke "fsm.clj" 147]

11:43 and lots of them, which is _completely_ useless as a human

11:44 puredanger: it's "read"able but maybe not readable if you know what I mean :)

11:44 hyPiRion: parseable

11:44 cemerick: yeah, the terminology is problematic :-)

11:46 puredanger: certainly having nested Throwables in the result implies that you want something in the printer, not in test.check

11:47 cemerick: puredanger: yah, trying to cope with this on a case-by-case basis would be nuts.

11:50 puredanger: so my take on this is:

11:50 1) I understand your problem and it seems like a reasonable complaint

11:50 2) many people would not be affected by this - I think you're more exposed than most which is why we haven't seen it

11:50 3) there is a hook in the printer to hack around it for now

11:50 4) some of the work in the queue for 1.8 could address this as well and I will try to factor it in

11:58 cemerick: puredanger: there's a hook in place now? I don't see anything obvious in core_print?

11:58 puredanger: can't you just override the print-method?

11:59 cemerick: puredanger: of course, I thought I misunderstood you previously and that a dynvar was available now

11:59 https://gist.github.com/cemerick/c8ed5730b0055f41cbef

11:59 (if anyone wants a quick copypasta)

11:59 puredanger: oh, no that was in the former socket repl work

11:59 which is not going to go in

12:01 if you wanted just to change throwables you should be able to defmethod print-method on Throwable

12:02 cemerick: puredanger: yeah, I prefer the un`read`able printing of Namespaces, too. :-P

12:02 puredanger: again, not *trying* to advocate for anything, mostly trying to "just" be a user at this point :-)

12:05 puredanger: :)

12:14 andyf_: If I have a local in a function, x, and its value is the symbol next, is there some code I can write to take x and produce the Var #'clojure.core/next ?

12:15 TEttinger: the symbol next, but not in the right namespace?

12:16 err

12:16 I admit I'm a bit fuzzy on symbols and vars

12:16 ,(resolve "next")

12:16 andyf_: Ah, got something: (get (ns-publics 'clojure.core) x)

12:16 clojurebot: #error {\n :cause "java.lang.String cannot be cast to clojure.lang.Symbol"\n :via\n [{:type java.lang.ClassCastException\n :message "java.lang.String cannot be cast to clojure.lang.Symbol"\n :at [clojure.core$ns_resolve invoke "core.clj" 4214]}]\n :trace\n [[clojure.core$ns_resolve invoke "core.clj" 4214]\n [clojure.core$ns_resolve invoke "core.clj" 4211]\n [clojure.core$resolve invoke "core...

12:16 TEttinger: ,(resolve next)

12:16 clojurebot: #error {\n :cause "clojure.core$next__4109 cannot be cast to clojure.lang.Symbol"\n :via\n [{:type java.lang.ClassCastException\n :message "clojure.core$next__4109 cannot be cast to clojure.lang.Symbol"\n :at [clojure.core$ns_resolve invoke "core.clj" 4214]}]\n :trace\n [[clojure.core$ns_resolve invoke "core.clj" 4214]\n [clojure.core$ns_resolve invoke "core.clj" 4211]\n [clojure.core$resolv...

12:16 TEttinger: ,(resolve 'next)

12:16 clojurebot: #'clojure.core/next

12:16 Bronsa: andyf_: isn't that just resolve?

12:17 andyf_: Yeah, I think I have almost never needed resolve before, so off my familiarity chart

12:17 Bronsa: or ns-resolve if not in the curr ns

12:19 TimMc: I don't know if this got brought up in the exception-printing discussion, but could println and prn behave differently here?

12:23 mmeix: can I do a (let [ ... ]) inside a loop? like (loop [x (...)])

12:23 (loop [x (...)] (let [ y (* x x)] ... ))

12:25 cemerick: puredanger: thanks for listening, appreciated

12:26 puredanger: TimMc: 's good question - print-method and print-dup could be different

12:26 shoky: ,(loop [x 3] (let [y (* x x)] (if (> y 20) y (recur (inc x)))))

12:26 clojurebot: 25

12:26 shoky: mmeix ^

12:26 mmeix: great!

12:27 thanks

12:28 TEttinger: (inc shoky)

12:28 lazybot: ⇒ 5

12:32 Bronsa: I too find the new readable printing a step back for the normal REPL

12:36 TEttinger: agreed, Bronsa

12:44 iamjarvo: is there a way to to not pass in app-id to create-cert (talkGET "/certs" [app-id] (create-cert app-id)) ?

12:47 mmeix: a stylistic question: is it more idiomatic to write "(if (= :up x)..." or "(if (= x :up)..."?

12:48 (I think the first focuses more on the 'switching' value)

12:50 TimMc: I like the latter unless you're comparing x each time in a whole chain of these.

12:50 And maybe even then?

12:51 mmeix: maybe because it's more with the flow of the language

12:51 (I'm not a native speaker)

12:52 (just now found it easier: "case x :up ... :down ...")

12:53 TimMc: oh, definitely

13:02 ionthas: Hei there. Is there any way to destructure a vector comming from a function call inside a let?

13:03 Bronsa: ,((fn [x] (let [[a b] x] b)) [1 2])

13:03 clojurebot: 2

13:03 TEttinger: ,(let [[x y] (vector 1 2)] (+ x y))

13:03 clojurebot: 3

13:04 TEttinger: ,(let [v (vector 1 2) [x y] v] (+ x y))

13:04 clojurebot: 3

13:04 TEttinger: does one of those satisfy the request, ionthas?

13:07 ionthas: yes thanks!

13:07 justin_smith: or ##(let [[_ a b] (range)] (+ a b))

13:07 lazybot: ⇒ 3

13:17 TEttinger: justin_smith: show-off

13:24 mmeix: If someone experienced would be so kind and have a look at https://www.refheap.com/101292 ... thanks!

13:25 ..

13:27 xemdetia: mmeix, here is some advice I see passed around from time to time about style. https://github.com/bbatsov/clojure-style-guide

13:28 mmeix: ah, thanks - will look into it

13:30 xemdetia: and if my understanding of what you are trying to do is correct you would be more functional if you used map instead of a loop. It's just not obvious to me since I am unaware of music what you are trying to do there

13:30 but smaller functions glued together with map seems more appropriate

13:31 mmeix: it solves a graphical problem: on which side of the stem do noteheads go in music notation

13:32 lok, will try to

13:32 break it up in smaller parts

13:32 thanks!

13:32 xemdetia: right, and since you are basically saying 'foreach note do a thing and generate a value' that is really what map is for

13:34 mmeix: tried this first but had the problem, that I need to do "book keeping" about already occupied positions (this is what "slots" collects for me)

13:35 since every next value (note) needs to know about this to find its value

13:36 couldn't wrap my head around doing this in parallel

13:36 but will try - thanks fpr advice!

13:36 xemdetia: well you may not be able to if it is a natively sequential process

13:38 if the processing of an element is dependent on the elements adjacent is no longer trivially parallelizable

13:39 Crate_: if you're just keeping/combining state as you accumulate elements tho, that's a reduce/fold

13:39 mmeix: yes, this is the case: the placement of a note is dependent on the ones before it

13:39 Crate_: which i feel like might work here

13:40 mmeix: reduce/fold is in core, or in another ns?

13:40 Crate_: reduce

13:40 in core

13:40 mmeix: reduce I know

13:41 fold I didn't

13:41 Crate_: fold is just what its called in other langs sometimes

13:41 mmeix: ok

13:41 xemdetia: yeah a reduce does make sense here

13:41 I am just not thinking :)

13:42 mmeix: I tried with reduce, but couldn't wrap my head around 'keepng the state'...

13:43 xemdetia: did you do the (reduce f val coll) style or did you try using (reduce f coll)

13:43 mmeix: reduce f val coll

13:43 but val is somehow multidimensional

13:44 (not sure though)

13:45 xemdetia: according to your problem you are returning a list of vectors

13:45 mmeix: yes

13:45 xemdetia: so would it break the universe if you returned a list of maps

13:45 might be easier to work with

13:46 mmeix: I tried with maps, with the pitches as keys, but the problem is, that pitches can occur multiple

13:47 so I would have to create some sort of index

13:47 xemdetia: wouldn't the list itself be implicitly the order?

13:47 mmeix: ah, ok

13:47 xemdetia: I mean I am assuming you are doing music graphical things going left to right in common notation

13:47 mmeix: yes

13:48 xemdetia: so if first is the leftmost note and last is the rightmost note

13:48 then you don't need an index and can just draw from it as a sequence

13:48 mmeix: but in this case it's about arrangement of noteheads on a single stem

13:49 xemdetia: so the case I indicated would not be true then

13:49 and my assumption was wrong :)

13:49 even still a list of maps could handle this as part of a reduce

13:50 ({:pitch [a b] :stemside :n}) would be equally as valid right?

13:50 mmeix: http://blog.steinberg.net/wp-content/uploads/2014/02/acc-stack-finale.png

13:50 xemdetia: so if you were in a situation where you were trying to merge dots to a single stem

13:50 you could join them that way

13:51 so is your goal to resolve an individual stem or many stems

13:51 mmeix: one stem

13:51 and then the next :-)

13:51 xeqi: mmeix: is next-free-slot the same as (first (remove (set (sl p)) [:n :f :sn :sf]) ?

13:52 mmeix: let me read this for some seconds ...

13:53 ah!

13:53 must play around with this - thanks!

13:53 xemdetia: so maybe a map like { :a :n :b :f } would be perfectly fine for a shared stem

13:54 mmeix: yes, this would work

13:54 xemdetia: and make it so the key's existence in the map is implying it is there and the value is what you want to draw

13:54 mmeix: I see

13:55 this is all great input - really appreciating it!

13:56 xemdetia: yeah I think something that you were missing is that the structure of your data is allowed to determine part of your value, e.g. an existence in a map or the order of a list.

13:56 that would definitely help you be more clojure-y

13:57 mmeix: (beginning to understand)

13:57 it's quite a journey :-)

13:57 xemdetia: I mean you don't have {:length 5 :value [1 2 3 4 5]} you just have [1 2 3 4 5] and as a value on its own you ask it how long it is via a function (count [1 2 3 4 5])

13:58 mmeix: yes, this I understood, but obviously I didn't see the data pattern

13:59 xemdetia: yep, you could see that with what you wrote but sometimes it's hard to get out of the problem domain to see it

13:59 mmeix: so my reducing function would need to ask all former elements somehaow

14:00 xemdetia: which is fine, that's available through val

14:00 mmeix: ok

14:00 xemdetia: but you should say that this function works on one stem at a time, and this function composes multiple stems

14:00 mmeix: no, not really

14:00 xemdetia: or maybe better described: this function takes the description from a vector and makes a stem, and this other function composes many stems

14:01 mmeix: sometimes a stem gets split, graphically

14:01 xemdetia: right with the 'flip' case in the image you showed right?

14:01 mmeix: you are talking about the doc string?

14:02 xemdetia: yeah I can only go by that

14:02 mmeix: yes: if a notehead cannot go on the proper side of the stem, it has to flip over

14:02 without colliding with other notes already there

14:02 xemdetia: but I mean then you have a recursive problem definition. A stem with one notehead writes to the normal side

14:02 mmeix: yes

14:03 xemdetia: the n+1 stem writes to side flip or normal based on the last n noteheads already decided on

14:03 mmeix: right

14:03 the n+1 notehead

14:03 (not the stem)

14:04 the noteheads attach all to a single stem

14:04 xemdetia: sorry, but I think you got what I mean

14:04 and if you need an implict order for pretty printing

14:04 well you are already using a sort somewhere

14:05 so if things are in a known order thats meaningful to you, and you are starting with a trivial basecase then iterating n+1 until you resolve all n noteheads should be not that bad

14:06 mmeix: ok: I'll learn to calculate the n-2, n-1 ... cases into n

14:06 reading back the result val

14:06 so far

14:06 right?

14:06 xemdetia: yep, since at each application of f during the reduce is the n+1 case

14:08 mmeix: the difficulty was, that sometimes f needs only the last n, but sometimes it has to look it 2 or 3 vals back,

14:08 there are several possible combinations

14:09 but yes, I had the feeling, that I don't need a loop really

14:10 xemdetia: mmeix, well that's where the sort comes in

14:10 if everything is in the order you expect it to be in so you can always work from beginning to end consistently then that would resolve any weirdness

14:11 mmeix: yes ...

14:13 xemdetia: I am imagining your problem like this. given a list of #'s if for a given number I, I-1 = n-1 then do the opposite of n-1's direction

14:13 otherwise do normal direction

14:13 mmeix: yes, that's the simple case

14:13 but there are cases, where this doesn't work

14:13 alas

14:13 xemdetia: can you show me one of those cases?

14:14 I am too unfamiliar with what you are trying to do

14:14 mmeix: just searching ...

14:16 can I paste a png here?

14:17 xemdetia: well you could use imgur or something

14:17 I mean unless it is nsfw music notes or something

14:17 mmeix: https://www.dropbox.com/s/k0wfniq1gsawmeg/Split%20Stem%20Cluster-2.png?dl=0

14:18 this is one of those more complicated cases

14:19 the calculaton begins - in this case - with the highest note head

14:19 and the works down

14:19 xemdetia: well that's what I say if you have an ordered list

14:19 mmeix: yes

14:19 xemdetia: going by my previous logic the vector would be [1, 2, 3, 5, 6]

14:20 because 3,5 fail the adjacent test it would be normal normal

14:20 mmeix: or rather [1 2 2 3 5 6]

14:20 xemdetia: is that thing that is tangentially attached part of the same stem?

14:20 mmeix: yes

14:20 a "split stem"

14:21 because this one doesn't fit on normal neither on flipped

14:21 xemdetia: what does it mean?

14:21 is it because it is a # note or something that normally would be put there?

14:21 mmeix: it belongs to the chord, but there is just not enaough room to place it on the normal stem without colliding

14:22 the accidentals are another complication

14:22 and both those have different pitch, yes

14:23 xemdetia: it seems like you might have to change how you are structuring the problem and first do a pass where you bucket every notehead into someplace that is meaningful

14:23 and then process that the way I was describing before

14:24 mmeix: so two passes, in a way

14:24 xemdetia: because you are effectively saying 'I have only so many buckets, and if a bucket is already filled it goes in the overflow bucket, and if that overflow bucket is filled it goes in a third bucket'

14:24 mmeix: yes

14:24 xemdetia: so really first you should make some structure that says 'here are all the noteheads that should go in bucket #3'

14:25 mmeix: but this depends on the situation, and cannot be calculated beforehand for every case

14:26 but I understand the message

14:26 xemdetia: I am not saying it should be, but how I look at it is that you have a stem with six noteheads

14:26 mmeix: yes

14:28 but it should be possible to decide one by one, in which bucket the heads should go, you are right

14:29 another similar problem comes with accidental placement, this is a really devilish one

14:29 :-)

14:29 faveteli1guis: what am i missing in this code https://gist.github.com/3e0b0a5d20d361128f9d?

14:30 mmeix: thanks again for thinktanking!

14:31 xemdetia: no problem it is an interesting formatting problem

14:32 TimMc: faveteli1guis: An explanation of why you are dissatisfied with it.

14:33 xemdetia: if accidentals are 'wiggly stacks of whole notes' according to google then the same bucketing strategy might work there

14:33 justin_smith: TimMc: well, a number will have a nil :beff

14:34 so it probably needs a default dispatch

14:34 TimMc: justin_smith: I was trying to prompt for e.g. a stack trace. :-P

14:35 faveteli1guis: justin_smith: does wy does not the dispach function return 1?

14:35 justin_smith: faveteli1guis: ##(:beff 1)

14:35 lazybot: ⇒ nil

14:36 justin_smith: the dispatch function returns 1, but when you call (jump 1) or (jump 2), there is no dispatch for that

14:36 faveteli1guis: I thought it did ##(:beef {:beef 1})

14:36 lazybot: ⇒ 1

14:36 justin_smith: why would it do that when you didn't write that?

14:37 (jump 1) is going to call (:beff 1) which will come up with no method found

14:37 faveteli1guis: I want to use :beef as dispatch function and i send {:beef 1} as input to the multi method

14:37 justin_smith: right

14:37 faveteli1guis: aa ok now i see thanks :)

14:38 was blindly looking at the first call

14:38 mmeix: thankfully we beginners get lots of help here :-)

14:38 justin_smith: so maybe you wanted (jump {:beff (inc v)})

14:39 or maybe you want jump to have a default method that handles numbers

14:40 faveteli1guis: would trampoline work for mutualy recursive multimethods?

14:40 to make them not stack overflow?

14:40 justin_smith: I guess you could use find-method

14:40 and return that

14:41 (doc find-method)

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

14:41 justin_smith: (doc get-method)

14:41 clojurebot: "([multifn dispatch-val]); Given a multimethod and a dispatch value, returns the dispatch fn that would apply to that value, or nil if none apply and no default"

14:41 justin_smith: so you could combine trampoline with calls to get-method

14:43 or anonymous functions that involve calls to multimethods, even

14:47 mmeix: (inc xemdetia)

14:47 lazybot: ⇒ 4

14:47 faveteli1guis: justin_smith: why is it not working to just put the first call in trampoline? im not getting any errors

14:48 https://gist.github.com/favetelinguis/3e0b0a5d20d361128f9d like so

15:12 justin_smith: faveteli1guis: that usage of trampoline requires returning a function to call

15:12 also, you'll run into the fact that jump is not defined for 3

15:19 TimMc: devn: Actually, I can't tell if Rust's "procedural macros" manipulate ASTs vs. turn a token stream into ASTs.

15:19 Both work, I guess -- you can build the former from the latter.

15:20 justin_smith: TimMc: the latter lets you define new tokenizing rules, while the former does not (kind of like the reader-macro / macro distinction in LISP I guess)

15:20 TimMc: yeah

15:21 Do you think I'm right about being able to build one from the other?

15:24 justin_smith: it's one way - the token stream to AST transform is a superset of transforming ASTs isn't it?

15:25 TimMc: What about recursive macroexpansion?

15:26 I wonder what the compiler plugins have access to.

15:28 justin_smith: given the ability to take a token stream and return an AST, implementing transformation of that AST (like recursive macroexpansion) should be straightforward

15:29 as an ad-hoc step, even if that step does not formally exist

15:31 TimMc: I guess it woul dbe like a lisp-2, though.

15:32 Oh, no, I misunderstood that -- that's fns vs. data?

15:32 justin_smith: yeah

15:33 the token stream to AST thing does not need to enforce that

16:44 kaiyin: https://gist.github.com/kindlychung/4745feeaec628cc8cda1 what does this cost function actually mean?

16:46 amalloy: it's a mystery, kaiyin, without understanding the context. presumably it is some sort of heuristic for a search algorithm in a specific search space laid out in the book

16:48 justin_smith: kaiyin: it's leading up to an introduction of an implementation of A* - it may help to look up A* and see what that's about

16:48 $google A* djikstra

16:48 lazybot: [Dijkstra's algorithm - Wikipedia, the free encyclopedia] http://en.wikipedia.org/wiki/Dijkstra's_algorithm

16:49 kaiyin: ok, thanks.

17:30 m1dnight_: Hi, I was reading up on sanitizing my SQL before reading it/storing it from/in postgres. I found Cascalog which looks super awesome, but I'm wondering if somebody can point me in the right direction of "doing it myself". By it i mean make sure im not vulnerable to injection.

17:30 Maybe fool around and build the minimal DSL myself..

17:32 TimMc: m1dnight_: You shouldn't "sanitize" SQL. Use parameters.

17:32 justin_smith: m1dnight_: are you using clojure.java.jdbc? if so, you can ensure that any parameters are used via parameterized queries

17:32 m1dnight_: (sanitize is a term i picked up reading google-fu)

17:33 justin_smith: m1dnight_: it's a flawed paradigm, as the security history of systems that count on sanitization will testify

17:35 m1dnight_: okay i think I misunderstood what parametrized queries were. I'm reading up on that now.

17:35 justin_smith: im using that indeed

17:36 thanks for the info, even though off topic guys

17:36 justin_smith: it's relevant because you are doing it via a clojure lib :)

17:37 sandbags: can anyone remind me the name of that nice search engine that can search across all Clojure projects in clojars?

17:37 (search sources i mean)

17:37 justin_smith: the difference is that with a parameterized query, string contents can't be interpreted as SQL syntax, instead of escaping the string, you are getting a context where the string can't be an sql command

17:38 sandbags: kind of a cross-reference doc search/browser thingy

17:38 m1dnight_: I was just thinking about it justin_smith . Sanitizing input does not prevent that at all indeed.

17:38 justin_smith: sandbags: it's on the tip of my tongue - I know the one you mean

17:38 sandbags: justin_smith: annoying isn't it ;-)

17:38 justin_smith: sandbags: http://crossclj.info

17:39 sandbags: bravo! thank you

17:41 m1dnight_: I recall somebody in #java saying that somebody should build something like that for java :D

17:41 also, it has the cover of mutter as favico, if im not mistaken

17:41 :D

17:42 justin_smith: m1dnight_: I thought that was a statue of the buddha

17:42 m1dnight_: hmm, that might look more like it

17:43 oh yeah, im wrong :D I just looked up the cover. It's from another angle.

17:43 justin_smith: mutter, the rammstein album?

17:43 m1dnight_: yep

17:44 justin_smith: yeah, I think it's pretty similar to one of these statues https://s-media-cache-ak0.pinimg.com/originals/be/2e/47/be2e473783b3779164af51030252ab00.jpg

17:45 new app idea: reverse image source for favicon.ico

17:46 m1dnight_: yeah definitely one of those statues

17:46 cool site though

17:46 clojurebot: Huh?

17:46 m1dnight_: yes clojurebot !

17:46 TimMc: Love that site.

17:47 m1dnight_: Depending on the definition of sanitize, it also means you can't enter names like O'Reilly, etc.

17:47 (That's the stupider version of the term.)

17:48 justin_smith: insanitize: https://github.com/prismofeverything/zalgo

17:48 I introduced my friend/co-worker to zalgo, and he immediately went and made the above lib

17:50 possibly the best definition I have ever seen: https://github.com/prismofeverything/zalgo/blob/master/src/zalgo/core.clj#L146

17:50 TimMc: Needs more unevenness and mid-height combining chars, I think.

17:51 Oh no, mojibake? https://github.com/prismofeverything/zalgo/blob/master/src/zalgo/core.clj#L101

17:51 justin_smith: combining characters can do weird things when taken on their own

17:53 or maybe some errors have snuck into that codebase

17:53 TimMc: They should just display offset at worst.

17:54 Is your coworker on Windows?

17:54 justin_smith: OSX

17:55 are json-web-tokens worth using?

17:56 TimMc: Depends n your security and availability requirements.

17:56 justin_smith: do you know of / have a good overview?

17:56 TimMc: I think they're just a formalization of the notion of HMAC in a web context.

17:57 I haven't read up on them properly, though.

17:58 justin_smith: yeah, I am trying to do exactly that, someone wants to use them to persist credentials, I am trying to figure out how good an idea that might be

17:59 I'm seeing references to vulns as recent as April first

18:13 TimMc: link?

18:13 justin_smith: https://auth0.com/blog/2015/03/31/critical-vulnerabilities-in-json-web-token-libraries/

18:14 TimMc: thanks

18:15 "This puts us in an awkward position: in order to validate the token, we have to allow attackers to select which method we use to verify the signature."

18:15 Interesting.

18:16 "Meet the "none" algorithm"

18:17 ლ(ಠ益ಠლ)

18:18 justin_smith: haha

18:19 TimMc: fucking nope

18:20 nope nope nope

18:20 justin_smith: "nope" algorithm: treats all contents as invalid

18:21 TimMc: yeah, that bug left me feeling very skeptical about the whole thing

18:22 TimMc: Give it another year and let Alexander Homokov take a swing at it, then reevaluate.

18:22 justin_smith: good plan

18:22 TimMc: I'm pretty sure this is worse than rolling your own HMAC'd JSON.

18:22 justin_smith: yeah, I'm just gonna use ring session, and then cross-correlate with a store that the websocket client can reference

20:19 sg2002: Hello. I know there are many cider users here... Are there any effective ways of navigating my cider repl history? I know about M-p and M-r, but they're not as useful as the generic M-r in comint.

21:24 justin_smith: sg2002: I assume you are using a history file between sessions?

21:30 sg2002: justin_smith: Hello Justin. I've just found the solution to my problem. It's just that cider history search is kind of weird. You do M-s to enter the pattern and then M-p and M-s to cycle between candidates. I think I already discovered that, used for some time and then forgotten. It's just kind of a different convention. And it's weird that cider does not inherit comint.

21:55 eraserhd: No remove-keys?

21:55 Oh, it's just dissoc :/

21:55 gfredericks: dissoc?

21:56 ,(def remove-keys dissoc)

21:56 clojurebot: #'sandbox/remove-keys

Logging service provided by n01se.net