#clojure log - Apr 03 2015

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

1:46 mordocai: I have an error with trying to create a schema for a record from another namespace. I'm importing it but still no go. What am I doing wrong? https://github.com/mordocai/clojure-maildir

1:46 Error shows up when compiling schemas.clj

1:56 Ugh, laptop is way too aggressive at turning off wifi. If anyone answered my query I missed it.

1:58 mavbozo: mordocai: records initialization should be Email. or ->Email or map->Email

1:59 mordocai: or maybe that's how scema.core works

2:00 mordocai: mavbozo: Yeah, AFAIK when specifying a record for a schema you are supposed to give the raw record not an initialized one. It appears to actually be erroring on the import btw.

2:05 mavbozo: mordocai: what's written in the error message?

2:12 mordocai: i cloned your repo and change the import line to (:import [clojure_maildir.records Email])

2:12 the schemas.clj compiled

2:13 although I got another error: No such var: records/->Email, compiling:(clojure_maildir/core.clj:22:5)

2:16 mordocai: mavbozo: Ah, just got my error in a pastebin. https://www.refheap.com/99187. Thanks for the import correction! I'll work on the next error.

2:22 Excellent, those errors are all fixed! Thanks for your help!

2:27 justin_smith: ~next

2:27 clojurebot: It's greek to me.

3:02 guthur: Is there a way to reload a project.clj in cider/nrepl

3:02 I have added a dependency and would like it loaded

3:03 justin_smith: guthur: sure, if you use pallet/alembic

3:03 or even pomegranate (but alembic is easier, it has a "load-project" function that does what you want)

3:03 jonasen: guthur: I usually do M-x cider-restart

3:04 guthur but that restarts everything I think

3:04 justin_smith: yeah, that shuts down your repl and makes a new one

3:05 guthur: yeah i figured restart would work

3:05 I will check out alembic and pomegranate

3:06 justin_smith: guthur: a good cantidate for putting in ~/.lein/profiles.clj under :user {:dependencies [ ... ]}

3:06 that, criterium (for benchmarking functions for speed) and tools.trace (for debugging)

3:07 guthur: justin_smith: yeah just in the process of adding it

3:15 TEttinger: hm, so, I have some questions for #clojure's masters of the immutable

3:19 if I were to make a new def-like macro that defines a symbol as being a "state variable" (not sure what to call it, really, but the idea is, any changes to any state variable update the same global collection that stores all state variables, increment a version number, append the new state to a list of remembered states)...

3:20 I basically have an append-only log of immutable historic states

3:21 but I want to be able to jump back to previous states, assigning the current state the value from an earlier version

3:24 I'm just not sure how all this will work

3:39 cfleming, I have a bit of confusion regarding the behavior of Cursive and lein projects with -main

3:40 it seems like right clicking a file or project and telling Cursive to Run a given module just does nothing and exits after a few seconds

3:40 I must be missing something

3:40 I'm on 13.1

3:49 guthur: I'm trying to use https://github.com/xsc/ancient-clj

3:50 if i require [ancient-clj.core :as ancient] i get the following exception...

3:50 Could not initialize class com.amazonaws.ClientConfiguration

3:51 any suggestions

3:53 TEttinger: guthur, it looks like ancient-clj depends on a com.amazonaws lib https://github.com/xsc/ancient-clj/blob/master/project.clj#L10

3:54 but it must be doing something as soon as it's read

3:54 guthur: TEttinger, yeah, does lein not grab those

3:54 TEttinger: a very old lein version wouldn't

3:54 an... ancient lein version :P

3:54 guthur: i'm pretty much upto date

3:54 Leiningen 2.5.1 on Java 1.7.0_75 OpenJDK 64-Bit Server VM

3:57 TEttinger: and the only stuff that actually is run by including ancient-clj.core seems awfully small

3:57 https://github.com/xsc/ancient-clj/blob/master/src/ancient_clj/core.clj#L9-L17

3:58 ah, that was added fairly recently though https://github.com/xsc/ancient-clj/commit/15b508f5ee5bd6212020b434a438ecaa8086567b

4:03 guthur: maybe i will try and earlier verson

4:04 TEttinger: that was sept 2014

4:05 if a version from august or earlier works, that might be an interesting issue to report

4:05 sveri: Hi, I just tried out core.typed and started annotating a namespace with two functions. I am calling a few other libraries there which are not under my control and it turns out I have to annotate each other function call I am doing into a different library? It makes sense following the logic of typing. How do people handle this? I mean, does it make sense to to collect external library annotations in a central place so I can access it

4:07 TEttinger: I'm curious about how that works in practice too, sveri, but I haven't used core.typed

4:07 sveri: TEttinger yea, I have a helper library and I think about making a namespace with just lots of annotation definitions that I need somewhere else

4:08 TEttinger: I wish there was some way to automate that, but I don't see how it could work

4:08 I guess some kind of type inference could be used if it had a basis of how they are used

4:09 sveri: TEttinger maybe a github repo makes sense too where people can contribute type definitions..

4:09 TEttinger: yep

4:11 sveri: I will ask on the core.typed mailing list what people think about that and maybe start one

4:14 I just looked at some github repo and found this: (ann ^:no-check clojure.java.io/writer [Socket -> BufferedWriter]) this is exactly what I mean, I guess so many people will have this line somewhere in the code...the duplication will be immense

4:18 TEttinger In case you want to follow: https://groups.google.com/forum/?fromgroups#!topic/clojure-core-typed/nrHx_1XO9cc

