This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-04-02
Channels
- # announcements (1)
- # architecture (1)
- # aws (21)
- # babashka (37)
- # beginners (173)
- # boot (12)
- # chlorine (5)
- # cider (36)
- # clara (11)
- # clj-kondo (25)
- # clojure (128)
- # clojure-europe (7)
- # clojure-finland (3)
- # clojure-germany (2)
- # clojure-nl (57)
- # clojure-uk (23)
- # clojurescript (71)
- # clojurex (1)
- # core-async (30)
- # core-typed (5)
- # cursive (35)
- # datomic (8)
- # duct (4)
- # emacs (8)
- # exercism (41)
- # fulcro (116)
- # jackdaw (4)
- # jobs-discuss (6)
- # juxt (4)
- # kaocha (16)
- # leiningen (14)
- # malli (5)
- # observability (4)
- # off-topic (2)
- # pathom (19)
- # pedestal (29)
- # re-frame (64)
- # reitit (18)
- # ring (8)
- # shadow-cljs (3)
- # sql (13)
- # tools-deps (32)
- # tree-sitter (5)
- # yada (17)
Good morning everyone.. I'm wondering about mapcat
. I was a bit surprised that it returns a list rather than respecting the type of its input. For example, I expected that if I mapcat
a sequence of sets, the result would be a set, but alas it is a list (mapcat identity #{ #{1} #{2} #{2 1} })
returns (`1 2 2 1)` rather than #{1 2}
. Should I construct my own application specific flatmap
function, or does such a function already exists. Clearly I can do what I want using reduce
and union
.
mapcat
actually returns a LazySeq, whose printed representation happens to be a list. You can check the type with
(type (mapcat reverse [[3 2 1 0] [6 5 4] [9 8 7]]))
Does there already exist a fold
variant of reduce
, one for which I can give the initial value. I.e., reduce
is documented to simply call the given function on 0 arguments if no argument is given. What I'd like to do is give a seed value, then always call the given function with two arguments. if the list has length 0, the return the seed value. if the list has 1 or more values then call the function n times, each time with the accumulated value and the next value.
That's a regular implementation of fold for which the types of the input and output value of the function are not the same. Of course i can implement that myself, just don't want to implement what's already there.
hmmm. trying to implement fold. I realized I don't know how to do it. How can I iterative recursively loop/recure
over an arbitrary sequence and detect when the sequence is finished?
(defn foldl [zero f items]
(loop [acc zero
items items]
(if items
(recur (f acc (first items))
(rest items))
acc)))
yes but I also so a library of fold related functions which seem to be related to parallelism.
Earlier you said you wanted this: "What I'd like to do is give a seed value, then always call the given function with two arguments. if the list has length 0, the return the seed value. if the list has 1 or more values then call the function n times, each time with the accumulated value and the next value"
It would probably be slightly easier to understand if the doc string for reduce
described the two arities in separate paragraphs, rather than one longer one.
(source reduce)
is nice if you want to see how Rich chose to implement it, except that in this case it is calls to Java methods.
Yes, when I re-read the paragraph it indeed explains it. But you're right, having two paragraphs to describe different use models would be easier for the first time reader.
I think the reason mapcat and other things tend to return an ISeq is because the collections are immutable, and the functions are lazy, like mapcat is.
So you can't construct a new set with the elements, because sets aren't lazy like that.
And since things are immutable, functions don't modify them in-place, so since you're having to copy into a new structure anyways, it opens the door for that new structure to be of a different type then the input one
So.on fact, all these functions are known as the Sequence functions, because they'll all return a sequence, and that's mostly because they are all lazy, so they need to returns a type that supports lazy semantics
If you do care about the return type, and you don't care about things being lazy, you can use the transducer variant instead. With those, you get to pick the collection into which you want the result to be put in
Transducers let you "pick the target type" while limiting memory overhead. https://youtu.be/6mTbuzafcII
Is there an easy way to convert from kebab-case to snake-case in jdbc? My api is using kebab-case and I’m using postgresql with snake-case
Thanks, I found it also, but was thinking are there other solutions, but will try that one.. :thumbsup:
There's some built-in support: https://github.com/seancorfield/next-jdbc/blob/master/doc/result-set-builders.md
Thanks @U3X7174KS, will check that out later on. Just used clj-commons camel-snake-kebab library
Hi
I am a newbie at Clj. I am running my repl in IntelliJ Idea, and I want to load my dev config (dev.edn) and fully start my program (which reads from JMS queues)
However after I start my repl and I send (dev)
I don’t see that my app starts running.
My question is is there a way I can fully start my app using config in my dev.edn than just run in repl? Any links that show me how to use config etc would be helpful too…Thank you
I found the unify
function in https://clojuredocs.org/clojure.core.logic/unify, what is it? It's not marked as dont-use-me, it just has blank documention.
I'm looking for a map-like version of every which takes multiple sequence arguments and an n-ary function: i.e. (every < '(1 2 3 4) '(10 20 30 40))
? I didn't see one in the every/every?
variants. (every f '(1 2 3) '(10 20 30) '(100 200 300) '(1000 2000 3000))
would expect f
to be a 4-ary function.
Yes, i'm not used to creating lists to throw away, does map create a lazy list, so that <
is only called as many times as needed?
The other idea was to use zip
although perhaps that's a question for another time, as I don't see the zip
function I was looking for. I.e., a function which takes n many sequences each of length, and returns m many sequences of n items each. And does so lazily.
One thing i noticed from using Common Lisp is that I never needed zip because so many functions behave like map, taking an n-ary function followed by n equi-length lists. Then when I started looking at Scala, i really missed this. you allways need to zip things and then distinguish between a n-ary function and a unary function taking an n-tuple.
Clojure doesn't have all of the keyword options on whatever large fraction of functions that Common Lisp does. It tends to be a little bit more Scheme-like (perhaps - I haven't looked at Scheme libraries in decades) in the sense that it has fewer options, but a good set of built-ins that often work well together, once you figure out how.
The Clojure cheat sheet can be a good index to Clojure built-in functions, in that it emphasizes grouping together related functions and macros: https://jafingerhut.github.io
But it won't figure out common combinations of functions for you, or anything like that.
I'm looking at the sort
function https://clojuredocs.org/clojure.core/sort. for the 2-ary form, it says I need a comparitor and that
comparator must implement
java.util.Comparator
I don't know Java. Is there a way to explain what this means to a non-java person?Is it just a function which will always return 1, 0 or -1 on any input encountered during the sort?
Yeah, that’s probably your best but, and also if you type (javadoc java.util.Comparator)
in the REPL the Java documentation will open up in your browser.
I looked over https://clojure.org/guides/comparators, It seems to me that as long as my function (fn [a b] ...)
accepts any value which will be encountered during the sort, and returns 1, 0, or -1 enforcing a total ordering, then that is good enough without having to understand how to implement a java interface. Am I being naive?
Short answer, yes.
For simple things, compare
is enough. For more complex cases, there is comparator
.
compare
has knowledge of how to compare common types. comparator
let's you implement it however you want.
The “must implement” language sounds like you need to implement the actual interface, but there’s no sign of that in the guide. I’d try it with a simple fn, and if that works, build the full-blown comparator.
Hello, I'm having hard time understanding how does the double evaluation happen in this piece of code from clojure for the brave and true: https://gist.github.com/gabbigum/e033175ed4773a03156b240fddd4fa26 , can somebody explain it?
(defmacro report
[to-try]
`(if ~to-try
(println (quote ~to-try) "was successful:" ~to-try) ;1st instance that gets replaced by input in ~to-try
(println (quote ~to-try) "was not successful:" ~to-try))) ;2nd instance replaced by input in ~to-try
When we invoke the macro called report, it will use the first argument in two places (both indicated by ~to-try)macro means meta code, or code describing other code, so it's not exactly evaluate-able until it becomes actual clojure (and is not just macro language)
@jimka.issy sort
itself uses the compare
function I posted the docs for (above), which is a plain function. So a plain function should work 🙂
See (source sort)
Does it make sense to store a collection of agents inside an atom? I'm thinking of changing my huge-atom-of-maps to a huge-atom-of-agents (for a simulation game) and I'm wondering if that's a good idea. In particular I'm trying to speed the game up, and while I don't expect agents to be "faster" than an atom, I'm thinking it might allow my code to be more flexible in so far as allowing the game objects to alter each others state or execute operations asynchronously.
I glanced at the iconic ant sim to see how it's done there but it actually didn't run on my computer, so I wasn't able to quite tease apart how it worked. For one thing, I don't see a way to change the number of ants after the simulation in in progress (could have missed it though)
Is there a way to tell the pretty printer, within cider, to print quoted lists as '(1 2 3)
rather than (quote (1 2 3))
similar for quoted anything?
How does it work, is it a global setting, or do I have to pass a flag every time i call print?
I don't remember, trying to find an example. It's obscure enough that I have to look it up every time. :)
user=> (println ''(1 2 3))
(quote (1 2 3))
nil
user=> (pprint ''(1 2 3))
'(1 2 3)
nil
it is the output of clojure.test in the emacs clojure repl. I'm seeing messages like the following:
FAIL in (t-canonicalize-pattern-once) (form-init4386036104585295471.clj:140)
canonicalize-pattern-once
not or 2
expected: (= (quote (:and (:not :clojure-rte.core-test/Cat) (:not :clojure-rte.core-test/Lion))) (canonicalize-pattern-once (quote (:not (:or :clojure-rte.core-test/Lion :clojure-rte.core-test/Cat)))))
actual: (not (= (:and (:not :clojure-rte.core-test/Cat) (:not :clojure-rte.core-test/Lion)) (:and (:not :clojure-rte.core-test/Lion) (:not :clojure-rte.core-test/Cat))))
> reading https://clojuredocs.org/clojure.core/contains_q the claim is that there is no basic function to determine whether a given element is in a collection. A poster suggests the following to detmine whether 1 is an element of the sequence. Not sure why the quote is missing in the example, perhaps just a typo
>
> is this good advise? Seems weird to me that no such function exist. Of course I can write my own using loop/recur ... or some
(some #(= 1 %) (1 2 3))
The docs on http://ClojureDocs.org are community-provided (and community-editable with a free account!), so you can fix mistakes if you find them and are so inclined. They are not edited by the core team, or at least not as a matter of policy (they might on occasion do so, perhaps, unknown to me).
Ah, I see the missing quote in an example you mention is in a comment, not in one of the examples. You can edit the examples to add a correct example, but you cannot edit the comments of others, AFAIK
there is intentionally no "linear search in a sequential collection" function (`some` is probably the closest) - in general the more Clojurey advice would be to put that data in a hash-indexed collection (map/set) and look it up
I'm reducing a symbolic expressions such as (op a b c d e a b c d e )
and if I find the identity element for the given op, I want to remove it.
If I use remove, how do I know whether it got removed if I don't know whether it was there in the first place? That's fine. I happy with some.
remove
won't tell you that directly. You could do =
on return value vs. input value, but that is linear time.
yes remove followed by = is linear in time and space, and find would be linear in time and constant in space
I am not aware of any built-in function that behaves like remove
but also returns whether it removed any elements. Not difficult to write, of course.
speaking of partition-by
I found group-by
for another purpose entirely. Is there a better way to group-by
a Boolean predicate, effectively splitting the sequence into a good and bad collection?
Maybe a partition-by
and then concatenating the odd groups and the even groups together.
can use destructuring to get you most of the way there:
(let [{matched true missing false} (group-by pred collection)]
;; do something)
Do you actually need a separate true/false return value indicating whether it removed any elements? Does your calling code actually care for some reason?
group-by
with a function that returns true or false is a good way to split into good/bad. I am not aware of a built-in that does the job any better.
scala has a function, i forget the name, friend of group-by which takes a collection and a Boolean predicte and returns a pair of collections, for the true and false items.
I guess I am having a hard time thinking of what is "wrong" with group-by
for that purpose. You don't want the overhead of creating a 2-element map?
(let [{odds true, evens false} (group-by odd? [1 3 5 6 7 9])]
(println odds evens))
;; [1 3 5 7 9] [6]
well, keys into the map in this particular context. They are literal constant Boolean values, in general.
you can examine what destructuring converts to using the (undocumented) destructure
function
user=> (pprint (destructure '[{odds true, evens false} (group-by odd? [1 3 5 6 7 9])]))
[map__161 (group-by odd? [1 3 5 6 7 9])
map__161 (if (clojure.core/seq? map__161)
(clojure.lang.PersistentHashMap/create (clojure.core/seq map__161))
map__161)
odds (clojure.core/get map__161 true)
evens (clojure.core/get map__161 false)]
I actually wanted something like (juxt false true)
but that won't work because true/false
cannot be invoked.
Can someone explain to me the purpose of (deref)
? For example;
user=> (def a (atom 99))
#'user/a
user=> a
#<[email protected]: 99>
user=> @a
99
Why does the first a
return #<[email protected]: 99>
? Is there something about the underlying Java that is making this happen? Is the atom effectively a pointer unless dereferenced?so you need two sorts of operations: operations on the location itself, and operation on the data in that location
you can have a function like (defn attach-foo [a] (swap! a conj :foo))
- it takes an atom, and replaces the contents using conj
it's almost like an assignable pointer, but it has rules about how it can be updated
@darrell vars work the opposite way - if you have (def a 99)
a
gives you 99, but #'a
gives the var itself
which is useful if you need the metadata on the var, or you need to manipulate it directly, or you want some function to have a handle to the var and not the value in it
and (deref #'a) and @#'a give you 99 as well as making you feel like a perl programmer again 😆
ins)user=> (def a (atom 99))
#'user/a
(ins)user=> #'a
#'user/a
(ins)user=> a
#object[clojure.lang.Atom 0x4e61e4c2 {:status :ready, :val 99}]
(ins)user=> @a
99
(ins)user=> @@#'a
99
refs and vars have some convenient behaviors too:
(ins)user=> (def r (ref {:a 0}))
#'user/r
(ins)user=> (r :a)
0
vars are only meant to be changed as a part of development process - you are loading new definitions, the var changes
i’m oversimplifying a lot here, but for getting started:
• use atoms for mutable state
• use vars for constants and function defintions via def
and defn
You can probably ignore agent
, and ref
at the start.
Regarding atom
, it’s typical in a non-clojure program to have lots of mutable state, but most clojure programs (even large ones) can get away with very little mutable state and very few atoms (like one or two).
atoms are meant to handle runtime data modification - things which are inconvenient to do purely (or seemingly impossible)
swap! on vars isn't possible (there's a similar function for vars, but it should be avoided and I'm forgetting the name :D )
it's called alter-var-root
, it's used for wrapper / middleware style extension and is basically a sign of "monkeypatching"
how can i construct a ratio (eg 22/7
) with expressions? (+ 20 2)/(+ 5 2)
doesn't work