Fork me on GitHub
#beginners
<
2022-05-04
>
dbsgtk00:05:03

There's something I don't understand about recur. I have the following code which is the outer form of a model of an "epistemic network", used in philosophy of science to model how beliefs spread among scientists

(defn play [game]
  (loop [game (round game)]
    (if (or (converged? game) (> (:rounds game) 10000))
      (assoc game :converged (converged? game))
      (recur (play game)))))


(let [game (make-game (make-cyclic-graph 6) :n 1 :A-success-prob 0.5 :B-success-prob 0.7)]
  (play game))
I think I'm using recur correctly, right? At any rate, it often works, but when it goes above ~2700 rounds without converging it blows the stack. The round function is a composite of three other functions operating on the game: take-action , update-params, and update-beliefs . The traceback says the stack overflow happens in a let form within update-params , which I'll paste below
(defn update-params
  "[network node n]  update the beta distribution parameters for a node based on the node and its neighbours. Returns an updated graph

   [game] update params for all the players in a game. Returns an updated game
  "
  ([network node n] 
   (let [node-attrs (uber/attrs network node)
         nodes (conj (uber/neighbors network node) node)
         all-attrs (map #(uber/attrs network %1) nodes)  ;;; <- this is a typical line marked in the traceback.
         a-attrs (filter #(= (:action %) :A ) all-attrs)
         b-attrs (filter #(= (:action %) :B ) all-attrs)
         a-result-sum   (reduce + (map :reward a-attrs))
         b-result-sum   (reduce + (map :reward b-attrs))]
     (uber/add-attrs network node
                     {:alpha-A (+ (:alpha-A  node-attrs) a-result-sum)
                      :beta-A (+ (- (:beta-A node-attrs) a-result-sum) (* n (count a-attrs)))
                      :alpha-B (+ (:alpha-B  node-attrs) b-result-sum)
                      :beta-B (+ (- (:beta-B node-attrs) b-result-sum) (* n (count b-attrs)))
                      }
                     )))
  ([game]
              (let [network (:network game)
                    update-fn #(update-params %1 %2 (:n game))]
                (assoc game
                       :network (reduce update-fn network (uber/nodes network))
                       :updates (inc (:updates game))))))

hiredman00:05:39

(recur (play ...)) Should just be (recur ...)

🙏 1
dbsgtk00:05:05

Thanks. I accidentally deleted my message while editing

quan xing10:05:33

how can I call wsdl webmethod in clojure?

delaguardo10:05:38

you can try this lib - https://github.com/xapix-io/paos but wsdl is very complicated technology and it might not work well enough

quan xing10:05:34

thanks. I have read that . It's too complicated to use. for example : call add method for calculate 1+2 😭

(let [soap-service (wsdl/parse "")
      srv          (get-in soap-service ["CalculatorSoap12" :operations "Add"])
      soap-url     (get-in soap-service ["CalculatorSoap12" :url])
      content-type (service/content-type srv)
      headers      (service/soap-headers srv)
      mapping      (service/request-mapping srv)
      context      (assoc-in mapping ["Envelope" "Body" "Add" "intA" :__value] 1)
      context2      (assoc-in context ["Envelope" "Body" "Add" "intB" :__value] 2)
      body         (service/wrap-body srv context2)
      parse-fn     (partial service/parse-response srv)]
  (-> soap-url
      (client/post {:content-type content-type
                    :body         body
                    :headers      headers})
      :body
      parse-fn))
;; => {"Envelope" {"Header" {"__value" nil}, "Body" {"AddResponse" {"AddResult" {"__value" "3"}}}}}

Serafeim Papastefanos10:05:47

i would totally recommend creating a java lib and calling it from clojure

Serafeim Papastefanos10:05:03

calling ws is a real PITA and have many, many special cases

quan xing10:05:14

what's mean PITA ?

delaguardo10:05:37

"pain in the ass" 🙂

delaguardo10:05:02

btw, even with a java lib call to Calculator service might be even more complex because of java interop.

quan xing10:05:29

Maybe I should use dotNET?

Serafeim Papastefanos11:05:46

why ? java is fine for calling WS

emccue16:05:20

Are you using tools.deps or leiningen? And yeah - wsdl do be like that

emccue16:05:55

you can make a wrapper for some of it obviously, but it will likely be one shot

emccue17:05:14

(defn soap-service [url]
  {::soap-service (wsdl/parse "")})

(defn invoke [service object method arguments]
  (let [{::keys [soap-service]} service
        srv          (get-in soap-service
                             [object :operations method])
        soap-url     (get-in soap-service [object :url])
        content-type (service/content-type srv)
        headers      (service/soap-headers srv)
        mapping      (service/request-mapping srv)
        context      (reduce (fn [ctx [arg v]]
                               (assoc-in ctx ["Envelope" "Body" method arg :__value] v))
                             mapping
                             arguments)
        body         (service/wrap-body srv context2)
        parse-fn     (partial service/parse-response srv)] 
    (-> soap-url 
        (client/post {:content-type content-type
                        :body         body
                        :headers      headers})
        :body 
        parse-fn)))    

emccue17:05:52

and then

(let [service (soap-service "")]
  (invoke service "CalculatorSoap12" "Add" {"intA" 1 "intB" 2}))

emccue17:05:32

have not validated this works, but would that be good enough for your use cases?

quan xing06:05:41

Thank you !! @U3JH98J4R I'll try it.

janezj13:05:40

@U025AG2H55F I think that paos is not too complicated with refactoring of the example and creating some supporting functions. Assigning params can be done with reduce,

emccue14:05:14

@U025AG2H55F just checkng back in did this solve your issue?

quan xing13:05:15

How can I mix java file and clj in deps like this?

:paths ["src" "java-src"]
but I run in calva show 'import error'

pez13:05:07

On the general question. I've written a short blog article about it: https://blog.agical.se/en/posts/mixed-clojure-and-java/ See if that setup is different in some significant way to the one you have, maybe?

quan xing13:05:09

do I need compile java to class first?

pez13:05:08

Yes, in that setup I have not added anything that auto-compiles the Java stuff.

quan xing14:05:05

I put the class files in java-src is ok . but put the class in target/classes show "unable to resolve classname". in my deps.edn add this. :paths ["src" "java-src" "resources" "config" "target/classes"]

pooriaTaj16:05:28

Hi , I am new to clojurescript development and I am having trouble with code Navgiation in VS code using the Calva Extension , When I press F12 to go to namespaces/function definitions vscode transitions to loading state and cannot navgiate to the targeted codeblock These are my configs

{:lein   true
 :nrepl  {:port 8777}
 :builds {:app {:target          :browser
                :output-dir      "resources/public/js/compiled"
                :asset-path      "/js/compiled"
                :modules         {:app {:init-fn stellar.awesome-o.core/init
                                        :preloads [devtools.preload
                                                   re-frisk.preload
                                                   ;; day8.re-frame-10x.preload
                                                   ]
                                        :main {:init-fn stellar.awesome-o.core/init}}}
                ;; :release         {:build-options
                ;;                   {:ns-aliases
                ;;                    {day8.re-frame.tracing day8.re-frame.tracing-stubs}}}
                :closure-defines {"re_frame.trace.trace_enabled_QMARK_" true
                                  ;; "day8.re_frame.tracing.trace_enabled_QMARK_"  true
                                  stellar.awesome-o.config/base-uri #shadow/env "APP_URL"}
                :devtools        {:http-root    "resources/public"
                                  :http-port    8280
                                  }}}}

pooriaTaj16:05:47

Lein Project.clj

(defproject stellar.awesome-o "1.0.0-SNAPSHOT"
  :dependencies [[org.clojure/clojure "1.10.1"]
                 [org.clojure/clojurescript "1.10.597"
                  :exclusions [com.google.javascript/closure-compiler-unshaded
                               org.clojure/google-closure-library
                               org.clojure/google-closure-library-third-party]]

                 [thheller/shadow-cljs "2.8.83"]
                 [reagent "0.10.0"]
                 [re-frame "0.11.0"]
                 [day8.re-frame/http-fx "v0.2.0"]
                 [hickory "0.7.1"]
                 [garden "1.3.9"]
                 [ns-tracker "0.4.0"]
                 [com.taoensso/timbre "4.10.0"]
                 [day8.re-frame/http-fx "v0.2.0"]
                 [reagent-utils "0.3.3"]
                 [mattinieminen/re-fill "0.2.0"]
                 [re-pollsive "0.1.0"]]

  :plugins [[lein-garden "0.3.0"]
            [lein-shell "0.5.0"]]

  :min-lein-version "2.5.3"

  :jvm-opts ["-Xmx1G"]

  :source-paths ["src/clj" "src/cljs"]

  :clean-targets ^{:protect false} ["resources/public/js/compiled" "target"
                                    "resources/public/css"]


  :garden {:builds [{:id           "screen"
                     :source-paths ["src/clj"]
                     :stylesheet   stellar.awesome-o.css/screen
                     :compiler     {:output-to     "resources/public/css/screen.css"
                                    :pretty-print? true}}]}

  :shell {:commands {"open" {:windows ["cmd" "/c" "start"]
                             :macosx  "open"
                             :linux   "xdg-open"}}}

  :aliases {"dev"          ["with-profile" "dev" "do"
                            ["run" "-m" "shadow.cljs.devtools.cli" "watch" "app"]]
            "prod"         ["with-profile" "prod" "do"
                            ["run" "-m" "shadow.cljs.devtools.cli" "release" "app"]]
            "build-report" ["with-profile" "prod" "do"
                            ["run" "-m" "shadow.cljs.devtools.cli" "run" "shadow.cljs.build-report" "app" "target/build-report.html"]
                            ["shell" "open" "target/build-report.html"]]
            "karma"        ["with-profile" "prod" "do"
                            ["run" "-m" "shadow.cljs.devtools.cli" "compile" "karma-test"]
                            ["shell" "karma" "start" "--single-run" "--reporters" "junit,dots"]]}

  :profiles
  {:dev {:dependencies [
                        [re-frisk "1.3.2"]

                        [binaryage/devtools "1.0.0"]]
         :source-paths ["dev"]}
   }

  :prep-tasks [["garden" "once"]])

pooriaTaj16:05:26

Also , I am using the Reframe framework and want to be able to easily navigate to my events and routes , is there any useful tool for this ?

bringe16:05:16

I’m not immediately sure what’s going on with the code navigation, but @U0ETXRFEW may be able to help you further soon (I’m a bit busy today). clojure-lsp allows you to navigate to re-frame events and subs and is built into Calva, so that should be working for you. (You can go to definition of a re-frame keyword and find all references.)

bringe16:05:38

If that’s not working, maybe clojure-lsp is not starting correctly for you, or there is some other issue related to it going on.

bringe16:05:43

What’s your OS?

pez16:05:44

How are you starting the REPL, @U02JS8BDHB9?

pooriaTaj16:05:13

my OS is ubuntu 21

pooriaTaj10:05:10

Hi again ,thank for the quick help . It's much appericiated , as mentioned I was starting my REPL In the wrong configuration ( Lein + ShadowCljs ) I started the repl using lein dev with my dev profile and connected to it using the connect to a repl in your project option in Calva As for the Code navigation issues, it was due to an overlap with the Clojure Extension which I think is incompatible with calva ( I think this is even mentioned ) I turned off the clojure extension and it worked!

metal 1
pez10:05:22

Great! Did you get the re-fram handler navigation to work as well? That should be independent on the REPL, even working when the REPL is not started, since it is a static service provided by clojure-lsp.

pooriaTaj10:05:07

yes the reframe handling works now too

pooriaTaj10:05:18

as i said it was an extentsion overlap

pez10:05:04

It's great that you got rid of the overlap. Probably a lot of users that fall into that trap... However, I'm thinking that the re-frame navigation shouldn't be affected. I could be wrong, and what matters is that it is working for you now! 😃

acim119:05:03

(instant/read-instant-date "2022-03-22T23:41:37.984-05:00")
=> #inst"2022-03-23T04:41:37.984-00:00"
(instant/read-instant-date "2022-03-22T23:41:37.984-0500")
Execution error at log-reader.schema/eval6320 (form-init5628881862092164982.clj:1).
Unrecognized date/time syntax: 2022-03-22T23:41:37.984-0500
I was surprised to see the latter case isn't handled, or offset without : Is there a convenient way to get around this or lightweight library that is more permissive? I could delve into SimpleDateFormat shennanigans, but seems a shame when the out of the box solution is so close

ghadi19:05:04

@mkeller02 what is the target object you are trying to get?

ghadi19:05:41

read-instant-date returns a java.util.Date read-instant-timestamp returns a java.sql.Timestamp

acim119:05:35

Oh, my fault. I'll correct the latter. But it's the same result

(instant/read-instant-date "2022-03-22T23:41:37.984-0500")
Execution error at log-reader.schema/eval6324 (form-init5628881862092164982.clj:1).
Unrecognized date/time syntax: 2022-03-22T23:41:37.984-0500

hiredman20:05:13

I don't know what library you are using, but java ships with date parsers for java.util.Date and java.time.Instant and both of those parsers are configurable (you give it a format string that describes the parts of the string to parse into a date)

NickName22:05:04

Is there a way to apply a macro to multiple expressions? For example, I have 3 expressions and want dosync for each of them, i.e, a separate transaction for each expression.

Bob B23:05:16

a way to do it would be with an anonymous function

Alex Miller (Clojure team)23:05:11

when in doubt, add more macros

Alex Miller (Clojure team)23:05:52

(defmacro nsync [& exprs]
  (cons 'do
    (map (fn [expr] `(dosync ~expr)) exprs)))

(macroexpand '(nsync (a) (b) (c)))

(do (clojure.core/dosync (a)) (clojure.core/dosync (b)) (clojure.core/dosync (c)))

😄 1
NickName00:05:07

This macro works, thanks! I haven't studied macros yet so the code seems a little bit obscure but nevertheless it enforces the feeling for me that with Clojure you can do wonderful things:) P.S. I tried to implement the same thing with anonymous function but I was doing it in a rather naive way: (map #(dosync %) [expr1 expr2 expr3]) which obviously didn't work because of No transaction running.

Alex Miller (Clojure team)00:05:51

macros are just functions that take code and return code. this macro takes (nsync (a) (b) (c)) and returns (do (dosync (a)) (dosync (b)) (dosync (c)))

Alex Miller (Clojure team)00:05:39

the problem with yours is that expr1/2/3 will be evaluated before they reach the function whereas the macro receives the arguments unevaluated

Alex Miller (Clojure team)00:05:12

macros can also be thought of as compiler extensions written by the user

NickName00:05:57

> macros can also be thought of as compiler extensions written by the user That's a nice way to put it! Thanks for explanation!