4:39 expez: how do I add the character literal ( to a clj file?

4:39 \( doesn't work and neither does \\(

4:40 dstockton: not sure what you mean expez

4:40 where in a clj file?

4:41 expez: dstockton: I want to compare against the character literal (, but I can't eval the code. I thought \( was the right way to do this but cider is barfing on an unmatched delimiter

4:42 dstockton: might be a cider issue, \( works fine in the repl

4:42 oddcully: ,(= \( \()

4:42 wagjo: ,\u0028

4:42 clojurebot: \(

4:42 true

4:43 wagjo: expez: you may use \u0028 as a workaround

4:43 oddcully: ,(= \( \u0028)

4:43 clojurebot: true

4:44 expez: submitted a ticket. going with workaround for now. Thanks!

4:51 TEttinger: &(map char "()[]{}")

4:51 lazybot: ⇒ (\( \) \[ \] \{ \})

4:51 TEttinger: &(map int "()[]{}")

4:51 lazybot: ⇒ (40 41 91 93 123 125)

4:51 TEttinger: hm

4:52 &(map (comp #(format "%04X" %) int) "()[]{}")

4:52 lazybot: ⇒ ("0028" "0029" "005B" "005D" "007B" "007D")

4:52 TEttinger: &(map (comp #(format "\\u%04X" %) int) "()[]{}")

4:52 lazybot: ⇒ ("\\u0028" "\\u0029" "\\u005B" "\\u005D" "\\u007B" "\\u007D")

4:52 TEttinger: there you go, all the brackets that might mess cider up

5:03 cfleming: TEttinger: Hmm, I'm not sure about the autodetection there - what you want is to go to Run->Edit Configurations and create an Application configuration

5:04 TEttinger: I checked that

5:04 I have one made

5:04 cfleming: What happens when you run it?

5:04 TEttinger: but it isn't... doing anything. and I don't see where to call -main

5:04 it doesn't print anything because it is supposed to open a window, but no window opens

5:04 if I call -main in the repl, I get the window just fine

5:05 cfleming: In that run config, you enter your main class - that should be the class generated from your main ns

5:05 TEttinger: if I terminate the repl and try to open again, Cursive throws an exception (I submitted a bug report)

5:06 cfleming: TEttinger: You did? I don't think I saw that

5:06 TEttinger: it was less than an hour ago

5:06 cfleming: TEttinger: Oh, you mean an exception report, not an issue

5:06 TEttinger: yes

5:06 cfleming: Right, I haven't checked those

5:06 Can you send a screenshot of your Application run config?

5:07 TEttinger: the options for the run config are "script path", where I have the file path to the clj

5:07 sure

5:07 cfleming: Ok

5:07 Hang ok

5:07 Hang on

5:07 You're talking about a Clojure Application config

5:08 elvis4526: Is there a way to provide a default implementation for a method when using protocols ?

5:08 TEttinger: cfleming, correct

5:09 cfleming: You use that one if you have a Clojure script to run, once you're using -main you're in Java land really

5:09 Although that config should handle it (there's an issue in the tracker for it)

5:09 TEttinger: should I just add a call to -main at the end?

5:10 cfleming: The config you want is just called Application, it's what you'd use if you were running a Java program

5:10 TEttinger: ah! ok

5:11 cfleming: Sorry, this is old code and more confusing than it should be, I'm planning to fix it soon as I re-vamp the run config stuff

5:12 TEttinger: nope, Application doesn't recognize anything in my project as a main type

5:12 main class, rather

5:12 it's not a big issue, I should be doing more from the REPL anyway

5:13 but it was certainly an early stumbling block

5:13 cfleming: Are you using :gen-class?

5:14 Yeah, it's surprising how infrequently people use -main, which is why I've never prioritised fixing it, but it's pretty nasty right now

5:15 TEttinger: yeah, I have :gen-class in the ns

5:16 thanks for the quick reply!

5:16 other than being very confused by structural editing, I've been pretty happy with Cursive so far

5:16 cfleming: Ok, so I think there' s a problem where Cursive doesn't correctly publish the main method in the class generated from the namespace

5:16 TEttinger: ah!

5:17 cfleming: Give me a sec

5:17 Was that confusion about structural editing in Cursive specifically, or do you just not use it?

5:20 TEttinger: I've never used structural editing before, I couldn't turn a variable into a call that uses that variable, so I ended up with all this weirdness trying to stick a paren in the middle of a form...

5:20 I had something like, let's say (* width height), and I wanted to change it to (* (/ width 3) height)

5:21 it let me add the first paren, but any time I typed ), it closed a much later form

5:22 cfleming: Ok, did you figure out how to turn it off?

5:22 (might be best until you get more used to Cursive - just learn one new thing at a time :-) )

5:23 TEttinger: oh yes, I turned it off right away

5:24 cfleming: So I just ran a main method, here's how: I used the Application config, you're right that it doesn't find the main class, I'll fix that. But you can type in the class anyway, which is basically your namespace name with dashes replaced with underscores

5:24 It'll warn you that the class doesn't have a main method, but you can ignore that

5:24 Are you using Leiningen?

5:24 TEttinger: yes

5:25 I imported a project by finding my existing project.clj

5:25 cfleming: Ok

5:25 One thing you should check if you're using AOT is that Cursive is set to compile your namespace - it doesn't autodetect the ones it should compile yet

5:25 TEttinger: oh, and just calling -main at the toplevel works for now

5:26 cfleming: That's under Settings->Build etc->Compiler->Clojure Compiler

5:26 Ok. I'm actually working on a bunch of run/execution stuff right now, I'll see if I can fix this for the next build

5:28 TEttinger: great, thanks!

6:56 noncom: anyone using neo4j + neocons here?

7:36 unindented: is there a way I can run all :test assertions for my module functions when executing `lein test`?

7:36 I mean these kinds of assertions: http://clojure.org/special_forms

8:03 borkdude: I want to change something in a database and upload something to s3. this has to occur in a synchronized fashion. maybe this is where "(locking ...)" comes in

8:03 ?

8:04 there may be a race condition when I don't lock

8:56 guthur: is there a way to force the output of print when printing to the shell

8:56 in CL you would use terpri

8:57 I am wanting to prompt and accept an input

8:57 but unless i use println the prompt will not show

9:10 ah, the answer was (flush)

9:56 gfredericks: this thing with iterate is so complicated

10:39 justin_smith: TEttinger2: regarding your history of states: make "place in state history" one of your history-tracked states of course :)

10:39 TEttinger2: that way you can walk not only history, but history of backtracking history

11:05 mikerod: Why would I get UnsupportedClassVersionError Unsupported major.minor version 51.0 types of exceptions running clojure 1.6 things in Java 7?

11:05 sobel: thx to whomever turned me onto Robert.Hooke yesterday

11:05 mikerod: I was under the impression that clj 1.6 was fine in Java7

11:05 specifically I got this compiling cider/nrepl/middleware/util/java/parser.clj

11:05 sobel: i'm cross-cutting through orthogonal concerns like butter

11:07 justin_smith: mikerod: odd

11:07 mikerod: usually jvms are really good at keeping these things compatible

11:08 mikerod: justin_smith: Java 7 does have a change in class format with JSR 202 https://jcp.org/en/jsr/detail?id=202

11:08 however, I thought many people were running Clojure fine in this Java version (pretty sure)

11:09 and this is JIT compiling - if it were AOT I may be more likely to understand having an issue

11:09 puredanger: clojure 1.6 works perfectly fine with java 7

11:09 justin_smith: yes, I have used 1.6, 1.7, and 1.8 extensively and have not seen these sorts of issues

11:09 puredanger: somehow you have newer class files and an older jvm

11:09 mikerod: java.lang.UnsupportedClassVersionError: com/sun/javadoc/ClassDoc : Unsupported major.minor version 51.0, compiling: ider/nrepl/middleware/util/java/parser.clj

11:09 Oh... that's odd

11:10 I guess I'll look at this some more.

11:10 puredanger: looks like what you'd get with a mismatched jvm / jdk ?

11:11 mikerod: puredanger: we accidentally had a node in a distributed cluster have java7 instead of java6 - that we have developed for currently in this case

11:11 I guess something could just be screwed up there

11:12 sobel: what's the most current 'release' quality Clojure version?

11:12 mikerod: I just can't understand how a JVM running with Java7 could cause a JIT compiled class to break during compilation. I'm sure I just am not connecting the dots here then. I just wanted to make sure I'm not crazy and Clojure is fine running on Java6 and above

11:12 puredanger: are you sure it's a java 7 jvm?

11:12 looks like java 6 jvm and java 7 classes to me I think?

11:13 51.0 is the JDK7 class format iirc

11:13 justin_smith: yeah, that would be the parsimonious explanation

11:14 mikerod: So it sounds like somehow I had a com/sun/javadoc/ClassDoc compiled from Java 7 trying to run on a Java 6 JVM - ok, I think that makes sense

11:14 which would be nothing to do with Clojure :P

11:14 justin_smith: mikerod: could be a cider bug?

11:15 puredanger: you could see this if you were running java 6 vm with the java 7 jdk jar

11:16 mikerod: justin_smith: perhaps, or potentially we really just had a very mixed up machine

11:16 puredanger: that sounds like a likely candidate of what happened there I'd guess

11:16 justin_smith: oh, wow

11:16 puredanger: for reference, you shouldn't do that :)

11:16 justin_smith: haha

11:16 mikerod: Cider middleware parser does use com.sun.javadoc.ClassDoc so the pieces are fitting more together

11:16 haha

11:16 puredanger: it's ok to do the reverse though if you have the right settings :)

11:17 mikerod: yes, it does sound like a bad idea. the machine was set up incorrectly - I was just trying to make sure we didn't run into a clj incompatibility since we do intend to be moving to Java7 for this stuff in the near future.

11:17 (inc puredanger)

11:17 lazybot: ⇒ 41

11:17 puredanger: might as well move to 8 ...

11:17 mikerod: (inc justin_smith)

11:17 lazybot: ⇒ 231

11:17 mikerod: puredanger: yes I'm pushing for the jump from 6 to 8

11:17 rather than stopping at 7

11:18 puredanger: a lot of clojure stuff I run sees ~10% improvement from 7 to 8

11:18 obviously, YMMV

11:18 mikerod: Especially after hearing all about lambdas from Brian Goetz at clojure/conj :P

11:18 Java lambdas that is

11:19 puredanger: some day we'll get those in Clojure too

11:19 mikerod: any particular reasons Clojure would get a speed up from Java7?

11:20 justin_smith: mikerod: to flip that - I would be surprised if you saw any slowdown

11:20 mikerod: justin_smith: true. I'd imagine any new versions of JVM should be more perfomant

11:20 puredanger: most java releases optimize things like object allocation, locking, etc

11:20 inlining

11:20 mikerod: I know clj isn't doing anything extreme like using invokedynamic at this time though

11:20 I see

11:21 puredanger: we're going straight to invokehyperdynamic

11:21 is it still april fool's?

11:21 mikerod: haha close enough

11:46 expez: Given a file is there some easier way to check if it's present on classpath than to list all stuff on classpath and check if file is either listed itself or if a parent dir is?

11:46 justin_smith: expez: do you know the expected relative path?

11:47 expez: I actually want to get all the project's clj files, perhaps there's an easy way to do that directly

11:47 justin_smith: oh, so you want to search for all clj files on the class path?

11:47 expez: ya

11:47 but only the project's own, I don't want stuff from jars

11:47 justin_smith: expez: assumed you only want things on disk in that project

11:48 yeah

11:48 so I guess you could look for classpath entries that are directories on disk, under the project root

11:48 matthavard`: ,(range 10)

11:48 clojurebot: (0 1 2 3 4 ...)

11:48 matthavard`: Oh that's so cool

11:48 justin_smith: expez: once you filtered for those, you could do a file tree

11:49 file-seq

11:49 (doc file-seq)

11:49 clojurebot: "([dir]); A tree seq on java.io.Files"

11:50 expez: justin_smith: I guess that's the way to go. Given the dirs I can use find-clojure-sources-in-dir from tools.namespace

11:50 (inc justin_smith)

11:50 lazybot: ⇒ 232

11:50 expez: thanks! :)

11:50 justin_smith: np

12:37 tahmid: Has anyone tried material-ui for om ? (this repo https://github.com/taylorSando/om-material-ui)

12:43 dnolen: tahmid: probably a better question for #clojurescript

13:09 TimMc: ,(clojure.string/join " " "hello")

13:09 clojurebot: "h e l l o"

13:16 gfredericks: ,(clojure.string/join "hello" "hello")

13:16 clojurebot: "hhelloehellolhellolhelloo"

13:19 hyPiRion: ,(.trim (clojure.string/join "hello" " "))

13:19 clojurebot: "hello hello hello"

13:20 justin_smith: ,(clojure.string/join "hello" "")

13:20 clojurebot: "hellohellohellohellohellohellohellohellohellohellohellohellohello"

13:20 justin_smith: TEttinger2: ^

13:41 brainproxy: for new projects happy to use the latest clj alpha, is it better to get on board with the new reader conditionals or go with cljx?

14:24 noncom: how do i make cheshire generate strings like {key: value} instead of {"key": value} from my data? i.e. how to make it omit quotes from the parameter key ?

14:25 dnolen: mpenet: ping

14:27 TimMc: noncom: Like... make not-JSON?

14:28 justin_smith: noncom: yeah - see for yourself, string is required for json http://jsonlint.com/

14:28 noncom: umm probably.. ok, i know, but neo4j does not accept it like that

14:29 it wants property names without quotes

14:29 TimMc: Does it call it JSON?

14:30 noncom: no, it does not. but the only difference from json is this

14:30 mpenet: dnolen: yes?

14:31 delaney1: do we have any transit experts in the house?

14:31 noncom: so instead of writing a brand new stringifyer, i thought cheshire might do. esp that this kind of json can be *read* by cheshire

14:31 dnolen: mpenet: ready to move on ASYNC-120, I reviewed your patch, it looked OK but when applied it did not work as intended

14:31 TimMc: Oh weird, it can?

14:31 gfredericks: I'd hope not

14:31 noncom: yes, see https://github.com/dakrone/cheshire/blob/master/src/cheshire/factory.clj

14:31 dnolen: mpenet: if you set up go blocks to take from the promise chan and then supply it via >! in a later go block only one of the <! takers will be fulfilled

14:31 noncom: :allow-unquoted-field-names factory param

14:31 delaney1: i'm trying to implement a transit-c# reader, but seeing what i think is a bug in one of the examples

14:31 gfredericks: woooah

14:32 noncom: i guess cheshire only allows that coz jackson allows that

14:32 TimMc: Oh, not by default, good.

14:32 dnolen: mpenet: the tests weren't translated well enough to capture this case, I'm not yet sure of the root cause

14:32 TimMc: noncom: There's a chance there's a key encoder...

14:32 mpenet: dnolen: hmmm ok, I'll have a look when I get some time, but I am on a trip at the moment, I wont be back until wed

14:33 dnolen: feel free to take over if you find the reason behind this problem

14:34 dnolen: mpenet: however it inspired me to rip out the old hand rolled runner and rely on cljs.test testing functionality & async test support. Happy to take a rebased patch.

14:34 mpenet: noted

14:34 dnolen: mpenet: if I don't get to it before you return

14:34 noncom: hmm, yes, looks like i have to get inside the encoder..

14:35 TimMc: delaney1: Link to example in case there is a transit expert around?

14:35 gfredericks: the best kind of json is json where the object keys are serialized json objects

14:35 delaney1: TimMc: i'll make a gist, thanks

14:36 noncom: gfredericks: sure, standards are out best good, but here i just want to be able to give my objects to neo4j and writing a custom string generator for this is a little overkill :)

14:36 TimMc: {[object Object] 5}

14:36 danielglauser: gfredericks: That's awesome

14:37 justin_smith: noncom: (cheshire/generate-string {{:a 0} 0})

14:37 gfredericks: noncom: I'd say this is a lot more neo4j's fault than cheshire's fault though

14:37 justin_smith: "{\"{:a 0}\":0}"

14:37 sorry, that really wasn't directed specifically to you, noncom

14:37 TimMc: noncom: http://jackson.codehaus.org/1.1.2/javadoc/org/codehaus/jackson/JsonGenerator.Feature.html#QUOTE_FIELD_NAMES

14:38 If you want to use Jackson directly.

14:38 Maybe cheshire supports that option though, or maybe it can pass through options?

14:39 noncom: TimMc: thanks for the hints, i will check this out!

14:41 TimMc: Although the phrasing "want to use Jackson directly" waas a little hard for me to type out.

14:43 noncom: yeah :D

14:43 maybe i'll just patch cheshire if i won't find another way around

14:43 delaney1: lol, in writing the gists i reread the spec ~ "if they are longer than 3 characters cache it"

14:55 TimMc: good ol' SSCCE

15:17 zanes: What would be the most idiomatic way to apply two transducer pipelines in parallel to an input, merging the results?

15:28 puredanger: the map transducer can read two inputs

15:28 that's the only one atm

15:31 gfredericks: puredanger: I'm apparently too timid to say this on the ML but the iterate thing Bronsa was bringing up feels pretty gross to me

15:31 unless it's well documented

15:31 puredanger: you mean the reduce caching aspect?

15:31 gfredericks: yeah

15:32 he brought up perf but I'm thinking functions with side effects

15:32 Bronsa: gfredericks: iterate's doc explicitly says f should be side-effect free, though

15:32 puredanger: iterate specifically says in the docstring that the f must not have side effects

15:32 gfredericks: the old docstring says that?

15:32 puredanger: yes

15:32 gfredericks: then maybe the answer is just to take that seriously I guess :)

15:33 okay I don't mind as much then

15:33 Bronsa: I still don't think the new impl is a good idea :)

15:33 gfredericks: Bronsa: just because of potential slowdown?

15:33 Bronsa: yes

15:33 puredanger: seqs cache. if you want caching, use seqs.

15:34 the new version is faster for that too.

15:34 Bronsa: puredanger: iterate's docstring says "returns a lazy sequence"

15:34 puredanger: it is a lazy sequence

15:34 it is also reducible NOT as a lazy sequence

15:34 gfredericks: hmm

15:34 Bronsa: it's a sequence and a generator

15:34 depending on how you use it

15:34 puredanger: yes

15:34 Bronsa: it's obviously not a sequence when you reduce it

15:34 we should document it

15:35 gfredericks: ^ that part bothers me just for being complicated to understand

15:35 puredanger: either path must produce the same values (if f does not have side effects)

15:35 Bronsa: I'd rather have it reverted, but if that's out of the question we should at least make it clear how it will behave

15:36 puredanger: I'll admit my ignorance, but no side effects === pure?

15:37 i.e. is `rand` considered side-effecty?

15:37 puredanger: well, I'm using them to mean the same thing, but I'm sure some smarter person than me has a distinction

15:37 rand *is* side effecty

15:37 amalloy: Bronsa: "side effects" and "pure" are both vague words; in some contexts they include rand, and in others they don't

15:37 puredanger: I think maybe it would be better to say "deterministic"

15:37 gfredericks: what about (let [r (java.util.Random. 42)] #(.nextLong r))

15:37 puredanger: same inputs = same outputs

15:37 amalloy: puredanger: no, that's super wrong

15:37 justin_smith: puredanger: see gfredericks' talk at clojure/west for a non-side-effecty rand I think

15:38 gfredericks: oh crap I just got cited

15:38 puredanger: pre-cited even

15:38 justin_smith: pre-cited

15:38 ntaylor: and now he's ex-cited!

15:38 * ntaylor shows himself out

15:38 Bronsa: puredanger: the new version of iterate is probably faster for seqs b/c it doesn't guarantee once only computation like LazySeq does

15:38 I don't like that either :P

15:39 puredanger: yes, that's exactly the point

15:39 justin_smith: Bronsa: seems like there are a few things in clojure that say "no side effects please" but in practice we use as if side effects were OK

15:39 and maybe those chickens are coming home to roost

15:39 gfredericks: yeah that's what I meant about taking it seriously

15:40 Bronsa: justin_smith: my complaints have little to do with side-effects, much more with predictable performances

15:40 puredanger: I spent a few hours looking through oss for places where someone had violated that instruction and I don't recall finding one

15:40 Bronsa: it is predictable. it's just different.

15:40 Bronsa: I always assumed functions returning lazy seqs guaranteed caching & once-only computation

15:40 not the case anymore

15:40 puredanger: they do, when used as a seq

15:40 gfredericks: passing something to reduce is something you can do with a seq

15:41 Bronsa: puredanger: not if the seq is realized in two different threads at the same time

15:41 puredanger: it's not synchronized

15:41 puredanger: this is not feasible in all cases, just these specific functions which generate the identical sequence of values every time

15:41 Bronsa: but the same values will be generated

15:42 this is the same technique used lazily cache hash codes once computed

15:42 TimMc: Throwing an exception is also a side-effect by some definitions.

15:43 puredanger: cycle, repeat, and range (fudging promotion cases) never throw exceptions

15:43 iterate can, but that is handled in the ticket CLJ-1692

15:44 gfredericks: cycle could throw an exception while realizing a lazy seq :)

15:44 puredanger: hmmm

15:44 gfredericks: ,(cycle (map #(/ 42 %) [2 1 0]))

15:44 clojurebot: #<ArithmeticException java.lang.ArithmeticException: Divide by zero>

15:45 gfredericks: would have to examine the stack trace to verify

15:45 solussd: What’s the recommended way to rcreate a test.check generator from a generator that will have duplicates?

15:45 gfredericks: solussd: to dedupe it you mean?

15:45 solussd: yes

15:45 gfredericks: solussd: what sort of thing are you trying to generate?

15:45 solussd: strings, but the system I’m testing does a uniqueness check

15:45 gfredericks: like ids?

15:46 solussd: unique names, so, yeah, like ids

15:46 puredanger: (take 2 (cycle (map #(/ 42 %) [2 1 0]))) indeed is this problem

15:46 gfredericks: solussd: it bugs me that there seems to be no foolproof way to provide that, but there's a few less-than-ideal tactics

15:47 certainly you can fmap with distinct

15:47 puredanger: with the obvious memory impact :)

15:48 gfredericks: now that I think about it maybe this could be done in a not-terrible way

15:48 shrinking is the sticky part

15:49 solussd: fmap with distinct would just generate strings without duplicate characters, right?

15:49 gfredericks: oh I mean generating a whole collection

15:49 (gen/fmap distinct (gen/vector my-string-generator))

15:49 solussd: gotcha

15:49 ambrosebs: puredanger: what difference does it make if eduction is no Seqable?

15:50 maybe I'll keep reading this email chain first.

15:50 ;)

15:51 lexi-lambda: Is there a clean way to map over every other element of a collection?

15:51 gfredericks: puredanger: thanks for backandforthing

15:51 partition can help

15:51 lexi-lambda: I.e., I want the result to contain all elements, but I only want the mapping fn to be applied to the even elements.

15:51 puredanger: ambrosebs: not much given that seq will wrap an Iterable

15:51 lexi-lambda: take-nth ?

15:52 ambrosebs: puredanger: is there a conceptual reason?

15:52 justin_smith: ,(mapcat (fn [[x y]] [(inc x) y]) (partition 2 (range))) ; lexi-lambda

15:52 clojurebot: (1 1 3 3 5 ...)

15:52 puredanger: ambrosebs: sorry, reason for what?

15:52 amalloy: justin_smith: careful. what if the coll has 9 elements?

15:52 ambrosebs: puredanger: why is eduction no longer Seqable?

15:52 puredanger: oh, there was just no reason for it to be

15:52 justin_smith: amalloy: good point, that makes the answer trickier

15:53 amalloy: justin_smith: map-indexed

15:53 lexi-lambda: this works, but I'd be curious if there were a nicer way to do it with built-in constructs http://stackoverflow.com/a/10326400/465378

15:54 amalloy: lexi-lambda: not really. that's how i'd write it

15:54 lexi-lambda: Alright, thanks.

15:55 amalloy: though in my many years of clojure i have never had a need for map-nth. i have trouble imagining scenarios where i'd have data in a shape that needs to be map-nth'd

15:56 justin_smith: amalloy: what if every 1000000th visitor to your site should get a free ipad?

15:56 amalloy: justin_smith: joke acknowledged

15:57 ambrosebs: puredanger: any other new data structures where similar decisions have been made?

15:57 amalloy: but seriously, map-nth still doesn't make sense there. i'd want a list of all the winners, not a list of all the guests where the millionth one has some extra data

15:57 puredanger: ambrosebs: repeat,cycle,iterate changed in alpha6. range is coming (CLJ-1515) but varies slightly b/c range is chunked where the others were not.

15:58 ambrosebs: puredanger: these are all Seqable though?

15:58 puredanger: oh, they *are* seqs

15:59 the extend ASeq

15:59 so they are also Seqable by returning this

16:00 ambrosebs: keys/vals both changed somewhat as well but they only committed to returning Seqable before and still do, but also happen to be IReduceInit now

16:00 really, all of repeat,cycle,iterate (and other seq functions as well) should preferably only commit to returning a Seqable, not a seq. but there's too much of an existing expectation to rely on that

16:01 ambrosebs: puredanger: well at least an IPersistentCOllection I hope

16:01 puredanger: ideally those functions could have done like keys/vals and just returned something that is Seqable/IReduceInit

16:02 they are, but that's what I'm saying I wish they weren't

16:03 too likely to break existing code if we changed that

16:04 every flavor of this has been tried on 1603 or 1515 - tons of patches there trying different things. I feel like I've spent a ridiculous amount of time on just counting with range :)

16:04 ambrosebs: puredanger: ok I'm kind of following.

16:04 gfredericks: it seems like making things try to be collection-like and special-reducible-like gets messy

16:04 ambrosebs: puredanger: I immediately thought of using coll? to check if something is immutable.

16:04 puredanger: yeah, tons of things like that

16:04 or seq?

16:04 * puredanger used in a branch on a condition

16:05 puredanger: who knows what we'd break if we made the results seqable but not seqs

16:06 there are a couple patches (referred to as the "split" impl where I tried this) that allow LazySeq to be created with a second function implementing reduce

16:06 making this a capability that others could use

16:06 but that's pretty dangerous without understanding all the cache tradeoffs and expectations

16:07 ambrosebs: this is interesting. we probably can't break this at runtime but I could assign less specific static types to sequence functions in core.typed to reflect what could have been.

16:07 I thought the contract of seq was returns nil or Seq.

16:07 ISeq

16:07 puredanger: that seems right

16:07 ambrosebs: but in a perfect world it's nil or Seqable?

16:08 puredanger: no, I'm saying functions like map, filter, etc should take a seqable and return a seqable

16:08 ambrosebs: aha

16:08 puredanger: right now they actually return a seq, which people have come to rely on

16:08 no takebacks! :)

16:08 amalloy: funnily, usually when people say they want map to take a seqable and return a seqable, they mean they want map on a vector to return a vector

16:09 puredanger: a vector is a perfectly good seqable :)

16:09 ambrosebs: puredanger: so I should rely on map returning an *immutable* seqable?

16:09 puredanger: but I think that desire is wanting even more :) (which you can get with transducers of course)

16:10 seqable is describing potential. I don't know what a mutable or immutable seqable would be

16:10 sequences should always be immutable

16:11 ambrosebs: so map could return a mutable structure?

16:11 theoretically :)

16:11 ie. something that returned a different value for first

16:12 puredanger: once you obtain a sequence from it, I would expect it to always be the same

16:12 ambrosebs: ah so (seq (map ...)) is immutable but (map ...) is fair game?

16:12 puredanger: once you open that box with the cat, you'll know whether it's angry

16:12 or dead

16:13 well trying to be careful here about what expectations are now and what they might theoretically have been if we started over designing Clojure knowing what we know now...

16:14 right now, I would say the expectation is that map returns a sequence, which is immutable

16:14 theoretically, it could have committed only to return a seqable, that when poked will yield a sequence, which is immutable

16:16 amalloy: i feel like there's a lot of code that depends on seqable things returning the same thing when seq'd twice. like, (let [xs (map whatever ys)] (if (empty? xs) "empty :(" (first xs)))

16:17 puredanger: absolutely

16:18 and that should always work

16:18 but what if xs was an object that only realized itself at the first point when you asked it for a value?

16:19 I'm not saying at all that we are or will change anything about this

16:19 purely in thought experiment land here

16:19 look at LazySeq for example

16:20 it does exactly this kind of thing. when you ask for a seq, it synchronizes and builds it

16:21 Bronsa: puredanger: I reopened CLJ-1694, you just used a bad example

16:24 puredanger: thx

16:33 ambrosebs: puredanger: ah I meant map returns an observationally immutable thing wtr first/next.

16:33 which sounds like what you just described.

16:33 puredanger: yes

17:01 bacon1989: so is there a single statement equivalent to (not (nil? <expression>)) with a single form?

17:01 like not-nil?

17:02 i've been using it constantly, I feel like there should be a function for this already

17:02 amalloy: bacon1989: in 1.6+ there's some?

17:03 bacon1989: amalloy: but doesn't that take a container?

17:03 amalloy: some?, not some

17:03 bacon1989: ,(some? nil)

17:03 clojurebot: false

17:04 bacon1989: ,(some? "value")

17:04 clojurebot: true

17:04 bacon1989: ,(some? [1 2 3])

17:04 clojurebot: true

17:04 bacon1989: ,(some? [])

17:04 devn: hello friends and uncles

17:04 clojurebot: true

17:04 bacon1989: interesting

17:04 justin_smith: devn: hello

17:05 bacon1989: that should work, thank you amalloy

17:05 i

17:05 i'm confused by the name though

17:05 justin_smith: bacon1989: some as opposed to none?

17:06 bacon1989: looking at it that way makes sense, but there's a nil? function, not-nil?

17:06 justin_smith: sure, (complement nil?)

17:06 ambrosebs: ,not-nil?

17:06 clojurebot: #error{:cause "Unable to resolve symbol: not-nil? in this context", :via [{:type clojure.lang.Compiler$CompilerException, :message "java.lang.RuntimeException: Unable to resolve symbol: not-nil? in this context, compiling:(NO_SOURCE_PATH:0:0)", :at [clojure.lang.Compiler analyze "Compiler.java" 6535]} {:type java.lang.RuntimeException, :message "Unable to resolve symbol: not-nil? in this context",...

17:06 bacon1989: i'm just being picky

17:07 justin_smith: ,(map (complement nil?) [:a [] () nil false])

17:07 clojurebot: (true true true false true)

17:07 bacon1989: some? is fine, but it's not the first thing I think of, when i'm looking for the complement of nil?

17:07 ambrosebs: it's like an option type on something being a reference

17:07 bacon1989: justin_smith: in that case, i'm better off just sticking with (not (nil? <expr>))

17:07 but some? appears to be a replacement

17:08 justin_smith: bacon1989: well, complement returns a function, is the difference

17:08 bacon1989: oh right

17:31 lalaland1125: Hi. I am trying to turn a persistent hashmap into a persistent array map. This is my current attempt "(print (type (apply array-map (flatten (seq {1 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 1})))))"

17:31 Is this incorrect?

17:31 It doesn't appear to work right in clojurescript.

17:32 justin_smith: lalaland1125: why do you care whether you have a persistent hashmap vs. persistent array map?

17:32 as far as I know, array maps above a certain size are always auto-promoted to hash-map

17:32 lalaland1125: I am trying to hot fix a library bug.

17:33 The library itself has to be changed to work with hash maps, but a simple fix should put that off.

17:34 gfredericks: yeah looks like cljs doesn't let you do this the way clj does

17:34 I feel like I pointed this out to david a year ago or something

17:35 justin_smith: gfredericks: can you make an arbitrary sized array-map in clj?

17:35 gfredericks: totes

17:35 just call array-map

17:35 ,(type (apply array-map (range 100000)))

17:35 it's greek to me

17:35 clojurebot: eval service is offline

17:35 gfredericks: &(type (apply array-map (range 1000)))

17:35 lazybot: ⇒ clojure.lang.PersistentArrayMap

17:35 gfredericks: anyhow there's one with 500 at least

17:36 lalaland1125: So its probably a clojurescript bug.

17:36 gfredericks: I dunno david might disagree

17:36 justin_smith: lalaland1125: a minor thing - (apply concat {1 2}) is much better than (flatten (seq {1 2}))

17:36 gfredericks: lalaland1125: what is the problem you're trying to hot fix?

17:36 justin_smith: because flatten can destroy your data (or cause an odd number of args)

17:36 lalaland1125: https://github.com/juxt/bidi/issues/55

17:39 justin_smith: lalaland1125: why not fork the lib and put the proper protocol in there instead of the concrete type? https://github.com/juxt/bidi/blob/master/src/bidi/bidi.cljx#L251

17:40 gfredericks: lalaland1125: so the problem is that the protocol isn't implemented for hash-map? why not just do that?

17:40 justin_smith: oh yeah, you can extend that from outside bidi

17:40 d'oh

17:40 (inc gfredericks)

17:40 lazybot: ⇒ 132

17:41 justin_smith: ILookup or maybe IAssociative or IMap

17:41 gfredericks: uh

17:41 justin_smith: https://github.com/clojure/clojurescript/blob/master/src/cljs/cljs/core.cljs#L391

17:41 gfredericks: no you'd do the concrete class right?

17:42 I don't think you're supposed to extend protocols to protocols

17:42 justin_smith: gfredericks: oh, is this extending a protocol to a protocol issue?

17:42 yeah

17:42 right, I keep forgetting that

17:47 lalaland1125: gfredericks, Your solution worked very well. I am new to clojure and didn't know that you could do that sort of thing outside of the implementing class.

17:49 justin_smith: lalaland1125: yeah, you don't have to "own" the protocol or the class you are extending it to in clojure. Which would be insane in an OO situation. But hey Madness? THIS IS FPP.

17:50 mix that with mutation and enough magic and things can still get weird though, of course

18:18 lewix: hello guys

18:18 justin_smith: ello, you lost your L

18:18 lewix: how does clojurescript compare to typescript

18:18 expez: favorably

18:19 lewix: @justin_smith, im on my phone ^^

18:19 yally04: Hi all, how would you partition a seq by groups of two values? e.g. [3 4 5 6 7 8] becomes ([3 4] [4 5] [5 6] [6 7])

18:19 lewix: expez: the talk of the town is all a out typescript

18:19 yally04: It's been way too long since I've written any Clojure and I know this should be very simple!

18:20 justin_smith: ,(partition 2 1 [3 4 5 6 7 8 'yally04])

18:20 clojurebot: ((3 4) (4 5) (5 6) (6 7) (7 8) ...)

18:20 yally04: oh man, of course ...

18:20 forgot that partition had that option.

18:20 thank you!

18:20 lewix: about*

18:20 justin_smith: np

18:21 lewix: justin: how would you partition it with map

18:21 justin_smith: with map?

18:21 lewix: justin: yup basically reinventing the wheel

18:22 amalloy: (map list xs (rest xs))

18:22 justin_smith: yup, that's the one

18:25 lewix: amalloy: xs (rest xs)?

18:25 justin_smith: ,(let [xs [1 2 3 4 5]] (map list xs (rest xs)))

18:25 clojurebot: ((1 2) (2 3) (3 4) (4 5))

18:26 justin_smith: xs is a common name for more than one x in the haskell / ml world

18:26 lewix: justin can you explain the map function

18:26 justin_smith: like what it does in general, or what it did that?

18:27 lewix: i dont understand the logic

18:27 justin_smith: it takes list, and applies list to one element from xs and one element from (rest xs)

18:31 then it does the same thing, from the next element of each

18:31 raspasov: lewix: here

18:31 ,(map list [1 2 3] [4 5 6])

18:31 clojurebot: ((1 4) (2 5) (3 6))

18:31 raspasov: you're "mapp-ing" list to first element of each collection, then to second elements of each collection, etc

18:31 lewix: dope. amalloy: how did you think about it so fast?

18:31 raspasppv: thanks

18:31 justin: thanks

18:31 amalloy: lewix: it's a very common trick

18:32 lewix: thanks guys

18:48 justin_smith: in case anyone was curious, XP table for programmers http://jimkang.com/namedlevels/#/class/programmer

19:15 mfikes: gfredericks: FWIW David fixed array-map http://dev.clojure.org/jira/browse/CLJS-1189

19:18 justin_smith: nice

19:26 andy___: Is there a reason (reverse ...) isn't also a transducer?

19:29 justin_smith: andy___: it needs to create a sequence of the entire input, so transducing would not really help

19:30 andy___: I know it needs to buffer, but so does --for instance-- partition-by

19:30 justin_smith: andy___: but it needs to buffer the entire input, at which point being a transducer has zero benefit

19:31 I mean, I could imagine an implementation that called rseq on vectors and walked arrays backwards, but we don't even have a non-transducer version of that reverse

19:31 andy___: but what if I want to use it for the sake of composability?

19:32 justin_smith: functions are composible, the only reason transducers are better is they avoid extra unneeded work, with reverse you cannot avoid that work

19:33 andy___: hmm I see, I guess it'd be a tough sale since transducers also also supposed to all work with core.async

19:33 and in that case it would just wait until that channel closes

19:33 justin_smith: right - that would kind of suck

19:34 catern: dear clojurists

19:34 andy___: alright, fair enough. :)

19:34 catern: if I wanted to convert this object into a clojure map, how would I go about that? http://libvirt.org/sources/java/javadoc/org/libvirt/DomainInfo.html

19:34 justin_smith: catern: have you tried bean?

19:35 ,(bean (java.util.Date.))

19:35 clojurebot: #error{:cause "denied", :via [{:type java.lang.ExceptionInInitializerError, :message nil, :at [java.lang.reflect.Proxy$ProxyClassFactory apply "Proxy.java" 672]} {:type java.lang.SecurityException, :message "denied", :at [clojurebot.sandbox$enable_security_manager$fn__835 invoke "sandbox.clj" 69]}], :trace [[clojurebot.sandbox$enable_security_manager$fn__835 invoke "sandbox.clj" 69] [clojurebot.sa...

19:35 justin_smith: err...

19:35 that usually works :)

19:35 catern: I found http://stackoverflow.com/questions/7916199/use-java-object-as-clojure-map which suggested bean, but it just returns {:class org.libvirt.DomainInfo}

19:35 amalloy: justin_smith: this thing doesn't have getters, it has public fields

19:36 justin_smith: ahh

19:36 catern: i don't know much about Java so even obvious suggestions are helpful

19:37 noonian: just to clarify, you want to be able to use an instance of a DomainInfo as a map? or represent the same data as a map?

19:37 justin_smith: for that few fields you could do it by hand, and look for something more automated if you need to do it for a bunch more classes

19:37 catern: noonian: yes, or something like that.

19:38 justin_smith: catern: noonian offered two options

19:38 catern: justin_smith: there's a bunch of these kinds of objects in the libvirt Java API

19:38 justin_smith: either of those options is acceptable

19:38 justin_smith: Ahh, yeah. I have seen reflection based macros to automate such things.

19:39 andy___: catern: Check out https://github.com/zcaudate 's libraries. They do a bunch of java interop. Maybe you can find something there

19:49 catern: justin_smith: what kind of approach could I take there? (.getFields (class info)) and.. then what?

19:52 justin_smith: catern: a macro could turn a collection of fields to a call to hash-map with keywords named after those fields mapped to their values

19:52 if the fields of the class are knowable at compile time, of course

19:54 noonian: hmm, that class looks like it will be mutating constantly though

19:54 cputime - the CPU time used in nanoseconds

19:55 so that approach would only give you the values when the map is created

19:55 catern: noonian: true

19:55 noonian: fortunately in practice actually no, it seems to be immutable

19:55 (i.e. once I get it, it doesn't change)

19:56 noonian: if that's the case then what justin_smith is describing is probably the way to go

19:59 catern: what if instead I

19:59 did

20:00 (let [fields (.getFields (class info))] (map (fn [field] [(str field) (.get field info)]) fields))

20:01 (into {} that)

20:02 how awful is that

20:02 too awful?

20:02 noonian: not too awful if it works :P

20:03 catern: but that's heavily abusing reflection

20:03 which is bad for performance

20:03 innit

20:03 noonian: could do a camelCase to kebab-case conversion and turn the keys into keywords if you wanted the maps to follow clojure idioms

20:03 yeah, but depending on what you are trying to do it might not matter

20:03 catern: yeah, something like that (rather than (str field))

20:04 er

20:04 rather than (str field)*

20:05 yeah, (.getName field) instead

20:10 raspasov: catern: I don't know the library internals very well, but I believe Amazonica does a very neat two way conversion between Java <-> Clojure

20:10 with the Amazon Java Library

20:10 might be helpful to look at, not sure

20:19 noonian: heres my quick attempt: https://www.refheap.com/99213

20:53 catern: for adding a bunch of new key-value pairs to a map, I should use assoc, right?

20:53 just checking

20:57 also!

20:57 how best to work with XML in Clojure?

20:57 this thing? https://github.com/clojure/data.xml

20:58 skelternet: What are you going to do with the XML?

20:59 catern: look through it for a specific field (or whatever it's called, <tag>the thing in here</tag>) and use the value inside

21:00 (among other read-only things, possibly. no generation)

21:00 skelternet: will the target tag always be in the same place in the hierarchy?

21:01 is the xml small?

21:02 catern: the xml is small

21:03 skelternet: You'll find a lot of choices. I asked about the size because sometimes XML sources are too large to want to load up as a dom.

21:03 catern: the target tag will always be in the same place hierarchy (if I understand what you mean. I could always use the same xpath expression)

21:03 same place in the hierarchy*

21:05 skelternet: It has been a while. I'd try it with data.xml

21:06 that should get you a clojure data structure from the xml

21:07 ugh…I remember doing this now

21:07 It's version of the datastructure was verbose

21:07 catern: ewwwww

21:08 {:tag foo :attrs [foo bar] :content "quux"}

21:08 that's pretty terrible

21:08 skelternet: let me look for what I ended up using

21:08 catern: would be appreciated

21:08 skelternet: it may have been a zipper

21:10 http://clojure.github.io/data.zip/#toc0

21:11 Yes…this is what I ended up using.

21:12 I had to scrounge for useful examples, and this was a a year ago or more.

21:12 I'd hope there was a better library or better examples.

21:12 catern: ehhhhhh

21:12 http://stackoverflow.com/questions/11215040/available-clojure-xml-parsing-libraries-that-complement-clojure-xml-parse

21:12 this answer is pretty true

21:12 skelternet: Once I had the zipper, I could use tags as the predicates

21:12 catern: I'll just transform this nested thing

21:13 alternatively, I could just use xpath

21:14 skelternet: I like that better than the zipper, I think

21:14 catern: which one?

21:14 the stackoverflow or the xpath?

21:14 skelternet: I think I used something like

21:15 (xml-> myxmlzip :outtertag :midtag :innertag text=)

21:15 I like the stackoverflow idea

21:16 seems like it should be a standard part of the xml library though, as frequently as we'd use it

21:19 amalloy: skelternet: and what if the xml looks like <outertag><midtag>...</midtag><midtag>...</midtag></outertag>?

21:20 the standard xml interface can't really be to treat them like maps, because they can encode structure that isn't mappy

21:21 skelternet: I'm thinking back to that session with the zipper.

21:22 Quick googling…

21:22 catern: okay

21:22 skelternet: Do we stil have xml-seq?

21:22 catern: I'm pretty sure that The Right Way is xpath

21:23 skelternet: http://blog.korny.info/2014/03/08/xml-for-fun-and-profit.html

21:23 catern: a nice, simple, standard, declarative way to navigate XML

21:24 skelternet: amalloy, I think that if you need all of them, then xml-> otherwise xml1->.

21:25 xml-> returns a sequence of the results of the predicates. Since :outertag :midtag text= can be applied to multiple nodes, I'd expect a sequence of the text of midtags

21:26 I remember thinking at the time I should right a library for the common task of tweaking xml files.

21:26 I was tweaking poms then.

21:27 right/write

21:29 catern, are you just extracting the value and using it, or are you changing the value and hoping to write it out?

21:31 https://github.com/kyleburton/clj-xpath

21:35 catern: skelternet: just extracting

21:35 indeed, I am using that library right now

21:35 and have solved my problem with it :D

21:35 :)

21:36 skelternet: you kids these days…with your libraries and your xpath...

21:36 what did the code end up looking like?

21:37 catern: http://ix.io/hiC

21:43 skelternet: doesn't seem terrible

21:43 I remember having to review xpath then, too.

21:43 Thanks!

21:46 the memories…

21:51 guthur: i have a key value list (:foo 1 :bar 2), what is the idomatic way of extracting values from this

21:51 skelternet: vals ?

21:52 '(vals {:foo 1 :bar 2})

21:52 ,(vals {:foo 1 , :bar 2})

21:52 clojurebot: (1 2)

21:52 guthur: but it's a list not a map

21:52 skelternet: ohhh

21:53 ,(into {} '(:foo 1 :bar 2))

21:53 clojurebot: #error{:cause "Don't know how to create ISeq from: clojure.lang.Keyword", :via [{:type java.lang.IllegalArgumentException, :message "Don't know how to create ISeq from: clojure.lang.Keyword", :at [clojure.lang.RT seqFrom "RT.java" 506]}], :trace [[clojure.lang.RT seqFrom "RT.java" 506] [clojure.lang.RT seq "RT.java" 487] [clojure.lang.ATransientMap conj "ATransientMap.java" 42] [clojure.lang.ATran...

21:54 skelternet: checking my cheatsheet…seems like I've seen that before and it seemed obvious after I saw it.

21:56 catern: is ring/compojure/hiccup still my best bet for a simple web application?

21:56 or, let me put this another way

21:56 skelternet: ,(hash-map '(:foo 1 :bar 2))

21:56 clojurebot: #error{:cause "No value supplied for key: (:foo 1 :bar 2)", :via [{:type java.lang.IllegalArgumentException, :message "No value supplied for key: (:foo 1 :bar 2)", :at [clojure.lang.PersistentHashMap create "PersistentHashMap.java" 77]}], :trace [[clojure.lang.PersistentHashMap create "PersistentHashMap.java" 77] [clojure.core$hash_map doInvoke "core.clj" 369] [clojure.lang.RestFn invoke "RestFn.j...

21:56 catern: what's the absolute simplest way I can start serving a map over the web?

21:56 skelternet: ,(apply hash-map '(:foo 1 :bar 2))

21:56 clojurebot: {:bar 2, :foo 1}

21:58 skelternet: Will that get you there, guthar?

21:58 guthur: skelternet: yeah that looks good, cheers

22:00 skelternet: catern I think ring/compojure is the quickest I can think of for just that, given no need for REST or anything else.

22:39 catern: i'm so lazy

22:39 i'd rather just convert a map directly into HTML

22:39 * arrubin was hoping for a FP joke.

22:39 catern: like, a list of maps into a table

22:39 ugh I wrote a function to do this before

22:40 now I have to write it again (because I can't find my earlier attempt)

22:40 lame

22:41 alternatively

22:41 i'll use something to convert to json

22:42 er, an actual question instead of complaints:

22:43 if one tries for a client-side web application, and serves up a bunch of stuff as JSON that is then rendered by Javascript on the front end, is it possible/natural to have this be a traditional multiple-page application or are you pretty much stuck with the single page app?

22:44 (I don't really know anything about web development)

22:49 (that's not actually a Clojure question though)

22:59 nuwanda_: catern: I don't see why you would be limited to a certain architecture just based on that description

22:59 catern: OK

22:59 and, another question

22:59 I knew this at some point

23:00 but I've forgotten it :(

23:00 How should I run a Ring server while developing, so I can keep restarting it as I make changes to my application?

23:00 It seems to background by default and keep the port bound... so I have to M-x cider-restart

23:03 tolstoy: catern: For what it's worth, I don't use "lein ring" and so on. I just use a function that starts the server and eval that in the repl.

23:03 Using http-kit, or jetty-runner, or aleph or something.

23:03 catern: tolstoy: yeah? I had the same thing, but when I interrupt it, it doesn't seem to actually stop the server.

23:04 tolstoy: How are you interrupting it?

23:04 catern: unless this function has the autoreload stuff

23:04 C-c C-c

23:05 tolstoy: I just re-evaluate routes and so on, though it's tricky if the handler isn't always re-evaluated each time a request comes in.

23:05 For instance (run-server (fn [r] (my-routes r)) {:port 8001}) or something like that seems to work.

23:06 Then you can re-compile my-routes with C-c C-c and have the new functionality take effect without restarting the server.

23:06 Does any of that make sense?

23:09 catern: I mean, I'm specifcally using ring/run-jetty

23:10 tolstoy: You have to, uh, (.close) it, I think?

23:12 Oh, (.stop server).

23:15 mgaare: Also, pass your handler to jetty symbol-quoted

23:28 tolstoy: I seem to have an issue with that in that I pass in deps through there: (make-app db other-thing whatever) which then returns a handler that takes those as params.

Logging service provided by n01se.net