This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-02-23
Channels
- # aleph (8)
- # aws (2)
- # beginners (36)
- # cider (35)
- # cljs-dev (157)
- # cljsjs (3)
- # cljsrn (5)
- # clojure (97)
- # clojure-dev (5)
- # clojure-gamedev (3)
- # clojure-italy (27)
- # clojure-russia (11)
- # clojure-spec (19)
- # clojure-uk (39)
- # clojured (6)
- # clojurescript (87)
- # clojutre (4)
- # community-development (35)
- # cursive (8)
- # datascript (2)
- # datomic (14)
- # dirac (8)
- # duct (3)
- # figwheel (13)
- # fulcro (22)
- # graphql (20)
- # jobs (1)
- # london-clojurians (1)
- # off-topic (55)
- # onyx (3)
- # parinfer (3)
- # protorepl (39)
- # re-frame (3)
- # reagent (26)
- # ring (7)
- # ring-swagger (2)
- # rum (1)
- # shadow-cljs (107)
- # spacemacs (8)
- # test-check (4)
- # unrepl (3)
Am I going insane? After adding this as a dev dependency I'm not seeing it on my classpath. lein with-profile dev classpath |tr ':' '\n' |grep cddr
:profiles
{:dev {:dependencies [[cddr/with-httpd "1.0.0"]]}}
However if I add it to my project deps, I see it fine.@cddr you've been stricken by the Gods who overwrite your profiles.clj :dev
key, since it doesn't perform a deep merge
for some reason, doing it this way performs a deep-merge, if anyone has a better method, i'm all ears 🙂
note that :dev-profile
within the profiles.clj will take precedence, when performing the merge
I'm mistaken! This will still only merge wrt- :dev-common
and :dev-profile
as though you performed a (merge ...)
between them, if I recall it still isn't wholly a deep-merge between profiles
so if you have a :dependencies
block in both :dev-common
and :dev-profile
, you will like only see the dependencies stored in :dev-profile
...
I assume the {{
in your project.clj example is a typo and should be {
?
@noisesmith yes indeed! I'll fix it
*with a different key
@caleb.macdonaldblack I'm not sure how that can be simplified...
Okay cheers
anyone is using the environ library ? I would like to have your opinion on the following PR: https://github.com/weavejester/environ/pull/79
it seems the construction of environ.core/env is reversed, but maybe I'm missing something
besides 'very carefully', is there a way in clojure to handle things that need to be released on gc? for examples: references to open gl array buffers . references to jni c pointers
uh.. isn’t that backwards, @fmind? You want system environments to override any properties defined in .lein-env
don’t you? And you want java props to override environment variables. So that if you do MY_PROP=2 java -Dmy-prop=3 some.jar
then (= 3 (:my-prop env))
?
@gnejs it's actually the opposite. I want (.lein-env | .boot-env) > system-env > system-props (as the readme state)
but at the moment, my understanding is that the order is reversed (.lein-env | .boot-env) < system-env < system-props
I think what the Readme says by "resolved in the following order" is that it tries to look for values in that order, and replacing any keys that have already exists from previous step. Essentially the system props take higher precedence.
Maybe it’s a question of how you interpret resolved
in the README. But I kinda agree that it can be interpreted the way you suggest. But IMO the order (as it’s implemented) makes most sense.
in my situation, I want my dev settings to override the environment variables of my system
I think it makes more sense since the local file (dev) should be isolated from the rest of the system
e.g. if I have a datomic database defined in .bashrc "datomic:<sql://prod>" and "datomic:<mem://dev>" in .lein-env, I want "datomic:<mem://dev>" > "datomic:<sql://prod>" in my project
since .lein-env does not exist in production, only the environment system will be resolved
it's quite easy to write this yourself, or build it on environ, or use something like juxt/aero to do it
@mpenet sure, my concern was that the current implementation did not reflect the intended usage
(Because I agree that it’s unclear. This is a better example: https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html on how to describe order)
still, don't you think it makes more sense to have .lein-env > environment variables ? At the moment, environment variables overrides the project settings
if you think the current implementation makes more sense, I will simply write a small lib
(oh well, I could simply use https://github.com/kennethreitz/autoenv) but I don't like having magical file settings in my projects
I think the current impl makes more sense. But that’s just me. I usually use component
or integrant
to create an application defined env
that uses environ but extends it with config from files or default-values as needed.
@gnejs I had the same setup, but I like having everything controlled by environment variable. The application is less complex and more explicit.
Maybe https://github.com/grammarly/omniconf could be interesting? No previous experience of it myself though.
do you think I could set system properties for dev/test with leiningen and use environment variables in prod ?
of course it’s possible. The downside is that environ builds its config map once during initialization and after that it’s immutable. And there’s no way to create a “new instance” of the env. So if you need to run tests with different environ-params you could be out of luck maybe.
Guys, what are your feelings about using monads in Clojure? It seems to me that it is used very rarely, even though I can see the value in them
@patrkris just my 2 cents: I think they are wonderful design patterns oriented around composition and abstraction, but they also had another "layer" around plain values
I think Rich Hickey explains it better than me in https://www.youtube.com/watch?v=2V1FtfBDsLU
@patrkris i'm reading the original monad paper by Wadler (it's surprisingly approachable), and he puts it like this: >>>Pure functional languages have this advantage: all flow of data is made explicit. And this disadvantage: sometimes it is painfully explicit. ... It is with regard to modularity that explicit data flow becomes both a blessing and a curse. On the one hand, it is the ultimate in modularity. All data in and all data out are rendered manifest and accessible, providing a maximum of flexibility. On the other hand, it is the nadir of modularity. The essence of an algorithm can become buried under the plumbing required to carry data from its point of creation to its point of use.
@patrkris @leonoel i've used monads a lot in clojure for async programming. once you get used to them the composability and simplicity / comprehensibility of the code really shine
I thing the big problem with monad is that they are tied to the type/value and not the function. You need to wrap-up your data in a context
while in clojure, I think it would make more sense to discriminate based on the type at runtime (e.g. throwable or not)
moreover, you need to agree on the monad implementation. You cannot have two Maybe monad in your langage, although their semantic are the same
if a library owner decides to let monad at the border of its API, it has to be used by the caller as well
@mccraigmccraig composability and simplicity is not provided by the monad abstraction per se.
I don't need to know that {:return list :bind mapcat}
is a monad to compose sequence the way I want.
Same for async, I can have composable async primitives, with operators fulfilling the monad laws, but what do I yield of the fact that my async primitive share some common properties with sequences ?
The only thing that comes to mind is to have a let-style notation, but in clojure this problem is easily solved with macros. In Haskell you need to have that built in the language.
not always so @fmind - most of the monad stuff i use works with promises - they are just regular manifold deferreds or bluebird promises
yes @leonoel let style notation is a big win - but the macros required are not trivial, so it's easier, and more robust, to have a generic monadic-let working with monadic structures, rather than a bunch of different let implementations for different structures
and when you want to reach for applicative-do notation... you definitely don't want to write that too often
it's a let notation for applicatives ( https://ghc.haskell.org/trac/ghc/wiki/ApplicativeDo ) which gets around the stepwise constraint of monads so you can e.g. do concurrent async operations. it's available in cats as alet
http://funcool.github.io/cats/latest/#alet
@mccraigmccraig @leonoel For me the problem is return
/`pure`. If you go down this route, you quickly get into trouble.
which trouble @lodin.johan? i've got a large codebase mostly using promise monads and haven't encountered any trouble with return
@mccraigmccraig It becomes a problem when you talk about monads in your code, not using a particular monad, i.e. you abstract over monads.
The same problem occurs with Monoid
's mempty
. What these functions have in common is that the only place the monadic type occurs is in the return value.
@lodin.johan you will have to be explicit and provide a type to return... that might be problematic sometimes, although it's not hurt me yet
For me I hit a hard wall when I went in this direction. There were functions that just hurt to much. I introduced a whole new level of debugging if I did the types wrong.
But if you have any Nothing in there, you get Nothing. [Just 1, Nothing, Just 3] => Nothing.
presumably Just []
Right, but you need to carry the type. And then, if you want to use that result generically, you need to know that you now have a f (t a)
instead of a t (f a)
.
yeah, that does sound like too much hard work without static checking
You also have things like Monoid a => Monoid (Maybe a)
, so Maybe a
is a monoid if you have a monoid in it. This you want to be able to express.
Another thing I find jarring is (<*>)
or ap
. Applicative functors work really well i Haskell-likes because functions are curried, i.e. it's a -> b -> c
instead of (a, b) -> c
. And I Clojure in don't want to give up variable arity. Like, how should (ap +)
work? You need to either use introspection to see the number of arguments (if single arity) or be explicit about that too.
At this point, I'd just switch to Haskell/PureScript if I wanted to program in that style. 🙂
yeah, i agree with that - otoh sugar around a promise monad has made async programming very nice
But talking about monads in general as its own thing in Clojure (or any language where a type system does not do inference on return values) will be awkward, I think.
Maybe not necessarily inference. I don't know how Scala people do it; they manage it through the type system somehow. Whether it's awkward or not, I don't know. 🙂
is there a construct in clojure for if x fulfills predicate, return x, otherwise return y
, I'm aware I can do this with let and if:
(let [r (some-calculation)]
(if (pred? r) r (other-calculation)))
but was hoping for something terser along the lines of (ifp pred? (some-calculation) (other-calculation))
...I also suspect I already received an answer to this once, but since the channel history is what it is and I'm apparently getting senile I'll post it again@mbjarland i believe the answer last time was this macro being written: https://gist.github.com/madstap/52f280f17289f1a1ec81f3c9f0b23778
@mbjarland if you write your pred to return the value instead of a boolean then (or (pred? (some-calculation)) (other-calculation))
should be enough right?
Something close @mbjarland (let [r (some-calc)] (cond-> r (not (pred? r)) other-calc))
@sundarj@thedavidmeister @reborg thanks all...somehow this still leaves me strangely unsatisfied but perhaps that just means it's time to write a custom macro. The or solution is nice, but then you can not use most of the out of the box predicates as they tend to return true/false and most of the other solutions I've come up with still need a let binding in some way
Or a helper function: (defn and-pred [x p?] (and (p? x) x)))
@noisesmith wow, and
...totally missed that one. Nice!
so it's usage might look like (or (and-pred 10 even?) 2)