Fork me on GitHub
#beginners
<
2016-12-26
>
drewverlee00:12:35

does anyone have any good resources for how to think about architecting domain models? Something in a similar vein as this talk? https://www.youtube.com/watch?v=jJIUoaIvD20&amp;list=PLZdCLR02grLofiMKo0bCeLHZC0_2rpqsz&amp;index=14

clojuregeek01:12:49

@drewverlee: have you read Clojure Applied ?

drewverlee01:12:31

@clojuregeek no i haven’t! i own it, but im working through joy of clojure at the moment.

mingp15:12:20

@tosh If you ever wanted to apply and, this StackOverflow post http://stackoverflow.com/a/9218185 has an alternative.

tosh15:12:26

@mingp thank you for the pointer, i’m using that pattern now 🙂

mingp15:12:01

@tosh You're welcome. Good luck.

kevinbheda17:12:33

is there more detailed example for using ring mock ? I looking to ring mock with bidi. The example on the repo link is too small. https://github.com/ring-clojure/ring-mock

neurogoo18:12:35

I am trying to display list with clojurescript and reagent. List items should expand when clicked, but I can't seem to get reagent rerender components. Can anyone offer some example code that is doing something like that?

seancorfield18:12:05

@roelof You asked whether you can use clojure.spec to check if the user supplied an incorrect parameter, such as — the answer is “yes” but there’s two different errors here: misspelling page as pag and providing a instead of an integer. Since you default page to ”1” and that would not be seen any different to just omitting page.

seancorfield18:12:58

So you’d need to have the spec for your API — where the :params are a map — check that no unexpected keys were provided.

seancorfield18:12:32

Right now you’re only spec’ing page-check — you’d need to spec the handler itself, where req is available, in order to check that no other keys are present in :params.

seancorfield18:12:03

I also noticed your fdef doesn’t have the correct syntax for any of the three keys… :args should always be a spec for a sequence of named values, e.g., (s/cat :page ::page). :ret should be a spec for whatever the return type is for the function, and :fn should be a spec for the overall function, if present, so it will be a spec for a hash map that has keys :args and :ret, which allows you to specify a relationship between the arguments and the return value.

seancorfield18:12:00

@neurogoo Perhaps you can share a Gist or Pastebin link to your code so we can take a look?

neurogoo18:12:03

I just solved the problem ^^' Needed to use with-let instead of let.

roelof18:12:23

@seancorfield oke, but no other params are needed. This will be a test for pagination. So only the page parameter is needed. The rest can be ignored.

roelof18:12:15

oke, the input is always the url-parameter page

roelof18:12:36

the output is normally a long

roelof18:12:51

and what I have tried with the fn is to test if the input is valid or not

roelof18:12:51

so to look if the input is "2" , the output is 2 where if the input is something like "a" the output is invalid

roelof18:12:11

so I thought I need to look that up in the fn

roelof18:12:04

so I misunderstood what fn schould do ? @seancorfield

roelof18:12:46

Regarding the req that is handled in the home-function so here :

(defn home-page [page]

  (let [page-num (page-check page)

        url ""

        options {:as :json :query-params {:key (env :key) :format "json" :type "schilderij" :toppieces "True" :p page :ps 10}}]

    (layout/render

      "home.html" {:paintings (-> (client/get url options)

                                  api/read-numbers

                                  api/fetch-paintings-and-images-front-page)})))  

roelof18:12:03

or here :

(defroutes home-routes

           (GET "/" [page] (home-page page))

           (resources "/")



           (GET "/detail/:id" [id] (detail-page id))

           (resources "/detail/:id")) 

seancorfield18:12:56

Right, because you’re pulling just a specific parameter out of the request and passing that alone to your handler function, you won’t be able to check that the request parameters contain only :page. You’d have to write your handler a different way.

seancorfield18:12:22

So it’s up to you whether that’s important enough to change...

seancorfield18:12:35

What do you want page-check to do if it is passed an invalid page number?

seancorfield18:12:54

