This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2023-03-20
Channels
- # aleph (15)
- # announcements (12)
- # aws-lambda (1)
- # babashka (54)
- # beginners (35)
- # calva (2)
- # cider (31)
- # clerk (13)
- # clj-kondo (65)
- # clj-on-windows (14)
- # cljsrn (7)
- # clojure (57)
- # clojure-art (1)
- # clojure-dev (1)
- # clojure-europe (19)
- # clojure-nl (1)
- # clojure-norway (7)
- # clojure-uk (1)
- # clojurescript (9)
- # community-development (25)
- # cursive (2)
- # data-science (3)
- # emacs (19)
- # events (1)
- # fulcro (21)
- # humbleui (1)
- # hyperfiddle (15)
- # jobs (8)
- # london-clojurians (2)
- # malli (18)
- # off-topic (1)
- # portal (6)
- # reagent (3)
- # releases (3)
- # sci (1)
- # shadow-cljs (73)
- # spacemacs (4)
- # sql (9)
hello can I ask something if possible? Where am I doing mistake?
(let [!db-map (atom {}) !table-id (atom 0) !state (atom {:in "" :in2 "" :username "" :email "" :button1 "" :button2 "" :bg-color "black" :bg-color2 "black" :placeholder "Please write your username..."})]
(let [in (get (e/watch !state) :in) in2 (get (e/watch !state) :in2) table-id (e/watch !table-id)]
(defn add-item-in-db-map [table-id username password] (swap! !db-map assoc-in [:person/id table-id] :person/id table-id :person/:name username :person/:grade password ))
(ui/button
(e/fn [] ((table-id-counter table-id)
(add-item-in-db-map ( table-id (get (e/watch !state) :button1) (get (e/watch !state) :button2)))
(swap! !state assoc :bg-color2 "inherit")
(swap! !state assoc :bg-color "inherit")
(swap! !state assoc :in "")
(swap! !state assoc :in2 "")))
(dom/text "Submit!!!")
(dom/props {:class "Button" :style {:color "white" :background-color "black"}}))
I think I doing a mistake or syntax error by using that code. ->
(swap! !db-map assoc-in [:person/id table-id] :person/id table-id :person/:name username :person/:grade password )
I want to create some kind of this map
{:person/id {1 {:person/id 1 :person/:name "Felix" :person/:grade "5"}
2 {:person/id 2 :person/:name "Villow" :person/:grade "10"}
}}
Can anyone take a look please?
Actually that swap!
call looks correct.
Things that definitely should be changed (might or might not be relevant to your issue):
• Format your forms properly, especially let
- don't multiple things on the same line
• It seems to be CLJS, so it's not a big deal there, but you should avoid using multiple atoms together since atoms don't offer co-operation
• Don't call swap!
multiple times on the same atom - call it once with the right function. In your case, you can just put all the kv pairs into one (swap! ... assoc ...)
• When asking questions, you should provide more details. If there are too many details, provide them in a thread. In this particular case, you haven't specified what you're actually getting, what that e
alias is (might or might not be important)
What's definitely relevant to your issue is the way you call add-item-in-db-map
- there's an extra nesting of parentheses in there, around its arguments.
Hello, Thank you for returning. All of my namespace code is little big that's why i just wanted cut some parts. Let me copy paste all of the my code, maybe that can be help little bit more who want to help me.
(ns app.P07b-PushMultipleInfoToTableByUsingMap
(:require [hyperfiddle.electric :as e]
[hyperfiddle.electric-dom2 :as dom]
[hyperfiddle.electric-ui4 :as ui]
))
(e/defn TableAppMultiByMap []
(e/client
(let [!db-map (atom {}) !table-id (atom 0) !state (atom {:in "" :in2 "" :username "" :email "" :button1 "" :button2 "" :bg-color "black" :bg-color2 "black" :placeholder "Please write your username..."})]
(let [in (get (e/watch !state) :in) in2 (get (e/watch !state) :in2) table-id (e/watch !table-id)]
(defn table-id-counter [last-table-id] (swap! !table-id inc last-table-id))
(defn add-item-in-db-map [table-id username password] (swap! !db-map assoc-in [:person/id table-id] :person/id table-id :person/:name username :person/:grade password ))
(ui/input in (e/fn [v] (swap! !state assoc :in v))
(dom/props {:id 1 :placeholder (get (e/watch !state) :placeholder) :style {:background-color (get (e/watch !state) :bg-color)}})
(dom/on "keydown" (e/fn [enter]
(when (= "Enter" (.-key enter))
(when-some [givenValue (contrib.str/empty->nil (-> enter .-target .-value))]
(swap! !state assoc :username givenValue)
(set! (.-value dom/node))
(swap! !state assoc :in "")
))))
(dom/on "keyup" (e/fn [keyup]
(when-some [givenValue (contrib.str/empty->nil (-> keyup .-target .-value))]
(swap! !state assoc :button1 givenValue)
)))
)
(ui/input in2 (e/fn [v] (swap! !state assoc :in2 v))
(dom/props {:placeholder (get (e/watch !state) :placeholder) :style {:background-color (get (e/watch !state) :bg-color2)}})
(dom/on "keydown" (e/fn [enter]
(when (= "Enter" (.-key enter))
(when-some [givenValue (contrib.str/empty->nil (-> enter .-target .-value))]
(swap! !state assoc :email givenValue)
(set! (.-value dom/node))
(swap! !state assoc :in2 "")
))))
(dom/on "keyup" (e/fn [keyup]
(when-some [givenValue (contrib.str/empty->nil (-> keyup .-target .-value))]
(swap! !state assoc :button2 givenValue)
)))
)
(ui/button
(e/fn [] ((table-id-counter table-id)
(add-item-in-db-map ( table-id (get (e/watch !state) :button1) (get (e/watch !state) :button2)))
(swap! !state assoc :bg-color2 "inherit")
(swap! !state assoc :bg-color "inherit")
(swap! !state assoc :in "")
(swap! !state assoc :in2 "")))
(dom/text "Submit!!!")
(dom/props {:class "Button" :style {:color "white" :background-color "black"}}))
(dom/table
(dom/props {:class "hyperfiddle"})
(e/client
(dom/table
(dom/tr
(dom/th (dom/text "asd"))
(dom/th (dom/text "table-id")))
(dom/tr
(dom/td (dom/text table-id))
(dom/td (dom/text (e/watch !db-map))))
)
)
)
)
)
)
)
Everything is working except the code which update's my atom map. I think that is
(swap! !db-map assoc-in [:person/id table-id] :person/id table-id :person/:name username :person/:grade password )
Because when I change Atom map's inside manually then I can see the values without having problem.As I said - that swap!
call is correct. But the way you call add-item-in-db-map
is wrong.
the usage of assoc-in looks wrong, i think you want:
(swap! !db-map assoc-in [:person/id table-id] {:person/id table-id :person/:name username :person/:grade password} )
(swap! !db-map assoc-in [:person/id table-id] {:person/id table-id :person/name username :person/grade password} )
fixed like this but still not working 😞I think I had two problems, first one is the assoc-in problem, and the second one was the parenthesis problem in my function call. Everthing working now! I deleting my post. I wish everyone have a good day 🙂
For future reference - please don't delete your posts even if you got an answer.
(+1 with @U2FRKM4TW, reading random questions & answers is the biggest reason I’m here) https://clojurians-log.clojureverse.org/clojure/2023-03-20/1679314813.676759
Hey guys, I am thinking about writing blogposts in hiccup / edn / clj directly, instead of markdown, and am looking for some opinions of yours 🙂 I wonder if this idea has been explored before.
I'm currently writing a static blog engine for myself and I am dealing with some hassles when translating my markdown files to html to hiccup because the lack of flexibility.
I could fix these problems, but I am left feeling that I am jumping through hoops this way.
I am using markdown-clj
for example, and ideally, when providing images in markdown syntax, I also want to specify width and height manually for some cases. I cannot change the default parsing of certain elements in this library, so I have to manually parse the hiccup after it has been generated, get the specific image I want, and add the attributes afterwards. This is not optimal.
My first thought was to persist a complementary hiccup .edn for every .md that I keep as the source of truth for rendering in the final step . I can make changes to this edn and lock the file, so it is not overwritten. I have more flexibility, because I can edit this file directly instead of programmatically changing the hiccup during runtime.
My second thought was, why not go all the way in? With edn, I have the limitation that I cannot call functions, so I still need to parse during runtime for some cases. I could hold the blogpost as a normal .clj file, accessing the functions of my namespaces.
I would trade the conciseness of markdown for the expressibility of clojure data.
What do you think?
i think raw HTML is supposed to be valid markdown right? Meaning if you want to customize an image maybe you could directly use an <img/>
tag?
imo having your writing be mostly plain-text is nice for portability, longevity, and enjoyment of the writing experience. so having it embedded within a .clj
file might be more friction than it's worth unless you want to make posts that are super interactive.
I’ve found that nothing beats the ability to actually execute Clojure expressions, which is why I built a static website generator that allows me to do so with far less friction than markdown-based tools. https://github.com/fabricate-site/fabricate https://fabricate.site
Another option is to use a more flexible markdown parser. I use https://github.com/vsch/flexmark-java and its https://github.com/vsch/flexmark-java/wiki/Extensions#xwiki-macro-extension to have arbitrary control over the output. It's not that much work to turn parsed markdown into html, https://github.com/phronmophobic/blog/blob/master/src/blog/mdown.clj.
Fabricate was motivated originally by similar concerns to yours: the ability to have more control over layout than was possible in Markdown. I think the markup format I landed on is flexible enough to be extremely useful but is not very ergonomic (it’s really only useful from emacs)
im literally working on a clerk thing right now and still forgot about it as a neat point in the design space 🙂 interesting how clerk parses comments as markdown to presumably reduce friction when you're writing
Clerk also has an option to parse markdown files rather than clj files, but I think it's less well supported.
For similar work which does (IMO) an excellent job providing elegant writing syntax with an escape hatch to the Full Power of Lisp, see Racket's https://docs.racket-lang.org/pollen/. Some colleagues and I use a Clojure port and it works great for blog posts and slideshow presentations both. Highly recommended.
Clerk is a great library, but if you want fine-grained control over the visual style of the output you might find yourself having to tweak a lot of things that Clerk’s defaults introduce into your documents (e.g. Tailwind CSS). It’s also pretty large: you may not necessarily want to ship an interactive Clojure environment with every static HTML page you generate. I use Clerk quite regularly, but I personally find it a better environment for prototyping than publication.
Personally I find http://cryogenweb.org/ more than adequate for static blog web sites, even with markdown, although asciidoc can also be used. Cryogen is pretty easy to extend. I'm still curious to find tooling in Clojure land that doesn't require more focus on development of the tool than writing static docs, unfortunately. If doing a lot of documentation, then https://github.com/juxt/site may be of interest.
Here is a pollen implementation in clojure: https://github.com/JeremS/prose For writing blogs in markdown there's also https://github.com/borkdude/quickblog written in clojure/bb
I've written my personal website directly in hiccup and bb: https://github.com/borkdude/michielborkent.nl/blob/master/script/generate.clj
(hiccup has been a part of bb for a while, but I see I made the last edit to that website in 2020 which was before that)
Thank you all for your replies. I am aware that I am most likely reinventing the wheel, all the while stumbling around problems others have thought of before. But I am willing to do that as a programming exercise. In the end, I want a simple solution without stuff I don't need, so it grows with me 🙂 @UFTRLDZEW I think you built what I imagined. Why is it only useful from emacs? I am using emacs extensively, but I'm interested in this limitation
@U04V15CAJ I am leaning towards a solution like your own. What is your experience with it? Do you think it extends well or are there problems that are not immediately obvious?
@U04JD5WSD9P which one, quickblog or my personal hiccup-based website?
When writing prose, I don't find myself needing to do any custom clojure evaluation, I can just write a tiny bit of raw html if I need to, which I hardly ever do
@U04JD5WSD9P the source file format in Fabricate can be used from any editor, but syntax highlighting for it will only work in emacs (via the polymode
package, which allows for a buffer to have multiple major modes active depending on the region)
https://github.com/fabricate-site/fabricate/blob/main/resources/fabricate-polymode.el
Does anyone know of a good article doing a roundup of strategies for describing errors (and perhaps even successful) responses in Clojure? Both in terms of representing success/error and performing control flow based on these representations. I'm doing some research of my own to try to understand the ecosystem and the common practices and I find there's a multitude of tools and approaches out there, but no "literature review".
For instance, a few of the libs/approaches I found: • https://github.com/adambard/failjure • https://github.com/kumarshantanu/promenade • https://github.com/lazy-cat-io/tenet • https://github.com/cognitect-labs/anomalies • https://github.com/igrishaev/pact • https://github.com/fmnoise/flow • https://github.com/scgilardi/slingshot • https://github.com/exoscale/ex
I find it curious that there are several libraries attempting to solve arguably the same problem in ways that seem to be only stylistically different.
It can probably be argued that more broadly, easily rolling your own X is “how things are supposed to be done” in lisp world. Blessing for individual devs, curse for the tooling/ecosystem imo
It's also useful to note that error handling is often simple enough that it doesn't require a library. Most solutions of the complexity of Cognitect's anomalies don't get released, for instance.
@U05092LD5 true, I've seen quite a few home grown solutions as well. Also, cognitect anomalies are far more abstract compared to the other ones I listed. I'm particularly interested in how people apply these in context of larger applications, how do people model failed operations in their domain, how do these approaches play with the ubiquitous exceptions, etc.
If you scroll back through #C8NUSGWG6 (or maybe you can find it browsing through https://clojure.org/news/2023/03/18/deref), somebody posted multiple blog posts on that topic within the last month or two.
possibly https://mbezjak.github.io/posts/error-model/ (4-part series)
Anyone know of ways to get static type checks in-editor, kind of like what VSCode does ootb for JS projects? Currently using VSC + Calva
Calva should already provide a number of "static checks" via LSP/clj-kondo in its default setup. If you need help configuring that, drop into #CBE668G4R and provide a bit more detail about your project setup and what makes you think the static checks are not happening...
...I would expect you to see clojure-lsp
in the status bar automatically (it starts, analyses the code, and then reports warnings/errors in the code editor -- such as unused private vars/local bindings etc).
I'm not sure what static checks you're expecting, given that Clojure doesn't have static types...?
You can use malli function schemas, once you instrument them they got used by clj-kondo (part of clojure-lsp) and will validate your input arguments https://github.com/metosin/malli/blob/master/docs/function-schemas.md