Fork me on GitHub
#beginners
<
2018-01-31
>
jakob08:01:43

Hi! Any ideas how I can improve this code? My gut feeling is that there is a more elegant way 🙂

(update data :product-users
        (fn [a] (map (fn [b] (update b :new-phone-number boolean-to-norwegian)) a)))

jakob08:01:48

one improvement but still not perfect:

(update data :product-users
        #(map (fn [b] (update b :new-phone-number boolean-to-norwegian)) %))

joelsanchez08:01:30

(letfn [(update-user [user]
         (update user :new-phone-number boolean-to-norwegian))]
  (-> data
      (update :product-users (partial map update-user))))

jakob09:01:33

interesting. didnt know letfn existed. and I am going to read what partial does 😄 thanks for the input!

joelsanchez09:01:53

(partial map update-user) is equivalent to #(map update-user %)

madstap14:01:38

I'd use mapv instead of map to keep the vector instead of making it a seq

joelsanchez09:01:08

although, to be honest, I'd def update-user

schmee09:01:39

@karl.jakob.lind what does the data structure look like?

jakob09:01:14

(def data {:product-users [{:new-phone-number false}]})

rauh09:01:15

@karl.jakob.lind Are you up for specter? It should be super easy with it

jakob09:01:32

I have never heard of specter 🙂

jakob09:01:12

:thumbsup: will look into it, but dont think i will include another dependency just for this.

rauh09:01:27

(transform [:product-users ALL :new-phone-number] boolean-to-noregian data)

jakob09:01:34

that was short, but think it will be too confusing learning clojure and that library simultaneously 🙂

timo09:01:05

hi there, how would you handle a POST- or PUT-request with a named parameter in compojure like this? (PUT "/api/article/:slug" [slug request] (update-article! slug request)))

timo09:01:22

ok...easy: (PUT "/api/article/:slug" {:keys [route-params params]} (update-article! article-params params))

Caio Guedes12:01:29

