Fork me on GitHub
#beginners
<
2016-12-24
>
Kamuela00:12:04

Is LightTable's inline repl supposed to work by default with no cajoling or setup?

sbauer00:12:36

Typically the inline repl will work given there is a project.clj it can find

Kamuela00:12:48

Hmm. Makes me wonder if I broke something

sbauer00:12:59

Are there any errors?

Kamuela00:12:39

Definite noobie question but, where would I see such errors?

sbauer00:12:10

If the inline repl was connected and it was an evaluation issue, then probably right next to the line. Otherwise there might be a little red number to the bottom right of the window, which will open the console if you click it

sbauer01:12:16

Hmm, silly question but did you trigger the inline evaluation with Ctrl-Enter or whole file evaluation with ctrl-shift-enter?

Kamuela01:12:38

Probably not a silly question, attempting

Kamuela01:12:01

Yes, to some degree fixed, I just think I don't know how to properly trigger what I need

Kamuela01:12:08

But no errors, and yes inline evaluation

sbauer01:12:24

Ah good to hear

sbauer01:12:01

You can always explore possible commands from the command panel, which can be accessed via ctrl-space

Drew Verlee04:12:45

Answer is i can choose the profile with lien with-profile which leads to some slightly wonky commands: lien with-profile test test for instance -_-

Drew Verlee04:12:28

meanwhile, yea for auto reloading tests!

roelof10:12:11

Im confused what this line does [page nil page-num (or (s/conform ::optional-page page) 1)]

roelof10:12:14

I think it means if page is nill then the pagenumber will be 1

sveri10:12:24

like this it constructs a vec of page, nil, page-num and a pagenumber or 1

sveri10:12:39

you could paste it into a REPL and see what comes out

sveri10:12:04

when you do that, there will be errors about undefined vars

roelof10:12:47

@sveri sean have shown some examples :

boot.user=> (let [page nil page-num (or (s/conform ::optional-page page) 1)] page-num)
1  

roelof10:12:03

so when page is nill the pagenumber will be 1

roelof10:12:29

and

boot.user=> (let [page "42" page-num (or (s/conform ::optional-page page) 1)] page-num)
42  

sveri10:12:53

yes, thats one whole let block that returns page

roelof10:12:14

when there is a valid pagenumber , it will be converted to a long of the page variable in a url

roelof10:12:43

that part I understand

roelof10:12:34

I have problems to see how it fits in this code :

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

roelof10:12:47

so I can validate if a given pagenumber is valid

sveri10:12:42

The thing is, if I tell you the answer, you wont learn a thing

sveri10:12:55

So, please, try it yourself, play around with the code

roelof10:12:59

I think it has to replace the pagenum line

sveri10:12:00

and make it fit yourself

sveri10:12:10

Your first solution was wrong, that happens, keep on trying

roelof10:12:30

@sveri it it right that the line (page-num (or (read-string page) 1) has to be deleted because it does the same as the line I want to use ?

sveri10:12:56

and write tests for it

sveri10:12:09

or break it down into smaller functions and test it in the REPL

roelof10:12:15

This is also wrong :

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

roelof10:12:30

and I do not have a clue why and how to solve it

sveri10:12:50

See, you said you wanted to learn something, thats why you redo it in clojure. And again I am telling you, you learn by reading and applying the things you read

sveri10:12:21

make a function that returns your page number

sveri10:12:31

call that function from home-page

sveri10:12:49

you can easily test a function that does one thing

sveri10:12:58

and is independent from the request / response cycle

roelof10:12:43

The pagenumber normally is a url parameter here

roelof10:12:48

I will try to make this work

roelof10:12:25

Thanks for the help

roelof10:12:43

I will take a break and hopefully I see what I have done wrong

sveri10:12:55

Again, move that to a single function

roelof10:12:10

I think it is already in a single function :

(defroutes home-routes
           (GET "/" [page] (home-page page))
           (resources "/")  

sveri10:12:24

no, I am talking about the retrieval of the page number

sveri10:12:50

this part: (let [page "42" page-num (or (s/conform ::optional-page page) 1)] page-num)

roelof10:12:11

oke, make that a single function

roelof10:12:29

@sveri so something like this :

(defn page-check [page]
  (let [page page page-num (or (s/conform ::optional-page page) 1)] page-num))

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

sveri10:12:21

something like this

sveri10:12:27

yes, then test it, with a written test

sveri10:12:31

and when it does what you want

sveri10:12:32

refactor it

sveri10:12:45

like removing unneeded assignments and making it look nice

roelof11:12:13

I do not get it . I have this code :

(defn page-check [page]
  (let [page page page-num (or (s/conform ::optional-page page) 1)] page-num))

(defn home-page [page]
  (let [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 (-> (client/get url options)
                                    api/read-numbers
                                    api/fetch-paintings-and-images-front-page)})]))  

