This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-03-31
Channels
- # announcements (20)
- # asami (14)
- # aws (6)
- # babashka (15)
- # beginners (83)
- # biff (6)
- # calva (93)
- # cider (3)
- # clj-kondo (21)
- # cljdoc (106)
- # cljs-dev (32)
- # clojure (165)
- # clojure-dev (78)
- # clojure-europe (54)
- # clojure-italy (9)
- # clojure-nl (9)
- # clojure-norway (24)
- # clojure-uk (4)
- # clojurescript (6)
- # community-development (2)
- # conjure (2)
- # core-typed (14)
- # datahike (4)
- # datomic (2)
- # emacs (40)
- # events (1)
- # fulcro (11)
- # graalvm-mobile (29)
- # graphql (8)
- # honeysql (19)
- # java (1)
- # jobs (1)
- # lsp (232)
- # malli (5)
- # membrane (112)
- # nextjournal (11)
- # off-topic (63)
- # portal (12)
- # re-frame (6)
- # reagent (3)
- # reitit (4)
- # rewrite-clj (2)
- # shadow-cljs (25)
- # tools-deps (6)
I’m trying to find a talk that I saw on YouTube a year ago where a gentleman and two ladies were demonstrating how they created a mobile app with Clojure. I believe they were using React Native via some Clojure libraries. They showed an app they made for some car manufacturer, where users could unlock and start the car from their app, share access with their friends, etc. During the presentation, they showed a lot of Clojure code and how two separate app instances on different simulated devices were sending and receiving messages from one another. I recall the speaker mentioning something about making it possible for the front-end designers to work on the graphical user interface independently and without understanding much Clojure code. That’s the part of the talk I want to revisit. Does anyone know about this talk? I can’t find it on YouTube anymore for the life of me.
Thank you, @UK0810AQ2! I’ve been searching for an hour 😅 Very much appreciate it!
By sheer luck, I also watched this talk and recognized it immediately from your description
Indeed! I didn’t want to burden others with doing my Googling, but it sure was fast! Haha.
I swear I have a superpower when it comes to search engines, I manage to always phrase the search just right
I think it actually did show up in some of my search results, but the content I was looking for was not recognizable until further into the talk, and the title and description of the video did not give me enough hints. And I didn’t recall which persons gave the talk. I was searching for things like “react native clojure mobile app car” etc.
well, if you remember who gave the talk and which talk it was then it's almost cheating 🙃
The lesson of the day for myself: “Don’t persist with “stubborn dumb-mode searching.” Ask the community first.
I bet this will happen to me at least one time, just like when you remember a song as being awesome, send it to someone only to realize it sort of sucks now, but with a conference talk
Yeah! It’s like that. When you remember the melody of a song or a fragment of the lyrics but can’t find the music. There’s a song that I’ve had stuck on my mind for nearly two years now. I’ve searched and searched and asked others about it. The fragment of the lyrics is “ooh, calypso, tell me to go…” (that’s all I remember)—And it’s a hoarse and raspy male voice, sort of new-age post-rock-ish music. I only find some songs by John Denver and Mamie Van Doren, but that’s not it. Search engines are not great at searching contents of video and audio yet.
By the way, here is https://youtu.be/3HxVMGaiZbc?t=1094 (it starts at 18:15). It’s where @U050B88UR talks about https://storybook.js.org: > “Conceptually, what it [Storybook] lets you do, is it lets you build your components in total isolation from your application.” He also mentions an analogous tool called “defparts” or “devparse” or something like that. I can’t make out exactly what David is saying due to insufficient audio quality in the recording. I’m interested in learning more about that concept because I work with customer experience designers and user experience designers who are not very technical. It would be fantastic if they could create the user interface elements in pure data structures or maybe a domain-specific language.
> He also mentions an analogous tool called “defparts” or “devparse” or something like that. I can’t make out exactly what David is saying due to insufficient audio quality in the recording. Pretty sure David is referring to “devcards”: https://github.com/bhauman/devcards
And then there is this 🙂 https://twitter.com/bhauman/status/1032329502603530242?lang=en
Thank you, @U01SX4U5LUA and @U031CHTGX1T! Now I have some reading to do. The idea of completely separating the “visual and layout stuff” from the presentation logic and back-end intrigues me, especially if it allows non-technical designers to work on the visual components intuitively, where the artifacts they produced can be versioned alongside any coupled code. Ideally, the visual designers would be able to work in drag-and-drop tools without needing to touch anything resembling code.
I understand why a set is not an ISeqable - basically, as it has no order, seq makes no sense when applied to the set. However, sorted-sets are also non-ISeqable. This makes less sense to me, as a sorted-set has an order implied by its comparator function. Can someone explain why a sorted-set is also non-ISeqable?
Hm?
user=> (seqable? #{})
true
That's odd, I'm getting a non-ISeqable error thrown in my code when I'm using a sorted-set. It must be some other issue.
(seqable? (sorted-set)) ;; => true
(seqable? (hash-set)) ;; => true
(sequential? (sorted-set)) ;; => false
(sequential? (hash-set)) ;; => false
(seq? (sorted-set)) ;; => false
(seq? (hash-set)) ;; => false
I found it - the ISequable error was being thrown because of an incorrect variable reference which was returning a nil rather than the sequence I thought I was using.
how can I parse xml in clojurescript I have tried to use https://github.com/funcool/tubax in my shadow-cljs project but it appears to be broken
I'm trying to understand transducers.
(transduce (comp (mapcat (fn [[a b]]
{:a a :b b})))
(completing
(fn [_ new-num]
(prn new-num)))
[]
(vec (take 3 (cycle [[1 2]]))))
Result:
[:a 1]
[:b 2]
[:a 1]
[:b 2]
[:a 1]
[:b 2]
Why the result a bunch of map entries being printed, rather than the map (`{:a a :b b}`) created in the transducer? Is the reducing function receiving the result of the transformation?Because of mapcat
, maybe you want map
instead?
Your mapcat
function produces maps, but mapcat will map+cat, treating the map as a sequence of items and return the concatenation of that.
(mapcat (fn [[a b]] {:a a :b b}) [[1 2] [1 2] [1 2]])
([:a 1] [:b 2] [:a 1] [:b 2] [:a 1] [:b 2])
Ah, okay. So mapcat applies the map
, which produces a hashmap, but then concat
calls seq
on the result, which turns each hashmap into a seq of entries, and then those are concat'ed into a vector.
My 10k foot view is that you provide transduce with some lazy sequence, the transform is a set of pure transformations on the sequence, and then the reducing function receives the result and can perform some IO. Does that sum it up well?
I think its better to think about transducers being a function that takes a reducing function and returns a new reducing function. Reducing functions do not have to be pure but can do io, etc
lazy sequence is not required and is just one collection type you can transduce over
If it's not lazy, you still get the benefit of not having to retain the entire set of transformations in memory, yeah? That's basically the point?
Even though it is tempting, I would not start with transduce
to understand transducers.
into
for example might be simpler:
(into [] (filter even?) (range 10))
[0 2 4 6 8]
So (filter even?)
returns a transducer, that when applied to a sequence will only keep even items.The idea behind transducers is actually that you don’t care for the sequence itself. Lazy, not lazy, async channels --- it does not matter to the transducer
@U031CHTGX1T I saw that example from the docs but I don't understand how that's supposed to make understanding it any easier. Seems like it just introduces an another abstraction layer into->transducer to explain the transducer.
https://clojure.org/reference/transducers is a good reference. As is (source transduce)
Your mileage might vary. For me, this is helpful be cause the key of a transducer is that it transforms items that “pass through it”. With transduce, you also have to worry about the f
parameter 🤷
If you haven’t seen it already, go watch Rich’s talk! https://www.youtube.com/watch?v=6mTbuzafcII
> I think its better to think about transducers being a function that takes a reducing function and returns a new reducing function. So transducers return a new reducing function, which is just the given reducing function with the given transforms applied to its input before it's evaluated? Sound better?
I think this is worse unfortunately. See, a transducer wraps a reducing function. If it calls the wrapped one or not is up to the transducer.
(map inc)
will call the passed reducing function for every item after transforming it
yeah. look at the source of map.
([f]
(fn [rf]
(fn
([] (rf))
([result] (rf result))
([result input]
(rf result (f input)))
([result input & inputs]
(rf result (apply f input inputs))))))
So it takes a reducing function and calls (rf result (f input))
.
(filter even?)
will not call the reducing function for odd items
(remove any?)
will never call its reducing function
(filter pred)
will also not transform the items themselves
> I think this is worse unfortunately. See, a transducer wraps a reducing function. If it calls the wrapped one or not is up to the transducer. But doesn't this align with my description? You've provided some examples where the transducer transforms the input by excluding some of the members. So the transducer is not "deciding" whether the wrapped function is called, but it is changing the size of the the original input and what ultimately gets to the wrapped function. Is that different from how I described it as: > the given reducing function with the given transforms applied to its input before it's evaluated
The input to a reducing function is each item individually, not the whole sequence, right?
I read your definition as “Transforms values before passing them to the wrapped reducing function”. This describes the map
transducer, but not filter

> The input to a reducing function is each item individually, not the whole sequence, right?
Hmm :thinking_face:
So the transformation receives the entire sequence and hands off individual items to the reducing function.
But I guess that's not quite right either. I remember from Rich's luggage handler analogy, the input can be filtered, transformed, and rebundled. So if there's a partition
step in there somewhere, the input to the reducing function could be a bundle of the individual items.
It's starting to come together for me, I think..
Hello,
What is the best way to dissoc
a value if it’s get empty?
(? {:foo {:a ("A" "B")} :bar {:x 1}} [:foo :a] "A")
;; => {:foo {:a ("B")} :bar {:x 1}}
(? {:foo {:a ("B")} :bar {:x 1}} [:foo :a] "B")
;; => {:bar {:x 1}}
There is no built in function that does that, there have been proposals to add something like that, sometimes called dissoc-in, but I think that ticket got nixed
I tried medley/dissoc-in
, but I got :
Execution error (ClassCastException) at medley.core/dissoc-in (core.cljc:31).
class clojure.lang.PersistentVector$ChunkedSeq cannot be cast to class clojure.lang.IPersistentMap (clojure.lang.PersistentVector$ChunkedSeq and clojure.lang.IPersistentMap are in unnamed module of loader 'app')
:thinking_face:You can remove from them, though!
(remove #{"A"} (list 1 "A" "B" "C" "A"))
;; => (1 "B" "C")
The times I have needed it, I think I just did an update-in at a level above where the dissoc is, and did the dissoc and checked the result and it was empty also dissoced that
I gave it a start:
(defn dissoc-in-seq [m path value]
(let [without-value (remove #{value}
(get-in m path))]
(if (empty? without-value)
;; Update m to remove value and the last key from the map
;; Messy.
:todo
;; else - just assoc in the new value
(assoc-in m path without-value))))
(dissoc-in-seq {:foo {:a (list "A" "B")} :bar {:x 1}} [:foo :a] "A")
;; => {:foo {:a ("B")}, :bar {:x 1}}
but ... I'm getting a feeling that there's a better way to organize the data than "arbitrary nested maps with sequences in them that need cleaning up".This feels like a bad idea 😄
;; remove empty sequences from map
(defn remove-empty-sequences [m]
(into {}
(remove (fn [[_ v]]
(empty? v)))
m))
(remove-empty-sequences {:x [1]
:y [2 3]
:z []})
;; => {:x [1], :y [2 3]}
;; recursively remove empty sequences from map
(clojure.walk/prewalk (fn [value]
(if (map? value)
(remove-empty-sequences value)
value))
{:a {:x [1]
:y [2 3]
:z []}
:b {:w [:a :b]
:y '()}})
;; => {:a {:x [1], :y [2 3]}, :b {:w [:a :b]}}
Maybe
(defn dissoc-in-val
[m path value]
(let [map-value (get-in m path)]
(if (coll? map-value)
(let [without-value (remove #{value} map-value)]
(if (empty? without-value)
(medley/dissoc-in m path)
(assoc-in m path without-value)))
(medley/dissoc-in m path))))
how can I parse xml in clojurescript I have tried to use https://github.com/funcool/tubax in my shadow-cljs project but it appears to be broken and giving me very strange error "The required namespace "tubax.core" is not available, it was required by "cljs/user.cljs".
When I see the REPL display 'nil' after executing some code, is that similar to 'return 0' that one sometimes sees in the OO realm with methods that don't return anything?
i'm not sure what OO Language you are referring to
>>> def a():
... print("...")
...
>>> a()
...
>>> b = a()
...
>>> b
>>> print(b)
None
>>> type(b)
<class 'NoneType'>
>>>
similar yes - in lisps (clojure included) the last form evaluation result is implicitly the return value of the function being called if that evals to nil, that's like 'false' or 'undefined' in most other langs, although clojure has false and nil (moved from non-thread to thread, my bad)
I think the last time I saw something like that was with Objective-C
The answer here is “no”.
Some languages have “void” as a return type for a side-effecting operation. That's not possible in Clojure, so you get the result of the last statements.
io operations like println
will return nil
which may be where this question came from? But that can't be relied on. There are also legitimate reasons to return nil
: it can be returned from a function that would typically return something else, and can indicate a missing value, an empty structure, a falsey value, and so on