This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-11-27
Channels
- # announcements (1)
- # beginners (54)
- # biff (7)
- # calva (6)
- # cider (7)
- # clojure (9)
- # clojure-art (3)
- # clojure-europe (27)
- # clojure-gamedev (16)
- # clojurescript (15)
- # editors (2)
- # emacs (1)
- # events (1)
- # fulcro (24)
- # gratitude (23)
- # humbleui (6)
- # lsp (9)
- # malli (3)
- # off-topic (52)
- # pathom (5)
- # portal (1)
- # rdf (9)
- # reveal (3)
- # shadow-cljs (52)
- # specter (2)
- # tools-build (9)
- # tools-deps (11)
- # tree-sitter (1)
- # xtdb (21)
range
is a lazy sequence right
is there a way to print out its lazy representation
every time i enter (range)
on the repl it tries to consume this infinite sequence and crash my repl
the dynamic vars *print-length*
and *print-level*
might be of interest:
user=> (set! *print-length* 20)
20
user=> (range)
(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ...)
I've written some code which works but seems more complicated than it needs to be. Curious if someone knows a better way?
(def misc [[1 2 3 4] [5 6 7 8] [9 10 11 12]])
(apply #(map * %1 %2 %3) misc)
(apply map * misc)
Try (map vector [1 2 3 4] [5 6 7 8] [9 10 11 12])
and see that map can take multiple collections and applies the function to the first of each, and then the second etc. etc...
yep I can give multiple collections to map
problem is the three collections are in a list
Just use apply
yep that is what I do in my example, just seemed a bit convoluted
You don't need the convoluted anonymous function... just (apply map * misc)
OK cool I just didn't realise I can do that. Thanks!
No problem. Has the advantage of handling any number of collections, but of course, stops once one of the collections has been used...
e.g. (map vector [1 2 3 4 5] [1 2])
gives ([1 1] [2 2]) which may not be what you want....
although it often is.... š
nope this is fine as this example was just psudocode. my real use-case is implementing a "save all" functionality on table of data from a web app. Here is my real code for your curiosity (after applying your fix):
(defn always-vector
"this function takes something which may or may not be a vector and makes it always a vector"
[item]
(cond
(= (type item) clojure.lang.PersistentVector) item
(nil? item) []
:else [item]))
(defmulti app-page-post (fn [request] ((:params request) :action)))
...
(defn modify-habit [habit_id habit_name freq_value freq_unit date_scheduled]
(db/modify-habit! (map-of habit_id habit_name freq_value freq_unit date_scheduled)))
(defmethod app-page-post "save_changes_habits" [request]
(let [{:keys [habit_id
habit_name
freq_value
freq_unit
date_scheduled]} (request :params)]
(doall (apply map modify-habit (map always-vector [habit_id habit_name freq_value freq_unit date_scheduled])))))
if you're wondering why I need always-vector it's because of how the framework handles posted data, if there is one item with a given name it's just a string, else it's a vector. which break everything so I need to sanitize that
well today I've learned something new about apply which is great! thanks
vec
turns most things into a vector. And see vector?
Have a good rest of day.
vec
does not do what I want but vector?
I can use. thanks!
I realise now my minimal example is not really valid
I've updated my original thread with an example which better captures what I am trying to do
does clojure expose continuations
not from the core, but clojure programs can use new (still experimental afaik) virtual threads from latest JVM 19
I'm working a simple proof of concept using the Apache Lucene library. On program launch I'm building an index from a CSV file. I originally was passing a data structure around to all the functions that needed it but that felt unwieldy as I started adding more and more functions to interact with the Lucene search index. The data structure is a simple map in my case that has the needed java objects like a writer, searcher (some of which are expensive to create). I'm not clear what the idiomatic way to do this is in clojure if I wanted to just have a reference in my lucene.clj namespace and reference it from within the functions instead of passing it around everywhere. Should I use a defonce
, ref
, atom
or a memoized function? Note I don't think at the moment I will be changing the data structure which I think would steer me to an atom
?
Hi. I do this using deftype and then pass around as an opaque handle. I then use a systems library (e.g. component or mount or integrant) to handle its lifecycle management in a running application or REPL. Personally I wouldn't use an atom for this. In many situations, I don't need to pass it around, because I then incorporate that opaque handle into a context (e.g. in a server implementation). In my implementation level code, which uses Lucene directly, I do pass around explicit handles to the required Lucene objects e.g. Searcher. Mostly, at that level, because functions do one thing, they only need one of the basic Lucene objects.
Here is an example: https://github.com/wardle/hermes if it is of any help.
thanks @U013CFKNP2R ! Very helpful. Iām just diving back into Clojure after about a year and forgot about how something like integrant could help here. Thanks for the code sample too.
How do I remove a defmulti from my active namespace in the repl so I can redefine it?
I'm not really understanding the difference between defrecord
and deftype
. I have a protocol that I've defined which contains a couple methods designed to operate on an adjacency list representation of a graph. I'd like to create something that contains the adjacency list that implements this protocol. Should I be using defrecord
or deftype
?
For more context, I would like to create a different type or record that represents a Graph that internally uses this adjacency list type as its representation. The end goal being defining several defmulti
functions such as walk-graph
that can dispatch on the graph's representation to the appropriate defmethod
fn that understands the representation. Given the context - are defrecord
and deftype
what I want for both the adjacency list protocol implementer, as well as the "graph" type that holds an instance of that protocol?
AFAIK I could have a defmulti
dispatching on either a defrecord
or deftype
by using class
to determine the "type" I'm dealing with
I ran through this in CL with CLOS and was able to use multiple dispatch to do relatively the same thing but I'm just balking doing this in clj
For the difference between deftype
and defrecord
, take a look at https://clojure.org/reference/datatypes (if you haven't already).
I'd go for defrecord
and see if that works for all your needs.
defrecord
creates a Record type, which has built-in implementations for a many core protocols, giving it out-of-the-box behavior fairly similar to a Map.
deftype
creates an empty type, with no implementations of anything except what you implement yourself.
If you can benefit from having key value pairs on your data structure, then Record will likely be easier to get going with than an empty type.
The basis fields (the keys named in defrecord
) will generally show improved performance characteristics than kv pairs of a map would. Additional keys assoc'ed on later will not get this boost. If you dissoc a basis field, you will lose your custom type, as it gets downgraded to a regular map.
If you're planning on implementing something that requires multiple dispatch you may be better off not using protocols and just sticking to multimethods + data. Protocols are a way of hooking into the high performance single dispatch mechanism provided by the JVM, which is not too say that multimethods are "slow". You may find them fast enough ;)
I originally was dispatching on "metadata" in the graph data structure I had which communicated the "representation" of the graph but I found that to be a little too fast and loose for my liking. I think I prefer being able to dispatch on the result of the class
fn for this specific application at least.
If you're only dispatching on the class
then protocols might be more appropriate.
In case you haven't already seen this, take a look at https://cemerick.com/blog/2011/07/05/flowchart-for-choosing-the-right-clojure-type-definition-form.html