This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-07-02
Channels
- # announcements (1)
- # beginners (119)
- # calva (2)
- # cider (40)
- # cljsrn (14)
- # clojure (145)
- # clojure-dev (122)
- # clojure-europe (4)
- # clojure-italy (9)
- # clojure-nl (5)
- # clojure-spec (2)
- # clojure-uk (32)
- # clojuredesign-podcast (1)
- # clojurescript (10)
- # cursive (44)
- # data-science (1)
- # datomic (53)
- # defnpodcast (6)
- # emacs (6)
- # fulcro (13)
- # garden (25)
- # graalvm (3)
- # graphql (7)
- # jobs (3)
- # liberator (4)
- # nrepl (1)
- # off-topic (21)
- # quil (27)
- # reagent (4)
- # reitit (2)
- # remote-jobs (1)
- # ring-swagger (3)
- # shadow-cljs (3)
- # spacemacs (24)
- # sql (29)
- # tools-deps (68)
- # xtdb (2)
@jeff.terrell probably not, though I ran into this when I was calling map
from a macro which was making use of a helper function to create gensyms, and it's possible that the resulting code would have been problematic. I write macros so very rarely...
Makes sense. Yeah I think I can see how that could be a problem in some cases. BTW in case it's helpful: https://jeffterrell.tech/posts/2016-04-29-macros/
Also, it occurs to me that a rule of thumb about not using an auto-gensym'd symbol outside of its enclosing backtick would avoid problems—at least the problems I can think of.
in this case, I'm creating a drop-in replacement for an existing defn
-like as a compatibility shim that wraps the body/arities in some tracing code, so a macro is unavoidable
Anyone use a clojure based migration tool, or do you just follow simple conventions?
@theeternalpulse We basically built our own Clojure based tool to replace an earlier script&ant based version.
I saw one just called "migrations" on github
I think if we'd been starting that piece of the project after we had adopted Clojure, we'd probably have used one of the existing libraries.
at least I have a few choices to pick from
I think these are all good enough. thanks for the options
I don't understand what are trade-offs of selecting one of these.
ragtime seems to allow you to specify the commands within edn itself, instead of sql files, which is nice
Yeah, that seems like a nice approach. We've ended up with SQL migrations and code migrations run separately (and manually coordinated). Migratus would have allowed us to integrate that. It also tries to solve the distributed development issue of migrations being added on multiple branches.
It's like our homegrown system -- and that does sometimes require careful coordination and renaming 😐
it reminds me a lot of rails migrations, except I've always thought those should be written as sql
Miagratus of Ragtime?
migratus does seem to have completeness over simplicity
Today we have about 800 migrations and our system supports dev-only as well as all-tier migrations so we can automate testing data setup as well as general schema changes etc. We've never needed down migrations tho', just up.
my goal is to coordinate some docker containers with compose and up one db container with the migrations
I'm still learning that whole thing so i'm slow to start my project, but it's always something I wanted to learn
the whole deploy coordination stack
I've been using ruby forever and even on non-ruby projects we use capistrano since it's so nice
Do you use it from Clojure?
I see.
What approach do you feel is better between Mount
and Integrant/Duct
?
I'm curious about trade-offs of both approaches.
Duct is a way to structure web apps with Integrant being one of its opinions.
@mloayzag I've wrote web app with Mount and Pedestal, now I'm reading Duct/Integrant codebase.
I like Mount approach better.
@jaihindh.reddy I've seen Duct only with Integrant. What do you mean by it's opinion?
Duct is a set of opinions on building a web app (much like Luminus), and one of the choices it made is Integrant
Integrant and Component require you to treat namespaces as purely code organisation constructs (which is what they're meant for), and indicate application state explicitly by implementing the protocol(s) and multimethods respectively.
Whereas Mount uses nses for both code organisation and state mgmt.
I found Integrant easiest to understand and the most data-oriented. Haven't built an app with Mount so my opinion is just that, an opinion.
Agreed. I was just saying the opinions of Integrant made sense to me.
>Keys in a Duct configuration are expected to initiate into functions that transform a configuration map. There are two broad types: profiles, which merge their value into the configuration, and modules, which provide more complex manipulation. https://github.com/duct-framework/duct#structure What is difference between Profiles and Modules concepts in Duct?
Modules are explained here: https://github.com/duct-framework/core#modules Haven't used Duct so can't speak to what profiles are. There were some design discussions about having something less expressive than modules, so maybe profiles are the result of that. I'm sure you'll get more help in #duct
if anything Mount is more opinionated, it forces you to use the namespace system for its own purposes
Hi there. What's the tools.deps
command equivalent to lein deps
? (just resolve and download project dependencies, do not start a REPL, do not start the app).
I use olical/depot
after watching @U04V70XH6’s videos on his dotclojure setup
https://github.com/seancorfield/dot-clojure
Can't find the link to the video now, but that's the repo ☝️
You end up just doing: clj -A:outdated
If it's just to download ahead of time I think people use things like clojure -Spath > /dev/null
or similar. Just do some small operation and it'll sync all of your dependencies to do so.
Note that, just like you occasionally needed lein clean
if your dependencies got stale / messed up, with deps.edn
you very occasionally need rm -rf .cpcache
to remove cached deps/paths. You only really need lein deps
if you're working with containers (to create a cache of dependencies) and the same is true with deps.edn
-- clj -Spath > /dev/null
is really only needed with containers.
(And @U08715BSS depot is great but not relevant to this question)
Thanks guys 🙏 went for my old clojure -e "(System/exit 0)"
, but admittedly clojure -Spath > /dev/null
is a smart upgrade :spock-hand:
Is there a recommended way to serialize a Clojure data structure to a string in a way that ensures that it can be deserialized properly at a later point?
We’ve tried with prn-str
and clojure.edn/read-string
, but encountered a problem where the printing would include a tagged literal representing an object, which could not be read by read-string
at a later point. I wonder if there’s a standard way to print Clojure data structures that would prevent such things from happening.
There are several ways to tell the reader what to do if it encounters an unknown tagged literal. Supporting this was an explicit design goal of tagged literals. While it’s good to ask questions about the printing side, also don’t be so quick to give up on the reading.
hi. guys, lein doesn't seem to run my test.check test...
lein test
lein test playground.core-test
Ran 0 tests containing 0 assertions.
0 failures, 0 errors.
(ns playground.core-test
(:require [clojure.test.check :as tc]
[clojure.test.check.generators :as gen]
[clojure.test.check.properties :as prop]))
(def sort-idempotent-prop
(prop/for-all [v (gen/vector gen/small-integer)]
(= (sort v) (sort (sort v)))))
(tc/quick-check 100 sort-idempotent-prop)
what am I missing?
run-tests
can't find sort-idempotent-prop
because it doesn't have :test
metadata (which deftest
, defspec
add for you)
same with repl...
playground.core=> (clojure.test/run-tests)
Testing playground.core
Ran 0 tests containing 0 assertions.
0 failures, 0 errors.
{:test 0, :pass 0, :fail 0, :error 0, :type :summary}
If you want use it with clojure.test
, you have to use defspec
:
https://github.com/clojure/test.check/blob/master/doc/intro.md#clojuretest-integration
ok, I'll try that, but lein test
should work... weird... any clue there?
...or maybe I got this wrong...
> lein test
should work...
Why? I'd expect it to operate in a similar fashion, given its tight integration with clojure.test
tc/quick-check
won't be run by the clojure test runner... is this it?
IIRC, defspec
wraps the test with a call to quick-check
, parses the result and reports accordingly
I understood the problem now
thank you!
run-tests
can't find sort-idempotent-prop
because it doesn't have :test
metadata (which deftest
, defspec
add for you)
{:swagger {:post {:tags ["resources"]
:summary "Define new resource"
::swagger/parameters {:body ::resource-definition}
::swagger/responses {201 {:description "Resource created"}
400 {:generate-handler :handle-not-found
:description "Malformed resource definition"}}}
:get {:tags ["resources"]
:summary "Define new resource"
::swagger/parameters {:body ::resource-definition}
::swagger/responses {201 {:description "Resource created"}
400 {:generate-handler :handle-not-found
:description "GET Malformed resource definition"}}}}}
;; transform into
{201 {:post {:description "Resource created"}
:get {:description "Resource created"}}
400 {:post {:description "Resource created"}
:get {:generate-handler :handle-not-found
:description "GET Malformed resource definition"}}}
I thought about using spectre, but I know nothing about it - and it requires quite amount of time invested into learning.
Is there anyone familiar with specter, or other similiar utilities, to tell me if this will be doable and I should learn how to do this?
or just dump it all in a datascript database and pull what you need from it (if performance is no issue)
with a well defined schema, the actual dumping is a single line of code, normalization happens automatically
It does not sound right for very simple library… and this code will be executed inside macro, at compilation time
alright then, there are ways to execute pull syntax directly on your data structure, there was a gist about that somewhere
Its not so bad as a map, merge:
(defn reorder [resource]
(->>
(:swagger resource)
(mapcat (fn [[k v]] (map (fn [[rk rv]] {rk {k rv}}) (::swagger/responses v))))
(apply merge-with merge)))
the function in the mapcat is the isolated transform, you might be able to make it less weird, but I believe even in a dsl (like spectre) it will be weird and you will need to learn a dsl
seems pretty meander
-y http://timothypratley.blogspot.com/2019/01/meander-answer-to-map-fatigue.html
I'm not sure what you are trying to do here, but if the basic task/goal is to transform or query a heavily nested map (or a multi-type nested datastructure) then Specter is definitely what you want to reach for. Check out #specter
Also, specter does not require a lot of investment to get various tasks working just fine. If you want to understand the whole thing, yeah, that will take some time and effort, but you don't need to do anything like that for most tasks. Things that look really hard/messy in plain Clojure are often trivial in specter.
With a helper called compress
, assuming your input is x
, this is what I came up with. Doesn't seem too bad:
(defn compress
"compresses a seq of paths into a map"
[paths]
(reduce #(assoc-in % (butlast %2) (last %2)) {} paths))
(compress (for [[method desc] (:swagger x)
[status status-desc] (::swagger/responses desc)]
[status method status-desc]))
anyone know why the multi-arity version of defn
allows an attr-map
at the end? are there historical reasons for this? it's apparently merged with the attr-map toward the beginning if it's supplied
From the defn
docstring:
>name doc-string? attr-map? ([params*] prepost-map? body) + attr-map?
I asked Rich this when I discovered it while writing the spec
the idea was that the meta could potentially get large (this pre-dated some of the modern meta and defn syntax) so the idea was to put the meat of the function at the beginning and push the meta to the end, syntactically
I have only ever seen this used once or twice (I found those cases when writing the spec :)
If you have an attr-map
in both places, are they merged?
(I guess I could easily test that in the REPL but figured you might answer faster 🙂 )
user=> (defn ^:foo foo {:bar 13} ([x] (* x x)) {:quux 42})
#'user/foo
user=> (meta #'foo)
{:bar 13, :ns #object[clojure.lang.Namespace 0x4fed80ad "user"], :name foo, :file "NO_SOURCE_PATH", :column 1, :line 5, :foo true, :quux 42, :arglists ([x])}
user=>
Weird 🙂> the idea was to put the meat of the function at the beginning and push the meta to the end, syntactically
If that was the motivation, why keep the attr-map
at the beginning as well? For backward compatibility?
Hey folks, how do we sign up for jira? I tried creating an account, but all I get is “Your email address <mailto:[email protected]|[email protected]> doesn’t have access to http://clojure.atlassian.net”
if you are looking just to vote or comment tickets, I'd ask that you wait as we are working on something new for that. if you're looking to add a new ticket, you can do that at https://clojure.atlassian.net/servicedesk/customer/portal/1 without an account. if you're looking to do work on tickets, provide patches, etc, you should fill out the CA at https://clojure.org/dev/contributor_agreement and then request an account at the same portal
and https://clojure.org/dev/dev is the doc for the above
got it - i got to the jira through https://clojure.org/dev/creating_tickets which doesn’t mention the service desk piece - thanks!
Does this exception make sense to folks?
java.lang.ClassCastException: com.badlogic.gdx.physics.bullet.collision.SWIGTYPE_p_p_btCollisionObject cannot be cast to com.badlogic.gdx.physics.bullet.collision.btCollisionObject
Is the SWIGTYPE
version of btCollisionObject
something clojure came up with that makes it so it can't compare itself against the java version of the class?my first guess would be the SWIGTYPE class is the class generated by the swig tool, and the non-swig type is a wrapper class to make it easier to use
you can even find generated java docs for the swigtype if you google it (the docs are pretty empty)
Ah okay, so it's very possible the wrong kind of object is being instantiated to be compared against?
you are trying to do something with the swig type that you can only do with the non-swig type
the type error is exactly that, the jvm saying this type you are trying to pass to some method doesn't match the signature of the method
Sure, here's the block of code where the exception is being thrown:
(when entities
(doseq [^btCollisionObject body (get-bodies screen)]
(when-not (some #(= body (-> % :body :object)) entities)
(cond
(instance? btRigidBody body)
(bullet-3d! screen :remove-rigid-body body)
(instance? btSoftBody body)
(bullet-3d! screen :remove-soft-body body) ;; <== This line
)
(.dispose body))))
you are type hinting it as the wrong type, so when you call the dispose method it generates the cast, which throws the exception
So the exception says it's thrown at this line:
(bullet-3d! screen :remove-soft-body body)
But so if I understand correctly that means the bullet-3d!
is not able to handle the SWIGTYPE?
Yeah, here's what we got there:
(defmacro bullet-3d!
"Calls a single method on a `bullet-3d`."
[screen k & options]
`(let [^btDynamicsWorld object# (:object (u/get-obj ~screen :world))]
(u/call! object# ~k [email protected])))
Ah! Let me show you the rest of the exception, that'll be helpful I'm sure:
Exception in thread "LWJGL Application" java.lang.ClassCastException: com.badlogic.gdx.physics.bullet.collision.SWIGTYPE_p_p_btCollisionObject cannot be cast to com.badlogic.gdx.physics.bullet.collision.btCollisionObject
at play_clj.g3d_physics$fn__1414.invokeStatic(g3d_physics.clj:311)
at play_clj.g3d_physics$fn__1414.doInvoke(g3d_physics.clj:289)
at clojure.lang.RestFn.invoke(RestFn.java:423)
at clojure.lang.MultiFn.invoke(MultiFn.java:234)
you have a SWIGTYPE_p_p_btCollisionObject, and are trying to tell the jvm that is a btCollisionObject (it is not) and you are trying to call methods that type doesn't have