This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-07-08
Channels
- # announcements (5)
- # aws (15)
- # babashka (7)
- # beginners (138)
- # bristol-clojurians (2)
- # chlorine-clover (11)
- # cider (9)
- # clara (4)
- # clj-kondo (17)
- # cljsrn (20)
- # clojars (1)
- # clojure (73)
- # clojure-europe (17)
- # clojure-italy (1)
- # clojure-nl (9)
- # clojure-spec (4)
- # clojure-uk (9)
- # clojurescript (43)
- # data-science (1)
- # datomic (87)
- # emacs (2)
- # figwheel-main (30)
- # fulcro (71)
- # helix (2)
- # hugsql (4)
- # jackdaw (5)
- # jobs (3)
- # jobs-discuss (31)
- # juxt (5)
- # kaocha (6)
- # lein-figwheel (16)
- # leiningen (1)
- # luminus (4)
- # malli (2)
- # meander (54)
- # music (8)
- # nrepl (12)
- # observability (28)
- # off-topic (85)
- # pathom (11)
- # re-frame (99)
- # reitit (9)
- # ring (1)
- # rum (6)
- # sci (11)
- # shadow-cljs (102)
- # sql (22)
- # tools-deps (10)
- # vim (65)
- # xtdb (14)
for clojure.data.xml
it seems like the alias-uri
mappings only apply when emitting xml, is there something similar for the inverse? i.e. when parsing instead of getting #...Element{:tag :xmlns.abcxyz/tagName}
I could get #...Element{:tag ::my-alias/tagName}
?
make an uberjar, put it into a java container running java -jar $yourjar.jar
as the docker CMD
For this 4Clojure problem interleaving two sequences http://www.4clojure.com/problem/39 I came up with:
(fn [coll-1 coll-2]
(flatten (into [] (zipmap coll-1 coll-2))))
Which works in my editor/repl for all the tests but fails on the first test in 4clojure with a "Failed the unit tests" error. Can't figure out what I'm doing wrong.4clojure uses an old version of clojure (1.4 or 1.5)
I looked at the source of all 3 core functions and the latest was flatten added with 1.2
btw the puzzle can be solved with two functions and no parens
It fails right on that first one. I copied over the unit tests to my editor and all come out true
user=> (def x (fn [coll-1 coll-2]
(flatten (into [] (zipmap coll-1 coll-2)))))
#'user/x
user=> (= (x [1 2 3] [:a :b :c]) '(1 :a 2 :b 3 :c))
false
user=> (x [1 2 3] [:a :b :c])
(3 :c 2 :b 1 :a)
oh I see what broke
maybe @U04V15CAJ has a good way to sandbox code for a fresher 4clojure experience
babashka is already used for 4clojure problems in the shell: https://github.com/porkostomus/4bb sci (the interpreter on which babashka builds) also has sandboxing options
the hash map has no defined order
btw flatten is terrible
it makes me flinch when I see it :D
I have a collection of videos that walk through how I though about and solved in different ways the first 60 challenges on 4Clojure. I encourage you to try the relevant challenges before looking at the video that covers those challenges 🙂 https://www.youtube.com/playlist?list=PLpr9V-R8ZxiDB_KGrbliCsCUrmcBvdW16
@chase-lambert due to 4clojure's substitution model, this works mapcat list
yeah, for a single level, you usually want concat (or something similar like cat
or mapcat
)
Hey guys! Been reading about Clojure a lot online and have decided to invest the time and effort in learning. Anywhere you would recommend starting? What is the fastest way to learn Clojure? What is the most enjoyable way to learn Clojure?
You may find the books and video guides I created useful https://practicalli.github.io/ I recommend finding a Clojure aware editor you like using. I use Spacemacs but there are several common editors that support Clojure http://practicalli.github.io/clojure/clojure-editors/ I learned a lot about the core functions in clojure by doing http://4Clojure.com challenges. There is a playlist of videos about that on the practicalli website. There are lots of tutorials on the internet on how to build things in Clojure. I am adding more to the books over the coming months, so let me know if you are looking for something specific. Good luck.
Wow thank you!
@U05254DQM, a video series on connecting to a db (SQL or Postgress) in a clojure'y way, doing selects, inserts etc would be great! I'm finding it hard to find good sources on this.
@U013YN3T4DA Thanks for the suggestion, it's a very useful topic so I'll move it up my (very long) Todo list. I have some basic content in the Practicalli webapps book, but it's very simplistic and needs updating. Many people use SQL fairly directly so next.jdbc seems a great project to use and I'll probably pick Sean Cornfield's brain on this. https://www.hugsql.org/ also seems a nice tool. I also like to use migrations with SQL too.
Take a look at the https://cljdoc.org/d/seancorfield/next.jdbc/1.1.547/doc/getting-started docs, the look very useful and have many examples
Thanks for these links! I'll have a read. THis has been a big stumbling block for me in Clojure, I think not being familiar with java doesn't help It's frustrating as in C# (my day job) accessing a db is really simple. I've noticed that with Clojure, it can take stuff that is quite hard in other language and make it so simple, yet some of the stuff that is simple that I don't have to think about in C# seem quite hard. Guess that will evaporate over time as I get more familiar with Clojure and what the popular / default packages are.
@igor.lenterman there truly is no one answer to any of those questions - everyone will find different material to connect with
many people like Clojure for the Brave and True as a fun intro
any projects you would recommend a beginner to practice building?
it's free online or you can buy it in paper form
I prefer building to reading for learning code
lots of other resources here https://clojure.org/community/resources
simple games are often a good starting point for me - rock paper scissors, etc
thank you!!!
super excited
babashka is already used for 4clojure problems in the shell: https://github.com/porkostomus/4bb sci (the interpreter on which babashka builds) also has sandboxing options
Also, unrelated to babashka/sci, but related to 4clojure: I do have a slightly updated version of clojail here: https://github.com/borkdude/clojail
@igor.lenterman, there is also codewars. https://www.codewars.com/kata/search/clojure?q=&r[]=-8&beta=false You can specify just to show kata that have clojure solutions. A nice thing here is once you solve the problem in clojure you get to see other peoples solutions and some are voted on best practice so you can often learn new techniques just by looking at others solutions.
Thank you! Excited to jump in
Codewars has a lot of mathematics oriented challenges, where you need to be able to recognise the maths techniques from the minimal description. There is also https://exercism.io/tracks/clojure which feels like a wider range of challenges. And http://4clojure.com helps you learn the clojure.core functions.
You can start off at 8 KYU (the easiest puzzles) and work your way up to 1 KYU, some of which can be very hard puzzles
(defn my-reduce
([f initial coll]
(loop [result initial
remaining coll]
(if (empty? remaining)
result
(recur (f result (first remaining)) (rest remaining)))))
([f [head & tail]] --> ?
(my-reduce f head tail)))
I'm having a little bit of trouble understanding the line marked with a question mark here. Anyone have any insight? I know that we start with a function definition which takes parameters f initial and coll, then we initialize a loop with result bound to initial and remaining bound to coll, if what's remaining in our collection is empty then return the result else we recur using the result of applying the function to the initial value and the first item of what's remaining? But, the lines after are a little confusing(defn ([x] ...) ([x y] ...))
defines a function with two bodies, and one is picked based on the count of the argument list
so we have here, if we ignoring destructuring:
(defn ([f init coll] ...) ([f init-and-coll] ...))
then the destructuring [head & tail]
uses one element as the "init" and the ones after as the coll
by a self call
hope that helps
So the first time we execute the second block to set init and tail and the first block handles breaking down until remaining is empty?
right - we call what you call "blocks" the bodies of the function
first clojure invokes the body matching the count of the arg list, then it can self-call (that's the most common pattern in multi-arity code)
sometimes functions have totally different code is invoked (see map for example) but that's more rare
Hi guys, here is a question that’s been bugging me for 3 weeks.. I’ve parsed the output generated by tree (with json output) and here is what the datastructure looks like: a Vector containing 1-n Maps:
[{:type "directory",
:name ".",
:contents
[{:type "directory",
:name "Intro",
:contents
[{:type "file", :name "01 What The Program is About and How to Do It.mp4"}
{:type "file", :name "02 How Training Works 5PS.mp4"}]}
{:type "directory",
:name "Session 01 - Fundamentals",
:contents
[{:type "directory",
:name "01 Prepare",
:contents
[{:type "file", :name "01 Standing Knee to Chest.mp4"} {:type "file", :name "02 Single Leg Deadlift.mp4"}]}
{:type "directory",
:name "02 Practice",
:contents
[{:type "file", :name "01 General Kneeling Lunge.mp4"} {:type "file", :name "02 Modified Pigeon Stretch.mp4"}]}
{:type "file", :name "Let's Get This Started.mp4"}]}]}]
I know this is a tree structure and I need some kind of recursion to parse itultimately i want to generate html using hiccup from this, but i can’t seem to ‘crack’ the puzzle
i’ve try’d many things, the latest:
(defn process-tree [vec-with-maps]
(map (fn [{:keys [type name contents]}]
(cond
(= "directory" type) (do
(println (str "dir:" name))
(when contents
(process-tree contents)))
(= "file" type) (println (str "file: " name))))
vec-with-maps))
(process-tree json-parsed)
a recursive function that eagerly walks to the bottom, then builds a data structure from the bottom up should work
as you go down, keep a stack of each level you visited
as you go up, return a "clojurization" of the item you are visiting to your parent, using the clojurized results your children passed back via that stack
do you know of an example where i could sneak peak at, as this makes sense, i just have no clue how to do it
sounds like I would reduce the tree structure into some other type of data structure and then ‘step through’ it?
what I'm talking about is how to make that data structure
if all you want is to process it for side effects, use tree-seq
(tree-seq :contents seq ...)
- that will give a lazy-seq of every node
then you can map across the top level of each node, knowing you'll only hit each one once
(ins)user=> (map :name (tree-seq :contents :contents dirs))
(nil)
(ins)user=> (map :name (tree-seq :contents :contents (first dirs)))
("." "Intro" "01 What The Program is About and How to Do It.mp4" "02 How Training Works 5PS.mp4" "Session 01 - Fundamentals" "01 Prepare" "01 Standing K
nee to Chest.mp4" "02 Single Leg Deadlift.mp4" "02 Practice" "01 General Kneeling Lunge.mp4" "02 Modified Pigeon Stretch.mp4" "Let's Get This
4")
(ins)user=> (pprint *1)
("."
"Intro"
"01 What The Program is About and How to Do It.mp4"
"02 How Training Works 5PS.mp4"
"Session 01 - Fundamentals"
"01 Prepare"
"01 Standing Knee to Chest.mp4"
"02 Single Leg Deadlift.mp4"
"02 Practice"
"01 General Kneeling Lunge.mp4"
"02 Modified Pigeon Stretch.mp4"
"Let's Get This Started.mp4")
nil
(where dirs is literally what you pasted)
I think that hit everything correctly, you should double check of course
that's a common experience with clojure - the right function turns your problem into a non-problem
the data structure / data manipulation libs just do most of the work
now i just want to generate h1 for directories and ul/li for files with hiccup and i’m done
nice, so you just replace (map :name ...)
with a a map of some function looking at type plus name and returning an h1...
sounds simple
you'd want to modify that code slightly if you ever had more than one hash-map in that top level vector
maybe it would be better to construct {:contents dirs}
instead of calling on (first dirs)
- that less likely to break in the future while offering the same behavior
i got 1 part working ha:
(defn directory-to-html [name]
(html [:h1 name]))
(map #(directory-to-html (:name %)) (tree-seq :contents :contents (first dirs)))
i think i got it:
(defn directory_or_folder [type name]
(cond
(= "directory" type) (directory-to-html name)
(= "file" type) (file-to-html name)))
(map #(directory_or_folder (:type %) (:name %)) (tree-seq :contents :contents (first dirs)))
with helper functions:
(defn directory-to-html [name]
(html [:h1 name]))
(defn file-to-html [filename]
(html [:li filename]))
right - there's nothing that tracks that in the current code
right - replace the second :contents
with a sort - that might suffice
err, with something that accesses :contents
but sorts files first that is
but if different nestings carry different meanings, you'll need something else I think - maybe something tricky where the second instance of :contents
(that is the function that returns the children) also looks at the current level, and increments the level of each child...
(defn children-of
[{:keys [level contents] :as el}]
(->> contents
(sort-by :type)
(map (fn [c] (assoc c :level (inc level))))))
#'user/children-of
(ins)user=> (map (juxt :name :type :level) (tree-seq :contents children-of {:contents dirs :level 0}))
([nil nil 0] ["." "directory" 1] ["Intro" "directory" 2] ["01 What The Program is About and How to Do It.mp4" "file" 3] ["02 How Training Works 5PS.mp4"
"file" 3] ["Session 01 - Fundamentals" "directory" 2] ["01 Prepare" "directory" 3] ["01 Standing Knee to Chest.mp4" "file" 4] ["02 Single Leg Deadlift.
mp4" "file" 4] ["02 Practice" "directory" 3] ["01 General Kneeling Lunge.mp4" "file" 4] ["02 Modified Pigeon Stretch.mp4" "file" 4] ["Let's Get This Sta
rted.mp4" "file" 3])
(ins)user=> (pprint *1)
([nil nil 0]
["." "directory" 1]
["Intro" "directory" 2]
["01 What The Program is About and How to Do It.mp4" "file" 3]
["02 How Training Works 5PS.mp4" "file" 3]
["Session 01 - Fundamentals" "directory" 2]
["01 Prepare" "directory" 3]
["01 Standing Knee to Chest.mp4" "file" 4]
["02 Single Leg Deadlift.mp4" "file" 4]
["02 Practice" "directory" 3]
["01 General Kneeling Lunge.mp4" "file" 4]
["02 Modified Pigeon Stretch.mp4" "file" 4]
["Let's Get This Started.mp4" "file" 3])
nil
one stab at it, it's an interesting problemall directories are before sibling files so the sort is opposite of what you want
but see how it accurately shows levels at least
by mapping a function that adds 1 to the level of the parent
you could use a similar approach to give each one an href link back to its parent, or to make an adjacency list that allows reconstructing the full form (with optional cycles) out of the "flattened" form here
all those things require is a unique id generator
(and a slight modification to the map fn of course)
while using tree-seq seems nice (I didn't even knew it existed), I would also recommend as a learning exercise to do it without it, so you know how to write this using plain recursion
How would you approach this @pavel.klavik as I was thinking the same thing after first getting a basic version working
i’m a beginner and i tried various approaches i got from books/internet but nothing got me actually there while it seems so simple
that diagram accurately describes how to descend, but doesn't describe how to create a result as you do so
I would start with thinking how it would work outside Clojure. What should each step do? If I assume that I already have a step as a black box, how their answers can be composed.