Guys, what this means langohr.core/*default-config*, those *?

hawari12:01:01

It's not a special characters per se, just a convention that usually used to indicate a dynamic vars. You can read more about it here https://clojure.org/guides/weird_characters#__code_var_name_code_earmuffs

hawari12:01:45

Hello everyone, I want to ask what is the safe yet idiomatic way to cast a string into boolean? I have query param in a ring application which is supposed to be a boolean flag. Since all query params' value is a string, I need to properly cast "false" into false.

sundarj12:01:01

@hawari.rahman17 i would just use a cond

sundarj12:01:47

@hawari.rahman17 (Boolean/parseBoolean "false") also does the trick

hawari14:01:33

By cond do you mean something like (cond (= "false" flag) false)?

hawari14:01:32

Alright, thanks @U61HA86AG!

joshkh12:01:11

has anyone had luck using any of the lein-sass plugins? i have a /sass/site.scss file and a /some/dir/bootstrap.scss file. site.scss has an import statement: @import "../some/dir/bootstrap" which produces the following sass error: file to import not found or unreadable: ../some/dir/bootstrap. manually compiling the scss works just fine though. any thoughts?

joshkh12:01:27

i've tried every combination of relative and absolute paths

manutter5112:01:41

I was having the same issue recently, switched to lein sassc instead https://github.com/apribase/lein-sassc

joshkh13:01:26

as someone switching from less, is there a way to install sassc without having to build it from source (linux / osx)?

joshkh13:01:22

ah okay, it works! thanks @manutter51

cperrone13:01:36

Hi all, I’m wrecking my head on this and I’m hoping you can offer me some pointers. At its simplest level, let’s say I have a ‘dumb’ container component, e.g.: `(defn my-component [content] [:div content])` … and a (possibly arbitrarily nested) tree structure, e.g.

(def tree [["a" ["b" "c" "d"]] "e"])
What approach would you use to walk the tree, plug-in the component and its content to return something like this?
(def result [:div
             [:div "a"
              [:div "b"]
              [:div "c"]
              [:div "d"]]
             [:div "e"]])
(My naive implementation has the component recursively calling itself on the children, which I really don’t want.) Do I need a zipper for this, or is there some other way to accomplish it? Thanks so much in advance!

joshkh14:01:58

@cperrone a zipper could work but might be overkill. maybe check out postwalk? you could use it to build up the component markup in one go https://clojuredocs.org/clojure.walk/postwalk

cperrone14:01:42

Mmm I had a look at postwalk but the examples I saw weren’t of much help as I needed to modify the structure a bit and postwalk seemed only ok for basic node replacement. (In fact I was using vectors and maps originally, so I knew I was going to change the structure). I’ll have a look again.

joshkh14:01:12

it was just an impulsive suggestion and i'm not entirely sure it will solve your problem. 😉

schmee14:01:12

@cperrone I would ask this question in #specter

cperrone14:01:06

I will… specter looks impressive 🙂

joshkh14:01:16

the last time i used specter in a cljs project it blew up the project size by a couple hundred kb, but that was 6+ months ago. any idea if that has improved?

schmee14:01:02

dunno, I’ve used it in clj only

schmee14:01:44

if it’s still a problem you should open an issue for it, I’m sure nathan would be interested in taking a look at that

joshkh14:01:30

yes, he even asked me to send some extra information but i never found the time. oopsies.

tbaldridge14:01:01

@cperrone yeah, that's pretty simple with clojure.walk/postwalk

tbaldridge14:01:21

something like this (I think, it's untested):

(walk/postwalk
   (fn [itm]
      (if (sequential? itm)
         (into [:div] itm)
         [:div itm]))
   data)

cperrone15:01:37

thanks @tbaldridge! It’s “almost” there:

[:div [:div
       [:div "a"]
       [:div
        [:div "b"]
        [:div "c"]
        [:div "d"]]]
 [:div "e"]]
but at least I can play with it a little more. a wraps b c d, e is at the same level of a

gganley15:01:07

Hello, I have pretty good experience with clojure but little to none with clojurescript. I’m using the guide from cemerick/piggieback to test stuff out but for some reason everyone is referencing the js namespace but for some reason my configuration doesnt load it? My first thought is that it requires the repl to be connected to a broswer but that doesn’t make sense either. Any help is appreciated.

delaguardo15:01:40

js is not a usual clojurescript namespace. It is a bridge between cljs and JavaScript runtime which give you ability to get access to global runtime variables. Like this - (js/console.log "some message") or (js/alert "Some alert message"). In those examples console.log and alert are functions defined in global runtime scope. If you want to use those functions - your repl should be started in the context of clojurescript which means - connected to javascript runtime (node or browser).

gganley15:01:32

Ok, right now I had the thought of switching the repl backend(?) from rhino to node

gganley16:01:03

Does node provide the js runtime?

delaguardo16:01:12

@gganley https://lambdaisland.com/guides/clojure-repls/clojurescript-repls there is good description of difference between rhino, node and browser backends for clojurescript

noisesmith17:01:40

the js runtime is the only way cljs can run - cljs creates js code, and using js/foo is how you directly engage with things in the js engine running your code, outside the cljs abstractions themselves

noisesmith17:01:09

it's like your escape hatch to access the regular vm, and can do anything javascript can

gganley17:01:10

It makes sense that it is the interop layer, but for some reason when I run cider-clojurescript-jack-in I can run commands like (+ 1 1) and the macroexpand is proper cljs a la (js* "(+ {} {})" 1 1) or something but js is not a bound symbol

noisesmith17:01:47

oh, js* is totally different

noisesmith17:01:54

the * is part of the name here

gganley17:01:17

I know that is not what I meant by that

gganley17:01:32

I meant to show that I’m in a clojurescript environment and not a clojure environment

noisesmith17:01:35

right, js does not exist, js/window etc. do

gganley17:01:37

but I still don’t have access to js

noisesmith17:01:48

just as clojure.core does not exist, but clojure.core/+ does, etc.

noisesmith17:01:55

(similar but not the same mechanism)

noisesmith17:01:30

I guess a better way to put that is that namespaces and packages are not first class

gganley17:01:37

something along those lines yes but unlike that example I can’t just (require [cljs.js :as js]) or whatever it would look like

gganley17:01:45

because that doesn’t make sense from my understanding

noisesmith17:01:47

right, that's invalid require syntax

noisesmith17:01:56

(require '[cljs.js :as js])

noisesmith17:01:12

but then that would clash with the built in js/foo syntax, so don't use that specific :as binding

noisesmith17:01:00

perhaps I am missing your actual issue and getting caught up in the wrong semantic questions, sorry

manutter5117:01:58

@gganley what happens when you type (js/console.log "Hello, world") in your ClojureScript REPL?

noisesmith18:01:41

minor nitpick - that syntax works but it's accidental that it does, (.log js/console "Hello, world") is the more canonical form (and there are cases where you can get a much better error message for eg. shadowed js globals if you use that syntax)

noisesmith18:01:00

I know that everybody uses js/console.log though, and I realize that it does work

manutter5118:01:18

definitely worth mentioning, especially in #beginners. Thanks!

gganley19:01:45

Do you want the stack trace or just the printout

gganley19:01:01

The following is just the printout

gganley19:01:03

(js/console.log "hello")
org.mozilla.javascript.EcmaError: ReferenceError: "console" is not defined. (rhino.clj#41)

manutter5119:01:15

That's enough to clarify the problem, I think

gganley19:01:29

I can post my project.clj if you’d like

manutter5119:01:20

I don't think you need to

manutter5119:01:36

Try one more thing for me: (js/print "Hello, world")

gganley19:01:58

(js/print "Hello, world")
org.mozilla.javascript.EcmaError: ReferenceError: "print" is not defined. (rhino.clj#41)

manutter5119:01:38

Hmm, I got that from the docs for rhino shell, but I'm guessing that's a separate product maybe?

gganley19:01:41

that lein-cljsbuild and com.cemerick/url, neither are called

noisesmith19:01:44

are those things rhino defines though?

gganley19:01:55

I’ve tried node as well

gganley19:01:29

node definitly should have (.log js/console "yadda yadda")

gganley19:01:53

but it doesn’t

noisesmith19:01:05

$ rlwrap lumo -d
Lumo 1.2.0
ClojureScript 1.9.482
 Docs: (doc function-name-here)
 Exit: Control+D or :cljs/quit or exit

+cljs.user=> (.log js/console "HELLO")
HELLO
nil

gganley19:01:21

I’ll try running through that again, but I’ve gone through that before

noisesmith19:01:26

@gganley also if you use the new "clj" script, it's straightforward to launch a node repl from that

noisesmith19:01:36

more info in #tools-deps

gganley19:01:40

I would REALLY prefer to have something that uses nREPL

gganley19:01:13

aka something that works with CIDER/Emacs

noisesmith19:01:03

yup - I like to occasionally glance at how much effort a supposed "productivity tool" extracts as a tax, but as long as you are clear about your decision that's cool 😄

noisesmith19:01:02

for myself, I discovered that a simpler editor with a lot less tooling was more productive, compared to something that nerd sniped me with cool features I could try to implement or forced me to spend hours fixing configs or library mismatches

noisesmith19:01:14

but that's a personal choice all the way

gganley19:01:26

Unfortunately in 5 short years my fingers can’t unlearn emacs

gganley19:01:53

But yeah I’ll shift this over to clojurescript since this is quickly getting away from beginner stuff

gganley19:01:57

thank you though

noisesmith19:01:56

you can use monroe.el with emacs - I specifically didn't say emacs was the problem - there's more than one kind of tooling available there

noisesmith19:01:29

(monroe uses nrepl but is much less complex - there's also inferior-clojure which talks directly to any clojure repl)

gganley19:01:49

It’s safe to say though that cider is the de facto way to edit Clojure(Script) code on emacs?

noisesmith19:01:46

right, just saying there are also simpler options

Will22:01:57

I am running this query (def get-card-account-emp-link "SELECT * FROM employee_card_account WHERE card_account_id = ?") with this command (j/query (@db-conn/db-connections (keyword db-name)) [queries/get-card-account-emp-link card-account-id] {:result-set-fn first}) This works, but I get all of the columns in that table which has a lot that I don’t necessarily need. How would I reduce the map I get back from the query to a specific set of columns? One approach would be to only select those columns in the query’s select statement, the other would be to manipulate the map / object after I retrieve it. I can change the select statement, but I’m not sure how to manipulates objects / maps in clojure, which I’m assuming is just as important in clojure as it is in java.

dadair22:01:10

(select-keys <some-map> [<keyword to keep> <other keyword to keep> ..]) should do the trick

dadair22:01:49

(let [m {:a 1 :b 2 :c 3}
  (select-keys m [:a :b])) ;; returns {:a 1 :b 2}

Will22:01:31

Awesome thank you @dadair!

noisesmith22:01:30

it seems a bit odd to SELECT * and throw away fields afterward

noisesmith22:01:40

is it that hard to construct a list of fields you want?

Will22:01:47

It won’t be that hard select the fields I want, I was just using that as an example. As I thought about how I would do it in clojure if changing the sql wasn’t an option, I realized I didn’t understand how to do it that way, which is kind of a big problem