This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-01-06
Channels
- # architecture (17)
- # beginners (118)
- # boot (22)
- # cider (9)
- # clara (38)
- # cljs-dev (4)
- # clojure (213)
- # clojure-austin (4)
- # clojure-greece (1)
- # clojure-italy (4)
- # clojure-russia (5)
- # clojure-spec (7)
- # clojure-uk (5)
- # clojurescript (3)
- # cursive (21)
- # datascript (3)
- # datomic (31)
- # duct (12)
- # emacs (9)
- # graphql (5)
- # gsoc (1)
- # hoplon (9)
- # leiningen (2)
- # off-topic (37)
- # om (2)
- # onyx (2)
- # parinfer (5)
- # perun (4)
- # reagent (2)
- # spacemacs (1)
- # specter (25)
what's good practice for def
ing constants in clojure?
is it better to use (let [])
in the function using the constants so the constants are grouped with the code, or something more like globals
what if the constants are used across different clj files?
@ackerleytng ideally clojure has nothing but constants, they don't need to be specially treated
if the constant is something that is independent of any input to the function, I'd put it in a def
thanks!
the special case is values that should change
for those, don't use def (or at least not def directly) - either use function arguments so that the value can be immutable and has no top level binding, or use a safe mutable container (atom, ref, agent) inside a def for the rare cases where you need a mutable singleton
sure, thanks!
I'm trying to add clojurescript to an existing server side clojure application and i got
Failed to compile "resources/public/js/main.js" in 1.744 seconds.
---- Could not Analyze resources/public/js/out/cljs/pprint.cljs ----
Invalid :refer, var cljs.core/IWriter does not exist
---- Analysis Error : Please see resources/public/js/out/cljs/pprint.cljs ----
Figwheel: initial compile failed - outputting temporary helper application to resources/public/js/main.js
where should i start looking?
got it! my directory structure was wrong.
if I have some input data that I need to translate two times before i can use it, wrapping the two transformation functions into a single one does it make my code simpler or more complicated?
i think i would keep those two steps seperately and just compose the 2 functions when you need to apply them in succession
thanks, i should've pointed out that this is a theoretical question, i am trying to understand this
in clojurescript, why does this not work?
app:cljs.user=> (js/google.maps.LatLng. 1.365035 103.644231)
#object[Object (1.365035, 103.64423099999999)]
app:cljs.user=> (apply js/google.maps.LatLng. [1.365035 103.644231])
nil
app:cljs.user=>
how do i do that?
(fn [x y] (js/google.maps.LatLng. x y))
?
ok it works, thanks!
How can I explore a Clojure or ClojureScript codebase? Is there something similar to cscope/gtags/global etc. from the C/C++ world?
jvm clojure? there's a library called at-at, or you can directly use ScheduledThreadPoolExecutor it's not a super difficult api and clojure functions are Callable
nice, thanks @noisesmith
you can programmatically explore in a repl as well, we have clojure.repl/dir, clojure.repl/doc, clojure.repl/source (all of these are in scope by default when you start up)
there's also all-ns and ns-publics which when combined allows programmatic exploration
those errors make me think you have versions of things out of sync
@akiroz @teikfaiv I believe tick is migrating their timestamp object from ZonedDateTime
to Instant
it's probably the best combination of up-to-date and performant yes
there were at one point at least
most of the problems are not with clojure itself, but with plugins and tooling (leiningen and boot related stuff)
what’s the point of making an empty defprotocol and then implementing it? I see this in the reagent source code where it does a (defprotocol IReactiveAtom)
and then implements it with a (deftype RAtom ...
in order to test that something implements the type
whether something implements it or not
that's it
you would need some other way to mark certain types, but exclude others, that could be extended from outside your code
so you can't use a simple conditional, or nobody else could make a thing for which that check returns true
it's one of the things people do when inheriting, but isolated from the other properties of inheretence
I’ll have to think on that. When looking at this example, it seems like the IReactiveAtom protocol is really a collection of several other protocols, because the properties I’d expect in a reagent atom are all of the protocols that the (deftype RAtom…)
implements. I guess I would have expected the defprotocol to collect all of those things together and relabel them as the meaning of the IReactiveAtom. https://github.com/reagent-project/reagent/blob/v0.8.0-alpha2/src/reagent/ratom.cljs#L117
you can't do protocols on protocols though
if you look at how clojure.core does things, protocols and interfaces contain as little as possible, and complex sets of behaviors are composed by implementing multiple protocols / interfaces
so it makes sense to me that one of those protocols is the one that says "you can react on this thing" and it doesn't need to define other behaviors
I run boot run
and it seems to be download the entire http://clojars.org and http://maven.org archives. It never ends. Is that normal?
if they are poms, those are just dependency info
and they are very small
I would expect a very large number of poms to get downloaded, then only the jars you need based on analyzing all the poms
right, it's a cache
@noisesmith thanks for the help. i don’t get it yet, but i think i just need some more time with the language
@lee.justin.m have you ever used a language with inheretence?
yes sure. i think the problem is that i’m trying to shoehorn this into a C++/Java paradigm and it just doesn’t work that way
I think one key here is that clojure avoids concrete inheretance - you will rarely see anything that inherits something other than an interface or protocol
it could be a marker for assumptions. it looks like there are only two types that implement IReactiveAtom. so if something satisfies that, they know what assumptions come along with that. ie, what other protocols are implemented. also, it's clear that it's an internal data type rather than something from outside of reagent's codebase
it really reminded me of opaque typing in a ML type language or flowtype, but I just don’t know what good that is in a dynamic setting
so where in java or c++ you would say "pass in something that inherits Foo", in clojure you would say "pass something that implements IFoo"
@justinlee yes it's a direct translation of that
I think at least...
right but in those languages you’d never have an empty interface, as far as i can recall
in ML you can make the language perform matching and inference based on a type tag, and in flowtype the purpose is for a library author to say “do not look inside here this thing will change”
yes - instead of pattern matching we use protocols or defmethod, both of which can look at what protocols you implement for dispatch
so if you had, for example, (defmulti render-thing type) and then (defmethod render-thing IReactiveAtom ...) - you can make sure your custom object hits that implementation of the multi by implementing that protocol
@noisesmith yea okay that does make sense. thanks
and I bet reagent has something much like that hidden down in there
@justinlee pure speculation - I bet reagent uses the presense of IReactiveAtom to decide whether a change should trigger rerenders
actually the whole reason why i’m reading the code is because i’m trying to figure out exactly what reagent is doing when it triggers updates
and then IReactiveAtom can't define deref - that's already defined by another protocol...
or the protocol that allows watching, etc.
here's a predicate based on it https://github.com/Day8/re-frame/blob/master/src/re_frame/interop.cljs#L21
@lee.justin.m also I'd say that understanding any of this brings us well out of the scope of #beginners
@dpsutton see that’s exactly what confused me: if the user ran (ratom? thing)
and got true you’d expect it to do all the ratom things (like be derefable and swappable and so forth). but you could, if I understand this right, implement IReactiveAtom with an empty object, since it requires nothing. that would be very confusing. (maybe the point is that IReactiveAtom is an internal concept and it is just a convenient way for the library author to tag something? i was just expecting the language itself to enforce some kind of duck typing here: i.e. an IReactiveAtom does all of this stuff.)
@noisesmith but I’m a beginner 🙂
going depth first I see
yes, that's what I suspected
if you make your own type and implement this it's understood that you should know what you are doing. and what you are doing is implementing the other protocols, which are the actual api surface of a ratom. so that a ratom can be used by normal clojure functions while doing ratom things
i suppose an alternative would be to make ratom?
smarter, checking all the individual protocols
regarding duck typing, we don't have that, and we don't have protocols that extend other protocols - those facts should also help
@sundarj but since that protocol exists only to inform reagent that you are like an ratom, the other checks are redundant, because clojure never enforces that you extend any of a protocol's methods
so checking the extra protocols provides no info, as it's no guarantee that the methods are implemented, so you can skip all that and just check for the marker protocol
oh - but then I can't use atoms any more inside my reagent code
I see that though, OK
(that is, non reactive atoms)
@lee.justin.m it's not enough to check that they satisfy all of the other protocols. as (atom {})
would pass on all of the others