roelof11:12:26

so no call to page-check

roelof11:12:06

and still I see this :

Caused by: clojure.lang.ExceptionInfo: Call to clojure.core/let did not conform to spec:
In: [0 4] val: (layout/render "home.html" {:paintings (-> (client/get url options) api/read-numbers api/fetch-paintings-and-images-front-page)}) fails spec: :clojure.core.specs/local-name at: [:args :bindings :binding :sym] predicate: simple-symbol?

roelof11:12:53

why does spec still look at the home-page when I do not make a call to a spec file ?

sveri11:12:41

it has nothing to do with spec itself, you could remove all the spec stuff in your source file and still get that error

sveri11:12:52

because spec is in 1.9 and it will generate the error output

roelof11:12:36

I think I leave spec for what is is

roelof11:12:47

it making me crazy now

sveri11:12:55

You will still hit the same error

sveri11:12:03

or a different one, if you switch to clojure 1.8

roelof11:12:22

the old code works without any problems

sveri11:12:44

then you get a runtime error

sveri11:12:47

or something similar

roelof11:12:09

this code works perfect : +

roelof11:12:15

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

sveri11:12:49

Its hard to believe that

sveri11:12:02

especially this line: [page nil page-num (or (s/conform ::optional-page page) 1)] page-num

roelof11:12:27

your are right. I have to change more things to get my old code

roelof11:12:27

This is working :

(defn home-page [page]
  (let [page-num  (or (read-string page) 1)
        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 (-> (client/get url options)
                                  api/read-numbers
                                  api/fetch-paintings-and-images-front-page)})))  

roelof11:12:28

The only thing is that users can change it to numbers which are bigger then 470 or smaller then 1

roelof11:12:32

I think I have to life with it at the moment

sveri11:12:15

You are on the wrong track

sveri11:12:58

There is a difference between this code and the code with the let error

sveri11:12:04

I urge you to try to find it

roelof11:12:21

yes this was the old code on 1.8 which works

roelof11:12:13

but I want to check also for nil and the 1 and 470 pages and sean suggest to me to use spec

sveri11:12:23

He is totally right

sveri11:12:34

The code above has a problem that has nothing to do with spec

sveri11:12:40

please try to find it

roelof11:12:01

you mean your code or the code I posted ?

sveri11:12:04

especially with this error message: Caused by: clojure.lang.ExceptionInfo: Call to clojure.core/let did not conform to spec: In: [0 4] val: (layout/render "home.html" {:paintings (-> (client/get url options) api/read-numbers api/fetch-paintings-and-images-front-page)}) fails spec: :clojure.core.specs/local-name at: [:args :bindings :binding :sym] predicate: simple-symbol?

sveri11:12:09

my code is the one you posted

roelof11:12:47

oke, I want to be sure that we talk about the same code

roelof11:12:37

oke, I said there is something wrong with the let binding

roelof11:12:45

in the layout/render part

sveri11:12:35

so look at the let binding and try to figure out what is wrong there

roelof11:12:21

the url looks fine to me

roelof11:12:31

so I has to be the options part

roelof11:12:29

@sveri I think this part : :p page-num

roelof11:12:38

pagenum is not known

roelof11:12:52

that has to be page

sveri11:12:40

where does your let binding end?

roelof11:12:03

after the api-fetch line

sveri11:12:25

please reformat the code and see if you can spot the error then

roelof11:12:29

otherwise url and options do not resolve

sveri11:12:02

and where does the binding vector of let end?

roelof11:12:06

