This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-10-19
Channels
- # 100-days-of-code (5)
- # announcements (1)
- # aws (1)
- # beginners (112)
- # cider (135)
- # cljdoc (6)
- # clojure (111)
- # clojure-dev (8)
- # clojure-italy (3)
- # clojure-nl (5)
- # clojure-sweden (3)
- # clojure-uk (152)
- # clojurescript (101)
- # datascript (14)
- # datomic (61)
- # editors (1)
- # emacs (29)
- # events (7)
- # figwheel (3)
- # figwheel-main (15)
- # fulcro (18)
- # funcool (2)
- # graphql (1)
- # juxt (2)
- # off-topic (51)
- # om (1)
- # overtone (28)
- # perun (2)
- # reagent (1)
- # reitit (6)
- # ring-swagger (5)
- # shadow-cljs (112)
- # spacemacs (49)
- # tools-deps (10)
- # unrepl (11)
- # yada (10)
Is there a way to redefine function calls ?
(with-redefs [+ -] (apply + [1 1]))
=> 0
(with-redefs [+ -] (+ 1 1))
=> 2
any further opinions on kwargs vs option map arguments? I've read the following posts about the topic, but i'm not convinced one way or the other https://clojurefun.wordpress.com/2012/08/13/keyword-arguments-in-clojure/ https://stuartsierra.com/2010/01/15/keyword-arguments-in-clojure http://yellerapp.com/posts/2015-03-22-the-trouble-with-kwargs.html
@timo.freiberg Writing clojure.spec for kwargs-api is more difficult than for explicit maps, IMO
@timo.freiberg there are also some arguments against kwargs in Elements of Clojure
you can use s/keys* in spec for this - itâs quite easy
Ah, there's one argument gone ;)
kwargs are pretty useful at the human edges
often more trouble than value in the internals
I'm gonna look into the elements of clojure reference
@alexmiller the function is currently the only public function of a new library
ok i'm not going to buy elements of clojure to read the argument agains kwargs đ
one thing i quite like about using kwargs with destructuring in the signature is that the function documentation immediately shows you the available keywords and their default values
when using an option map i would have to spec it or reference a map of defaults in the docstring
unless there are better options i haven't though of yet?
As long as you destructure it (so that it shows for the docs) kwargs or not is the same in that respect
in emacs the function signature appears at the bottom so you see func-name [{:port :hostname ...}]
oh true, i can just destructure the option map as well and have the exact same docstring... woops :thinking_face:
so it seems to me like the pros of option maps win out slightly, although i like not having to type opening and closing braces
Working on a codebase that has a lot of kwargs immediately wrapped in a map, they've been a huge ergonomic loss. I can't get nice alignment of the arguments from my editor (emacs), I can't easily pass the kwargs I got higher up the callstack to lower down, we use a lot of medley/mapply
to unpack maps into kwargs.
I've found them to be a greater pain than benefit, especially because it's somewhat random which functions will take kwargs and which will take a map.
Pretty much every time I see (defn foo [x & {:as opts}])
it strikes me as a codesmell.
thanks for the soapbox!
(deftest underscore
(let [a- "foo"
a_ "foo"]
(is (= a_ a-))
(is true)))
This does not compile on clojure 1.9 ?!?!
At least in namespace names, and also in defn names and apparently let symbols, dashes are changed to underscores to make them legal class/package names in Java.
kind of interesting - any time you get both a- and a_ closed over, those create fields in the closed over function with the same munged name
I think that can be reasonably called a bug
(let [a- "foo" a_ "bar"] (= a_ a-))
yields false
for me on Clojure v1.9.0.
no closed over function here, so doesnât trigger it
Ah, OK.
the compiler error is much better than silently proceeding as if both were called a_
.
>>> user=> (let [a- "foo" a_ "foo"] #(= a- a_)) CompilerException java.lang.ClassFormatError: Duplicate field name "a_" with signature "Ljava.lang.Object;" in class file user$eval155$fn__156, compiling:(NO_SOURCE_PATH:13:1)
for clojurescript, we don't seem to get the compiler warning. We get this js:
(function (){var a_ = "foo";
var a_ = "bar";
return ((function (a_,a_){
return (function (){
return cljs.core._EQ_.call(null,a_,a_);
});
;})(a_,a_))
})().call(null);
There is a ticket covering this sort of stuff: https://dev.clojure.org/jira/browse/CLJS-2461
when creating stateful components in component system like integrant, am I wrong to want to only expose a subset (or an immutable view, even) to the rest of the system? Is this possible currently? Seems like no.
this is trivial to do in stuartsierra/component - the start method is a closure, you can return what you like
Example: component that maintains a datascript DB, and a timer to incrementally update it, but then only exposes the immutable view of the DB to the rest
@noisesmith interesting. What if you need some of the state in order to be able to "stop" it later?
@isak I see it more like OO, itâs an object with state and you could expose function to mutate the internal state, like a setter would on an object
@borkdude I agree it is pretty OO type thinking. Though if I do the obvious thing (e.g., return a record), then I also expose maybe more would make sense to the rest of the system. Also make it more clunky to use.
Expose only the public API, let the component deal with the implementation details of managing the state.
Or create functions that given that component, do something with it and consider that your API.
Maybe with a record that implements deref
to return the immutable view, it would be good enough, and just treat reaching into it otherwise from other components as a nono by convention.
If you donât want others to mutate the db, create a bunch of functions that provide read-only access and expose only those?
I can see your strategy working too, just worried I'd have to copy and paste APIs that are already fine
@borkdude but as mentioned, the issue is exposing the db to both start and stop methods, since records don't close over construction scope
right, records don't do closure or private fields
What I do in that case: create some functions in the same namespace which is the API of dealing with that component, and donât use the component directly
Can't you just use reify and reify your proto + component lifecycle. Then expose whatever you want from your proto fns
you would also need to implement hash-map
Clojure isnât too obsessed over making things private, itâs usually by convention anyway
E.g. Iâm doing this:
(defcomponent SSE
"Server sent events component"
[channels &]
(new [cfg] {})
(start [component]
(let [channels (atom {})
sse {:channels channels}]
(info "Starting SSE component")
sse))
(stop [component]
(info "Stopping SSE component")
(doseq [c (vals @channels)]
(a/close! c))
nil))
(defn send-message-to-user
[sse user-id message]
(let [c (channel-for-user sse user-id)]
(a/put! c message)))
Nobody is expected to use the channels directly from this component, but to go through send-message-to-user
only
which is fine when data is immutable, but for necessarily mutable state you end up with something that's either overly complex or exposing things others shouldn't be touching and relying on convention
Here was what I was hoping for in integrant
:
(defmethod ig/init-key ::service [_ {:keys [db-pool tmp-dir]}]
(ig/map->State
:private-state {:exec-service nil
:datascript-conn nil}
:public-state
(fn [private-state]
@(:datascript-conn private-state)))
(defmethod ig/halt-key! ::service [_ private-state]
(.stop (:exec-service private-state))
private-state)
@borkdude yea i'm not to worried, but good to hear how other people are thinking about this
no, i just made it up as a possible API, for when you want your private state to be different from public
right. you could also use an underscored field or another convention to signal âinternalâ or âimplementationâ, like _datascript-conn
(datascript's btree sorted set is really great and can be used outside of the datomic like stuff)
{(keyword " ") :my-secret :public :touch-me}
;;=> {: :my-secret, :public :touch-me}
đif anyone is curious, for about 3 million datoms, it takes about 3 seconds to read it from a file via fressian, but about 30 seconds to initialize it from scratch with the data
@isak are you familiar with #datahike as well? it supports durability out of the box
@borkdude i just learned about it the other day. Looks interesting, but I haven't tried it yet.
I've been toying with a little library that wraps datascript's btree as an aorset delta crdt, with the idea that at some point I might use it in a chat server at work for presence information, it seems super promising
I heard that Tonsky would be working on durability for datascript in his Clojurists Together funding
@hiredman cool idea. #datahike is trying to get funding for making it suitable for p2p, same kind of idea I guess?
maybe? my little library is only about 200 lines (on top of datascript and minus and network communication), but it really is only the sorted set aspect. A lot of the datomic like bits are very hard to make work in a sane way on top of a crdt
there are things like, if you have a unique attribute, and concurrent modifications each add conflicting things, how do you merge them together? so I just left all that stuff out
@isak found the ultimate way to obfuscate your private state
{(keyword "x\u0008") :secret (keyword "y\u0008") :anothersecret}
Interesting: a CLI repl just shows :
, but a cider repl shows :x^H
.
oh, {(keyword "x\u0008\u0008") :secret (keyword "y\u0008\u0008") :anothersecret}
even doesnât show the colon, hehe.
hello people, is there someone here using pure deps.edn
for deploying to clojars? if so, what are you using? I'm trying to figure if I can get rid of lein
because currently I only use it to deploy to clojars, you know a solution for it?
Though in that guide it just swaps lein for maven, which might not be an improvement!
I've added function args or defined new protocols just to make something testable, so
(defn fake-effect-handler [f]
(defmethod graph-proto/run-effect :rerender-components
[gm effect]
(swap! results conj effect))
(f) ;; run tests
(remove-method graph-proto/run-effect :rerender-components))
why remove the method afterward? if you care about the behavior for that dispatch outside the test, wouldn't you want to restore the previous method (if any)?