Fork me on GitHub
#beginners
<
2021-05-29
>
Jacob Rosenzweig03:05:52

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.

seancorfield04:05:07

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.

👍 6
Jacob Rosenzweig04:05:07

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.

seancorfield04:05:03

What's your prior main language?

Jacob Rosenzweig04:05:55

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.

seancorfield04:05:51

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.

dpsutton04:05:44

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.

seancorfield04:05:15

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.

Jacob Rosenzweig07:05:38

@U064WBEPL suggests using create fetch and other verbs for methods that produce side-effects (e.g. upserting a row into a DB)

seancorfield16:05:37

@U02313K7TSL 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.

👀 3
Jacob Rosenzweig16:05:32

It's actually not that far off base. We do that at my work as well. Only methods with side-effects get verbs.

Lukas07:05:18

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:

Lukas07:05:45

Any pointers are greatly appreciated ☺️

dpsutton07:05:52

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

Lukas08:05:23

:thinking_face: form seems to do exactly what I expect it to do

> (rf/dispatch [:new-result '(+ 2 2)])  ;; repl input
(+ 2 2) core.cljs:200:23                        ;; browser console

> (rf/dispatch [:new-result '(+ 2 3)])
(+ 2 3) core.cljs:200:23

> (rf/dispatch [:new-result '(+ 2 4)])
(+ 2 4) core.cljs:200:23

Lukas08:05:59

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 ....

Lukas08:05:02

(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?

indy08:05:08

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.

indy08:05:24

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

Lukas08:05:33

Indeed, it is codemirror.

Lukas08:05:11

okay :thinking_face: this seems like a somewhat advanced topic though

Lukas08:05:04

Is there any resource where I could read about how to approach this?

Lukas08:05:58

🙏 ty I will try it

indy08:05:08

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.

Lukas08:05:35

took the example code and try to make it work for my usecase 🙈 not very successfully so far 😂

Fra09:05:02

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

EsakkiSundar Varatharajan12:05:08

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

indy13:05:04

The ns form is wrong, the requires need to be inside the ns form. There is an extra paren after shopping

indy13:05:17

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 🙂

EsakkiSundar Varatharajan14:05:38

Thanks indy for your suggestion. I have changed it and working fine.

Njeri15:05:25

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?

practicalli-johnny04:05:51

Perhaps using a user.clj file would allow you to run one or more functions before figwheel. The REPL will automatically read and evaluate code in a user.clj file, if found on the classpath. I am not sure of the ordering, but hopefully the user.clj code is evaluated before figwheel-main. There is an example here for Clojure project.clj fileCLI tools, but the code should be the same for Leiningen. Add the directory to a dev profile in Leiningen by including :source-paths ["dev"] in the https://practical.li/clojure/clojure-tools/projects/configure-repl-startup.html

Njeri22:06:14

How would I get the function to run in production?

BuddhiLW16:05:13

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?

sandeep16:05:46

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

sandeep16:05:25

proc file - > web: java -cp phs.jar clojure.main -m phs.system

paul.nguyen18:05:57

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.

seancorfield19:05:30

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

paul.nguyen19:05:32

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 value

dabrazhe19:05:49

The 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?

Tero Matinlassi06:05:00

Maybe not exactly the format your looking for, but you might want to check https://clojuredocs.org/clojure.pprint/print-table

sova-soars-the-sora19:05:01

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

dabrazhe09:06:18

Thanks, I managed to use print-table

dabrazhe19:05:11

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"})