Fork me on GitHub
#beginners
<
2019-02-22
>
Tessy Thomas11:02:50

I have an array of art pieces. I want to find the route length and associate it with each art pieces. My code will look like: (defn load-art-routes [art-list ctx] (doall (map-indexed (fn [index art] (let [user-location (select-keys (:coords (sub> ctx :geolocation)) [:latitude :longitude]) art-location (:geoLocation art)] (->> (map-request {:origin (str (:latitude user-location) "," (:longitude user-location)) :destination (str (:lat art-location) "," (:lon art-location)) :mode (name (sub> ctx :transition-mode))}) (p/map (fn [data] (let [route-length (ocall js/Math "round" (/ (get-in data [:routes 0 :legs 0 :distance :value]) (* 0.621371192 1000)) 2) route-duration (ocall js/Math "floor" (/ (get-in data [:routes 0 :legs 0 :duration :value]) 60))] (js/console.log "load-art-routes route-length " route-length") (assoc art :route-length route-length)))) (p/error (fn [error] (util/log (str "GOOGLE DIRECTIONS API ERRORS" params) error) ))))) art-list)) art-list) (defn map-request [params] (when params (let [endpoint google-directions-api-endpoint] (->> (make-get-req (str endpoint "&" (encode-query-params params)) {}) (p/map (fn [data] (util/log "GOOGLE DIRECTIONS API " data) data)) (p/error (fn [error] (util/log (str "GOOGLE DIRECTIONS API ERRORS" params ) error) )))))) The route length calculation is correct but, assoc is not working. It is not actually associating it. I don't know what the issue is. Can anyone help me?

superancetre13:02:08

you have a " too many in line (js/console.log "load-art-routes route-length " route-length"), is that your problem? or a copypaste problem?

Tessy Thomas14:02:15

that is a copy pase problem. that is not real problem.

skykanin14:02:32

I'm trying a write a spec for this map to check its types, but I'm not exactly sure what the best way to spec a nested map is.

alexmiller14:02:21

by writing another map spec

skykanin14:02:57

well, I did that, but I was confusing qualified and unqualified keys so spec/valid? was returning false

Mario C.16:02:50

Any issues I should be aware of with saving to multiple databases using pmap? Say we have a map that looks like (def engines {:mongodb <mongodb connection> :postgres <postgres-db connection> :mariadb <mariadb connection>}) and I do something to the effect of (pmap <function that uses the connection to save to db> engines)

butterguns16:02:28

I'm unsure why that would be a problem, if you're using completely separate DB connections

butterguns16:02:13

If you were sharing a single DB connection to a single database, that might be a problem if your driver isn't threadsafe

butterguns16:02:43

Make sure you're prepared to handle any exceptions thrown by the save-function

Mario C.16:02:17

What I am unsure is the exception handling. Since pmap uses futures under the hood and Ive come across situations where I wont see the exceptions until I try to deref the future. If an exception occurs in one save function will the process continue to other save functions?

Mario C.16:02:42

How does semi lazy work? Will it save my data as its mapping or not until I try to consume the results?

butterguns16:02:11

It's a good question. I don't know the answer. But it might be worth writing code that behaves in exactly the way you want (and makes it explicit to readers of your code), rather than using pmap.

butterguns16:02:46

I imagine making use of pmap when the function is not side-effecting

Mario C.16:02:21

Thanks for the link.. I am going to have to some REPL testing then

alexmiller16:02:02

I think you have already asked enough specific questions that you will want something more than pmap

alexmiller16:02:51

it's a good quick and dirty answer for coarse-grained parallel tasks, but lacks all control over how that happens

alexmiller16:02:34

Java's built-in executors (queue + thread pool) gives you many more options

alexmiller16:02:50

claypoole is a decent clojure lib that gives you a nicer entry to that and other stuff

Mario C.17:02:13

Oh this looks interesting actually

Daniel Hines19:02:32

Why does comp work from right to left?

superancetre19:02:59

I think because it maps what you would write without comp, but cleaner

superancetre19:02:05

(count (vec '(1 2 3)))

superancetre19:02:26

is rewritten ((comp count vec) '(1 2 3)) if I'm not mistaken

Mitch19:02:43

It also mirrors how function composition is written in standard mathematical notation

Mitch19:02:04

(g ∘ f )(x) = g(f(x))

parens 5
Mitch19:02:58

but yeah that sometimes trips me up, too

noisesmith19:02:21

right - it keeps the order of the functions, and moves / eliminates parens

chocksmith19:02:23

In the system I've been working on, I have a complex business logic that must run both on server and client side. (due to performance non-functional requirements) I am writing this business logic in Clojure and it is nicely interacting with the rest of the server side controllers and services in Groovy (Grails). I have no experience on Clojurescript. My question is: Will I be able to use the same business logic functions, the same code itself, I wrote in Clojure, as Clojurescript in the client side? And make it interact with the rest of the client side interface in TypeScript/Angular? Is there any gotcha? That would be a major achievement on the project because we will avoid writing 2 codes, in 2 languages for the same (very) complex business logic. It will save us endless hours in both coding and testing. My understanding is that it is true if we keep the core of my business in "pure" Clojure, I mean, away from fancy dependencies that might exist only in Java world or Javascript world. Is that right?

noisesmith19:02:43

the typical way to do this is use a cljc file, which allows conditional java side vs. js side code

noisesmith19:02:10

IMHO using the actual java deps or js deps directly instead of a clojure wrapper is usually the right choice

noisesmith19:02:37

and your java side or js side functions will be callable easily by java or js, yes

👍 5
superancetre19:02:42

If I remeber correctly, there are certain features you can't use on cljs, but once you know them, you can try to avoid them to have valid clj/cljs code

noisesmith19:02:09

there are also features you can use in cljs but not clj - cljc makes this work

superancetre19:02:36

Look at the difference page

chocksmith19:02:03

Perfect! Thank you guys!

chocksmith19:02:34

After my first quick read through, I can say that it will work for me. This will be game changer here.

noisesmith19:02:55

also I recommend using the transit lib for communication between client and server - it supports all the most common clojure data types directly, is easy to extend, and avoids a bunch of problems with just using edn directly

noisesmith19:02:55

a common pattern when I had a mixed clj / cljs codebase was a core library file (cljc) that was shared, plus implementation files that were conditionally included with anything vm specific

chocksmith19:02:31

I will take a look on that.

alexmiller19:02:19

and is much faster for clj to cljs

chocksmith19:02:47

It might not be the case. The client side is written in Angular/TypeScript. Only a specific business logic will be written in ClojureScript. A vanilla TypeScript code will call the ClojureScript logic. The communication with server will be handled by TypeScript/Angular.

alexmiller19:02:10

there is a transit-js library

alexmiller19:02:36

the reason it's faster is that transit is actually done over the top of json and leverages the super fast json parsers in browsers

alexmiller19:02:27

and because it also supports caching of repeated map keys and things like that, it can actually be faster than json (even though it's done over json)

alexmiller19:02:50

which is admittedly counter-intuitive, but easy to show via measurements, which have been done

chocksmith19:02:30

I will definitely take a good look on that. Thank you! Very helpful! You guys are awesome.

alexmiller19:02:37

no, you're awesome

noisesmith19:02:21

that's the one for jvm clojure, there's another one for javascript (doesn't even need cljs) https://github.com/cognitect/transit-js