#clojure log - Sep 23 2015

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

0:00 rritoch: TEttinger: My project is a fork of armed bear common lisp, with the key difference that mine is 100% maven compatible (The developers of ABCL specifically refuse to support using ABCL from maven), also my fork passes all of the ansi tests.

0:00 TEttinger: ABCL isn't compatible with clojure at all really since it can't be included as a dependency in it's current state.

0:01 TEttinger: I don't think clojure has a huge amount of effort put into interop relative to other important language features. the key features were all present in 1.0 for java interop except for maybe a few for gen-class things?

0:01 I think the STM was probably much more challenging than playing nicely with java

0:02 rritoch: TEttinger: As for the multithreadding issue, there's a few reasons. It inherited ABCL's circular dependencies which outnumber class files 10x1 at least, and the massive use of static finals for things that should be "interned".

0:03 arrubin: TEttinger: For a lot of development, it can make a huge difference though. Having good database drivers through JDBC for instance.

0:03 TEttinger: what's the problem with static finals? I'm a bit unclear since I don't know a better way to imitate a constant in java

0:04 rritoch: TEttinger: It's is an architectural flaw with the ABCL codebase that it has placed most of it's symbols as static finals so they can't be utilized in a thread-local context.

0:05 TEttinger: It isn't a problem with the java language, and it is something that can technically be corrected. The other developer on the jrelisp project I believe is working on that issue. Along with CLI support.

0:06 Err, maybe CLI isn't the correct term, he's working on .NET support. I don't recall the name of the interpreter.

0:07 TEttinger: CLR is a common term but not a synonym for CLI. CLR is common language runtime

0:07 not sure what CLI stands for in .NET context

0:08 rritoch: aconz2: Either way, if your trying to make a big splash I can suggest a few open source projects that you could probably produce with the aid of jrelisp & clojure.

0:08 TEttinger: Sorry, I think your right, I think it was CLR. I'm really not a big .NET fan.

0:10 aconz2: Notably are opencyg, which I believe has it's own native lisp implementation, and common-lisp-stat. Neither of those projects will run on a JVM (yet) and could both make headlines if ported to clojure/JVM.

0:11 TEttinger: it really is remarkable to me what the MS team managed to do with C# relative to Java. generics without boxing and a really well-thought-out collection API that uses a similar concept to clojure's seq abstraction (almost all collection methods operate on the IEnumerable interface and return one as well), technically more powerful first-class functions than java's lambdas (since lambdas aren't closures)...

0:12 the open source version of most of .NET appears to include immutable data structures in the core lib

0:12 including an equivalent to transients

