Fork me on GitHub
#beginners
<
2017-11-22
>
bigdaddys1oth09:11:48

Real quick for anyone who's up, is [this](https://pastebin.com/TV3Ebabk) a correct database-esque map?

Empperi14:11:45

It all depends on what you are trying to do. However, within your paste you are using defn within map declaration. This isn’t doing what you think it is doing I think. It is now creating three named functions into current namespace: those will be visible directly on the namespace. If you want to have those functions within the map and still have them as named functions you have two options: 1) use (fn deposit-calc [& x]...) which will create a named function which isn’t tied to any namespace. Name in this context is mostly useful for stacktraces. 2) do following: ` (defn deposit-calc [& x] ....) ... (def account-map {... :dep-amnt deposit-calc ... }) ´``

Empperi14:11:06

But anyway, if you want to model data within clojure datastructures in such a way that it would be your “database” then no, this is not a proper way to model such a thing.

Empperi14:11:40

You shouldn’t mix functionality and data, you should keep them separate

Empperi14:11:23

Also, these days I would suggest you to dig into Clojure Spec to define the spec definitions for your data (more or less can be described as your “database schema”)

fingertoe16:11:46

I have a incoming JSON post request and if I do a (js->clj ( :body req)) I get [object Object] --- I figure I am missing something simple?

matan17:11:43

boy is it annoying trying to accomplish an indexed kind of do-seq without shooting your own foot

matan17:11:04

and what did I ask for? merely a loop with a counter 🙂

matan17:11:19

that performs all of its side-effects (hence doseq)

matan17:11:32

Any mutable way out, for a loop counter?

matan17:11:44

As in concurrency-safe mutable without the weight

matan17:11:05

I guess not

madstap17:11:02

I think I need a slightly more detailed use-case to understand what you're after @matan

chris17:11:42

or just like loop...`recur`

matan17:11:53

use case: iterate rows writing them to an output file, along with their row number

matan17:11:50

yeah I see the point of the recur way

matan17:11:59

still scratching my head regarding an elegant use of reduce

markmarkmark17:11:28

you can use doseq, and just wrap your sequence in (map-indexed vector coll)

madstap17:11:32

(defn indexed [coll]
  (map-indexed vector coll))

(doseq [[idx row] (indexed rows)]
  (write-to-file idx row))

markmarkmark17:11:42

yeah, like that

madstap17:11:02

I'd change ((merge {product []} @products-ticks) product) to (get @products-ticks product [])

TobiasR17:11:02

@madstap Ah yes, that is a leftover from when I tried to implement something like pythons defaultdict. That doesn't make any sense here anymore. Thanks for spotting?

matan17:11:28

looping with an index sure does bring python to mind @tobias994

matan17:11:04

a simple dumb language that lets you shoot your own foot, but lets you have readable loops like you were 5 years old lol 🙂

TobiasR17:11:24

@matan It might be a dumb language but at least I didn't feel as dumb as I feel know when trying to get Clojure. But what do you mean with "looping with an index".

TobiasR17:11:45

@madstab Is the use of let ok? Would there be a readable version without? What about the fomating/intending?

matan17:11:05

@tobias994 yes clojure requires a mind flip if you've done non-functional programming for a long while, it is not because anyone is stupid, rather because rewiring what you already know to do into a different form is oftentimes one of the more difficult things

matan17:11:53

@sundarj doesn't this actually fully realize the collection coll?

madstap17:11:20

@matan no, map-indexed is lazy

matan17:11:05

ah, right, now it all falls into place and it's a great functional composition now!

madstap17:11:35

@tobias994 Yeah, I'd keep the let. The code's pretty alright, I think, without really understanding what it does. I'd change the underscores to hyphens and write some docstrings though.

madstap17:11:08

An alternate implementation to consider could be something like:

(defn store-tick [product time best_ask best_bid]
  (let [f #(push-cyclic % {:time     time
                           :best_ask best_ask
                           :best_bid best_bid} 1000)]
    (swap! products-ticks update product (fnil f []))))

tdantas18:11:43

I’m felling dirty .. finally I started my new startup project with clojure I’ve read a lot of books and did a lot of questions here ( I thought I was ready …. I’m not 🙂 )

tdantas18:11:25

How would you guys change that simple code feature: signup user , and after signup send sms to mobile user

(defn send-activation-sms [phone-number text]
  ;; it will be a sms component ( twilio / amazon sms )
  (println phone-number))


(defn activation-codes [n]
  (clojure.string/join
    (take n
          (repeatedly (partial rand-int 10)))))

(defn user-does-not-exists [db phone-number]
  (not (boolean (users/find-by-phone-number db {:phone_number phone-number}))))

(defn create-user [db phone-number]
  (let [api-key (.toString (UUID/randomUUID))
        activation-code (activation-codes 6)
        activation-code-expiration (t/now)]

     (users/create db {:phone_number phone-number
                      :activation_code activation-code
                      :activation_code_expiration activation-code-expiration
                      :api_key api-key})))


(defn signup [{:keys [components params] :as request}]
  (let [phone-number (:phone_number params)
        db (:db components)]
    (if (user-does-not-exists db phone-number)
      (let [user (create-user db phone-number)
            _ (send-activation-sms phone-number "sms")]
        (r/response  {:api_key (:api_key user)} ))
      (r/response {:error "User already exists"}))))

lum18:11:45

Hi, given these:

lum18:11:39

`(def octavia {:name "Octavia E. Butler" :birth-year 1947 :death-year 2006})`

lum18:11:58

(def wild-seed {:title "Wild Seed", :authors [octavia]})

lum19:11:20

(defn has-author? [book author]
  (if (contains? (:authors book) author)
    true
    false))

tdantas19:11:03

contains? returns a boolean . I think you could remove the if

lum19:11:08

Trying to define books-by-author

lum19:11:14

(defn books-by-author [author books] (filter (fn [book] (has-author? [book author] author)) books ))

lum19:11:22

but it's not working

lum19:11:21

I'm having dificulties because has-author? has two parameters and don't know how to build the helper function for filter

dpsutton19:11:20

what's wront with that one?

dpsutton19:11:42

oh, the vector for sure doesn't go there

dpsutton19:11:06

(filter (fn [book] (has-author? book author)) books)

lum19:11:26

(books-by-author octavia books) returns () instead of a book

dpsutton19:11:17

i think you have the params backwards

dpsutton19:11:24

your signature is book author, not author book

dpsutton19:11:04

well your predicate is separate. can you test that (has-author? wild-seed octavia) returns what you expect?

lum19:11:31

returns true

dpsutton19:11:13

can you paste your books-by-author function? It looks like the call is malformed in your previous code

TobiasR19:11:17

@madstapThanks a lot. That looks much better. Using let to move an anonymous function to the top makes it more readable. I didn't know about fnil yet and you forced me to understand !swap a bit better.👍

dpsutton19:11:29

(fn [book] (has-author? [book author] author) is not doing the right thing

lum19:11:47

@oliv Checked contains? and you're right, already removed the if

dpsutton19:11:50

should be (has-author book author)

lum19:11:55

yes, but how do I build the filterand the helper regarding the order of parameters?

dpsutton19:11:23

(filter (fn [book] (has-author book author)) books)

dpsutton19:11:46

author is bound from the function args

lum19:11:55

@dpsutton Thank you very much. It's the first time I had this situation. The brain is not yet completely formatted to Clojure 😉

noisesmith21:11:40

@matan regarding indexing, why not just (let [v (vec col)] (dotimes [i (count v)] (do something with (get v i) ...)))

tdantas21:11:46

@noisesmith sorry to ask you directly … https://clojurians.slack.com/archives/C053AK3F9/p1511375305000122 how would you change that feature ?

noisesmith21:11:20

@oliv - some small trivial things to start with - (not (boolean x)) is (not x), (clojure.string/join coll) can be replaced with (apply str coll), in the body of signup, it might make more sense to move the nested let into the let above, - I find 1 let and three ifs nicer than two lets and an if in between

tdantas21:11:07

overall looks good then

tdantas21:11:13

thanks for the feedback

noisesmith21:11:32

oh, and .toString can be replaced with str - almost always

noisesmith21:11:57

yeah, looks decent over all

tdantas21:11:08

thanks mate !

jaysherby21:11:20

I thought once upon a time I saw someone make an uberjar with leiningen and make it so that the resultant jar file was saved to a different path. Is that a thing or did I just imagine it? How do you do that?

jaysherby21:11:52

I tried altering :target-path but that just made it so all the build artifacts moved there.

athomasoriginal23:11:05

I have a piece of code like this:

(defn do 
   [] 
   (when condition-met
      do-stuff))
The above works and does what I expect. The issue is when condition-met is false. The above function do is going to return nil. I would like it to always return an empty list instead. I could resolve this with if, but I wonder if there is a better way?

phronmophobic23:11:29

I can’t imagine a more straightforward way to do this than using if

phronmophobic23:11:47

possibly using cond

phronmophobic23:11:33

(cond
  condition-met
  (do-stuff)
  :else
  ())

phronmophobic23:11:43

but i would still use an if

athomasoriginal23:11:24

I think what is holding me back is that do-stuff looks like this:

(let [sorted-events (sort-by :start-time events)]
      (remove nil?
        (for [[x :as xs] (take (count sorted-events) (iterate next sorted-events))
               y xs
               :when (not= x y)]
          (find-conflict x y))))

noisesmith23:11:37

(or (and condition-met (do-stuff)) ()) would work

athomasoriginal23:11:37

which makes the false difficult to see

noisesmith23:11:51

never mind, clearly (if condition-met (do-stuff) ())

phronmophobic23:11:48

not making the else branch of an if apparent is something I’ve noticed

phronmophobic23:11:01

but i’m not sure how to improve it

athomasoriginal23:11:28

especially if the else is something like ()

noisesmith23:11:31

I always put the true / false cases of the if on separate lines

noisesmith23:11:41

no matter how small they are

phronmophobic23:11:07

sometimes, if the else case is really small, I use if-not so that the shorter branch is on top

phronmophobic23:11:14

but that doesn’t always improve readability

johnj23:11:56

an if with no else sounds like bad design

jaysherby23:11:05

I don't necessarily agree. In my experience, an if with no else clause isn't uncommon as long as you know it returns nil on falsy.

jaysherby23:11:26

Although, to be fair, I've never seen when used before.

jaysherby23:11:23

A little googling says when is idiomatic for when there's no else clause, though.

phronmophobic23:11:36

I usually use when instead of if if there’s no else clause

jaysherby23:11:51

Well, you learn something new every day. From now on, I'll be using when rather than if when it's idiomatic.

jaysherby23:11:54

Funny story, though. If you look at the source for the when macro, it actually expands to just use if. 😄

athomasoriginal23:11:09

True. Thanks all, going to go with the if.