This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2016-09-21
Channels
- # alda (1)
- # bangalore-clj (1)
- # beginners (7)
- # boot (88)
- # carry (2)
- # cider (8)
- # cljs-dev (60)
- # cljsjs (2)
- # cljsrn (45)
- # clojure (255)
- # clojure-belgium (5)
- # clojure-boston (1)
- # clojure-dusseldorf (3)
- # clojure-greece (49)
- # clojure-italy (10)
- # clojure-russia (30)
- # clojure-spec (78)
- # clojure-uk (11)
- # clojurebridge (1)
- # clojurescript (80)
- # cursive (14)
- # datomic (33)
- # defnpodcast (4)
- # devcards (2)
- # dirac (15)
- # editors (23)
- # emacs (5)
- # events (11)
- # funcool (1)
- # hoplon (1)
- # juxt (1)
- # luminus (2)
- # mount (7)
- # off-topic (15)
- # om (152)
- # om-next (2)
- # onyx (17)
- # parinfer (1)
- # proton (38)
- # re-frame (35)
- # reagent (110)
- # rum (3)
- # spacemacs (3)
- # specter (51)
- # test-check (2)
- # testing (5)
- # untangled (234)
Deepest apologies, this is a dunce cap question. I have an out-of-the-way namespace, bad.core
defined in src/clj/bad/core.clj
, that does some exploratory stuff. This namespace isn't referenced in any other Clojure code, most of which lives in src/clj/good/
, and which lein actually starts: grep -rns bad src/
yields results on in bad/core.clj
, nothing outside it. However, I'm seeing that, when I launch the app via lein, at some point, bad.core
is loaded and run, and I see its side-effects (files being created and deleted). Why would Clojure be loading and running a namespace that I don't reference anywhere?
@fasiha are you using clojure.tools.namespace or anything else that walks your source path?
@bfabry hmm, I'm not using clojure.tools.namespace
specifically, I'm trying to think if anything could be walking the source path (which is not something I knew was a thing one could do)
@fasiha well, some testing libs do it, for instance midje in order to do autotesting. I don't have a big list of things that do it though. if you only want to use that namespace in development it might be simpler to just have different :source-paths in different profiles in project.clj than track it down
I believe a lot of cljs development involves watching the fs for changes and recompiling. that could be something. I don't do cljs myself though
Hm, is the syntax for Annotations ^{Annotation {}}
specialcased or something? It doesn’t seem to work through the metadata system although it looks like it
Thanks @bfabry it's most likely figwheel or possibly cljs-devtools/Dirac re-loading clj files 👿, I didn't even suspect ClojureScript-related paraphernalia because this was a Clojure-only namespace…!
~/caesium> date; and env JVM_OPTS="-XX:+UnlockDiagnosticVMOptions -XX:+LogCompilation -XX:+TraceClassLoading -XX:+PrintAssembly -XX:PrintAssemblyOptions=intel -XX:-UseCompressedOops" ~/.local/bin/lein with-profile +benchmarks test > hotspot-asm-output; and date
design questions: I have a number of namespaces which depend on each other (I struggled a bit with cyclic dependencies, but clojure makes me think harder about this 🙂 ). However, one way to decouple them, is using channels/core.async. I did that, but than, I just wondered if it makes sense to 'decouple the channels from the namespaces'. What I mean here: does it make sense to define a namespace which has as only task 'messaging', meaning, it actually only defines channels?
If so:
1. Does it make sense to implement methods to put something on a channels (and/or read from it), so that one can spec/fdef
these functions, or do spec/conform
inside and possibly other logic inside them (e.g. durability, if applicable)?
2. If defining only channels, should I use a var or atom/defstate (from tolitius/mount
). My gut feeling tells me a var (which is globally accessible?) is enough, but I always have a bit of an strange feeling with global vars (however, global atoms might be even worse).
yeah... problem with component is: your whole system has to be build around it - makes me think too much about all kinds of bloated java frameworks, not saying that component is bloated, though. component/mount is a nice discussion - but what about separating messaging in a dedicated namespace?
but I do feel the same about globals, really. I'm always struggling with anything that's global (and not a api-like function)
I would step back before messaging, it sounds like you have a code organizational issue, and are trying to solve that with messaging instead of re-organizing your code
component is very minimal (although it has been growing with each release, which is shame)
yeah, I do agree component is minimal, but still, your whole 'system' has to be build around it.
it is not global, and it separates the runtime relationship between components and the relationships between clojure namespaces
... that depends? You mean you shouldn't build your whole system around it?
and it is very flexible, at my last job some people weren't a fan of protocols, so we replaced the lifecycle protocol stuff with multimethods, which we could do with component without rewritin the library
@oscnet hello
is in my.a
@oscnet (my.a/hello (->Prec ""))
I worked for about four years on a clojure system that organized runtime state very similar to what mount does (mount didn't exist at the time), and given the chance on a new project we went with component (only worked on that for about a year)
component is great, and simple enough that if I couldn't use the library for whatever reason I would just implement it myself
@hiredman Going back again to my code: it has some organizational issues... I'll try to explain where I'm at... give me a sec 🙂. Anyway, just to be clear: I can use component just in a small fraction of my code, right? (I should check component again, probably)
a lot of code organization issues in clojure come from conflating the sort of static structure of the code (defs in namespaces) with the dynamic runtime structure of whatever you are doing
you can break up the static dependencies by saying, instead of this code being hardwired to call function f over in that namespace, it will have the function it needs to call passed in
then you can either wire that all together yourself or use something like component to do it
Allright, this is the use case:
I have two main methods: in-message
and out-message
, let's call namespace mess
😉. The names are somewhat self-explanatory. If receiving a message, the message is dispatched via a dispatcher (separate namespace) to the right handler. After the message is handled, it may send a reply. Very very basic.
So, the namespace mess
depends on dispatch
(since it just calls dispatch whenever a messages is sent to in-message
). However, if there is a reply, dispatch must call out-message
, which is in the mess
namespace.
Yeah, I could use higher order function passing, but this tends to result in a kind of pretty messy 'keep on passing a function down a few levels' and such.
- yeah, I keep struggling with these dependencies. Will check component 😛
yeah, breaking up mess
was another thought. I probably really need to do that.
so, now we're about: component or breaking up mess? - just to have your thought.
True about the messaging stuff. Will try component
. Thx!
Someone has any experience with Maven and Lightable ? It seems that maven don't run the middleware.
@hiredman @kurt-yagram I have been using component almost exclusively (trying mount when it was new several times) and I prefered it, because somehow the reloading went smoother. Also I have to disagree, I think you can perfectly use component for some components and bypass it for other stuff. Its not intended to be used like this, but totally possible.
@sveri allright, thx. I'm trying to define a system which is only part of my application now.
I've also noticed that I prefer dependency-passing in the function arguments over globals anyway. I think it would be quite easy to move from component to mount when using this pattern.
thats true, when I was trying mount I took an existing application and switched between mount and component like 3 or 4 times. All it was, was some tedious comment / uncomment
I overall prefer component as it more strongly encourages passing in state as an argument instead of referring to vars. Even if mount can be used in this way.
In Schema, how can I make a Schema that checks if two map values are identical, e.g. {:password s/Str :password-confirmation s/Str}
On https://news.ycombinator.com/item?id=11233866, I read I believe that's 220ms. Which isn't too bad. But Clojure can usually match that if you AOT everything.
As mentioned, do you AOT your clj files? Otherwise AFAIK they would be compiled by JIT which takes some time doesn’t it?
Is the default Clojure jar fully AOT?
@crocket run this java -cp clojure-1.8.0.jar clojure.main
and make sure the jar file is fully AOT
I think as soon as you include any dependencies that time will grow even with AOT
How can I optimize the startup time of https://github.com/crocket/clj-ddns-client/blob/master/project.clj?
Currently, https://github.com/crocket/clj-ddns-client#build is how I build.
@crocket not sure what that ^:skip-aot
does exactly but you may want to try without it
@crocket I just run a couple of tests, and if I run uberjared with or w/o aot I get the same time:
1.38s user 0.09s system 171% cpu 0.856 total
same goes with downloaded clojure-1.8.0.jar
time java -cp clojure-1.8.0.jar:. foo.core
Hello, World!
java -cp clojure-1.8.0.jar:. foo.core 1.38s user 0.09s system 173% cpu 0.849 total
all of that compiled with :aot :all
Clojure compilation is pretty fast! It’s the JVM and Clojure runtime startups that take all the time
well AFAIK, most of clojure's startup time actually comes from loading all the built-in namespaces and not JIT compiling code
Haskell also has a huge runtime, but startup time of a haskell program is usually fast.
because of LISP's dynamic nature, there's no way to tell what needs to be loaded so it just loads everything.
you can check out this clojure implementation for faster startups: http://clojure-android.info/skummet/
@crocket from what I've seen it's pretty decent, you can build real world stuff with it, but it doesn't have much traction, and so lacks a lot of polish
If you want to build mobile apps the clojurescript+react-native route is much more popular
both skummet and clojure-android seem to not have much activity anymore, although that might just be impression. you can ask in #clojure-android . I see an occasional burst of activity in there
these are completely different animals, they are just wrappers for a web view, react-native is very much not that
@crocket just out of curiosity, as I’m gaining speed at project in react-native, what didn’t work for you that made you look for alternatives?
I see, but I’m exploring this path: http://cljsrn.org
@crocket React doesn't prevent you from using mutation, but it doesn't prevent you from programming functionally either, I'd say it's too low-level for those considerations. Reagent, via reactions, provides something close to FRP atop React IMHO. While not perfect, I think that React-native is by far your best shot for mobile
@crocket Cordova, which is really the same thing as Phonegap, is way more limited as a platform (poor access to native functionality, and quite slow too).
note that I haven't used either platforms extensively, just heard a lot of feedback 🙂
Most people I know who tried Cordova eventually dismissed it as non viable for mobile
for mobile, you really want native, and to get native, it's either the default SDKs with their mutation-based UI kits, or React Native
because mobile web works poorly 😕 really no rational argument here, just an experience report
.. and trust me, at that point, you're not picky about what language you want, you just want a sane API
@crocket there are plenty of React wrappers out there that prove that you can live without mutation in React
look at quiescent in the Clojure community for example
@akiroz I think JavaScript has an undeserved reputation amongst Clojure programmers. Of all mainstream languages, it's the one from which the principles of Clojure are most accessible IMO (e.g immutability, data-orientation, first-class functions, polymorphism à la carte, etc.). I remember having a very bad initial reaction when I was introduced to JavaScript as a Java programmer, but then I realized that once you're past the superficial twarts it can be quite elegant and powerful.
It depends on which part of react you're referring to. It's core concept is pretty functional: - you have a data struct representing the DOM you want - react does a tree-diff against the existing data struct to find the minimal DOM operations needed to make it into the shape you want it and applies them the the actual DOM. The component API however is very much based on OOP and mutations but this part is completely optional if you're got a better way to manage your state.
maybe we're not talking about the same "component" tho, I am just realizing now (react vs clj component)
@val_waeselynck I don't necessarily mean it in a bad way, It's just that: teenage -> rapidly growing language (think ES6 / ES7) mutant -> strange syntax semantics (things like == vs === and the list goes on....) ninja -> does tricks, lots of features and gadgets though I personally do in fact hate JS mainly because of it's syntax.
@mpenet yeah, I'm referring to the react ones (which could still be functional, but their official guides teach the OO way so that's how people will use them in real life)
The warts are, arguably, more than superificial. Just too many strange / bad decisions continuing to be made over time.
Ones that tend to make programming in it directly continually hostile to the focus of the developer. Too many background concerns to watch out for.
@lukism well look who's here lol
I mostly hang out in #beginners though. Because, well, I'm still a clojure noob!
@fellshard warts like ==
vs ===
are much more superficial and easy to fix to me than, say, the limitations of classes in Java
while there are warts that are not superficial, you can actually avoid them
although I acknowledge that they still bite you when consuming non-functional js libs
@akiroz I don't actually think there's a point in having a debate about this, just want to encourage people to give JavaScript a second chance 🙂
Not talking about ==
vs ===
. Talking more about its choices around primitives, hoisting, scope, etc. Sure, you can do some cool and funky things with them, but they'll more likely than not bite you in the tail when you're not paying close enough attention.
yeah hoisting and coercion rules are awful, no excuse for those
@val_waeselynck sure, there are worse languages out there but that doesn't really make JS a good one... I currently have to write JS almost every day at work and it pains me to know that stuff I wrote could have been so much more elegant in cljs 😞
I once did the js->cljs transition, and by far the biggest difference to me was hot-code reloading. Damn that rocks.
But I'd much rather use React from javascript than Angular from cljs
Just saw this in twitter, looks pretty relevant to the discussion - https://purelyfunctional.tv/infographic/functional-javascript/
There are also hot code reloading solutions in JS (I think you can even use figwheel for it). My first experience with figwheel was so amazingly eye opening too 🙂
@shaun-mahood yeah I think the JS ecosystem has caught up a bit since when I did that
re: hot-code reloading I mean
Oh yeah, JS it getting tons of good ideas from ClojureScript as far as I can see.
I mean, for instance, when working in JS I missed multimethods, so it was pretty easy to re-implement them. Not so in most other languages I believe
biggest challenge remains educating the developers I guess 🙂
Yeah my view of JS is that you can do pretty much anything, good or bad.
JS' class / object system is still pretty much "broken" but the majority of the community are embracing OOP.
anyone ever seen this? console.log.bind(console)
I still like JS’s OOP better than Java’s or C#’s, prototypes are great
@akiroz yeah JS ecosystem moving towards classes makes me sad
even tho I use it as little as possible
but at least the prototype system of JS can pretty much emulate all class systems
what I don’t like about JS is the bloat, its become SO easy to include 20 libraries into your project and every single minifier except google closure is really bad
@lambdacoder yeah always funny to compare a CLJS project's project.clj to a JS project's build file
im constantly amazed at the output of cljs
its often an order of magnitude faster than the exact same code through uglify
er not faster, smaller
@lambdacoder isn't that because you run it on CLJS -generated code ?
no I mean the libraries’ code getting stripped, regardless of the project’s language
uglify will bundle everything cause it has no static analysis of the code
so even if I know cljs will be heavier in its raw output than the JS equivalent, once through closure whats left is much much smaller
Probably worth moving this conversation to #clojurescript or somewhere else though - not really clojure related anymore 🙂
What I find amazing about cljs is that's it's probably the most complete answer to the issues of front-end development, and it's not even in JavaScript
@shaun-mahood yeah, sorry :)
Although ClojureScript is Clojure, don't let anyone say otherwise
for the most part
going back to clj to write macros feels different 🙂
I’ve got a (probably simple) macro debugging question. I’ve got a simple datomic query that takes a base namespace arg to construct the query: (defmacro pull-all-items [nsname] `(let [idname# (keyword ~nsname "uuid") uuids# (d/q '[:find ?uuid# :where [_ idname# ?uuid#]] (db-conn)) ] (into [] (flatten (into [] uuids#))))) When I run it I get: java.lang.RuntimeException: Unable to resolve symbol: idname__14091__auto__ in this context macroexpand shows: (let* [idname__19476__auto__ (clojure.core/keyword "test" "uuid") uuids__19477__auto__ (datomic.api/q (quote [:find ?uuid__19478__auto__ :where [ff-server.api.datomic.util/ idname_19476__auto__ ?uuid__19478__auto__]]) (ff-server.api.datomic.core/db-conn))] (clojure.core/into [] (clojure.core/flatten (clojure.core/into [] uuids__19477__auto__)))) So 2 questions: 1. when you use ‘_’ in a macro does it need to get autogen’ed? 2. Why doesn’t this work?! (hahaha)
on 2, that error is from idname#
- it has meaning inside the syntax-quoted form but you're quoting it inside that datomic.api/q
expression, so you pass that exact symbol into datomic. i'm guessing you really want to be passing its value at runtime instead - and since that vector is wrapped in a quote
, you lose the ability to get its runtime value.
you could quote the pieces of that vector instead of wrapping the quote
around the whole thing in order to make sure runtime values get where they need to be
and sorry about question #1 - i don't know how datomic queries work so can't answer that one, but in general it depends on your use case / what _
is getting used for.
@trptcolin thanks! That makes a lot of sense
@bfabry Good question. Its being called inside this:
(defmacro defqueries
[nsname]
`(do
(require '['ff-server.api.datomic.util :refer ['pull-all-items
~'simple-query
~'simple-transact
~'simple-enum
~'add-to-list
~'rm-from-list ]])
(defn ~'pull-all []
(pull-all-items ~nsname))
:
Which declares a bunch of fns in a calling namespace. When I had it as a simple fn, putting it inside the macro broke it
ah. you could define it as a function that returned code and then call it like (pull-all-items nsname), or you could define it as a function that returned items and use it like (pull-all-items 'nsname)
That's good advice for most macros, btw. Even the source of clojure.spec breaks macros up into "foo" (a macro wrapper) and "foo-impl" (the actual processing of the forms passed to the macro". Also makes it easier to debug at the repl because you can pass data into the -impl function and examine the output without messing with macroexpand.
Yeah, that makes so much sense. I started to despair at the thought that my implementations started becoming 'macros all the way down’… 😛
okay, so theres this pattern i regularly come across and I cant find the clojure function to do it.
what i want ??? to do is take items and put them into a vector. conj doesnt work, because the first collision
yeah, I just keep seeing this so often I figured there had to be a core function for doing it that i was overlooking
it's an interesting little problem. personally I'd probably modify all the map values to wrap them in a vector, and then merge-with into
(apply merge-with into (map #(into {} (map (fn [[k v]] [k [v]]) %) [{:a 1} {:a 2} {:a 3}]))
ah, this sort of hints at how my problem is not as generic as I thought it was. i actually would prefer the unique keyvals to remain unwrapped
orrrrr I might generate a seed map with all the possible keys with an empty vec as its value. (apply merge-with conj (zipmap (distinct (flatten (map keys maps))) (constantly [])) maps)
oh, hey, one more question. how do i convert keywords (or strings, specifically) into namespaced keywords?
I am reading programming clojure now. But I cannot get the point of > Variable arity is very useful in recursive definitions. any example?
@cddr I use vim-clojure and put this line in .vimrc let g:clojure_fuzzy_indent_patterns = ['^with', '^def', '^let', 'render', 'for', 'doall’]
which could be expanded
(defn foo
([] (foo :bar))
([a] (foo a :bar))
([a b] (apply str a b)))
he, yeah ^^^
I am fairly sure the author is simply saying "defining the function in terms of itself"
the use of “recursive” is confusing there
or, said another way "re-using your existing function definition to describe the behavior of your function when passed a different number of arguments"
@lambeta Here’s a silly example, which may be a little opaque if you’re not used to the style
(defn factorial
([n] (factorial n 1))
([n acc] (if (> n 0) (factorial (dec n) (* n acc)) acc)))
We pass along an accumulator variable into the recursive case, but we want to be able to call the function in the first place without specifying an accumulator value
the whole sentences here is > Variable arity is very useful in recursive definitions. See Chapter 4, Functional Programming, on page 85 for examples.