This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2016-09-19
Channels
- # bangalore-clj (35)
- # beginners (42)
- # boot (89)
- # cider (9)
- # clara (2)
- # cljs-dev (29)
- # cljsjs (3)
- # cljsrn (14)
- # clojars (9)
- # clojure (332)
- # clojure-brasil (1)
- # clojure-dev (5)
- # clojure-italy (4)
- # clojure-russia (36)
- # clojure-spec (38)
- # clojure-uk (65)
- # clojurescript (114)
- # clr (11)
- # community-development (105)
- # core-async (10)
- # cursive (4)
- # datascript (1)
- # datomic (58)
- # defnpodcast (3)
- # emacs (4)
- # hoplon (7)
- # juxt (3)
- # keechma (8)
- # off-topic (7)
- # om (109)
- # om-next (8)
- # onyx (26)
- # pedestal (3)
- # planck (8)
- # re-frame (76)
- # reagent (28)
- # rum (25)
- # spacemacs (2)
- # specter (35)
- # untangled (31)
- # yada (27)
is exceptions considered bad practice for error handling in clojure? i googled and came across https://adambard.com/blog/acceptable-error-handling-in-clojure/ post, is this the community standard for?
@fenak: I'm not sure there is a community standard, though that's a totally reasonable way to approach errors Exceptions are fine too, though
@lopalghost good - i’m writing some code that uses a java library, but don’t know how should i expose the errors to my clojure part.
yes, but you have to know how macros work
in particular that they are functions with two extra magical arguments
otherwise you will have arity issues
also depending on what you want to do it might not even make sense
i.e., you'd have to do it before compiling the relevant code that uses the macro
So you want a fmap?
hehehe. Yes, almost exactly. https://github.com/maitria/avi/blob/master/src/avi/xforms.clj
you could always um
I'm trying to make a reasonable default for the xfmap
arg that's like clojure.walk/postwalk.
I bet that
what's that library
I think it has its own protocol
no I was thinking of...
specter
welp.
@gfredericks thanks, I saw the 'magic' args
@eraserhd smells like a multimethod
Sorry for x-posting from #beginners but... kinda stalled here. Very basic question. Why does this code tell me Parameter declaration "let" should be a vector
? feels like I'm missing something small.
(defn start-socket
(let [ws-address (:url (:body (http/get (str API "/gateway") {:as :json})))]
(connect-socket ws-address)))
@eslachance translating compiler-ese: you're missing the function arguments, and the compiler thinks the let
is the args
yeah... did not catch parameters
as being the function params
added []
to first line.
I knew it was something small 😒
So, good news. Clojure 1.9 gets rids of that cryptic message and shows you something amazing
user=> (defn start-socket
(let [ws-address (:url (:body (http/get (str API "/gateway") {:as :json})))]
(connect-socket ws-address)))
CompilerException java.lang.IllegalArgumentException: Call to clojure.core/defn did not conform to spec:
In: [1] val: (let [ws-address (:url (:body (http/get (str API "/gateway") {:as :json})))] (connect-socket ws-address)) fails spec: :clojure.core.specs/arg-list at: [:args :bs :arity-1 :args] predicate: vector?
In: [1 0] val: let fails spec: :clojure.core.specs/arg-list at: [:args :bs :arity-n :bodies :args] predicate: vector?
:clojure.spec/args (start-socket (let [ws-address (:url (:body (http/get (str API "/gateway") {:as :json})))] (connect-socket ws-address)))
, compiling:(NO_SOURCE_PATH:1:1)
Is that released or still in beta?
Alright. Wasn't really that cryptic to be honest. I just glazed over the word "Parameter", even though I know exactly what that means
The let
threw me off my game. My very noobish game ^_^
No on to figure out why my websocket isn't working
Maybe you have some experience with stylefruits/gniazdo
?
I'm trying to troubleshoot this, connecting to a local websocket server works fine, but connecting to a remove wss://
address I'm not receiving the expected message (should be a HELLO of some sort)
so if I have a macro like
(defmacro ui2
[& forms]
(let [t (with-meta (gensym "ui_") {:anonymous true})]
`(do (om.next/defui ~t ~@forms) ~t)))
you can see it does gensym to get a unique name to def, let's say I call ui2 in a function e.g. (defn mk-ui [] (ui2 ...))
then I call mk-ui repeatedly in my code, since macros are expanded at compile time, how would I get a unique symbol for each call to mk-uiif that macro is expanded at compile time, it'll pick a unique symbol name once, as oppose to once per call to mk-ui
Morning, I have a question regarding clojure zippers and would appreciate some help: http://stackoverflow.com/questions/39558330/clojure-xml-zipper-walk-and-cut
@arohner there is a clojure client gen in SwaggerHub. Just poked them if that’s open source and somewhere.
Hi, how would I go about accessing a Scala implicit? A lá .toDF
liked use here https://spark.apache.org/docs/latest/sql-programming-guide.html#inferring-the-schema-using-reflection
Or a slightly different question, how do I go about using import spark.implicits._
in Clojure
@ghadi 1.9 replaces a cryptic error message with another larger cryptic error message. I personally know what it means, it's data, etc, but I doubt it makes beginners experience better ("Parameter declaration "let" should be a vector" is arguably better in that case).
I hit an annoying example earlier: a set as predicate will not even suggest what values are acceptable with s/explain*
in short, there's room for improvement (so far Schema is better at error reporting imho)
can I define recursive specs in Spec ?
hi guys
i'm trying to define trace clatrix matrix like this https://gist.github.com/aibrahim/968b6b5ecd80c7289dfa209e0d5145d2
is there a better solution than what i did?
trace is the summation of diagonal of matrix
as example:
user=> (trace-mat (cl/matrix [[1 2 3] [4 5 6] [7 8 9]])) 15.0
@abdullahibra it looks like clatrix has its own trace function; you can look at its source for a good solution at http://quantisan.github.io/clatrix/
Crossposted from #clojurescript… Deploying a uberjar to ec2 (ubuntu 14.1, openjdk 8), and I get this error which I didn’t get locally or on another local server: Failed to get driver instance for jdbcUrl=jdbc:
project.clj does seem to have the right dependency…
:dependencies [
[ring "1.5.0"]
[metosin/compojure-api "1.1.8"]
[cheshire "5.6.3"]
[clj-time "0.12.0"]
[im.chit/cronj "1.4.4"]
[hiccup "1.0.5"]
[cljs-ajax "0.5.8"]
[secretary "1.2.3"]
[reagent-utils "0.2.0"]
[reagent "0.6.0"]
[org.clojure/clojure "1.8.0"]
[org.clojure/clojurescript "1.9.229" :scope "provided" :exclusions [org.clojure/clojure]]
[selmer "1.0.7"]
[markdown-clj "0.9.89"]
[ring-middleware-format "0.7.0"]
[metosin/ring-http-response "0.8.0"]
[bouncer "1.0.0"]
[org.webjars/bootstrap "4.0.0-alpha.3"]
[org.webjars/font-awesome "4.6.3"]
[org.webjars.bower/tether "1.3.3"]
[org.clojure/tools.logging "0.3.1"]
[compojure "1.5.1"]
[ring-webjars "0.1.1"]
[ring/ring-defaults "0.2.1"]
[mount "0.1.10"]
[buddy "1.1.0"]
[cprop "0.1.9"]
[org.clojure/tools.cli "0.3.5"]
[luminus-nrepl "0.1.4"]
[abengoa/clj-stripe "1.0.4"]
[luminus-migrations "0.2.6"]
[conman "0.6.0"]
[org.postgresql/postgresql "9.4.1209"]
[org.webjars/webjars-locator-jboss-vfs "0.1.0"]
[com.novemberain/monger "3.0.2" :exclusions [com.google.guava/guava]]
[luminus-immutant "0.2.2"]]
All Google wants me to do is add org.postgresql/postgresql, which I have. Not sure how to diagnose.
@credulous you can debug your deps using lein deps :tree
@credulous some web containers fail to classloading the jdbc driver. try explicitly putting this before connection code (Class/forName "org.postgresql.Driver")
@credulous some friends of mine ran into that recently, the DATABASE_URL that Heroku gives you is not in the format that JDBC understands. There's a package to convert it https://github.com/ariaru/workshop-manager/commit/fa47e23226ee4a07c8590347fa287eeb66762032#diff-fdee768673c47c26b8e610ec61e0a508R21
still I'd look into the URL you're using, compare it with how it looks on the other server
@credulous I think @gon is right, we use Korma and we specifically tell it to load the postgresql driver.
It might be me, but (doc spit)
: "Options passed to http://clojure.java.io/writer"
and then https://clojuredocs.org/clojure.java.io/writer - what are the options?
Hi everyone. I'm trying to split a channel in to multiple channels. I'm using a file object like this {:id #uuid ..., :path "somewhere.txt"}
and I have a pub/sub channel that uses :id
as the topic. I was just wondering if that's bad practice? Having single use subscriber channels?
Do you ever need to worry about which version a clojure jar had been compiled with, using it as a dependency in your clojure application?
the answer to that is kind of complicated, largely because the recommended way to package clojure is as source, not compiled to jvm bytecode
interesting... @hiredman I'll come back for your full answer which you are composing now I think 🙂
you can do what is called AOT compilation, where you save the compiled bytecode, and people will often do that for applications (for all the wrong reasons)
and I would argue bad practice for your applications (aot compilation has quirks that will bite you)
@matan we endeavor to make Clojure largely backwards compatible. it’s relatively rare that we introduce a change that breaks that and most older Clojure code will still work today.
we also do consider whether existing AOT compiled Clojure code will be affected when we modify portions of the runtime invoked by AOT compiled code (calls to RT, Reflector, etc) and often leave shims to make that work (most people don’t encounter this both because those signatures don’t change much and because usually I test for that kind of thing in advance when I suspect it’s an issue)
one area that will be more prominent in Clojure 1.9 is that due to the added specs there was some syntax that was accepted and either worked or was ignored in the past that will now fail due to more stringent enforcement of what we considered to be accepted syntax all along
I think it’s a matter of perspective whether you consider that a “breaking" change or not.
coming form scala, it is likely you will think you need to AOT compile everything to bytecode, you don't. at best it does nothing at worst you will aot compile some open source library and someone else will try to use it and it will break everything for them
@matan @alexmiller I was working few years in a project where we were building more than dozen of micro services. One of the key reasons we started switching those services from Scala to Clojure was the backwards compatibility. With Scala we had a lot of issues with version upgrades but with Clojure usually none. So I have really good experience with Clojure upgrades.
just yesterday I finished killing the last bits of AOT in a codebase. very pleased. judicious use of Clojure.var and shock-horror java can usually get you out of it
I’m trying to create a helper fn in one namespace that, when called, defn’s some fn’s in the calling namespace. I’ve tried something like this: (defn define-fns [] (require ‘[stuff]) (defn fn1 [] (+ 1 1)) ) then call it in a namespace: (define-fns) (println (fn1)) I get a runtime ‘unable to resolve symbol’ in the calling namespace. I’ve tried adding (in-ns ‘calling.namespace) which makes no difference. 1) Is this approach a bad idea in general? (Basically it will eliminate a lot of replicated boilerplate) 2) What’s the ideomatic way to approach situations like this?
@georgek a macro as the entry point for your helper function, or just a macro altogether, would probably be a better idea. Because then the generated 'boilerplate' code gets inserted in the namespace where it was called, and evaluated there
That’s what I suspected. How do you properly define a fn in a macro? When i’ve tried: (defmacro define-things [] `(defn some-name# [v1#] (stuff))) I get wierd errors
boot.user=> (defmacro define-things
#_=> []
#_=> `(defn some-name#
#_=> [v1#]
#_=> (stuff)))
#'boot.user/define-things
boot.user=> (macroexpand
macroexpand macroexpand-1
boot.user=> (macroexpand '(define-things))
(def some-name__2332__auto__ (clojure.core/fn ([v1__2333__auto__] (boot.user/stuff))))
macroexpand is super useful with stuff like this. afaict your example should work, except stuff
is undefined and you're giving the function a random nameoh yeah, the random name is a problem. I see what I didn’t quite get w.r.t properly defining a name inside the macro. That explains why the fn I thought defined couldn’t actually be found. thanks!
@hiredman @alexmiller @mhjort @bfabry thanks a lot. so how do you deploy and start clojure applications outside a development environment then? what's the best practice?
@matan you’re going to get a variety of suggestions there but the most common will probably be to produce an "uberjar" (containing all the dependencies, but mostly in source form), and then you can just java -jar
it.
something like java -cp ... clojure.main -m your.main.namespace
where your.main.namespace contains a '-main' function works great
Or lein run
if you’re using Leiningen 🙂
(`lein uberjar` then java -jar target/myproject…-standalone.jar
for the "uberjar" approach)
one of the reasons people aot compile is to get a Main-Class for use with java's -jar flag
I really like the uberjar approach - devops doesn’t even needs to know they’re running clojure that way 🙂
@hiredman you can do that with a thin shim though, don’t need to AOT the world
plus you’re deploying a jar without any dependencies on your build toolchain
@hiredman @alexmiller Yeah, I wish there was more "best practice" out there about having a shim for -main
and dynamically loading the rest… It’s a Frequently Asked Question from folks new to Clojure.
most of my clojure projects are being deployed into some gigantic java behemoth like hadoop or google dataflow, so I have a java class that implements their required junk framework interface and then that calls into clojure. If I was doing a pure clojure app I would have a single very small clojure namespace aot'd as an entry point
if someone drafts a PR, I’m happy to add it to the http://clojure.org/guides/faq
or as a separate guide, not sure how long that would be
Heh, touché @alexmiller — someone should get right on that… quietly steps back into the shadows 🙂
thats good to know! I wasn’t aware you could AOT just -main and not everything it touches
@lambdacoder: it takes a bit of care
yeah, I just assumed since the main ns requires everything else, the whole programs gets AOT’d transitively
so java -jar
which was suggested above in this context, will it compile all the sources?
java -jar is to launch a jarfile, not compile it
java -jar will just invoke the .class file referenced in the manifest as main. so you need to have at least one compiled class, with a main method in it
You main ns doesn’t need to require anything at compile time, it can (require …)
at runtime, then (resolve …)
and call into that. So when you AOT that ns, you get just that file’s stuff (and Clojure itself, unfortunately) but the rest of your app and all its libraries remain in source form.
nice, I somehow always frowned on dynamic requires for some reason 😛
@lambdacoder @seancorfield so what should I make of the earlier suggestion above ―
> @matan you’re going to get a variety of suggestions there but the most common will probably be to produce an "uberjar" (containing all the dependencies, but mostly in source form), and then you can just java -jar
it.
?
(until the AOT transitive code bug is fixed)
@matan Like I said, you’ll get multiple suggestions 🙂
@seancorfield indeed right now they are all kind of mixed in my head what a small can of worms 🙂
@matan I think the simplest route is to run “lein uberjar” and then run “java -jar” on the *.jar file it outputs
@lambdacoder there is more to the story than that though
@lambdacoder wouldn't that AOT?
Historically, at World Singles, we’ve deployed source and used Leiningen (and now Boot) to simply run the functions we want. But we are moving toward uberjar deployment as we move to Docker since it makes devops much simpler.
oh yeah that will AOT everything
As noted above, you can set it up to AOT just your main entry point and nothing else.
fwiw,
(defn- main []
(require '[my.application.system])
(my.application.system/start))
You mean (defn -main [] …)
but yeah.
The nice thing about @hiredman’s suggestion is you can have a single JAR with multiple -main
functions in different namespaces and choose which one to run at startup time (right?).
isnt the main class just an argument of the JVM anyways?
☝️:skin-tone-2:
-m
can also take a reference to a var, so you can have an entry point function that isn't named -main
these things make me nervous deploying applications.... a position I would not like to be in. when I'm deploying stuff, the last thing I want to be thinking about is whether I'm doing something that will make it behave differently than in test environments or backfire at the language infrastructure level. there's too many other concerns to look after when deploying, it's a bad time for shoehorning.
it looks worse than it actually is
So I hope there'd be something authoritative about how all these things interrelate and recepies for what the commands should be.
There’s no One True Way.
what you’re changing is how the program’s entry point is called
not the environment or the program
@seancorfield that's why I used the plural word "recepies" 🙂
and i feel its a legacy of the java ecosystem: theres already a lot of ways to run your java programs to begin with
I'll start off with the lein approach (should I say hack?) I think. Cons: possibly one extra process to complicate managing production
you could also run your tests the same way you run production: using -m
instead of making your live environment like your test one, make your test environment like the live one
and keep developing with the repl 🙂
at that point its probably better called staging, but thats just nomenclature 🙂
@matan personally I'd go with hiredman's suggestion of java -jar clojure.main -m your.main.ns. less devops. no dependency on lein in prod. conceptually simple.
this wont be AOT, unless you want it to
@lambdacoder yep, it is just hard for me to compose the full procedure and rational about the -m approach, from the interwining comments here.
I think I'll try compiling your suggestions to StackOverflow here: http://stackoverflow.com/questions/39579669/how-to-package-and-deploy-your-clojure-application
its a two parts process: generate a jar file containing clojure and your program’s sources, then launch that on the JVM telling clojure to boot your program
lein uberjar will take care of the first, java -jar <uberjar> clojure.main -m <your main> will do the rest
unless I typo’d something
you dont need AOT to use uberjar
id just do it for the convenience of having a single jar
there are a lot of options, generally what forces you to choose between them is some outside constraint
yeah, all of this is useless if devops wants a *.war file
that being said, use lein uberjar
to build an uberjar, launch it with -m
, that don't AOT
lein can automate your entire release process actually, from pre/post build tasks to extra packaging to signing to tagging and whatnot
@lambdacoder that sounds interesting as well
check out :release-tasks in project.clj
A disclaimer about cognitive limitations: Maybe very theoretically I would manage to separate the different threads and viable methods here along with their rationalizations, but it's been a whirlwind. Some of you would be much better at cohesively explaining and rationalizing them up there for common good. http://stackoverflow.com/questions/39579669/how-to-package-and-start-your-clojure-application I will do my best in return, to contribute to clojure open source projects, like I've done elsewhere, but alas I cannot offer anything beyond that....
in the interest of completeness, lein actually defaults the Main-Class in ubjerjars to clojure.main, when you don't specify a main class to lein, so you can even leave that out when running the uberjar using -jar
As the so-called "owner" of the SO page about how to start a new scala project, I suspect this will become a popular (and more importantly useful!) page.
you don't know anything about clojure, so having you own a page about how to do stuff doesn't seem like it would be useful
i am trying to remove keys from my map. i need to apply a function over the key first to see if i need to remove it.
here is the code I have
(->> '({"1" "some-value"}
{"1/2" "some value"}
{"1-gds" "something"}
{"" ""}
{{:a :b} "some-other-value"})
(remove (fn [[k v]] (or (empty? k) (map? k)))))
1. Unhandled java.lang.UnsupportedOperationException
nth not supported on this type: PersistentArrayMap
but i get this error. I’ve no idea whythat is the error you get when you try to sequential destructure a map, which is not sequential
Hey! I want to write a few unit tests for a private function. Is this sort of thing considered legit? Best practice is considered not to test private functions?
Does it matter if you’re trying to have some sort of public api? Just put the ‘private’ stuff in a different ns?
agreed w/ @hiredman 😉 yeah exactly - i think the fact that you want to/can test it is a signal that it's some legit thing you might want to reuse or replace
even in OO-land where people tend care more about encapsulation, i've heard people say private fns are a class waiting to be extracted
@trptcolin “private fns are a namespace waiting to be extracted” 😜
Re: private functions — my experience is that I’ve often made private functions public later on as I’ve discovered uses for them beyond the namespace in which they were defined: unexpected reuse.
I used to make fns private by default at first and only expose the "API" in each namespace, but now I almost never make a fn private. That was me letting go of my decades of OOP experience and going back to me FP roots 😆
When using {:keys [foo bar baz]}
destructuring, it doesn't seem to make a difference if I use symbols or keywords in the vector. Is there a "best practice"? Or maybe something subtle I'm missing?
I think it’s still sometimes useful to specifically demark public vs private api if you’re providing code for others to use...
haha, reminds me of when I started with clojure. Oh yea, thats a utility function, make it private and this one, and this one too and, almost all the functions. And some time later I was like, uhm, what for? What does it do to make them private?
@smw thats what I just wanted to say, an api has to be exposed in its own namespace, thats what I concluded for me some time ago
@grzm I believe keywords only work by accident, and may actually blow up with the new specs for the let
form in clj 1.9
yup you're right, just checked that. but yeah I'm 100% sure symbols are the correct thing to use
boot.user=> (let [#:foo{:keys [:second]} #:foo{:second 'bar}] second)
#object[clojure.core$second__6211 0x73045ded "clojure.core$second__6211@73045ded"]
clojure.lang.Compiler$CompilerException: java.lang.IllegalArgumentException: Call to clojure.core/let did not conform to spec:
vs
boot.user=> (let [#:foo{:keys [second]} #:foo{:second 'bar}] second)
bar
That said, I wouldn't expect the first example you provided to work, as the non-namespaced part of the key isn't a keyword: only the whole thing is. (or at least that's how I think of it)
No, I'm finding it hard to read them in my own code, or the output rather. I haven't found myself writing them yet.
We’re starting down the namespaced keyword path as we’re adopting clojure.spec
. So far I’m liking the extra clarity they bring but it does mean you have to work a bit harder to prevent code becoming too dense.
I'm definitely using namespaced keywords, I'm just having trouble reading #:blah{:second 'bar :some-num 3}
the error message for that spec exception btw is a good argument that the parse tree that managed the most depth before failing should maybe come first
Hi, sorry, but I’d like to touch back to the AOT conversation. I was always under the impression that AOT is what you did with uberjar
. I’m fine with shims. I have one to use fork()
with systemd
in Ubuntu.
In: [0 0] val: #:foo{:keys [:second]} fails spec: :clojure.core.specs/local-name at: [:args :bindings :binding :sym] predicate: simple-symbol?
In: [0 0 0] val: ([:foo/keys [:second]]) fails spec: :clojure.core.specs/seq-binding-form at: [:args :bindings :binding :seq] predicate: (cat :elems :clojure.core.specs/binding-form) :rest (? (cat :amp #{(quote &)} :form :clojure.core.specs/binding-form)) :as (? (cat :as #{:as} :sym :clojure.core.specs/local-name))), Extra input
In: [0 0 0 0] val: :foo/keys fails spec: :clojure.core.specs/local-name at: [:args :bindings :binding :map :mb 0 :sym] predicate: simple-symbol?
In: [0 0 0 0] val: :foo/keys fails spec: :clojure.core.specs/seq-binding-form at: [:args :bindings :binding :map :mb 0 :seq] predicate: (cat :elems (* :clojure.core.specs/binding-form) :rest (? (cat :amp #{(quote &)} :form :clojure.core.specs/binding-form)) :as (? (cat :as #{:as} :sym :clojure.core.specs/local-name)))
In: [0 0 0 0] val: :foo/keys fails spec: :clojure.core.specs/map-bindings at: [:args :bindings :binding :map :mb 0 :map] predicate: coll?
In: [0 0 0 0] val: :foo/keys fails spec: :clojure.core.specs/map-special-binding at: [:args :bindings :binding :map :mb 0 :map] predicate: map?
In: [0 0 0 1 0] val: :second fails spec: :clojure.core.specs/ns-keys at: [:args :bindings :binding :map :nsk 1] predicate: simple-symbol?
In: [0 0 0 0] val: :foo/keys fails spec: :clojure.core.specs/map-bindings at: [:args :bindings :binding :map :msb 0] predicate: #{:as :or :syms :keys :strs}
going to quickly learn a heuristic of "jump to explanation with the longest In form" if that's common@akiva uberjar just packages up all your dependencies and resources into a jar and creates a manifest (basically). if some of those resources are compiled class files it will include them, but they don't need to be there
Gotcha. I think when I got into Clojure, whatever I had read at first was all about AOT with a few caveats and I just went with that.
@smw you can wrap in doall
@bwstearns that’s still lazy
do you intend to make that recursive?
@smw do you want the results of the calls to summarize-hits? in what data structure do you want them?
yes, or (doall (summarize-hits ...
(mapv summarize-hit hits)
would be non-lazy
@smw then I would (mapv summarize-hits hits)
(and I would change the name of that function to summarize-hit
)
Actual: java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Keyword
I assume summarize-hits
and summarize-hit
are two separate functions? Otherwise you’re calling yourself recursively there...
fwiw if you don't care about the return results of summarize-hit
then run!
is another good option
@seancorfield That's what I read it as at first. Is there any other logic? It seems like something bad should happen when it bottoms out on hit not being iterable?
(defn summarize-hit [hit]
(select-keys hit [:verb :ecr_code]))
(defn summarize-hits [hits]
;(info hits)
(mapv summarize-hit hits))
cool cool. I don't really see any particular reason why that can't be left lazy, but to each their own.
yeah, creating log output… possibly I can switch it back to lazy, but it was making debugging hell.
Also, midje is really cool. especially being able to do what amount to mocks with (provided)
and (against-background)
ha, I agree, midje is really cool, and just plain friendlier than clojure.test, but you might want to beware that most of the clojure community has decided on clojure.test, and so that's what most of the tooling and other libs are geared around. just a friendly caution
If I’m going to release something for public consumption, I might port (the easy) tests to clojure.test.
(if you do want to walk on the wild side — but slightly less wild than Midje — you could take a look at Expectations… nice, simple, idiomatic BDD-style testing)
From a style p.o.v. it’s usually not worth having a function that just maps another function over its argument — just call map (or mapv as needed) directly instead
i.e., I would not define summarize-hits
at all, just call (mapv summarize-hit hits)
where it was needed.
But I ran into some issues, so was trying to get better debugging than the error I pasted above.
I agree with sean on that. that extra layer of abstraction might obscure a better abstraction later
Yeah. I have a tendency to err the other way on this… was disappointed that you couldn’t nest anonymous function literals the other day 🙂
my only problem with long let forms is that when things go wrong, sometimes it’s hard to understand exactly which piece is breaking.
Is there any significant difference between (use)
and (require :refer :all)
? (I wouldn’t use either except when exercising things in the repl)
Someone really needs to collect all of Stuart’s posts into a blog or… waaaaait a second here.
I look forward to all of what @ericnormand and @danielcompton publish weekly but I get giddy when Stuart writes something new.