This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-03-31
Channels
- # announcements (4)
- # aws (1)
- # babashka (52)
- # beginners (178)
- # boot (4)
- # cider (2)
- # clj-kondo (10)
- # cljs-dev (39)
- # clojure (744)
- # clojure-europe (12)
- # clojure-germany (6)
- # clojure-india (56)
- # clojure-italy (5)
- # clojure-nl (60)
- # clojure-spec (9)
- # clojure-sweden (14)
- # clojure-uk (36)
- # clojuredesign-podcast (6)
- # clojurescript (11)
- # community-development (5)
- # core-async (4)
- # data-science (6)
- # datomic (6)
- # emacs (7)
- # events (4)
- # exercism (33)
- # fulcro (11)
- # funimage (2)
- # graalvm (29)
- # java (1)
- # joker (3)
- # lambdaisland (15)
- # malli (2)
- # meander (55)
- # mid-cities-meetup (1)
- # nrepl (8)
- # observability (4)
- # off-topic (2)
- # pathom (5)
- # re-frame (31)
- # shadow-cljs (73)
- # spacemacs (18)
- # sql (27)
- # test-check (14)
- # testing (1)
- # tools-deps (5)
- # xtdb (13)
I'm trying to learn Reagent, but I'm kind of struggling with how most of the variables are mutable. Isn't the idea with ClojureScript to have immutable values? How do you program functionally when most of your functions are impure? Or am I just completely on the wrong track?
the fundamental thing that react does is provide a way to re-render when your data changes - reagent engages with that directly
your code should avoid mutating state, but it should render a form using data that could update (and you can define a form to re-render when that data updates)
So how does that work? If you need to mutate state, how do you avoid mutating state? I'm sorry if I'm being confusing, I'm a little new to this.
I intentionally say "avoid" instead of don't - it's something we intentionally minimize but can't eliminate
OK. Thanks for clarifying.
most changes to state are going to come from the browser: some user input changes something, your app has a defined way to react
so there's inherently a tracking of state in each widget that's wired into react - that should be mostly hidden from your code
what your code does is access the current value out of app state from inside a component, and when that happens the react engine will know to come back and re-render that component if the state it reads from changes
thus instead of a bunch of commands saying "re-render this, re-render its children" or whatever, the framework can decide what needs rendering based on how you define and use your data
that's the big picture tl;dr at least
So only make things mutable if they directly involve what's being put on the screen?
I think I get the idea.
yeah - that's pretty much it - you can actually treat the mutables as immutable args to your rendering function - and reagent will make sure your rendering function is called again if the args change
so it's a lot like data flow if you've heard of that
OK. Thanks @U051SS2EU.
There's a good talk on this: https://www.youtube.com/watch?v=vK1DazRK_a0 where the mutation progressively gets minimized throughout the talk
question about nesting defn
- you could put defn
inside of a let
form, but that wouldn't be idiomatic, would it?
I dunno the context, but if you are coming from scheme, it is important to know in clojure def always creates a global "top level" definition regardless of the scope it is in
does the clojure community have opinions about (if pred x)
versus (when pred x)
? should when
be used if there's no else?
or should it merely be used instead of (if (do
it is a divisive issue, at my last job you would bring that up if you wanted a break from arguing about git branching
I like when for any single branched if, but some common lisp style guides (which a lot of cues for clojure style came from) suggest only using when if there are side effects
to me, when
means single branched if
. i had no idea about the side effects.
i had no idea do
is for side effects! I thought it was just for combining multiple expressions... which i guess you only need if you're doing side-effects?
i feel like i mostly see let
within def
or defn
, not the other way around
the normal thing is to put the bindings that would be in the outer let into a def
clojure code tends to avoid data hiding, this is viable when your values are mostly immutable
thanks!
Looks like it. The ratoms put the components that are watching them in a queue and they just get batch rerendered. No did update, etc
I tried with this simple component, and apparently it does trigger the component-did-update! What’s wrong here?
(defn test-comp []
(let [counter (r/atom 0)]
(r/create-class
{:display-name "test-comp"
:component-did-update
(fn [this]
(prn "component did update"))
:reagent-render
(fn []
[:div
[:div @counter]
[:button {:on-click #(swap! counter inc)} "click"]])})))
https://github.com/reagent-project/reagent/blob/master/src/reagent/impl/batching.cljs#L35-L38
https://reactjs.org/docs/react-component.html#forceupdate
> Calling forceUpdate()
will cause render()
to be called on the component, skipping shouldComponentUpdate()
. This will trigger the normal lifecycle methods for child components, including the shouldComponentUpdate()
method of each child. React will still only update the DOM if the markup changes.
just reading the docs. I also wonder if react has changed what it does since those docs for reagent were first written
When using something like mount, should I wrap all my state in it? Even small things like an atom that contains a timestamp
you should not. only create a state for something low level and inherently stateful: i.e. I/O, queues/topics, connections, etc.
while it might feel "uncomfortable" at first it will encourage you to learn to design and keep your functions stateless.
for example a function that needs an "atom with a timestamp": it can take it as an argument or destructure a timestamp from configuration state that is passed in or, most likely, it could create one inside itself in a let
block, use it and forget it. it would depend on a business use case of course.
I tried following the clojurescript guide, getting started guide. The browser showing the landing page is appeared but the repl never show its prompt. I have waited for about 5 minutes I think and never showed up.. Any flag/running option I can try to spit out which causing the error.
If you are new to ClojureScript, I recommend jumping straight to shadow-cljs. I am new too and I find it super easy. It just works.
Hi guys, I'm currently reading clojure for the brave and true and I encountered a simple problem that I cannot solve, it is related to namespaces. When I use the "require {namespace-name} " it simply doesn't work, it throws syntax check error although I have the correct name of the namespace, any ideas what it might be? I can send the code if it would be more helpful, thanks!
(ns the-divine-cheese-code.visualization.svg)
(defn latlng->point
"Convert lat/lng map to comma-separated string"
[latlng]
(str (:lat latlng) "," (:lng latlng)))
(defn points
[locations]
(clojure.string/join " " (map latlng->point locations)))
that is the code in my /visualization folder in the project directoryand this is in my core.clj
(ns the-divine-cheese-code.core)
;; Ensure that the SVG code is evaluated
(require 'the-divine-cheese-code.visualization.svg)
;; Refer the namespace so that you don't have to use the
;; fully qualified name to reference svg functions
(refer 'the-divine-cheese-code.visualization.svg)
I have the error on the line that I require the divine cheese visualizationit is filenotfound exception
Thanks very much!
It worked
Another REPL question. I'm used to SLIME / Lisp and CIDER is confusing me a bit. if I do C-c C-c in a source file, it seems to evaluate there rather than in the Repl.
Ahhh, never mind. I think I fixed it. I was trying to use (in-ns ... ) to get to the right namespace, but apparently I have a Prelude menu command for that instead that works.
![cider](https://emoji.slack-edge.com/T03RZGPFR/cider/44d3c1a93e44ea40.png)
How can I create a non-namespaced map if I have namespaced keys in it? I get this:
(map (fn [item] {(first item) {:foo/bar (second item)}})
'[[foo "bar"]])
;; => ({foo #:foo{:bar "bar"}})
But would want ({foo {:foo/bar "bar"}})
those are the same identical object, just different syntaxes
if you want to turn off namespace map printing you can do (set! *print-namespace-maps* false)
that's actually off by default, but turned on by most repls
if you're printing edn to a file or something, you can also (binding [*print-namespace-maps* false] (spit "foo.edn" a-map))
> i think nrepl might have trouble with this one actually
So, not in this case, this was going through nrepl and (set! *print-namespace-maps* false)
works as it should.
If I want to get 1 item out of a list (like search a list for the item with the correct id), is there a func for that?
I know I can (->> items (filter …) first)
but is there something better?
also that would short circuit when it finds the match
oh, good point. I don’t think of some
like that, but I guess that makes sense
I think you can also do something like (some #{1} [2 3 1 4])
, depending on what your list looks like.
(some->> pred coll ...)
is just shorthand for (->> coll (some pred) ...)
right?
no - it's not, some->> is like ->> but stops if something is nil
user=> (some->> nil (+ 1))
nil
there's little relationship between some
some?
and some->
/ some->>
they are totally different functions, yes
ok, thanks
For me, the original code is clearest in its intent. And does it matter about the short-circuiting given that filter
is lazy anyway?
Ahahah the power of the remote nrepl socket in prod (well actually staging, but next step?), it's corrupting meeeeeee
It would have taken me forever to find out that a dumb error on my staging conf was setting my redis uri to true
instead of the actual uri
yeah, it's like a superpower
though in practice what I'm looking up is almost always an environment variable or config, so you can get 80% with a function that just dumps all env and configs readably
@kelveden good point on filter being lazy. I guess which is more clear
1️⃣ (first (filter #() items))
2️⃣ (some #(when (filter #()) %) items)
obviously the second one has nested anonymous functions which doesn’t work
As with a lot of Clojure (and other languages) I guess it partly comes down to what you're used to. I always use the former but thread it usually; so: (->> items (filter #()) first)
.
That, to me looks more like the "pipeline" I imagine in my head when I have to do this sort of thing.
I'd also argue that as a function name, some
doesn't intuitively describe what it does. But again, that could be just me.
I’m have some questions regarding instants in clj. I have a map of entities, all of which are properly timestamped and instantified, and I want to sort it in descending recency. In cljs, I can do (sort-by :date > coll)
, but it seems that clj does not have a built in comparator for insts. What are my options?
you could try (comp #(.getTime %) :date)
instead of :date to make it use a numeric type
getTime gets the epoch ms
compare should be working though
(ins)user=> (java.util.Date. 0)
#inst "1970-01-01T00:00:00.000-00:00"
(ins)user=> (java.util.Date. 1)
#inst "1970-01-01T00:00:00.001-00:00"
(ins)user=> (compare *2 *1)
-1
the #inst
notation is clojure specific, there's more than one type that prints that way
but if you consume a #inst tagged object, you'll get a java.util.Date
Hi. If I understand corretly, defmethods are slow because it takes time to resolve them (please correct me if I'm wrong).
I'm wondering if I were to use get-method
, would that result in just a regular fn
? Meaning the resulting value of get-method
would have the same performance as calling an fn
?
Here's basically an example of what I'm trying to do. Both versions technically do the same. But is there an extra performance hit on the second version? I would think not but I don't really have anything to support that claim
I think you're working awfully hard in the absence of any data
feels like the caching of the lookup would be negligeable in a real system
I don't think putting it in anothervar is going to help you at all perf wise
I would challenge your presumption that the first one is slow enough that you need to do anything special
I need to use it in a game loop, so I need to squeeze every bit of performance I can get
as a pretty good programmer I know named Rich once said to me, why guess when you can measure?
my suspicion is that something like (let [fun (get-method some-multi :dispatch-k)] (loop [] ...)) is probably better than the var
@kevin.van.rooijen What are you using for timing stuff for benchmarks?
Hi, I was using criterium/quick-bench
. But I made a mistake in my test. Looks like these two cases are pretty much equal in performance
hash-maps are not ordered, there's a library with an insertion-ordered variant though
IOW adding a new element can change the order of everything in the map
user=> (def m {:a 0 :b 1 :c 3 :d 4 :e 5 :f 6 :g 7 :h 8})
#'user/m
user=> m
{:a 0, :b 1, :c 3, :d 4, :e 5, :f 6, :g 7, :h 8}
user=> (assoc m :i 9)
{:e 5, :g 7, :c 3, :h 8, :b 1, :d 4, :f 6, :i 9, :a 0}
Why the sudden hot take on Python 🙃? PS: I'm not offended, I'm usually the one doing this in my friend circle 😛
I just wrote some Python this afternoon 🙂 I think they are conflating promises that a specific map impl makes with the fundamentals of associative memory
I think the problem they ran into was that, in practice, beginners relied on the implementation’s order no matter what it was
so they felt that not having an order at all was priming beginners for nasty mysterious bugs
meh, beginners are going to abuse anything until they learn better, just like in clojure some beginners abuse records when they should be using maps
well, this is one reason that python is a better language for beginners than clojure: they think about different traps beginners can get into, and if one of them is a serious trap that doesn’t fail fast, they fix it
that's very debateable. it also teaches a habit of expecting maps to have an order which will burn them in any language where they opted not to take the performance hit (pretty much everything except ruby and python I think)
I think there's a sorted-map or something, if that's what you're looking for.
that uses a sorting function, yeah (and of course there is an insertion ordered mutable hash-map that comes with the JVM)
I have some client side code that displays a tab-navigated component (A user clicks on a tab and it shows them different content depending on that tab clicked.). So far so good. The problem I am facing is that sometimes the content is very large. And when a user clicks on a new tab it takes a few seconds to display the content. I thought perhaps if I, instead, only render the content that needs to be displayed then it might be slightly faster since there would be less DOM elements on the page. I was wrong since the process to actually build and render the content is a lot slower than if I just show/hide via css. Am I just SoL or are there ways that I can speed this thing up?
can you generate the html serverside?
is the full table visible on the screen? you might be able to only generate the part of the table that will be visible on screen and generate the non visible part in the background
I am not sure if I could do the rendering serverside. But would that help with the laggy tab switching? I need to look into only showing the visible parts of the table. Not sure how tricky that will be though
it should make the tab switching faster, but might slow down the page load
although, if your content is gzipped, then it might not be that big a slowdown
and there might be speedup opportunities depending on how you’re generating the html on the tab switch
Well currently it builds everything and then it dynamically hides everything but the active tab's content. I guess am not understanding how building the html serverside would help.
so the tab switch is still slow even if the html is already built?
that must be a ton of html.
yea, I would look into chunking the table into smaller pieces
yup, that would do 🙂
I remember watching a tech talk about someone who had a similar problem. trying to see if I can find it
maybe it was something like https://www.datatables.net/extensions/scroller/examples/initialisation/large_js_source.html
UX wise, what kind of data is in a table with 10-30k cells such that having a user scroll through that much stuff is the optimal way to present information?
In our apps at my job, we cap all tables to a 500 record limit. No paging controls either. We provide filters and other controls to narrow down whatever it is the user needs.
I know this approach doesn't necessarily work for all scenarios (like "infinite scrollers" a la Facebook where you're just browsing, not lifting something specific), but it definitely works for our apps. I've always disliked "pagers", and huuuuuuge (yet finite) lists/tables. Narrow down what you want, no human can digest 30k cells of data in a single shot.
Its an HTML representation of an excel workbook. Users upload an excel workbook that can contain multiple sheets. We then extract information cell-by-cell including cell-styling, content, formatting, etc and build a data-structure that looks more or less like this
{"sheet-name" {[1 4] {:backGroundColor "#000"}}
Where [1 4]
is the cell on column 1 and row 4 on the "sheet-name" worksheet. The client receives this structure and builds out a table by looping over the dimensions of the worksheet, say 500 rows by 500 columns.I believe there is a better way to create a projection of that workbook but this is how it was built so I am working with this set up for now until we get time to refactor. lol
Sorted map is sorted. Ordered map retains insertion order.