My feeling is that you either want to spec home-page itself or you want home-page to use clojure.spec internally to validate / coerce the page argument — you don’t really want to spec page-check.

seancorfield18:12:33

(and which path you choose depends on what you’re really trying to do)

neurogoo19:12:10

If I want to distribute my clojure application, what is the most common way to have config file that user can modify and the application can easily find?

seancorfield19:12:40

@neurogoo I don’t think there’s really any single common way. If you’re distributing your app as a self-contained JAR file, I’d probably support using either a command line argument or an environment variable to locate the configuration file.

seancorfield19:12:08

With, perhaps, a default location that it would look if no such argument / variable was provided.

roelof19:12:53

What I want is to check if home-page gets a valid pagenumber so I want really check the arguments

roelof19:12:40

I have to rewrite homepage so when non-valid pagenumber is entered then the homepage is seen

roelof19:12:59

on a valid pagenumber the page itself must be seen

roelof19:12:14

@seancorfield it is clear what I mean ?

seancorfield19:12:49

something like (let [page-num (s/conform ::page page) …] … (if (s/invalid? page-num) 1 page-num) …)

seancorfield19:12:12

(so you don’t need page-check at all, nor an fdef spec for it)

roelof19:12:57

oke, some one else I need it so I can if can test if the pagenumber is valid or not

roelof19:12:45

oke, next I need to figure out then what schould be at the .....

roelof19:12:39

the let could be into the homepage-function ?

roelof19:12:19

@seancorfield I think you mean something like this :

(defn home-page [page]
  (let [page-num (s/conform ::page page)
        url ""
        options {:as :json :query-params {:key (env :key) :format "json" :type "schilderij" :toppieces "True" :p page-num :ps 10}}]
    (layout/render
      "home.html" {:paintings (-> (if (s/invalid? page-num) 1 page-num) 
                                  (client/get url options)
                                  api/read-numbers
                                  api/fetch-paintings-and-images-front-page)})))
 

roelof19:12:48

Do I test this way if no non-valid page url parameters can be used ?

roelof19:12:20

I think this handler cannot be tested more because the output is always html which is different for each page

roelof19:12:51

nope, pagenumber is a string here . With this code I see this error message :

java.lang.String cannot be cast to clojure.lang.IPersistentCollection  

roelof19:12:50

the if then is not doing what I expect

drewverlee20:12:34

i’m reading Clojure Applied and i have a question about this advice on when to use maps: > One specific case for which you should strongly consider maps is in public-facing APIs, whether they’re expected to be consumed by Java or by Clojure. In an API, it’s important to minimize the constraints on our callers. Requiring them to create instances of our record classes causes some of the details of those classes to be effectively public as well. In this case, maps with a well-known set of keys commit to less and are a simpler and better choice. How could an API require a caller to initialize a class? Is the author suggesting that a API could give the caller data which had to be initialized to a class in order to be usable? I have never seen this done.

donaldball20:12:17

API methods that require instances of specific classes as arguments are very common in java

roelof20:12:27

@seancorfield oke, this seems to be working fine :

(defn home-page [page]
  (let [page-num (s/conform ::page page)
        url ""
        options {:as :json :query-params {:key (env :key) :format "json" :type "schilderij" :toppieces "True" :p page-num :ps 10}}]
    (if (s/invalid? page-num) 1 page-num)
    (layout/render
      "home.html" {:paintings (-> (client/get url options)
                                  api/read-numbers
                                  api/fetch-paintings-and-images-front-page)})))  

roelof20:12:52

Do I now need to use instrument to test if the parameters part is working fine

roelof20:12:03

and how do I do this exactly Something like this (s/instrument 1 ) and (s/instrument "a") and how does spec knows to which function this must be applied

roelof20:12:24

I find the spec guide a little confusing at this part

drewverlee20:12:12

@donaldball ah, ok. I understand. No pressure on the next couple questions below. I’m just thinking out load... What details of the class if made public would cause a problem? Why is this a problem at the API layer and not else where?

