Are create
or init
or builder
functions popular at all in Clojure? I'm doing this programming exercise where I need to create pizzas. Usually, in a statically typed language, I'd write a few functions for creating a Pizza
type, usually mapping args from the function to certain fields in the Pizza
ADT (e.g. a struct). But in Clojure, you're encouraged to use maps anywhere. So if I use a map in my create-pizza
function and I return a map, is there any point in having this create-pizza
function in the first place? Seems like the only reason for it existing is to take raw valuese and construct an internal type for it.
I tend not to use create
/`make` functions unless they actually need to compute something from their arguments in order to produce the data structure I need: data is a first class citizen in Clojure, after all.
@stuartsierra suggests using create
fetch
and other verbs for methods that produce side-effects (e.g. upserting a row into a DB)
@rosenjcb Yeah, I’m not sure I agree 100% with Stuart on all of his naming recommendations but most of his Do’s/Don’ts series is very good. I highly recommend Zach Tellman’s “Elements of Clojure” book for its in-depth analysis of naming, idioms, indirection, and composition.
It's actually not that far off base. We do that at my work as well. Only methods with side-effects get verbs.
This seems to be what I'm leaning towards. Unless I'm transforming something, no need to make create
/`make` functions. That's what data is for.
What's your prior main language?
I split on frontend work and backend work in my personal life. So it's usually JS and Rust. Though at my work I use more boring languages. This pizza shop exercise I did in F# though.
In JS you could take a data-first approach and just construct an "object" on the fly (like a hash map). F# is certainly going to go straight to types by default though.
also very common to take advantage of the immutable data structures and def an initial state that provides the skeleton of the structure. {:crust :hand-tossed :toppings #{:cheese}}
or whatever.
Yeah, if you have a structure where several things have a standard default, then a create
/`make` function that just merge
's the new values onto the defaults and returns that makes sense -- but that's what I mean about computing something.
Hey
guys, I'm a bit puzzled right now: I'm working with reagent/re-frame
and one of my components is not a "react"-component. What I'm trying to
achieve is actually pretty simple, but I guess I'm right now overwhelmed
by all the new stuff I try to learn:see_no_evil:. All I want to do is swap out the result-view
when new data arrives. That is what I got so far
(defn result-view [source]
[:div
{:ref
(fn [el]
(EditorView.
#js {:state
(.create
EditorState
#js {:doc (with-out-str (fipp source))
:extensions extensions-read-only})
:parent el}))}])
(defn result-box []
(let [source (rf/subscribe [:results])]
(fn []
(let [[_ form] @source]
[:div {:class "code-box"}
[result-view form]]))))
The problem is, that the old result remains in the view and the new result is appended on bottom like this:Any pointers are greatly appreciated ☺️
can you determine whether form
has extra or if the state of the EditorView
is out of sync? Log form
to see if that has two lines or if your editor view is misbehaving. bisect the problem
:thinking_face: form
seems to do exactly what I expect it to do
<http://lhrb.app|lhrb.app>> (rf/dispatch [:new-result '(+ 2 2)]) ;; repl input
(+ 2 2) core.cljs:200:23 ;; browser console
<http://lhrb.app|lhrb.app>> (rf/dispatch [:new-result '(+ 2 3)])
(+ 2 3) core.cljs:200:23
<http://lhrb.app|lhrb.app>> (rf/dispatch [:new-result '(+ 2 4)])
(+ 2 4) core.cljs:200:23
but I guess you are right the EditorView
is out of sync, I figured the easiest way is maybe to swap the whole view component instead of updating the EditorView
....
(defn result-view [source]
(let [!view (atom nil)]
(if-let [v @!view]
;; find out how to update the view
(update-view v)
;; else init
(fn [source]
[:div
{:ref
(reset!
!view
(fn [el]
(EditorView.
#js {:state
(.create
EditorState
#js {:doc (with-out-str (fipp source))
:extensions extensions-read-only})
:parent el})))}]))))
would this be a suitable approach to just update the EditorView
on new data?I'm guessing the EditorView is either prosemirror or codemirror, in which case, I think it has something like transactions to update the EditorView. Recreating the EditorView would not be optimal.
Prosemirror/Codemirror require a lot of interop code and it's cleaner to have them as js components and import them into cljs wherever required
Indeed, it is codemirror.
okay :thinking_face: this seems like a somewhat advanced topic though
Is there any resource where I could read about how to approach this?
To update EditorState, you should check https://codemirror.net/6/docs/ref/#state.Transaction.
🙏 ty I will try it
I think https://nextjournal.com/ uses prosemirror and cljs. Maybe they have some recommended resources. We use prosemirror and even in JS, the code requires specialist prosemirror knowledge. I have dabbled at using prosemirror with CLJS and it was not fun. If I were to do it, I'd write the prosemirror bits in JS and import that in the cljs code.
yeah, I use their https://github.com/nextjournal/clojure-mode library here
took the example code and try to make it work for my usecase 🙈 not very successfully so far 😂
Hi 👋 I'm looking for an auth2 library I can use with ring and reitit, do you have any general advice for me? there are quite a few in clojars and I don't know which to pick up. Thanks
Hello Clojurians, Im beginning to learn Clara Rules and wanted to execute them from Java. Im getting an error when trying to run the code,. ExceptionInInitializerError: Syntax error compiling at (example/shopping.clj:2:3). clara.rules.accumulators
I'm attaching the project source for your reference. Could you please help. Please install Maven. Go to your project root directory and to compile the project execute mvn -q compile
To run the code mvn -q exec:java -Dexec.mainClass=example.ClaraExampleMain
The ns form is wrong, the requires need to be inside the ns form. There is an extra paren after shopping
Also it would be easier to share the code as a gist or github repo or a pastebin. Not super safe for people to extract rar's or open binaries 🙂
Thanks indy for your suggestion. I have changed it and working fine.
I have a function that needs to run before the Figwheel server starts. Is there a way to run the function without having to install lein-ring and use its :init
key?
How would I get the function to run in production?
Hello everyone! I would like to integrate Incanter, or any library that let me plot, with the browser. I would like to render and display it through a browser canvas or something in those lines. Anyone familiar with a working example repository, or video-tutorial?
hello, any idea how to fix the following error Error R10 (Boot timeout) -> Web process failed to bind to $PORT within 60 seconds of launch
proc file - > web: java -cp phs.jar clojure.main -m phs.system
How would I apply a function to every key in a nested map? Here's an example of the data structure I'm working with:
{:key "foo"
:options [{:key "bar"
:items [{:id "baz"}]
]
}
I want to apply the function to every map with :key
and :id
and put those specific maps into a vector. The rest of them aren't necessary for the output, but I do need to traverse through each vector of maps.What output are you after from the input above? (and perhaps show more than one :id
instance so we can see how it should behave for multiple items) @paul.nguyen
Something like this:
[{:key "foo"}
{:key "bar", :parent-key "foo"}
{:id "baz", :parent-key "bar"}
{:id "baz2", :parent-key "bar"}]
The function I'm applying basically pulls out values from the original map and places it into a new one with different keys, along with a key that references the parent's valueThe idea is to align the keys under each other so that I can easily compare the values, like in a table. How can I achieve this?
Might not be the answer you're looking for, but you can make a display for your data and use (filter #(= (key %) :BUY) mmms)
to grab just the :BUY
keys from your maps-coll mmms
...and do that for however many keys you have, which you could arrange however on the page. I think eventually you'll want a separate "view" on the data but maybe you're striving to keep it as simple as possible
Thanks, I managed to use print-table
The structure looks like this
({:BUY {:change 0.08000001
:lastPrice 0.5
:volume 1
:etc :bunchotherkeys}
:SELL {:lastPrice 1.95
:safetyMargin 18.360813190331367
:volume 46
:etc :otherkeys}
:p2margin 17.35
:s-premium 1.27
:ticker "TSLA"}
{:BUY {:change 0.08000001
:lastPrice 0.9
:volume 100
:etc :bunchotherkeys}
:SELL {:lastPrice 2.0
:safetyMargin 18.360813190331367
:volume 460
:etc :otherkeys}
:p2margin 18.2342420
:s-premium 1.27
:ticker "TSLA"})