#clojure log - Oct 11 2015

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

3:59 Seylerius: I'm trying to use org-babel with clojure, and nrepl is returning (when I example *nrepl messages*) "namespace not found" with each attempt to execute something.

4:47 noncom|2: why specifying explicit ObjectId in monger upon a document creation is "recommended" ?

4:47 (ctrl+f "(recommended)" here http://clojuremongodb.info/articles/getting_started.html )

4:48 ddellacosta: hi! ever worked with monger ?

4:54 Seylerius: Okay, clj-barcode (a clojure port of barbecue) seems to crash my repl regularly.

6:15 crocket: Is (go) similar to go's concurrency model?

6:15 go-lang

6:26 Empperi: yes, the basic idea of channels etc was taken from Go as far as I remember

6:31 crocket: coroutine?

6:31 Empperi, ^^

6:54 hellofunk: crocket: both go and core.async are implementations of much much older ideas in CSP

7:00 crocket: hellofunk, What do you mean by go?

7:00 There is core.async/go

7:06 hellofunk: crocket: the go language

7:09 crocket: I'm not sure if core.async/go is a coroutine.

8:54 ane: no, but it's CSP

8:55 just like go channels are CSP

8:58 sobel: what's the salient diff between csp and coroutines?

9:09 ane: they're completely different ideas

9:10 csp is about channels, sharing by communication, coroutines are more or less python's 'yield' keyword

9:10 jsabeaudry: For people hosting their apps on heroku, where do you host your datomic db?

9:11 ane: (Go's goroutine's aren't coroutines)

10:42 luxbock: Pulsar (https://github.com/puniverse/pulsar/) provides coroutines for Clojure

10:43 it uses this: http://www.matthiasmann.de/content/view/24/26/ under the hoods

12:09 vise890: hi all. i'm trying to make a small proxy with compojure. when the host i'm redirecting traffic to puts the header "Transfer-encoding=chunked", the browser consuming the proxy hangs. This is what I have: https://github.com/vise890/dropwiki/blob/add_backend_proxy_to_figwheel/frontend/src/frontend/server.clj#L20

13:49 ben99: hello

13:50 I have a ring webapp. running it with lein run works fine, but with the uberjar I get

13:50 Error: A JNI error has occurred, please check your installation and try again

13:50 Exception in thread "main" java.lang.NoClassDefFoundError: clojure/lang/IFn

13:50 ...Caused by: java.lang.ClassNotFoundException: clojure.lang.IFn

13:51 rhg135: is clojure actually on the classpath?

13:52 ben99: thx, checking.. does lein find the cp itself?

13:52 rhg135: actually... this sounds like the wrong order

13:52 it does. hmm

13:53 ben99: can I use something like trampoline ?

13:53 I basically just want to run the lein project as a daemon, e..g through upstart

13:53 rhg135: seems a native dep is getting loaded before clojure

13:53 ben99: instead of worrying about jars and cp's

13:54 i.e. I have the git repo on a server and want to run that

13:54 rhg135: you'll still have to

13:55 I'd make an uberjar, and just run that

13:55 ben99: yes, that's what I'm trying.. I haven't see this error before

13:56 rhg135: neither have I

13:57 ben99: perhaps some of the depenencies have JNI

13:57 thx for the help

13:57 rhg135: np

14:01 ben99: any idea to avoid making jars?

14:01 seems very time consuming

14:04 rhg135: It's rather complex, but you can get the classpath from `lein cp` and pass it manually

14:05 ben99: ok. because I saw an upstart script which just does exec lein

14:05 not sure whether that's a good idea

14:06 rhg135: if it is lein trampoline sure

14:34 LuckWins: hey

15:55 Seylerius: So, clj-barcode seems to crash my repl on the regular.

15:55 I've tried it in Gorilla-REPL, I've tried it in org-babel through nrepl, but it crashes.

15:56 justin_smith: Seylerius: is it using native code or something?

15:56 Seylerius: Don't think so. It's a thin wrapper around Barbecue.

15:57 justin_smith: Seylerius: does "crashes" mean the jvm exits, or just that you get a stack trace and your program is interrupted?

15:59 ben99 is gone now, but that specific error means he is not using the right jar - when you use the uberjar it creates two jars, one that is only your project, one that is actually uber, and running the one that is just your project gets that error ( rhg135 FYI )

15:59 Seylerius: JVM itself goes down.

16:00 rhg135: ah, thanks

16:00 justin_smith: Seylerius: that means either a jvm bug or native code, usually

16:02 Seylerius: justin_smith: I'll investigate Apache Barbecue, then, because that must be where the native code, if any, lives.

16:06 justin_smith: Seylerius: here's the pom file for barbecue 1.5-beta1 if that helps - I don't see anything suspicious in the deps list

16:06 http://central.maven.org/maven2/net/sourceforge/barbecue/barbecue/1.5-beta1/barbecue-1.5-beta1.pom

17:29 is there a cheaper way to detect if the string created from a given object would be over a certain size?

17:30 I don't actually care what the string is (the object is in fact being encoded by another library), but if it is above a certain size, I want it to be split and encoded in parts.

17:31 by "cheaper" I of course mean "cheaper than just generating the (perhaps huge) string"

17:45 hmm... maybe a walk/post-walk which cumulatively counts the size of leaves as strings returning early if some threshold is crossed...

17:54 ,(defn small-enough? [limit input] (reduce (fn [total el] (if (> total limit) (reduced false) (+ total (count (str el))))) 0 (remove coll? (tree-seq coll? seq input)))) ; bingo!

17:54 clojurebot: #'sandbox/small-enough?

17:54 justin_smith: ,(small-enough? 12 "HELLO, WORLD!")

17:54 clojurebot: 13

17:54 justin_smith: hrm...

17:56 ,(defn small-enough? [limit input] (reduce (fn [total el] (let [result (+ total (count (pr-str el)))] (if (> result limit) (reduced false) result))) 0 (remove coll? (tree-seq coll? seq input))))

17:56 clojurebot: #'sandbox/small-enough?

17:57 justin_smith: ,(small-enough? 12 "HELLO, WORLD!")

17:57 clojurebot: false

17:57 justin_smith: ,(small-enough 12 "HELLO WORLD")

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

17:57 justin_smith: ergh

17:57 ,(small-enough? 12 "HELLO WORLD")

17:57 clojurebot: false

17:57 justin_smith: ,(small-enough? 13 "HELLO WORLD")

17:57 clojurebot: 13

17:58 justin_smith: ,(small-enough? 10 {:a 0 :b 1 :c 2 :d 3})

17:58 clojurebot: false

17:58 justin_smith: ,(small-enough? 13 {:a 0 :b 1 :c 2 :d 3})

17:58 clojurebot: 12

18:22 n3vtelen: I'm new to clojure

18:23 I wanna use enlive library

18:23 is there a convention how to use it?

18:23 I mean clojure libraries

18:24 ianhedoesit: just add the dependency to lein or boot and use it. is that what you mean?

18:24 jplur: Anyone know how to config a repl to allow reader conditionals?

18:24 as in (read-string {:read-cond :allow} "#?(:clj :foo))")

18:24 justin_smith: n3vtelen: sure - use a build tool like leiningen or boot to add the dep to your project, then use require to make it accessible in a namespace

18:24 n3vtelen: thanks

18:25 justin_smith: jplur: your repl will allow reader conditionals if your clojure is recent enough that they are present - I don't know about that extra hash-map arg, but reader-conditionals in forms for clj / cljs work for me in a 1.7 repl

18:26 n3vtelen: other conventions for using libraries are to use :require in the ns form, with the :as clause to give the lib a shorthand prefix, and avoiding :use or :refer in most cases

18:28 pilne: am i strange for liking clojure even more because of nightcode being simple and easy to setup? (:

18:36 sobel: no, but there's much more to love

18:37 pilne: i'm hoping so, i come from a functional background, but i've found myself needed to write some java/javascript compatible things, so I'm happy I found clojure (:

18:37 a buddy of mine suggested scala first, but i like to do my own googling, scala is a lot nicer than java, but it still felt very object based and alien to my brain lol

18:39 justin_smith: ~scala

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

18:40 pilne: ?

18:40 neoncontrails: pi1ne: what's nightcode?

18:41 j-pb: clojure ide written in clojue

18:41 pilne: it is (so far for me) a quick, light, easy ide, i tried setting up eclipse with java... and coming from a vim or atom and a terminal background... i was more lost than a blind man in the middle of the sahara

18:42 eclipse with scala when my buddy recommended it*

18:42 neoncontrails: Oh cool. By any chance does it have inline evaluation like lighttable does?

18:43 pilne: i don't see it explicitly stated, but the website is sparse, and nothing I have attempted to learn so far has required it

18:43 https://sekao.net/nightcode/

18:43 neoncontrails: I don't know of any other editors besides lighttable which implement that feature, which is a little unfortunate because lighttable feels quite beta

18:44 pilne: i looked at lighttable, and it feels like it could win me away from atom someday, but not quite yet

18:44 ianhedoesit: light table is more of an alternative for nightcode, not atom, no?

18:44 justin_smith: it's based on atom-shell and isn't actively developed

18:44 neoncontrails: It's definitely a great concept and very lightweight compared to IntelliJ, which is what I use 99% of the time

18:44 Seylerius: justin_smith: I think part of the problem with clj-barcode is that it's using barbecue 1.5-beta.

18:45 pilne: atom and light table to me feel about the same, highly advanced window-based text editors with great plugin extensibility

18:45 justin_smith: pilne: yes, light-table uses atom-shell, it's basically a variation on atom in a lot of ways

18:46 pilne: so, in theory, a plugin could do the inline evaluation in atom?

18:46 justin_smith: the hard part would be hooking up to the nrepl protocol, after that it should be quite simple

18:47 neoncontrails: lighttable borrows a few aspects of emacs as well I feel (like lisp-encoded user preferences) which limits the love I have for it

18:53 pilne: i think what i liked most about clojure (besides that it is a functional lisp dialect) is that it was the only jvm targeting language i found that a) wasn't superbly obscure b) hasn't hammered a giantmegazord IDE down my throat as "the way"

18:55 neoncontrails: pi1ne: Your b) refers to Scala and Eclipse right?

19:00 Seylerius: Okay, it's fscking weird. I can require clj-barcode, I can create a barcode with it, but about a minute or two after /saving/ the barcode using clj-barcode's save-to-file function, the JVM dies in a fire.

19:00 jplur: justin_smith: ah you are right, my repl was using load-string to sanitize the input

19:00 Seylerius: I've tried saving as both jpeg and png, to no avail.

19:03 pilne: yes, scala, as well as that "ceylon" thing that redhat is making

19:04 does the jvm give any reason for self-conflagrating?

19:05 and just reading groovy's description was enough to tell me that it wasn't the path i wanted to explore >.<

19:05 Seylerius: Yep, there we go. I'd stuck a barcode in a var, waited around a while, did other shit in the repl, then came back and saved the barcode to a file, and it died.

19:05 Reasons? Let's see...

19:06 justin_smith: Seylerius: maybe you could turn on core dumps and use gdb to see what the jvm was doing when it died

19:06 Seylerius: or connect the vm to jvisualvm, turn on tracing, and visualvm should tell you what was happening when it died too

19:09 pilne: hrm... i think i just found a project to do at some point in the future.... re-write something like "how to design programs" but target clojure, a racket to clojure translation shouldn't be too hard, and that was honestly one of the best book/tutorials i've ever worked with.

19:09 Seylerius: Here's the error output, as unhelpful as it is: http://sprunge.us/ZYUT

19:10 justin_smith: I think I will try connecting the JVM up to something.

19:12 Time to learn visualvm.

19:13 justin_smith: Seylerius: visualvm is pretty simple - it comes with the jdk, on the left side of the window you get a list of java processes, double click one to connect to it

19:14 then it has tabs for tracing, metrics, etc.

19:14 it's a really cool way to figure out what the hell your clojure program is doing sometimes

19:15 Seylerius: Shiny.

19:16 Anything in particular I should set it to do other than attach to my jvm before instructing it to DIAF?

19:17 justin_smith: Seylerius: hmm... you could try to turn on CPU profiling, but sometimes that fails - but if it works that would end up giving you the best info

19:17 but no matter what visualvm should be able to give you some idea of what was happening when the vm death occured

19:19 Seylerius: Okay, CPU profiling turned on happily.

19:20 justin_smith: so yeah, in that case, when it dies visualvm should have very detailed info about what was happening

19:34 Seylerius: justin_smith: Okay, so I did a thread dump before requiring clj-barcode, after requiring clj-barcode, and after saving the barcode but before the crash.

19:46 justin_smith: So, it seems that after creating and saving the barcode, an AWT_XAWT thread was launched, and then immediately thereafter a Java2D Disposer. The Disposer sat "WAITING (on object monitor)" for the remainder of the run.

19:47 justin_smith: Seylerius: interesting - and do you have a vm with all the awt classes (eg. not headless)?

19:47 Seylerius: Hmm?

19:48 justin_smith: Seylerius: there are "headless" jvms that don't have the awt classes

19:48 it's one source of odd behavior I have seen

19:49 Seylerius: justin_smith: Active JVM: java-8-jdk (oracle)

19:49 justin_smith: OK, so yeah, that's not a headless jdk

19:49 was worth checking though

19:49 * Seylerius nods.

19:50 Seylerius: Should I try again with coredumps enabled?

19:50 justin_smith: oh, so you did see the crash, but visualvm didn't tell you what crashed?

19:51 Seylerius: visualvm didn't seem to do anything special with the crash.

19:51 justin_smith: did it acknowledge that the vm crashed?

19:51 Seylerius: Just says "application terminated"

19:52 justin_smith: interesting

19:52 Seylerius: Didn't do anything other than quietly note that the vm is no longer running.

19:52 And stop producing new data.

19:53 justin_smith: yeah, I would check out if you can find the return value ($? in the shell iirc) and maybe try with core-dumps on so you can use gdb to see what it was doing when it crashed

19:53 Seylerius: How do I turn on core dumps?

19:53 justin_smith: Seylerius: what OS?

19:53 Seylerius: Linux

19:54 (ArchLinux x64)

19:54 justin_smith: there's a ulimit that by default has core dumps turned off on most distros

19:54 so you would set the limit higher than the size of a clojure vm core dump (some huge number I guess lol)

19:55 Seylerius: http://www.akadia.com/services/ora_enable_core.html

19:57 Seylerius: Yeah, the JVM's output suggests `ulimit -c unlimited`

19:57 justin_smith: ulimit core settings are a reminder of a time when running program size was a larger percentage of hard disk size :)

20:23 pilne: is this tutorial correct in stating that clojure is "not well-suited for high-performance numeric operations. Though it is possible, you have to jump through hoops to achieve performance comparable with Java." https://aphyr.com/posts/301-clojure-from-the-ground-up-welcome

20:24 justin_smith: pilne: yes, but it should be noted that it is straightforward to code numerically intensive parts of your application in java, and the rest in clojure, and integrate the two

20:25 pilne: clojure has better host interop than any other language I know of - in fact its usually easier to use java code from clojure than it is from java

20:25 pilne: sweet, so it is kinda like ocaml or racket in that regard, except it is only meant to bring in java, not "any language(1)" (1) =(if you are willing to write your own bindings)

20:26 justin_smith: right, there's no "write the bindings" step

20:26 pilne: i can totally live with the agony of a few lines of java here and there, everyone has at least a little inner masochist right? (:

20:26 justin_smith: which is why I mention that clojure has better interop (I have done ffi in ocaml and guile)

20:27 pilne: a cool example of a mixed java / clojure project is pink, which is an audio synthesis engine written mostly in clojure, with a few java classes for the most performance sensitive internals

20:28 the cool thing about that to me is that unlike most exploritory audio programming environments, you can use a high level language (clojure natch) for the DSP level, not just for plumbing between predefined DSP units

20:28 pilne: so it can kinda be seen similar to inline compiling in c++ except without the horror of assembly (:

20:29 justin_smith: compared to supercollider where all DSP code is in c++, or pd, where all DSP code is c, or csound where you can do custom DSP but csound still isn't all that high level :P

20:29 heh

20:29 WickedShell: I'm tripping over problems with lein uberjar. It was working but it seems to be related to when I added a second namespace. ie my project was in src/foo (namespaces of foo.core and such)and I've now added src/bar (namespace bar.tools etc) is there anything I need to do to uberjar to make this work?

20:29 justin_smith: but it's separate files - you still have .java in one file and .clj in another, it's just that the work together nicely

20:29 WickedShell: what error are you getting?

20:30 pilne: i think clojure is going to make my somewhat forced to jvm experience, a very plesant one, maybe even a semi permanent change (:

20:30 WickedShell: justin_smith, it hangs forever after compiling everything in the foo namespace

20:30 justin_smith: WickedShell: I'd check for top level side effects in the end of foo or in bar

20:30 WickedShell: or at least on the last file, which is where it includes bar

20:30 justin_smith: WickedShell: this would include any go loops launched at the top level, any futures, db connections, etc.

20:31 any of those can make uberjar compilation hang - clojure only has one compilation mode even if you are doing aot for packaging, and it's exactly the same compilation behavior you would expect in the repl - no top level effects are deferred unless you defer them

20:32 WickedShell: the bar namespaces has no side effects/go's etc. Its a wrapper for a small bit of java I wrote that also has no sideeffects

20:32 justin_smith: WickedShell: try using jstack to see what the compiling process is doing

20:33 WickedShell: I bet it is inside some async or side effecting code - that's the common cause of a hang at least

20:33 WickedShell: justin_smith, what's jstack? I'm unfamiliar with it, but I'd love to find where this is happening

20:33 justin_smith: WickedShell: jstack comes with the jdk, it's a command line program that shows you a thread dump for every thread in a vm, if you pass it the PID of your program

20:33 one of those stack traces will probably be very enlightening

20:34 WickedShell: if you have a terminal with the process running, kill -3 or control+break will also make it dump all stacks

20:34 but jstack is nice because it's more flexible, you can pipe it to a file or less, etc.

20:34 WickedShell: I'm on windows at the moment sadly

20:35 justin_smith: WickedShell: jstack, or the control+break shortcut should still work on windows

20:35 WickedShell: yeah jstack is working, looking at the results now, still figuring out how to interpret the results

20:36 justin_smith: heh, yeah, welcome to the fun world of clojure stack traces!

20:36 it's the dark side of "lots of small simple functions that each do only one simple thing" :)

20:42 pilne: eh, i'd rather find problems at compile time, which is why i've always enjoyed racket ocaml and haskell lol

20:42 justin_smith: pilne: this can be an issue with clojure, in many ways inherent in the lispy design

20:43 though racket is better than clojure at finding problems statically

20:43 pilne: yeah, but i'm used to those kinda things (: every time i've tried/had to learn one of the "OO" languages, my brain has wanted to put itself in the garbage disposal lol

20:44 justin_smith: pilne: part of the issue here is clojure made the intentional decision not to abstract very far from the vm - which is awesome for interop and performance, but can be ugly when debugging because there is no layer hiding the vm implementation details

20:44 pilne: ahhhhhh

20:45 justin_smith: compare scala, which abstracts away from the vm quite a bit (which causes a separate set of problems, but also allows very clear error handling)

20:45 or can, at least, even if they don't always succeed

20:45 pilne: meh, i like to write my programs gradually, debugging small functional parts, and then weaving them together, so hopefully i'll avoid the nastiest of those

20:46 WickedShell: justin_smith, I'm a bit lost here, would you mind taking a look at the stack dump? I'm struggling to see what the compilier is waiting on

20:46 justin_smith: WickedShell: feel free to share on refheap, I've done this a few times so I have a decent clue of what to look for

20:47 WickedShell: justin_smith, https://www.refheap.com/110527

20:47 justin_smith: pilne: for some context, what WickedShell is running into is one of the few cases where something isn't identical between repl interaction and packaging / deploying scenarios - things like this are not super common

20:48 WickedShell: This is the first time I've ever run into it, till now its been shockingly easy to deploy

20:48 justin_smith: WickedShell: this is suspicious "swiftgcs.maprenderer$fn__15220$fn__15221.invoke(maprenderer.clj:353)"

20:48 this should not be hapening at compile time

20:49 it's being invoked by core.async somewhere

20:49 pilne: hrm, i tend to not trust repls because the first one i really messed with was haskell's and it is not exact due to it running inside the Io Monad, so i see the repl as a snippet type thing for the most part.

20:49 justin_smith: pilne: clojure only has one compiler, and it's the one in the repl

20:49 pilne: so that means it is being run at the top level (the maprenderer.clg)

20:50 clj*

20:50 justin_smith: pilne: the issue we are seeing here is running a task that would not cause an error if run when loading the code in a repl, but will if all you are doing is trying to compile byte code and then exit

20:50 pilne: same as haskell, but since the repl is running in a "monad" it behaves differently than compiled code

20:50 justin_smith: pilne: well, indirectly - like I said core.async is invoking it

20:50 WickedShell: It's not new, that line hasn't changed in a long time, although i'm starting to work on moving away some of the spinups that were happening eariler

20:51 pilne: it sounds like something similar to putting an "impure" function in the top level of haskell without handling the IO properly

20:51 justin_smith: exactly the same problem, though the details are different of course

20:52 WickedShell: the crux of this, is you should not have a go block started up and trying to render anything or load files or whatever that code is doing, when aot compiling

20:52 pilne: because the compiler will try and run it, instead of compiling it?

20:52 justin_smith: pilne: compiling it will run it - the clojure compiler doesn't have a separate "compile only" mode

20:53 WickedShell: justin_smith, out of curiosity is the line number refering to the start of the statement? (the line in question is the start of a let)

20:53 justin_smith: if you have (def x (some-side-effecting-fn)) - then compiling that line of code means running htat side effecting fn

20:54 WickedShell: it's being invoked by core.async, so there is no stack trace showing where the go block was launched

20:54 that's the nature of core.async

20:54 WickedShell: Yeah that's what I thought

20:54 justin_smith: somebody started a go block, and it should be wrapped up and started only from your -main

20:54 or some apropriate init

20:55 WickedShell: in fact, there are many of thse blocks running it seems

20:55 WickedShell: I'll chase it all down, and see if that fixes anything. It was on my todo list

20:55 Yeahh I spin up a bunch of pub/subs in weird spots becuase I didn't know where to do it when I first started

20:56 justin_smith: WickedShell: if you didn't guess, the trick to finding what hangs the uberjar process is scanning the stack traces for things that are not java or clojure internals. Because only clojure internals or their java basis should be running while making a jar.

20:57 WickedShell: I'm suspicous that the Graphics2D dispose stuff is resposnsible but I'm not sure

20:57 justin_smith: WickedShell: it's not!

20:57 the thing that is responsible is the parked go block

20:57 the vm will not exit while go blocks are parked, unless you tell it to forcefully

20:58 but I'm sure you agree it's cleaner not to be starting them up in the first place if you are just packaging a jar

20:58 WickedShell: there's a function (shutdown-agents) that will make all that stuff stop in a friendly way

21:00 WickedShell: justin_smith, I do, I just didn't know where to put them early on.

21:00 justin_smith: WickedShell: my typical MO is to move each startup into a function definition, and call all those functions from -main

21:01 WickedShell: or in the case of a library, have a single "init" that starts all the rest up, and document that the client should call it

21:01 WickedShell: there's also stuartsierra/component if any of this has return values that other stuff needs to use at init time

21:01 WickedShell: Yeah. The biggest reason I hadn't was I had some early teething problems with access/startup order

21:02 justin_smith: yeah, stuartsierra/component helps with startup order too

21:20 neoncontrails: Say you've broken the src files of your web app into /clj and /cljs branches. Assuming the location of your handler and source paths was correct before, how do those change with the update?

21:21 justin_smith: neoncontrails: not at all, unless you fucked it up

21:21 neoncontrails: oh, sorry, never mind

21:21 neoncontrails: justin_smith: Oh wow. The one case I didn't even consider

21:21 justin_smith: neoncontrails: point at the new location of the files :P

21:21 I was thinking of something different

21:22 so if instead of src/ it's now clj/ or cljs/ that's the change you would make in your :source-paths and :cljsbuild keys respectively

21:22 but if it's src/clj and src/cljs that's a different change, of course

21:22 neoncontrails: I'm getting a FileNotFoundException pointing at "clj/myapp/handler.clj" which is precisely where it is in the structure...

21:23 justin_smith: what is your :source-paths setting?

21:23 the default (if you didn't specify at all) is ["src"] - which of course would be wrong now

21:24 neoncontrails: :source-paths is ["src/clj"], which could have something to do with it. But I've tried a lot of permutations

21:24 justin_smith: similar change in your :cljsbuild :build :source-paths vector (works the same way)

21:24 neoncontrails: well, if you don't have a directory called src, that's broken

21:24 neoncontrails: and my cljsbuild source-paths is ["src/cljs"]

21:24 justin_smith: same

21:25 what's the full path from the dir project.clj is in to handler.clj?

21:25 neoncontrails: my dir structure is myapp > src > cljs | clj > myapp > handler.clj | core.cljs

21:26 justin_smith: so src -> clj -> myapp -> handler.clj? then that :source-paths setting should work

21:26 neoncontrails: yup. Alright, that's what I thought too. Hmm.

21:27 justin_smith: this might sound dumb, but have you tried lein clean?

21:27 sometimes uncleaned stuff can have very odd results

21:28 neoncontrails: that's a good point. I'll try that

21:30 Ooh, a new error. "No such namespace" at least resolves that one :P

21:32 Aaand hallelujah. It's alive! My HTTP server is finally alive.

21:32 Beers for everyone.

21:32 WickedShell: justin_smith, apparently despite having not changed that code for a long time, that was the problem I've moved some arbitrary portion of the async/spin up stuff into functions from main and that fixed it.. I would have bet money that nothing I touched wasn't responsible but I'll take it. Thanks for the assistance

21:33 Now I'm going to move the rest of them so I don't have to go through this again in the future :)

21:36 justin_smith: haha

21:36 neoncontrails: so it was a "lein clean" issue? lol

21:37 * justin_smith is on a roll tonight.

21:37 * WickedShell bows at justin_smith's feet

21:38 neoncontrails: justin_smith: that's merely one of a few obstacles I cleared today, but thankfully one of the last

21:39 justin_smith: So, I have a concurrency problem. I have a cljc file where I am handling potentially multipart messages. The message parts are in an atom containing a map of maps. The problem is that I need to remove all the parts of one message and send that message when its last part comes in, but not send it twice.

21:39 so I can't do the send inside the swap!, because retries

21:40 and I can't just test the state of the atom after returning from the swap!, because I think two threads could see the state of the atom with all of the parts present...

21:40 in cljs I can use an agent and all is well

21:40 maybe the easy fix is to use an agent in clj, and atom in cljs?

21:41 blergh

21:41 neoncontrails: justin_smith: above my skill level, but I'm so starving for fun programming puzzles I'd like to give it a shot

21:41 What happens if you send the message twice? Just hypothetically.

21:42 justin_smith: neoncontrails: a single expensive graph computation, that uses up a big chunk of server CPU and doesn't finish for 15 minutes or so, could happen twice in parallel

21:42 huge waste of resources, and degradation of performance visible to clients

21:43 maybe I can store the message send as a memoized / delayed thing that would be guaranteed to only run once for a given message? but I think that would be an abuse of memoize

21:45 this makes me think cljs should have agents :P

21:45 neoncontrails: I was gonna say something similar. If the message is indeed the same, perhaps you could insert messages into a set before offloading them to the threadpool

21:45 justin_smith: just to make cross platform code easier

21:46 neoncontrails: oh yeah, and blacklist based on the set

21:46 neoncontrails: Sounds sensible to me :)

22:49 My compiler is having namespace issues following the steps in this tut: http://www.christopherbiscardi.com/2014/01/15/scaffolding-a-clojurecompojure-webapp-for-heroku/

22:50 Is it implicit in these steps where run-jetty and the 'handler' namespace are declared? I followed the steps exactly and they're not resolving

22:50 http://pastebin.com/thHPDTAf

22:53 I considered modifying the namespace of the handler.clj file itself to 'handler', but that leaves open the question of what 'site' refers to in that context

23:10 justin_smith: neoncontrails: if the file is named scaffold_app.handler, the ns should be scaffold-app.handler

23:11 neoncontrails: also you are referring to a function handler/site that is not pulled into scope in that file

23:11 you could change run-jetty to ring/run-jetty and you need to require the namespace that defines handler/site

23:12 neoncontrails: I concluded as much, but what I'm stuck on is the ambiguity of filling in those blanks (handler especially)

23:12 justin_smith: neoncontrails: well, you as the app developer are expected to implement a handler

23:13 neoncontrails: usually people use a lib like compojure or polaris that lets you declare routes and generate a handler that will access those routes when given a request

23:15 neoncontrails: That's reasonable, but my understanding of the tutorial is that it illustrates the process of doing precisely that. No?

23:16 justin_smith: neoncontrails: did you run the lein-new compojure command to generate the project?

23:17 the unorthodox ns name makes me think no, and lein new compojure would have generated a handler

23:17 neoncontrails: I did. They don't change those templates year to year, do they?

23:18 justin_smith: sometimes weekly

23:18 but really, lein new compojure foo should generate foo/handler

23:18 or something like that

23:21 neoncontrails: Wait, wait: when you say 'lein new compojure would have generated a handler'... I should *not* be modifying that handler then

23:21 Is that what you're saying?

23:21 justin_smith: neoncontrails: no no, a template is for making your initial project

23:22 it should create and hook up a handler, and that's your starting point

23:22 and you should modify it

23:22 neoncontrails: The pastebin link above is a modified version of the scaffold_app.handler which came with the template

23:22 justin_smith: umm... then the template is broken

23:22 neoncontrails: Oh.

23:22 justin_smith: how did you call the template?

23:22 neoncontrails: :(

23:22 "lein new compojure scaffold_app"

23:23 justin_smith: OK I am recreating here

23:23 it makes a file in src/scaffold_app/handler.clj

23:23 neoncontrails: much appreciated

23:24 Correct. Here's my version of that with the updates: http://pastebin.com/thHPDTAf

23:24 justin_smith: neoncontrails: the thing your tutorial calls "handler" the template calls "app-routes"

23:24 the tutorial is old

23:25 neoncontrails: I see. Got it, so replace all instances of app-routes with 'handler' then

23:26 justin_smith: also, my src/scaffold_app/handler.clj has an ns called scaffold-app.handler, and the fact that your ns had scaffold_app as part of it made me think you were not using the template

23:26 because that's not normal naming in clojure, at all

23:27 neoncontrails: oh. You're referring to the underscore, yes?

23:27 justin_smith: right

23:28 neoncontrails: Yeah like I said I tried a few things that seemed halfway reasonable to declare a handler namespace

23:29 one of them was modifying the handler's namespace to handler but that didn't work, clearly

23:29 but good point, I'll fix that.

23:44 justin_smith: does anything stick out to you w/r/t that ring.middleware.defaults :require statement? It's looking for assets in that library that don't exist

23:47 justin_smith: neoncontrails: resources/public by any chance?

23:48 neoncontrails: justin_smith: Specifically it's looking for "ring/middleware/not_modified.clj" which lies outside the scope of any variables mentioned in the handler

23:49 justin_smith: it requires the ring.middleware.not-modified ns, yes https://github.com/ring-clojure/ring-defaults/blob/master/src/ring/middleware/defaults.clj#L14

23:49 so it's not finding it?

23:49 neoncontrails: It isn't. I'll add that one as well

Logging service provided by n01se.net