oke, I change it to this : ` (defn home-page [page] (let [url "https://www.rijksmuseum.nl/api/nl/collection" options {:as :json :query-params {:key (env :key) :format "json" :type "schilderij" :toppieces "True" 😛 page :ps 10}}] (layout/render "home.html" {:paintings (-> (client/get url options) api/read-numbers api/fetch-paintings-and-images-front-page)})))

roelof11:12:27

so the let end before the layout-render

sveri11:12:00

that looks better

roelof11:12:05

and I do not see the spec error message 🙂

roelof11:12:19

when I try to open repl

roelof11:12:56

wierd that one 1.8 everything works well

roelof11:12:14

I did not see any error message and I see output on my browser

sveri11:12:49

its not weird, because in the 1.8 code, there was no error

sveri11:12:00

while in the 1.9 code you had the error

sveri11:12:09

and like I said, it had nothing to do with spec

roelof11:12:54

oke, so now I can add the spec files and hopefully I can check the url parameter page now well

sveri11:12:45

should be 😄

sveri11:12:06

and do like I said, leave the page number part in its own function, so you can test it easily

roelof11:12:02

It works finally :

(page-check nil)
=> 1
(page-check 1)
=> :clojure.spec/invalid
(page-check "1")
=> 1
(page-check 23)
=> :clojure.spec/invalid
(page-check "23")
=> 23
(page-check "500")
=> :clojure.spec/invalid  

sveri11:12:27

@roelof Awesome 🙂

roelof11:12:55

Now I have to think of what schould be happen when a user enters a invalid pagenumber

roelof11:12:31

I could send it to a 404 error page or make it work that a user gets send back to the homepage without any errors

roelof11:12:17

with the last one I think hackers do not get info about using of the parameters

roelof11:12:55

@sveri Thanks a lot with your help and patience

sveri11:12:22

I think hackers can get hold of the parameters in different ways

sveri11:12:29

try to make it useable for normal users

sveri11:12:41

security is a whole different story with like a million pitfalls

sveri11:12:19

I mean, if you think about that hardly, you should not put up a public web page 😄

sveri11:12:33

But on the other hand, its no fun then 😄

roelof11:12:56

Then I think I send a user to the home-page

roelof11:12:17

a 404 page I do not find very useable

roelof12:12:02

and after that I can try to make test for the homepage

sveri12:12:19

you should make tests first 😉

sveri12:12:19

😄

roelof12:12:20

I read I can do that with spec.test

roelof12:12:05

I know , I thought this was the right way to make tests with spec

roelof12:12:17

first write the predicates

roelof12:12:22

and then tests

sveri12:12:14

yep and after the tests, the functions 😄

roelof12:12:23

oke, I have to use spec/tests or instrument

roelof12:12:36

time to hit the manuals of spec one more time

roelof12:12:58

oke , I have to write a sdef where I enter the input and output

roelof12:12:53

That would be a problem , The input is a seq of maps with some keywords and the output will also be a vector of id's

roelof13:12:30

Last question before X-mas night. Can I have something like invalid as return for a spec function test ?

sveri13:12:04

@roelof There are different spec functions, one of them returns true or false depending if the data conforms to the spec.

sveri13:12:12

I think it was even conform

roelof13:12:52

oke, I ask because the page-check returns or a number or invalid

roelof13:12:34

so I have to test with "1" "2" which gives a number or the rest which gives invalid

roelof13:12:48

@sveri , I think you mean valid?

(s/valid? nil? nil)  ;; true
(s/valid? string? "abc")  ;; true

(s/valid? #(> % 5) 10) ;; true
(s/valid? #(> % 5) 0) ;; false

(import java.util.Date)
(s/valid? inst? (Date.))  ;; true   

sveri13:12:19

True, that could be used here

roelof13:12:41

oke, so I can check if a number is valid or not

roelof13:12:52

time to experiment again

roelof15:12:24

Sorry, still another spec problem.

roelof15:12:46

How do I tell that the args: are strings or integers . I tried (s/cat string? ::page :page) but that one gives this error : Assert failed: cat expects k1 p1 k2 p2..., where ks are keywords

roelof15:12:07

which makes clear that s/cat is not the right one

roelof15:12:01

and when I do

(s/fdef page-check
        :args (string? :page)
        :ret  (number? :page)
        :fn  (s/valid? #{true? %} :page  )
       )  

roelof15:12:14

the % is not resolved