0:16 rritoch: aconz2: Small correction, it isnt' opencyg, it's opencyc (https://en.wikipedia.org/wiki/Cyc). Porting Cyc to clojure brings about 50% of AI technology to clojure, and porting common-lisp-state brings advanced statistical analysis to clojure. I've considered both projects but I'm not going to touch either project without funding since I neither work in the AI field or statistical analysis.

0:19 TEttinger: a direct port might not be ideal for the common-lisp-state one, I would say. the approaches to pure/lazy functional code are different between the original language and in clojure, and statistics stuff seems like a perfect match for immutable/persistent data since you never want to change the data you're analyzing in the process of analyzing it

0:21 if you can do what it does in broad capability terms, that would be huge. even a small library that does statistics work that is challenging now would be nice

1:43 rritoch: Does anyone know how to fix vinyasa? "Failed: Java files did not properly compile [{java source directory}]

1:47 Looks like a known issue (https://github.com/zcaudate/vinyasa/issues/4)

1:55 I re-reported the issue as it's a slightly different, but related problem. https://github.com/zcaudate/vinyasa/issues/20

3:14 neurostorm: i have som keyvals in a hash-map and would like to use it in a let... like (def b {:x 1 :y 2}) (let [b] (+ x y)) , can it be done?

3:15 justin_smith: neurostorm: no

3:16 neurostorm: ah, come on... a macro perhaps?

3:17 justin_smith: neurostorm: if the map is known at compile time, you could make that macro

3:17 neurostorm: i just want to dynamicly set some bindings... they are not known at compile time.

3:17 justin_smith: macros only run at compile time

3:18 and I'm not alone in the opinion that magical bindings that are inaccessible while reading the code and only known at runtime lead to terrible unreadable code

3:18 (which is why nobody made this functionality yet)

3:18 neurostorm: yeah, i just wanted easy access to some data retuned from a request.

3:19 justin_smith: then pass the data in?

3:19 neurostorm: and would like a generic mehtod to do that.

3:19 justin_smith: you know about destructuring, right?

3:20 neurostorm: i do, and its nice, but for 10 vars 2 leves inside a map, it does not look nice.

3:20 justin_smith: with destructuring you can bind the keys you expect to find to local values. That totally works. But how would you even write code that does anything meaningful with bindings you don't even know the names for until runtime?

3:21 you are allowed to spread the left hand side of a let binding over multiple lines, I do it all the time

3:22 neurostorm: i know the names, but would like to avoid have to do the deconstruction. And i would like to use this different placeres with different names.

3:22 justin_smith: neurostorm: best of luck

3:22 neurostorm: jusk asking...

3:23 justin_smith: I'm doing my best to explain why this feature doesn't exist. If you don't agree with the rationale, feel free to try it I guess.

3:24 the general clojure approach is that bindings should be explicit and clear, and any time you refer to some binding, it should be simple to see where that binding came from. It's something I personally like a lot about mainstream clojure code. But of course there are ways to break these rules if you really want.

3:25 rritoch: neurostorm: See: https://clojuredocs.org/clojure.core/binding

3:26 justin_smith: rritoch: that has nothing to do with what he wants. He wants the values to be magically bound without him having to type out their names (getting them automatically from a map only known at runtime).

3:26 binding has all the same limitations that let does

3:27 neurostorm: i understand your argument, and maybe in general its a bad ide. Still i would have thought it was possible to set some binding in a more dymanic manner. I just want a closure or let-over-lambda make some keyvals from a hash-map accessible in the scope.

3:27 justin_smith: you can do it, but it doesn't exist yet

3:27 of course it is possible, it would probably involve a macro plus eval

3:29 rritoch: justin_smith: Oh, ok. I see the problem.

3:31 neurostorm: ok... well, better ditch that idear. thanks for the input.

3:32 rritoch: neurostorm: Sure, you can do it, but your going to have errors constantly, especially if you use variables not defined in the provided map.

3:33 neuostorm: Basically you just create a function that accepts a map and a form, you wrap the form in a function definition & let statement populated with the key/value pairs.

3:35 neurostorm: I'd think it would be something like... (fn [myvars myform] (do #_manipulate form #_(eval form which returns a function) #_( call function with values from myvars to populate let values)

3:36 neorostorm: You could make a macro which would generate that code so your final product is cleaner. It is going to be very error prone because your call to eval will fail if undefined variables (keys) are used.

3:37 neurostorm: If you can think it up, clojure can find a way to do it, but just because you can do something, doesn't mean you should.

3:38 neurostorm: yes, i can see your point, will be difficult to use without make much more error handling.

3:38 justin_smith: which is fixed by explicitly attempting to bind those keys, which brings us back to how you would do it with destructuring anyway

3:46 rritoch: neurostorm: If your going to use that psudocode, you should also switch the order of the arguments from myvars myform to myform myvars and take a partial of it since your form isn't going to change on each call.

7:43 ashwink005: can anyone suggest a good source to learn how to write deftests?

7:43 i.e. compojure project testing

8:08 sandbags: amalloy_: ping .. wanted to ask you about (apply map list (partition xs))

8:32 triss: gosh I'm sure I'm finding searching the JIRA way harder than it should be....

8:33 I'm told a ticket exists for adding documentation strings/error messages to :pre and :post conditions exists but I really can't find it.

8:34 does anyone know where it is?

8:44 puredanger: I looked and I don't see it

8:46 I I must be misremembering

8:48 triss: ah thanks v much puredanger... good to know I'm not gong blind!

9:13 the-kenny: Anyone noticed issues with leiningen and clojure.test/use-fixtures? It seems that my :once fixture is run in parallel (or nested).

9:14 Background: I start a webserver for an api in there. When running the tests with C-c , in Emacs, everything works fine. When I run `lein test', I get an AddressAlreadyInUseError and my logging says the server is started once, then stopped immediately, without any tests in-between

9:19 Okay, it works fine after updating Clojure from 1.6 to 1.7

9:26 jeremyheiler: the-kenny: are you sure you didn't have any lingering processes?

9:26 the-kenny: jeremyheiler: It might have been that, yeah. That wouldn't explain why it worked in the REPL though.

9:26 I just wrote some code to randomize the port the server listens on for every test. That should prevent that in the future.

9:27 jeremyheiler: occasionally i'll find that i have 10 nrepl servers running because they were never closed by emacs

9:27 or whatever should have closed them

9:28 noncom: what is the most idiomatic way to get all dates for the current week with clj-time?

9:38 bja: jeremyheiler: that's more realistic anyway (randomized ports). if you had a service that needed to both bind a port and have multiple copies listening on the same ip, you'd need to either assign those ip:port combinations ahead of time or use some sort of registry (I use zookeeper for an nrepl registry)

9:50 noncom, I feel like you'd have to define current week

9:50 do you mean the next 7 days (inclusive of today)

9:50 do you mean this Sunday through Saturday cycle? Monday through Sunday? Thursday through Wednesday?

9:51 in any event, I'd imagine the answer involves either take or take-while and clj-time.periodic/periodic-seq

9:52 egli: bja: yes probably, but how do you get the start of the week?

9:52 bja: how do you define the start of the week?

9:52 mungojelly: yeah weeks start differently in different cultures

9:52 egli: let's assume monday :-)

9:53 if I knew the current weekday I could (ago date ,,,)

9:54 jeremyheiler: bja: sure, wasn't arguing against randomized ports :-)

10:00 bja: (monday? (first (take 7 (periodic-seq (ago (-> (today) day-of-week dec days)) (days 1)))))

10:02 (require '[clj-time.core :refer [ago days day-of-week today]] '[clj-time.periodic :refer [periodic-seq]] '[clj-time.predicates :refer [monday?]])

10:03 that code probably has a bug if the day is monday

10:03 actually, (days 0) works

10:03 well, works the way I want it to

10:03 egli: bja: is there a day-of-week function? I can't find it on http://clj-time.github.io/clj-time/doc/index.html

10:03 bja: it's part of the DateTime protocol

10:04 http://clj-time.github.io/clj-time/doc/clj-time.core.html#var-DateTimeProtocol

10:04 egli: ah, you're right

10:04 did a search on http://clj-time.github.io/clj-time/doc/index.html where it wasn't listed

10:04 bja: the latest docs are for 0.8 though

10:04 I think clj-time has newer versions

10:09 mungojelly: add the current day, stop if it's monday, go back and add days until one of them is monday, add days to the end until it makes seven

10:12 noncom: bja: egli: mungojelly: so, take (now), find current day-of-the-week, lapse back to, say, monday, that's the start. add 7 - that's the end.. correct? that is straightforward but i thought maybe there is a simpler way

10:12 bja: noncom, my code works

10:12 just remove the monday? first functions where I prove the first day is a monday

10:13 it returns a seq, starting with monday and containing datetimes for the entire week

10:13 there is a function called ago which does the legwork for you

10:13 so you just need to find monday, and then tell periodic seq to start with monday, and give you datetimes in day increments

10:13 noncom: bja: ah, i see, spotted your code. i missed that while reading the char

10:13 *chat

10:13 very cool!

10:14 bja: periodic-seq is awesome

10:14 troydm: is it possible to create alist in clojure? or even a pair?

10:14 bja: troydm: what do you mean?

10:14 '(1 2) is a list

10:15 if you were inclined to do so, you could have a reader dispatch on some new mutable list and have syntax for it

10:19 csd_: How might I translate the CL macro (defmacro macro (&rest fn-names) '(progn ,(if fn-names '',fn-names '*fns*)))? The double syntax quote has me confused

10:22 troydm: bja: I mean something like (cons 1 2) in Scheme

10:23 bja: no, if you want something like that define it and then add syntax for it via reader dispatch

10:25 troydm: ic

10:26 bja: by define it, I mean create the data type and functions to manipulate it, and then use http://clojure.org/reader#toc4

10:26 jeremyheiler: csd_: which are backticks and which are quotes? my editor doesn't differentiate them

10:26 my irc client*

10:26 they all look like single quotes to me

10:26 bja: ^^^ what jeremyheiler said

10:27 csd_: jeremyheiler: all are single quotes

10:27 jeremyheiler: csd_: that doesn't compile

10:27 so, my approach is to macroexpand the cl code to see the output

10:28 csd_: hm maybe the book i'm looking at has a transcription error

10:28 jeremyheiler: the quote in front of progn is probably a backtick

10:29 because of the , in front of if

10:29 csd_: see fn profile at the bottom of the page 290 https://books.google.com/books?id=eH6jBQAAQBAJ&lpg=PA913&dq=paradigms%20in%20artificial&pg=PA290#v=onepage&q=profile1&f=false

10:30 sorry, unprofile

10:30 jeremyheiler: it doesn't let me see page 290

10:30 wait, nvm, it does

10:32 csd_ ok, i got it. the quote in front of progn needs to be a backtick `, not a single quote '

10:32 also, the two quotes in front of ,fnames need to be backticks, not single quotes

10:32 that at least compiles...

10:35 csd_: i'd think you can just directly translate that backtick to clojure's backtick / single quote, right?

10:35 jeremyheiler: i think so

10:35 and cl , is clj ~

10:35 csd_: yeah

10:35 jeremyheiler: it's hard to tell which is a backtick and which is a quote in that book

10:35 i have a copy at home, but i'm not at home, so i can verify :-/

10:36 csd_: but if fn-names is a list, i can see why '~ makes sense, but not why the extra '

10:37 maybe because without it, the unquote at the beginning of `if` will unquote it too>

10:37 jeremyheiler: in clojure, you may want to quote a symbol before syntax quoting it so that it doesn't become namespace-qualified

10:39 csd_: why syntax-quote at all? why not just use only regular quote

10:39 jeremyheiler: ,'bar

10:39 clojurebot: bar

10:39 jeremyheiler: ,`bar

10:39 clojurebot: sandbox/bar

10:40 jeremyheiler: see how the syntax quote implies a namespace

10:40 csd_: yeah

10:41 ,''bar

10:41 clojurebot: (quote bar)

10:41 csd_: ,`'bar

10:41 clojurebot: (quote sandbox/bar)

10:41 csd_: ,'`bar

10:41 clojurebot: (quote sandbox/bar)

10:42 TMA: ,``bar

10:42 clojurebot: (quote sandbox/bar)

10:42 csd_: i guess i should probably just install a CL compiler and see what this actually expands to and compare that with what happens in clojure

10:44 jeremyheiler: csd_: i consulted the resident cl'er who sits next to me and it is bakctick, quote

10:44 ,`'~'(foo bar baz)

10:44 clojurebot: (quote (foo bar baz))

10:45 jeremyheiler: ,`~'(foo bar baz)

10:45 clojurebot: (foo bar baz)

10:45 TMA: ,`quote

10:45 clojurebot: quote

10:45 sobel: here i sit at my javajob with a data integration engineer (sql lackey) title. contemplating whether i might need to find me a proper clojob.

10:46 TMA: oh, so quote symbol is a special case

10:46 jeremyheiler: csd_: so this code is evaluating fn-names once, and then quoting it so the list of fn-names isn't called as a function.

10:46 (defmacro macro (&rest fn-names) `(progn ,(if fn-names `',fn-names '*fns*)))

10:46 (macro foo bar baz) ;=> (PROGN '(FOO BAR BAZ))

10:47 csd_: ohh

10:48 right and so if there wasnt the unquote before the `if` sexp then that extra backtick wouldnt have been necessary

10:49 jeremyheiler: ,(do (defmacro macro [& fn-names] `(do ~(if fn-names `'~fn-names '*fns*))) (macro foo bar baz))

10:49 clojurebot: (foo bar baz)

10:50 jeremyheiler: ,(do (defmacro macro [& fn-names] `(do ~(if fn-names `'~fn-names '*fns*))) (macroexpand '(macro foo bar baz)))

10:50 clojurebot: (do (quote (foo bar baz)))

10:51 jeremyheiler: csd_: correct, but then the if would be the resulting expansion

10:53 csd_: yeah

10:53 i'd imagine that as you work more with macros that this all becomes idiomatic eventually

10:54 jeremyheiler: yeah, but then you try to write a macro that expands into a macro

10:55 if you successfully do it, you become a wizard

10:55 csd_: good luck maintaining it too :-P

10:55 jeremyheiler: lol

10:55 csd_: thanks for explaining this all to me, very helpful

10:55 jeremyheiler: sur!

10:55 sure*

12:55 codefinger: Pupeno: here's another option that might work well for you case (deploy local artifacts) https://github.com/heroku/lein-heroku

12:59 jeremyheiler: that looks nice. i wasn't a fan of the git approach for clojure/java

13:00 codefinger: jeremyheiler: what was the rub? i agree in some cases -- especially since JVM artifacts so portable

13:01 jeremyheiler: having a lot of stuff in my git repos that don't need to be sent to heroku

13:01 especially when my build pipline is designed for deploying a jar

13:02 codefinger: jeremyheiler: yea, i'm not a fan of checking things into Git that don't need to be there. So lein-heroku is perfect for uberjars

13:32 pseudonymous: Hey - can anyone explain why this explodes (kicker: it never does when testing in a repl) https://gist.github.com/anonymous/3e9f961067277e71cee0

13:34 amalloy: uh, because you are referring to stuff in cider.nrepl?

13:35 if-require doesn't really work at all

13:35 hm, actually if-require looks okayish

13:36 but you have to call it at the top level to be effective, not inside a function

13:36 pseudonymous: I hope so, I literally spent 2 hours baby-stepping through its writing.

13:36 Oh, and then capture the results in a def ? )

13:36 amalloy: actually as written i'm not sure it even works at the top level, because you're using a let

13:37 doing requires outside of ns is pretty tricky

13:39 pseudonymous: amalloy: Yea, I'm coming to see that :(

13:40 justin_smith: pseudonymous: the only time I have successfully used require at runtime, is if I also use resolve instead of referring to the symbols required directly

13:40 pseudonymous: this is helpful for avoiding needing to do AOT for example

13:42 pseudonymous: the problem is that clojure won't compile code that calls cider.nrepl unless cider.nrepl is available at compile time. Your macro needs to be a bit more magical than it is.

13:42 or you need to use resolve

13:42 (perhaps even a combination of these things - the macro could use resolve!)

13:44 pseudonymous: justin_smith: not quite sure I follow. Just tested something from another library (which I already use in other files) - that worked. If I'm understanding you correctly, this trick will basically only work provided the ns in question is already referred to in other parts of the project ?

13:45 justin_smith: pseudonymous: the compiler won't compile code that calls things that it can't resolve

13:45 pseudonymous: which means you need to manually use resolve yourself

13:45 it works accidentally if the namespace is actually available because someone else (eg. your lein tooling) required the thing already

13:45 pseudonymous: Ah, so the reason why it works for other libs is that I'm already using them and they're already resolved. This one isn't, so I'm fubar'ed.

13:46 justin_smith: right

13:46 but, clojure will gladly compile code that *attempts* to resolve something at runtime

13:46 pseudonymous: So time to delve into the mysteries of resolve...

13:46 justin_smith: so instead of foo.bar/baz you use (resolve 'foo.bar/baz) and cross your fingers it doesn't blow up with a nil at runtime

13:47 ,(resolve 'this.does.not/exist)

13:47 clojurebot: nil

13:47 justin_smith: ,(resolve 'clojure.set/union)

13:47 clojurebot: nil

13:47 justin_smith: ,(require 'clojure.set)

13:47 clojurebot: nil

13:47 justin_smith: ,(resolve 'clojure.set/union)

13:47 clojurebot: #'clojure.set/union

13:47 justin_smith: see, magic!

13:48 pseudonymous: Oooh. Hmm Well.. that shouldn't be a problem, the macro is written to guard against that exact case

13:48 justin_smith: pseudonymous: right, you don't even need require - just use resolve, and sometimes you get nil and deal with it

13:48 easy-peasy

13:49 if resolve returns something non-nil, you know you can use it

13:49 also this is all terrible and should have a fancy evocative name like monkey-summoning

13:49 pseudonymous: eh? Which part, exactly ?

13:50 justin_smith: conditional behaviors determined by the side effects of other dependencies

13:50 pseudonymous: I can't remember exactly *where* I found it, but Immutant has a dev plugin which (in hindsight) used resolve to conditionally pull in various plugins

13:50 justin_smith: which can lead to weaird things like bugs that only happen if you require foo.bar in another namespace - just consider how weird that is

13:51 I'm not saying it's never useful! but let's be real about how spooky and illogical it is

13:52 pseudonymous: justin_smith: well it's not like I'd want to build everything around it, but for the odd wrapper somewhere, it should be OK, so long as it isn't extremely necessary to have it (which is exactly the case here)

13:53 justin_smith: pseudonymous: sure, just trying to keep perspective about the terrible consequences if we accept this sort of thing as normal - using resolve at runtime should always be guilty until proven otherwise

13:54 but sometimes it's a fine way to do something that would be a total mess if you couldn't do it that way

13:54 pseudonymous: justin_smith: btw, this was really enlightening. It's so much simpler and doesn't require a custom macro (and THAT is a real win in my book). On the downside, I spent all that time writing one ;__;

13:55 justin_smith: heh :)

13:58 amalloy: pseudonymous: you also could have just found someone else's implementation of it. that macro has been written many times

14:00 pseudonymous: amalloy: I searched a little (not well enough) and found something much like the macro I wrote - but the one I came across didn't support a vector-style libspec, so I set out modifying it, with terrible results (repl issues) and finally I decided to write everything one step at a time to minimize chances of screwing up. It was educational enough, so I'm OK with having done it.

14:01 justin_smith: clearly we need a variation on "require", more like "nice-to-have"

14:02 (ns foo.bar (:nice-to-have [dwim.core :as dwim])) ...

14:04 bja: justin_smith: I'm going to steal "monkey-summoning" for the next time I do something ambiguously evil in clojure

14:04 justin_smith: bja: heh, I really think it should be reserved for situations where a feature might ambiguously exist and you don't know until runtime, but OK

14:05 bja: ok, there is a precise usage

14:05 justin_smith: bja: I guess that could also be called "petting schroedinger's cat"

14:05 bja: how about for conditional execution between deployed scenarios and non-deployment

14:05 justin_smith: oh yeah...

14:06 * rhg135 summons monkeys

14:07 bja: justin_smith: so this is monkey summoning? https://gist.github.com/3b4096aeec6a4f6992ab

14:08 justin_smith: bja: since you get significant difference in definitions based on runtime environment it could count

14:09 funny enough, I did something similar as a lein plugin (so that we could unambiguously see the state of the git repo inside artifacts)

14:09 bja: yeah, we have a ring middleware that exposes this

14:10 we just have it stashed inside a utility library

14:10 along with like 30 components

14:28 neoncontrails: Is any particular data type implied by the term 'register'?

14:29 I typically think of registers as lists, but must they be?

14:29 rhg135: stacks maybe

14:31 I always hear 'push onto' which screams stack

14:32 neoncontrails: Yeah that's true. Would it be preposterous to call a string a register?

14:33 rhg135: it technically could be used as one

14:34 but semantically, they're very different

14:38 neoncontrails: Yeah that's sort of what I was thinking too. Thanks, just wanted to make sure it wouldn't be wildly inaccurate to call this generic arithmetic calculator a register machine

14:38 it's structurally like one, but uses concatenate instead of cons to build the result

14:42 mikerod: would I be correct in thinking that from a stacktrace - if I see a my.ns.name__init.<clinit> in it that that means that it is an AOT-compiled loading path vs no AOT files present?

14:43 I guess what I mean is, is it true that my.ns.name__init does not exist at all if there is no AOT compilation

14:43 in a purely JIT world, there are no classes loaded that have a name suffixed with __init

14:53 rhg135: I think that file gets compiled on load even on no aot

14:57 mikerod: rhg135: I was trying to determine if that were true or not

14:58 rhg135: i may be wrong though

15:00 mikerod: I don't see anywhere in clojure.lang.Compiler that refers to that suffix other than Compiler.compile() which is for AOT

15:01 I searched all over for both RT.LOADER_SUFFIX

15:01 and __init strings

15:01 and when I track the JIT compile path, I don't see any place that'd be generated. it is meant to compile the ns itself, so it may not have any place in the JIT world

15:02 this was just something helpful in troubleshooting a crazy classloader issue with some mixed AOT (bad). I started thinking the presence of the my.ns__init at all meant there was loading off of AOT classes

15:09 RedNifre: So I just started with the REPL and for fun, I tried (def man doc) but it says "can't take value of a macro". What does that mean?

15:09 jeremyheiler: ,(doc doc)

15:09 clojurebot: "([name]); Prints documentation for a var or special form given its name"

15:09 jeremyheiler: ,(source doc)

15:09 clojurebot: Source not found\n

15:09 rhg135: that doc is a macro

15:09 jeremyheiler: yeah

15:10 RedNifre: does that mean that it only works when I type it in the REPL? That it's sort of not meant to be used in the code? Or is it more complicated and I should learn about macros first?

15:11 jeremyheiler: macros are code that generate code, and cannot be referenced

15:11 they only exist at compile time, not runtime

15:11 rhg135: you can't pass it around like a function

15:12 ,+

15:12 clojurebot: #object[clojure.core$_PLUS_ 0x281717fa "clojure.core$_PLUS_@281717fa"]

15:12 rhg135: ,doc

15:12 clojurebot: #error {\n :cause "Can't take value of a macro: #'clojure.repl/doc"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Can't take value of a macro: #'clojure.repl/doc, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6704]}\n {:type java.lang.RuntimeException\n :message "Can't take value of a macro: #'clojure....

15:16 justin_smith: RedNifre: also, the repl uses clojure.repl (which includes doc), and your files won't have access to clojure.repl unless you explicitly require it

15:16 RedNifre: but usually you only need the stuff from clojure.repl in ... a repl

15:16 RedNifre: makes sense

15:17 mungojelly: i guess the reason macros and functions are both all lower case is so you can add an optional different shape to a function that already has callers?!

15:17 justin_smith: mungojelly: what does that even mean?

15:18 mungojelly: if you're not going to change existing function calls silently to macros, then it would make sense to distinguish them so you can see in the code if things are macros, so i assume the invisibility is to sneak them in like that

15:18 justin_smith: functions and macros are both lower case because that's how it's been as long as lisps have been case sensitive, upper case macros are a convention in languages with crappy macros that only do string substitution, because string substitution breaks things in really weird ways

15:19 mungojelly: i'm just talking about for readability, in clojure you have to guess whether things are macros or not, a lot of stuff is like, how does this function do this, oh ok it's all macros it turns out, all lower case just means "function or macro" and you have to learn/guess/experiment to know which is which

15:20 jeremyheiler: "all lower case" is just the status quo in clojure

15:20 justin_smith: mungojelly: the assumption that a macro would not be lower case is newer than lisp macros are

15:20 mungojelly: it's become "obvious" to me that defn is a macro, but it gradually got "obvious" over the course of several weeks of getting accustomed to it

15:21 RedNifre: By the way, how far does clojure go on the functional side? Are things like curried functions, monads etc. included?

15:21 ToBeReplaced: i would consider a change from function to macro a breaking, non-backwards compatible change in any library

15:21 justin_smith: RedNifre: neither of those. Because we get varargs and dynamic typing instead, respectively

15:21 mungojelly: someone a couple days ago here was talking about writing their own currying so that must not be there? there's monads somewhere but no one uses them

15:22 ToBeReplaced: then do you think there's any reason to have the same style for them?

15:22 justin_smith: RedNifre: but the normal data types are all immutable

15:22 ToBeReplaced: mungojelly: no, i loosely agree that i'd rather see a naming convention for macros that distinguishes them from functions

15:23 RedNifre: Why is "defn" a macro instead of a function? Is it to not allow strange programs that define functions at runtime?

15:23 justin_smith: RedNifre: the opposite, because you can't use macros first class

15:23 wait...

15:23 mungojelly: RedNifre: it's just to write the syntax of it, to make it shaped the way it is

15:23 amalloy: RedNifre: here is one of the basic things distinguishing macros from functions

15:24 ToBeReplaced: RedNifre: "intern" is the function it calls... it's just convenience around that

15:24 amalloy: functions always evaluate all of their arguments before running the function

15:24 RedNifre: awww

15:24 amalloy: so if defn were a function, (defn foo [x] 1) would evaluate foo (which doesn't exist), then [x], (which doesn't exist), and then 1

15:24 RedNifre: I was hoping for Io-like "lazy if you want" evaluation of parameters.

15:24 justin_smith: nope!

15:24 mungojelly: yeah a macro is like, wait, hold on, before you evaluate those things, i'm gonna rearrange them a little, ok now evaluate them

15:26 RedNifre: If Clojure has strict evaluation, how can the defn macro use a regular function internally? How to write a function body without evaluating it?

15:27 justin_smith: RedNifre: btw you can do (defmacro man [& args] (cons 'doc args))

15:27 mungojelly: fn is a "special form" right? even more powerful yet

15:27 rhg135: quoting

15:28 mungojelly: and there's some built-in reader macros that look for some ~*!@*~&!@ around words but there's no (easy) way to add more of those

15:28 rhg135: and code is just data

15:28 amalloy: RedNifre: various "special forms" have special evaluation rules

15:28 RedNifre: I guess I'll have to read more of the book before I drown in an endless sea of further questions (currently reading "seven languages in seven weeks")

15:28 ToBeReplaced: RedNifre: "intern" is the "def" part, "fn" is the special form part

15:28 amalloy: eg, "if" is a special form, whose evaluation rule is different from the rule for function calls

15:29 neoncontrails: RedNifre: These are awesome questions, but don't worry if none of this makes sense to you yet. Macros are without a doubt the most advanced feature of the language, and I noticed in #clojure-beginners you're literally beginning your first REPL session

15:29 RedNifre: ah, so I guess (defn id [a] a) is a macro for something like (intern "id" ["a"] '(getParam "a")) huh?

15:30 rhg135: sorta

15:30 justin_smith: RedNifre: 'a instead of "a", and it uses the fn special form

15:30 and then fn calls fn* which calls some java

15:30 RedNifre: Yes, I'm in my first REPL session and in the first Clojure chapter of the book :)

15:31 amalloy: RedNifre: that is the general idea, yes. wrong in basically every particular, but going in the right direction

15:31 mungojelly: ,(macroexpand '(defn twice [n] (* n 2)))

15:32 rhg135: clojurebot is gone

15:32 mungojelly: :(

15:33 ToBeReplaced: in case it's of interest... i wrote a lib a while back that uses intern to programmatically create public functions instead of writing a bunch of defns: https://github.com/ToBeReplaced/lettercase/blob/master/src/org/tobereplaced/lettercase.clj#L11

15:33 oddcully: so we are finally botfree

15:33 RedNifre: humans win

15:33 oddcully: jay!

15:33 neoncontrails: I noticed that. Who maintains clojurebot? I feel moved to help

15:34 mungojelly: i think it's hiredman

15:35 neoncontrails: hiredman: do you need more hands to help with Clojurebot?

15:40 hiredman: nope

15:42 RedNifre: I don't understand why (< 1) is true but (<) is not allowed. My intuition is that (<) should also be true.

15:43 ...because all elements or an empty list are ordered in accending order, like all elements in a list with one element in it.

15:44 justin_smith: RedNifre: that's actually a fair point, and you're not the first one to bring it up here

15:44 ,(=)

15:44 amalloy: justin_smith: it's more true for = than for < though

15:45 i think gfredericks argued fairly convincingly on that point last time

15:45 justin_smith: right, I was attempting to provide an even better example

15:45 amalloy: notably, RedNifre, you'd lose the "law" that < is the inverse of >=

15:46 RedNifre: Is it? What about (< 1) vs (>= 1)? Both are true...

15:46 amalloy: oh, are they? i guess so. i take it back then

15:49 RedNifre: How much success did you have trying to introduce Clojure at the office?

15:49 neoncontrails: I've always just thought of < > as functions with a fixed arity of 1 or 2, defaulting to true in the base case

15:49 Is that not right?

15:49 RedNifre: No, you can also do (< 1 2 3) -> true or (< 1 2 3 1) -> false

15:50 neoncontrails: Oh interesting. That's more consistent with other arithmetic functions, I suppose

15:50 RedNifre: I tried (< 1) and was surprised that it worked, then I remembered that + works for varargs, so it made sense to try (< 1 2 3) which worked and (<) which didn't.

15:51 Strange, (+) is 0 but (-) isn't allowed.

15:52 (*) is 1, which makes sense, so I guess it gives me the Monoid for * or +, but why not for - or /? Shouldn't (-) be 0 and (/) be 1?

15:53 amalloy: RedNifre: - and / aren't monoids either way, because they're not associative

15:53 RedNifre: point taken

16:00 neoncontrails: amalloy: Not to sound creepy, but do you blog? I feel like I could learn a lot from you

16:01 amalloy: no. i wrote a few articles several years ago, mostly about clojure, when i was working at hubpages

16:02 http://amalloy.hubpages.com/ confuses me, because it says i have 7 articles but only lists 4 of them and i don't see any way to find the rest

16:02 neoncontrails: If you ever feel inspired to start one, I'd love to read it.

16:05 Even reading your solutions to 4clojure-like problems (if not those problems exactly) would be a great resource. Your solutions remind me of what good code can look like

16:05 amalloy: you can mostly find my writings on stack overflow and in #clojure

16:05 neoncontrails: well, so look at my 4clojure solutions then

16:05 neoncontrails: Heh, I didn't know they were published. I'll go look

16:06 amalloy: although actually not all of them are things i would endorse; i replaced my solutions with other users' solutions if they reported a bug like "hey my solution to #43 isn't working"

16:06 neoncontrails: (almost) everyone's 4clojure solutions are published

16:06 once you solve a problem, you can see anyone's solution unless they opt out

16:07 neoncontrails: I noticed yeah. Which is a cool idea, but certain problems I couldn't solve right away

16:09 shem: it is edifying to see good code in small portions.

16:10 justin_smith: yeah, that makes the bots very useful, when they are here

16:10 but bot-running is a chore

16:14 RedNifre: I just noticed that nil behaves like an empty list/set/map/string etc. but not as 0 in (+ nil) or 1 in (* nil). So I guess the rule for nil is that it's an empty container? Or what exactly?

16:14 justin_smith: RedNifre: it is equal to the Java NULL

16:15 RedNifre: but you can't (map count nil) in java and get an empty map.

16:15 justin_smith: RedNifre: and not equal to 0, and overloaded with the empty list for cons, and overloaded with false for truth checks

16:16 RedNifre: also seq treats nil as an empty sequence (and eg. map, filter, etc. call seq on their last arg)

16:16 RedNifre: ah, that makes sense.

16:16 justin_smith: it's a weird mix of historical reason stuff

16:16 lodin_: RedNifre: seq of an empty collection returns nil.

16:16 ,(seq {})

16:17 justin_smith: but for our particular lineage, equality with 0 is not part of the heritage

16:17 lodin_: No bot?

16:17 RedNifre: Regarding other languages, what do you think of Scala, Erlang and Haskell?

16:17 bot broke earlier today.

16:18 justin_smith: Scala isn't simple enough, Haskell is great but makes me feel stupid, I haven't tried Erlang

16:20 neoncontrails: Heh. Yeah, the evaluation of nil has taken some getting used to.

16:20 Someone pointed out to me here (was it you, justin_smith?) to use (not (seq (<your list>)) as a base case for recursion

16:21 That hasn't gotten less weird to me in the past three weeks, heh

16:21 amalloy: justin_smith probably would have told you to use empty?

16:21 justin_smith: neoncontrails: in the original lisp, a list was a cell containing the current item's value and a cell containing the address of the next cell. There was a special nil cell which meant "there is not next cell", and using that alone meant an empty list

16:21 amalloy: yes, I would have

16:22 neoncontrails: right, which enabled (null? the-empty-list) to return true right?

16:22 justin_smith: right

16:24 RedNifre: Hm, looks like I don't have "null?". Is that a 1.7 thing? I just went with the Clojure in the Ubuntu repository which is 1.6... how old is that one and how much does Clojure change between versions?

16:24 justin_smith: the current value was the Content of the Address Register, and the address of the next cell was in the Content of the Decrement Register, leading to the famous "car" and "cdr" functions (which I keep forgetting don't exist in clojure)

16:24 neoncontrails: just a wild guess, but is the presence/absence of that sentinel cell predicated on whether the language spec supports tail-end recusion?

16:24 justin_smith: no

16:25 amalloy: RedNifre: they're talking about a different language

16:25 neoncontrails: Don't they by another name? first:car::rest:cdr

16:25 justin_smith: sure, yeah

16:26 RedNifre: yeah, sorry, this is all legacy / background

16:31 lodin_: nil is actually a bit odd in Clojure I think, since it complects (to use Clojure jargon) empty collections and missing values.

16:32 justin_smith: lodin_: and falseness

16:33 neoncontrails: Scold me if I'm being a little too Louis Reasoner here: would this definition work in Clojure the way null? does in Scheme?

16:33 (defn null? [lat] (or (empty? lat) (= (first lat) nil)))

16:33 justin_smith: neoncontrails: shoudl null? return true for [nil 1] ?

16:34 neoncontrails: Aw man. Right you are

16:34 justin_smith: neoncontrails: try (comp nil? seq)

16:35 lodin_: That too. I would probably be OK with empty collections being false though (like empty list in Python is false), which they're not in Clojure, so you have to seq it.

16:35 justin_smith: except I think that gives a result you wouldn't expect for ""

16:35 #(and (coll? %) (nil? (seq %))) something like this maybe?

16:36 amalloy: justin_smith: should it return false for nil?

16:36 justin_smith: oh, right

16:36 :P

16:36 so wrap the whole thing in a (or (nil? %) (and ...))

16:37 which probably still gets it wrong for some case

16:37 RedNifre: Hm, I'm not sure I understand varargs and "empty?"... this gives me "array is not a function" or "empty list is not a function" errors... but I thought the "empty?" check would preventh that? What's wrong with this: (defn >>= [maybe & f] (if (empty? f) maybe (if (= maybe nil) nil (>>= (apply (first f) [maybe]) (rest f)))))

16:38 I'm trying to use it like (>>= "hello" count #(+ 3 %))

16:40 justin_smith: RedNifre: that (rest f) adds a new level of list nesting at each recursion

16:40 maybe you want (apply >>= ...)

16:41 RedNifre: oh, right, the list counts as one parameter... good catch...

16:41 I guess apply also works with multiple lists, huh?

16:41 justin_smith: it works with multiple args, only the last arg is unpacked

16:41 lodin_: RedNifre: And you don't need (apply (first f) [arg]), just do ((first f) arg).

16:42 justin_smith: unless you expect to unpack arg...

16:42 which does not seem correct here

16:42 oh wait, the vector, hah, neverm ind

16:42 yeah, drop the apply and the vector

16:43 lodin_: RedNifre: The base case, so to speak, of apply takes a function and a sequence. Then there's convenience forms that essentially conses stuff onto the args.

16:44 RedNifre: great, this works now: (defn >>= [maybe & f] (if (empty? f) maybe (if (= maybe nil) nil (apply >>= ((first f) maybe) (rest f)))))

16:44 justin_smith: (+ 1 2 3) (apply + 1 2 [3]) (apply + 1 [2 3]) and (apply + [1 2 3]) are all the same thing

16:45 lodin_: RedNifre: See also some-> btw.

16:46 RedNifre: Hm, I don't understand the doc for some-> and (some-> "hello" count #(+ 3 %)) gives me something odd...

16:46 justin_smith: RedNifre: some-> rewrites forms

16:47 it would work if you changed #(+ 3 %) to (+ 3) or (#(+ 3 %))

16:49 RedNifre: indeed it does but I neither understand why nor what "rewrites forms" means.

16:49 But it's getting late anyway, gotta go.

16:49 Well, the language looks interesting, so I guess I'll be here again tomorrow :)

16:49 justin_smith: RedNifre: try (macroexpand '(some-> "hello" count))

16:49 it's a macro, it rewrites the code before compiling it

16:50 RedNifre: admittedly (macroexpand '(-> "hello" count)) is much easier to read, and gives almost as much information (given that some-> is much like -> ...)

16:51 RedNifre: Hm, I peeked ahead, macros are part of chapter two so I'll hopefully be wiser tomorrow ;)

16:51 Thank you all for your help and have a good night.

16:51 justin_smith: you too

16:54 lodin_: I think maybe I will start to call macros "user-defined keywords".

16:54 justin_smith: lodin_: but we already have something called keywords

16:55 lodin_: Haha, yes. So "User-defined syntax keywords"?

16:55 justin_smith: lodin_: "user defined syntax"

16:56 because it doesn't just define a symbol, it defines a syntax for evaluation

16:56 or else it didn't need to be a macro

16:58 lodin_: justin_smith: I wanted to avoid syntax because I think non-lisp people associate syntax with stuff like semicolons, where the brackets to, if a comma is allowed at the end of a list, if whitespaces matters, etc.

16:58 And keywords are not thought of as syntax, but rather language features.

16:58 amalloy: lodin_: stuff like, whether you need []s around the bindings in a let?

16:59 lodin_: amalloy: Or that you have [] instead of () in bindings. And #{} for literal sets, etc.

17:00 amalloy: right, my point is that that *is* syntax, and it's exactly what macros do

17:00 let is a macro

17:03 lodin_: amalloy: Right. So is defn, but in most other languages I think people would think of it as "the keyword for defining a function".

17:04 amalloy: i don't think that's true at all. java and c, for example, don't have any keyword for defining a function

17:04 lodin_: amalloy: "class"?

17:06 mungojelly: people associate syntax with getting confused by syntax which is why they should associate macros with syntax so they'll know what's going on when they're confused by the syntax of macros

17:07 amalloy: a keyword indeed, for defining a class

17:09 mungojelly: project naming around here is funny! i feel like i'm supposed to think of just one quirky word for my names! but i think i'm going to go with stringplayground

17:20 lodin_: mungojelly, amalloy: I've found that people that do not know any lisp but are sufficiently interested think that writing macros is what you do all day as a lisp programmer. I've read and heard people be hindered in learning Clojure because of it, because they think they should write a macro to solve the problem (or "write a program to write the program"), rather than just solving it directly.

17:30 neoncontrails: justin_smith: curious. Why is this? http://pastebin.com/N0PTgx6a

17:34 lodin_: neoncontrails: null-v2? always returns true (because it returns a function).

17:38 neoncontrails: Hmm. I see that you're right, I must've mistranslated his idea

17:39 irctc: Hi everyone. :)

17:39 lodin_: neoncontrails: When he wrote (comp nil? seq) he ment the function seq. Not as a placeholder for a sequence.

17:40 *meant

17:40 neoncontrails: Oh! That makes sense

17:40 lodin_: neoncontrails: So (def null-v2? (comp nil? seq))

17:40 irctc: Does anyone know how to refer to an actual html file from compojure handler without actually writing views functions with Hiccup html generating?

17:41 I want to simply point to an existing html file, not to a function that will generate it.

17:48 does anyone have experience doing this in Compojure?

17:49 lodin_: irctc: I don't really, but would compojure.route/files function help you?

17:51 irctc: I tried with ring resource-response but that didn't seem to work.

17:52 Thanks lodin_ that seems like it could help. I'll test it out in a min and get back to you with the results. :)

17:59 lodin_ for some reason it just skips over my designated route and evaluates true for a route which accepts some parameters.

18:00 Maybe I'm not using it right. I am new to Clojure so maybe I'm not doing something as I should.

18:01 lodin_: irctc: Haven't really used compojure, so I'm not of much help I'm afraid.

18:03 irctc: Ok, thanks for pointing me to some resources though. I appreciate that. :)

18:13 hlolli: ,(defn debug [s] (prn s))

18:14 ,(defn quoted-prn [f] (prn `@f))

18:14 ,(quted-prn (debug "dontcare"))

18:15 sandbox broken?

18:15 ,(quoted-prn (debug "dontcare"))

18:17 How can I deref an arity and symbolic quote it?

18:17 lodin_: hlolli: Huh?

18:17 hlolli: the `~ and ~@ dont work

18:18 lodin_: hlolli: What do you want to achieve?

18:19 hlolli: In what I wrote above Id want it to print (#'sandbox/debug "dontcare")

18:20 lodin_: hlolli: Then you want to resolve 'debug, using the function resolve.

18:20 CVTJNII: What is the best way in Clojure to perform a function on two contiguous values in a vector, returning a vector that is one entry shorter? So say if I have [ 1 2 3 4 5 ] and I want to add contiguous entries, getting [ 3 5 7 9 ].

18:21 hlolli: you mean `(resolve f) instead of `@f ?

18:22 lodin_: CVTJNII: Don't know about best, but you could do (map + x (rest x)) where x is your vector.

18:23 hlolli: f will be a list containing the symbol 'debug and the string "dontcare".

18:23 CVTJNII: lodin_, That's a lot better than what I thought I'd have to do, thanks

18:24 lodin_: CVTJNII: map is extra nice in that it works on functions with higher arities than one.

18:25 hlolli: all I get is (clojure.core/resolve sandbox.quoted-prn/f)

18:26 sorry if I mistunderstand you

18:26 lodin_: hlolli: What is it you want to do again? Really.

18:26 hlolli: ,(defn debug [s] (prn s))

18:26 ,(defn quoted-prn [f] (prn `(resolve f)))

18:26 lodin_: Wait. You're not using defmacro.

18:27 hlolli: ,(quoted-prn (debug "dontcare"))

18:27 hoping for (#'sandbox/debug

18:27 "dontcare")

18:30 lodin_: hlolli: I'm still not really sure what you want to do, but you probably want to use defmacro somewhere.

18:31 hlolli: hmm yes, when you mention it

18:33 lodin_: hlolli: If you use defmacro, the values that you get in your parameters are unevaluated Clojure forms, which is probably want you want. Don't use ` or anything in there yet.

18:35 hlolli: yes, I think so too. But maybe it doesnt matter that Im calling from (clojure.core/quote namespace.function arg) instead of (namespace/function arg)

18:36 lodin_: hlolli: ?

18:36 hlolli: nevermind :)

18:37 my technical english is also bad.

18:39 lodin_: hlolli: Just see what happens if you do (defmacro quoted-prn [f] (prn f)).

18:41 hlolli: It will print correctly, still doesnt give me namespace before the function name.

18:43 only if I symbolic-quote it as argument... but maybe I wont need it in my case...

18:43 symbolic-quote I mean ` symbol

18:43 lodin_: hlolli: You shouldn't do syntax quote (is the proper term, I think) at all in this case.

18:44 hlolli: What you get is unevaluated, meaning that the symbol is just a symbol. It's up to you to decide what to do with it.

18:44 hlolli: yes I think so too, thanks so much

18:45 lodin_: hlolli: Which is why you need resolve. Resolves looks up what's associated with a symbol in the namespace.

18:45 s/Resolves/resolve/.

18:46 TEttinger: clojurebot seems down. hiredman, no rush, but is clojurebot easy to bring back?

18:47 hiredman: yeah, just got oomkilled

18:48 lodin_: hlolli: Note that it will only work if you have something that resolves as the first value in your form.

18:48 TEttinger: thanks hiredman

19:04 Trioxin: I should be able to run Clojure on rPI no problem right

19:04 it comes with JVM on it

19:05 maybe even arduino too?

19:07 spoofednoob: on a raspberry you are better served with Clojurescript/nodejs

19:09 for arduino you are out of luck ;)

19:27 irctc: Take care everyone. Good night! :)

19:40 triss: hey all.. just raised a jira about allowing messages to be specified for pre and post conditions: http://dev.clojure.org/jira/browse/CLJ-1817

19:41 would somebody mind checking it for anything I might have missed?

19:41 all comments much appreciated!

19:57 erm I accidentally inserted my ticket twice? can i delete it or is leaving an apologetic message the only way to get rid of it?

19:58 oh poop... bit worried that all made quite a bit of email noise and stuff. sorry if anyone recieved it!

20:07 mungojelly: triss: i'm new here but i think that idea sounds awesome, i've been wanting more places in clojure to put strings explaining

20:12 amalloy: just send them an email apologizing for the excess emails

20:18 triss: amalloy: sounds like a plan!

20:19 cheers mungojelly... pleased someone thinks its a reasonable idea!

20:19 mungojelly: just to be clear, the "core" ns means nothing, and this core.clj has no particular purpose and i should just delete it and put a nameofminethatmakessensetome.clj?

20:21 triss: i think it's the best sweet spot between the idea that code is just self documenting (which it isn't), and sprinkling random observations around (which just get out of date or are noise), if there's text attached to it in an actually meaningful way, then it really accurately explains itself. but idk that's just my guesses/intuitions.

20:22 i'm thinking for stringplayground i'm going to start with a stringplayground.sandbox and then next i'm planning to add stringplayground.slides which will be blending infinite string sequences and then stringplayground.swingset can be a gui frontend 8)

20:25 triss: mungojelly: I like to think so. Error messages make nice docs sometimes.

20:25 mungojelly: one of my favorite parts of clojure so far is the idiom of bringing in a long .ed name into a shorthand form, like it's something.thingy.blah so it's :as s.t.blah or whatever, and then if you read the file you can expand that shorthand in your mind, it's succinct without being um encoded

22:28 how can i get "lein test" to run inline unit tests? i tried putting (with-test ...) around things and it doesn't see them?

22:35 or should i use midje?

22:44 justin_smith: mungojelly: lein test looks for files under test/ in your project, and loads those, it doesn't load regular namespaces for test definitions directly

22:47 mungojelly: am i missing some benefit to putting tests separate from other code? why not mix them?

22:48 justin_smith: it's just a preference thing I think

22:48 I don't have a strong opinion on it myself

22:49 mungojelly: as a workaround you could make test/foo/bar_test.clj that just requires your regular ns, and that would make the test definitions load so that lein test runs them

22:49 it's a little silly, but it would work

22:49 mungojelly: well i'm looking instead at midje, it seems sensible and interesting so far

22:50 justin_smith: lein test and clojure.test are two different things btw

22:50 clojure.test is part of clojure itself, lein test is just a tool using it

22:55 mungojelly: hmm, midje has an infix bit to its syntax with the => thing so someone called it "faux infix" that's funny, it's like infix is so rare around here it doesn't register as existing even if it does

22:55 justin_smith: it's called "faux infix" because clojure doesn't start by resolving => and applying it to the surrounding forms

22:55 because there's no way to make clojure do that

22:55 so it's faux

22:56 mungojelly: ok sure i see, it has a prefix too so it doesn't actually infix

22:57 i think it's pretty whatever you call it, the prefixing and then infixing, very readable

22:57 justin_smith: the "fact" is the part of the form that clojure resolves, and the fact macro is the thing that looks for => and generates the resulting forms

22:58 mungojelly: it does make sense to choose who gets to decide the syntax, and "the middle" isn't as defined a place as the beginning. hmm, the end is perfectly well defined too but i've never heard of any backwards lisps.

22:59 justin_smith: mungojelly: forth works that way

22:59 mungojelly: no it's just endless, i mean just like lisp syntax but reversed

22:59 justin_smith: the funny thing, with postfix you don't need parens - the interpreter / compiler whatever just invokes each word as it gets to it

22:59 mungojelly: ((n 2 +) [n] foo defn)

23:00 justin_smith: mungojelly: what I'm saying is that because it is postfix it doesn't need parens

23:00 so they don't use them

23:00 mungojelly: you don't need them if you otherwise distinguish who gets to determine the syntax

23:00 forth just is lacking in syntax, thus why everyone hates it i suppose, i found it fun enough, but i didn't make anything serious with it

23:01 but if you do a reverse lisp then you can have the last element be a macro that decides what happens with the evaluation of the earlier elements

Logging service provided by n01se.net