drewverlee20:12:08

I suppose because the caller might not need that domain model

drewverlee20:12:36

I suppose i might want to read on … > Don’t fret about making the wrong choice between maps and records!

seancorfield21:12:25

@roelof Think about where you are using page-num in your code! Where would that if need to go? Don’t just randomly add it into various places...

seancorfield21:12:07

@roelof Re: instrument — that is used to turn on instrumentation for a symbol (a function) so that the :args part of an fdef is checked. But you are not using fdef any more so it’s not relevant to you.

seancorfield21:12:01

@roelof Your if expression is just thrown away (`let` evaluates all the expressions in the body but only uses the value of the last expression).

roelof21:12:26

@seancorfield I used it in the let in the options variable

roelof21:12:07

So I think I need to use it there

roelof21:12:12

so this line will be

options {:as :json :query-params {:key (env :key) :format "json" :type "schilderij" :toppieces "True" :p    (if (s/invalid? page-num) 1 page-num)   :ps 10}}]  

roelof21:12:26

So I cannot test home-page if the right parameters are used .

yogidevbear21:12:56

Does anyone know if Carin Meier (author of Living Clojure) is part of this slack group?

seancorfield22:12:12

@roelof That looks better — now an invalid page argument in the URL should be replaced by 1 in the options and a valid page argument will be used “as-is”.

seancorfield22:12:01

@yogidevbear She is signed up but currently shows as inactive due to not logging in recently.

mikepjb23:12:11

(->> (complete-puzzle-position 1 5 6 puzzle)
     (complete-puzzle-position 2 4 6)
     (complete-puzzle-position 4 3 6))
Does anyone know how something similar to this code block could be run as a function? e.g (complete-puzzle-series [[1 5] [2 4] [4 3]])

mikepjb23:12:40

the trouble being that the function complete-puzzle-position returns an updated version of the puzzle board and I want to pass this to the next function in the sequence

seancorfield23:12:38

(fn [puzzle]
  (->> (complete-puzzle-position 1 5 6 puzzle)
       (complete-puzzle-position 2 4 6)
       (complete-puzzle-position 4 3 6)))
Like that?

seancorfield23:12:05

(not quite sure what you’re asking)

seancorfield23:12:57

Or are you asking how to break apart a series of pairs and use them in calls?

mikepjb23:12:29

(let [posseq [[1 5] [1 4] [1 3]]]
  (->> (complete-puzzle-position (first (first posseq))
                                 (second (first posseq))6 puzzle)
       (for [pos (rest posseq)]
         (complete-puzzle-position (first pos) (second pos) 6))))

mikepjb23:12:06

I'm trying to take a list of x y coordinates and apply each of these coordinates from a list and apply them to a function

mikepjb23:12:24

the result of each function should be passed to the next function too

mikepjb23:12:02

the code I've included just now is what I want to do but it feels like there is a more idomatic way of using clojure for this solution

seancorfield23:12:01

Where does the 6 come from? Are you looking for a general case of N pairs of x, y coords?

seancorfield23:12:19

Since you want to apply complete-puzzle-position repeatedly to an initial puzzle, it feels like reduce is what you’re looking for here...

seancorfield23:12:18

(reduce (fn [puzzle [x y]] (complete-puzzle-position x y 6 puzzle)) initial-puzzle [[1 5] [1 4] [1 3]])

seancorfield23:12:04

(I don’t know what the initial-puzzle should be nor how 6 should be calculated but that expression should match what you were trying above)

mikepjb23:12:42

thanks, I play around with this idea

mikepjb23:12:54

it's a sudoku solver, 6 is arbitrary

mikepjb23:12:38

6 is just the current number the function is trying to fill the sudoku puzzle in with for the given coordinate position

mikepjb23:12:00

thanks @seancorfield that works exactly as required 🙂

seancorfield23:12:43

Glad to help — many things that look like loops in other languages are reduce in Clojure 🙂

mikepjb23:12:47

will bare this is mine, I had missed that reduce can take more than one argument!