Fork me on GitHub
#beginners
<
2018-02-08
>
pooboy01:02:02

` (ns hi.core (:gen-class)) (defn -main [& args] (println "Hi whats your name?") (def name) (read-line name) (println (str "Hi " name)) (println "Im clojure") ) `

pooboy01:02:15

What am i doing wrong?

pooboy01:02:59

Getting an error about unable to resolve symbol : def in this context

Vincent Cantin02:02:57

def should be used at the root level. You are using it inside a function, that's not right.

Vincent Cantin02:02:27

You might want to use let instead.

pooboy02:02:55

So.. (let name)

Vincent Cantin02:02:24

(let [name value] ...)

madstap02:02:53

And read-line takes no arguments

pooboy02:02:58

I want to take value from read-line

madstap02:02:27

(read-line), ie calling it with no args, produces a value.

Ryan Radomski02:02:47

you can google any clojure function and clojuredocs with come up pretty fast. It's community powered with examples to really drive the message home https://clojuredocs.org/clojure.core/let https://clojuredocs.org/clojure.core/read-line

pooboy02:02:09

Thanks guys !!

pooboy02:02:21

And im using vim and micro for clojure

pooboy02:02:25

Is that ok ?

pooboy02:02:40

Or do i get superpowers if use emacs + clojure ?

pooboy02:02:37

@madstap sure ! Thanks !

Ryan Radomski02:02:01

Wow you guys make me wish I went to #beginners when I started out

Ryan Radomski02:02:36

Of course, brave clojure was more than enough to get the ball rolling

andy.fingerhut03:02:21

I would say that you don't get superpowers if you use emacs + clojure, at least not when you are starting out. Any text editor that can help you balance parentheses (e.g. highlighting the matching paren when the cursor is next to a paren) is a very very useful thing to have, as a beginner or an experienced developer in any language.

andy.fingerhut03:02:06

Focus on learning the language first, I'd recommend, without learning a bunch of editor/IDE tricks at the same time -- but then, this advice is coming from someone who doesn't use those much, so I may be biased.

seancorfield05:02:51

@suryapjr I would say that you get a huge productivity boost when you have an editor setup that allows you to evaluate expressions in a REPL from your editor with just a hot key. Atom/ProtoREPL, Cursive, Emacs/CIDER all provide that (as others probably do). I highly recommend Stuart Halloway's REPL-Driven Development talk for that https://vimeo.com/channels/1116889/223309989

roelof06:02:42

good morning all

roelof06:02:49

@seancorfield almost time to sleep for you ?

seancorfield06:02:43

It's only half past ten. Early!

seancorfield06:02:08

We're watching Doctor Who (but happy to answer any beginner questions!).

roelof06:02:28

oke, it;s here half past 7 in the morning. Very busy to get my daugther to school and with breakfast

raheel06:02:37

are there some good reads on how unit testing, testing in general, and spec fit into the Clojure ecosystem? Would like to get a sense of good practices around testing as I build my first non-hobby application. I have done the REPL-driven development, plus some clojure.test unit tests and now starting to use spec.

seancorfield06:02:20

Unfortunately, no, there's not much in that area...

seancorfield06:02:13

Rich has talked about tests as "guard rails" and between Rich and Stu there's an emphasis on the REPL, rather than tests.

rymndhng06:02:32

@raheel here's a good one about setting up test-fixtures for clojure.test: https://stuartsierra.com/2016/05/19/fixtures-as-caches

seancorfield06:02:32

I don't like the procedural nature of clojure.test asserts which is why I took over maintenance of Expectations and then added expectations.clojure.test with compatibility with all the clojure.test tooling.

seancorfield06:02:22

No one likes clojure.test even tho' it's the greatest common denominator.

roelof06:02:30

@seancorfield and what is your oponion then about midje ?

rymndhng06:02:33

- In general, I try to make my tests as pure as possible - in some cases, i.e. testing DB wrappers, I do want to interact with stateful resources, i.e. database to ensure I'm writing SQL queries properly - If i'm integrating with a API that has a contract, I will occasionally use with-redefs to mock out particular calls (it's part of the language so you don't have to learn something new)

seancorfield06:02:53

@roelof I'm opinionated but I think Midje is terrible

rymndhng06:02:54

I think it's a bit of a overstatement to say no one likes clojure.test. It's good for getting started and having a minimal API surface area.

raheel06:02:08

that's what I did, even though I favor expectation / rspec kind of testing

seancorfield06:02:12

It's a completely non-idiomatic DSL on top of Clojure.

roelof06:02:45

oke, I wonder if I make my first project which test framework Im wanted to use . There is midje, speclij, Expectations

seancorfield06:02:06

@rymndhng clojure.tests creator doesn't like it šŸ™‚ But it's a lowest common denominator so it has that going for it.

rymndhng06:02:46

that's unfortunate, I quite like it šŸ˜„. i will admit there's interesting quirks to figure out about it, and there aren't a whole lot of docs about it

raheel06:02:11

1 question is: how guilty should i feel that I am writing less tests with the REPL based development?

Vincent Cantin07:02:18

I only feel guilty when my app unexpectedly does not work.

raheel07:02:13

point taken!

rmprescott14:02:01

The question is: "would this error have been covered by a test if you weren't 'writing less tests'?" I.e. is this an expected boundary case or behavioral constraint you didn't test or a "surprise" you hadn't thought of before? It always comes back to the value of tests as executable specifications: primarily as validation, preventing future breakage or documentation for later maintainers. Are they are speeding your current work or investments in reducing future work?

seancorfield06:02:14

@roelof I'd recommend either clojure.test or expectations.clojure.test šŸ™‚

rymndhng06:02:03

@raheel I write enough tests to give me confidence in the code. If you don't feel like you need it, you don't have to feel guilty A lightweight way of testing changes is put this in our source code to provide examples

(comment
   (make-some-call "foo" "bar"))

seancorfield06:02:09

@raheel As long as you're capturing your REPL experiments in a (comment ...) I wouldn't feel guilty about anything.

raheel06:02:00

ah, hmm. so your experiments in REPL get documented? So you can show use cases etc.?

rymndhng06:02:19

yep, you can also use it as a basic regression test when you make changes to the namespace

raheel06:02:53

to be run manually, right?

rymndhng06:02:59

correct, there is no magic

seancorfield06:02:29

We typically have stuff like this at the bottom of our main namespace

(comment
  (boot.user/inject-subproject-deps-with-test! "login")
  (def l (component/start (new-system 9130 :http-kit)))
  (component/stop l))

seancorfield06:02:44

so we can evaluate each form

seancorfield06:02:20

We can start and stop any of our myriad applications in the REPL like this.

seancorfield06:02:30

and then we'll have things like this at the bottom of our test namespaces

(comment
  (boot.user/inject-subproject-deps-with-test! "migration")
  (worldsingles.migration.test-system/test-start)
  (worldsingles.migration.test-system/test-stop))
so that we can load / start / stop the test context.

seancorfield06:02:12

Everything is all about sending forms to the REPL...

raheel06:02:59

gotcha. Any benefit to using comment over a defn with a descriptive name?

seancorfield06:02:11

comment means the code is never loaded in dev / test / production -- but you can still evaluate it in the REPL...

raheel06:02:08

makes sense

seancorfield07:02:17

Development should be all about evaluating forms ... šŸ™‚

raheel07:02:37

still learning... so much to learn šŸ˜‰

roelof07:02:03

I know the feeling @raheel

roelof08:02:44

@seancorfield wierd, first you say clojure.test is not good and if I ask for a recommendation you say first clojure.test

roelof08:02:07

Can I also use clojure.test for testing a web project

hawari09:02:28

Hi guys, I was wondering, is there a way for a Java instance method to be treated as a function in clojure? I need it as a predicate for my spec definition:

(import 'org.apache.commons.validator.UrlValidator)

(.isValid (UrlValidator.) "")
=> true

;; it doesn't work
(def valid-url?
  (.isValid (UrlValidator.)))

gnejs09:02:22

(def valid-url? [url] (.isValid (UrlValidator.) url))

gnejs09:02:52

or maybe (def valid-url? (partial .isValid (UrlValidator.))) (untested)

hawari09:02:36

thanks @gnejs the first one works, tried the second one though, it doesn't works.

sundarj09:02:38

Java interop syntax is built into the compiler, you can't pass it around like you can with functions: so you have to wrap it in a function

gnejs09:02:03

I discovered that. There seems to be a memfn fn that can be used to do something similar for java interop.

sundarj09:02:12

right. or one can do #(.foo %)

Kari Marttila10:02:36

I hava a dependency in my project.clj: [org.clojure/clojure "1.9.0"] [amazonica "0.3.118"] [ring/ring-json "0.4.0"] ... this causes: :message java.lang.NoSuchMethodError: com.fasterxml.jackson.databind.JavaType.isReferenceType()Z, compiling:(core.clj:218:1) ... Obviously there is some library mismatch how amazonica and ring/ring-json use fasterxml.jackson library. Do you know how to solve this issue?

delaguardo11:02:22

lein deps :tree should give you a clue, usually it is about adding some exclusions for some dependencies

delaguardo11:02:27

In your case it should look like this

[org.clojure/clojure "1.9.0"]
                 [amazonica "0.3.118" :exclusions [com.fasterxml.jackson.dataformat/jackson-dataformat-cbor
                                                   commons-logging
                                                   commons-codec
                                                   com.fasterxml.jackson.core/jackson-databind
                                                   com.fasterxml.jackson.core/jackson-core]]
                 [ring/ring-json "0.4.0"]

Kari Marttila12:02:51

Thanks! That code snippet you gave didn't quite work out but I now know how to proceed solving this issue.

Kari Marttila13:02:32

Fixed it finally. [ring/ring-json "0.4.0"] [amazonica "0.3.118" :exclusions [com.fasterxml.jackson.dataformat/jackson-dataformat-cbor commons-logging commons-codec org.clojure/tools.reader com.fasterxml.jackson.core/jackson-databind com.fasterxml.jackson.core/jackson-core]] and then I had to give the excluded libraries explicitely earlier: [org.clojure/tools.logging "0.4.0"] [commons-logging "1.2"] [com.fasterxml.jackson.core/jackson-databind "2.9.4"] [com.fasterxml.jackson.dataformat/jackson-dataformat-cbor "2.9.4"]

Sabbatical201712:02:53

@bmaddy Thank you! I'll try that

Nick Stares13:02:14

Are there any tutorials on scheduling background jobs on heroku in clojure? I found https://devcenter.heroku.com/articles/queuing-in-clojure-with-langohr-and-rabbitmq#using-the-langohr-library but that seems to be overkill for my use case. I just want to be able to schedule a few twilio notifications at arbitrary (usually not repeating or regular) times. Edit: I found Temporize. Seems simple enough that I may not need a library. Gonna research it some more.

roelof15:02:39

Could I use the same trick to read a lot of data from a external api which can read some 3800 images

noisesmith17:02:04

@nickstares0 the ScheduledThreadPoolExecutor API is pretty simple, it comes with the JVM, and clojure functions can be used directly as Runnable / Callable

noisesmith17:02:39

itā€™s like four lines of interop to create a scheduled executor, and set up an existing clojure function to run at some fixed frequency in it

noisesmith17:02:27

@nickstares0

justin@justin: ~/sprinklr/peregrine$ clj
Clojure 1.9.0
(ins)user=> (def tpe (java.util.concurrent.ScheduledThreadPoolExecutor. 4))
#'user/tpe
(ins)user=> (def task (.scheduleAtFixedRate tpe #(println "RUNNING" (java.util.Date.)) 0 10000 java.util.concurrent.TimeUnit/MILLISECONDS))
#'user/task
user=> RUNNING #inst "2018-02-08T17:09:51.690-00:00"
RUNNING #inst "2018-02-08T17:10:01.692-00:00"
(future-cancel task)
true

Nick Stares23:02:54

ok, thanks! I'll try this out

noisesmith17:02:56

after executing future-cancel the task stopped printing

noisesmith17:02:36

I also should have included (.shutdown tpe) in the above example - returns nil, cleans up resources

justinlee17:02:08

any atom+protorepl+figwheel users out there: is there a clean way to shutdown figwheel from within an atom repl session? nothing I do seems to actually kill the java processes that figwheel kicks off (including :cljs/quit and closing the repl)

roelof18:02:21

Hello, im following this book : "web development with clojure" I made the guestbook as described in the book

roelof18:02:59

but as soon as I do lein run I see this error message : No :main namespace specified in project.clj.

roelof18:02:15

but how do I know where the main spacespace is hidden ?

seancorfield18:02:04

@roelof Re: testing -- I don't like clojure.test but it is the best way to get started since it's included in the Clojure core stuff.

roelof18:02:53

@seancorfield thanks for the explanation

seancorfield18:02:03

Once you've gotten used to writing tests that way, you can look at other testing libraries. I personally like Expectations. And I maintain that library these days.

roelof18:02:48

oke, can I use Expectations to test web pages or can I then better use another library @seancorfield

seancorfield18:02:37

What do you mean by "test web pages"?

roelof18:02:09

I wanted to use clojure to make web sites

roelof18:02:27

can i use Expectations to test the pages of the website ?

roelof18:02:47

so I know for sure things are working fine

seancorfield18:02:00

I am not sure what you mean by "test the pages of the website"...

seancorfield18:02:36

clojure.test (and Expectations) are about unit testing.

seancorfield18:02:40

@roelof Normally, you'd test functions (although you can use them to write assertions about anything).

seancorfield18:02:06

It sounds to me like you want to interact with your running application at the browser level?

roelof18:02:15

oke, I think for version 0.01 I do not use many functions

roelof18:02:28

it will be a form that writes to the database

roelof18:02:47

so I think there are not many unit test possible

roelof18:02:17

Yep, I think I can better test version 0.0.1 at browser level

seancorfield18:02:39

If you want to "drive" your whole application as part of your tests, you're going to be looking at Selenium or HtmlUnit or something like that https://stackoverflow.com/questions/12807689/selenium-vs-htmlunit

seancorfield18:02:30

We use both at work -- but they're complex and fussy and I think they're the wrong level to write tests at for simple applications like yours.

seancorfield18:02:34

Remember that in a Ring application, your handlers are functions, so you can write tests for them (although at that point you're doing integration testing).

roelof18:02:27

oke, first I try to follow the "web development with clojure" book and ran into problems

roelof18:02:56

Made a project with `lein new luminus guestbook + h2"

roelof18:02:24

but as soon as I try to run it I see a error message that there is no :main in the project file

roelof18:02:50

So I have to figure out what the main is in the guestbook part of that book

roelof18:02:10

Can someone help me figure out what schould be in the call of :main in project.cli

seancorfield19:02:18

@roelof do you have a -main function defined in one of your namespaces that starts and runs the web server and application?

roelof19:02:54

I have made nothing. Just as I said do lein new .....

roelof19:02:08

and then lein run as the book says

seancorfield19:02:55

Your project.clj has

:main guestbook.core
but you have no matching namespace for that.

roelof19:02:42

yep, I tried something

roelof19:02:26

if I search in the code there is no main anywhere

roelof19:02:05

he, I miss a core.cli file

roelof19:02:27

wierd that i does not get made by lein new ....

roelof19:02:15

wierd, the tutorial says to do this : lein new luminus guestbook +h2 and the book says the same : lein new luminus guestbook +h2

roelof19:02:55

and I did : lein new luminus guestbook +h2

roelof19:02:14

why did I then not get a core.cli file ?

roelof19:02:14

and I also miss the migrations directory

seancorfield19:02:52

When I run that lein new command, I get a core.clj namespace

(! 1025)-> ls -l guestbook/src/clj/guestbook/core.clj 
-rw-r--r--  1 sean  staff  1800 Feb  8 11:15 guestbook/src/clj/guestbook/core.clj

roelof19:02:29

and im not :

PS C:\Users\rwobb\Documents\clojure\web development\guestbook\src\guestbook> ls


    Directory: C:\Users\rwobb\Documents\clojure\web development\guestbook\src\guestbook


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----         8-2-2018     19:15                db
d-----         8-2-2018     19:15                routes
-a----         8-2-2018     19:15           2668 handler.clj
-a----         8-2-2018     19:15           1157 layout.clj
-a----         8-2-2018     19:15            699 middleware.clj
-a----         8-2-2018     19:15           1187 repl.clj
-a----         8-2-2018     19:15            314 session_manager.clj
-a----         8-2-2018     19:15            245 util.clj

roelof19:02:53

Can it be a problem that I work on windows

seancorfield19:02:27

Likely a problem that you have a space in the file system path: web development -- Windows doesn't like that.

seancorfield19:02:43

That will break a lot of tools.

roelof19:02:47

oke, then I start over again

roelof19:02:33

oke, then there is something else a problem too

roelof19:02:00

I made a new directory and did again : lein new .......

roelof19:02:38

and still no clj directory with a core.cli in it

roelof19:02:12

and no spaces in the directory : C:\Users\rwobb\Documents\clojure\web\guestbook

roelof19:02:33

anyone a idea ?

roelof19:02:54

also when im doing this on the root of c disk I do not have a core.cli file

seancorfield19:02:11

@roelof Could well be a Windows-specific problem... Are you on Windows 10? If so, you could use the WSL (Linux) feature. You'd probably have more success that way.

seancorfield19:02:44

Windows has never been a particularly well-supported platform for a lot of Clojure projects.

roelof20:02:10

I can try WSL but then I do not have the possibilty to use things like atom because there is no graphical possible as far as I know

roelof20:02:48

maybe I can try to run Clojure on http://c9.io because I then get a Linux box but then I could not use parinfer

seancorfield20:02:34

WSL can use the Windows file system /mnt/c/Users/rwobb/Documents/clojure/web would be your Windows web folder that you're working in.

seancorfield20:02:56

Then you can use Atom on the Windows side and Linux for command line stuff. That's how I work on Windows.

roelof20:02:05

oke, so do the mount on WSL and then I could use the Linux for doing things like lein new and I can use my editor like normal ?

roelof20:02:22

Do I understand you well, @seancorfield

seancorfield20:02:39

No need to mount. The C: drive is auto-mounted as /mnt/c in WSL @roelof

seancorfield20:02:11

(I'd expect /mnt/d etc for other partitions -- but I only have a C: drive on my Win10 laptop)

seancorfield20:02:44

I use all the regular Windows programs as normal, and just do command line stuff in WSL in /mnt/c/Users/sean/... -- works great! And the nice thing is that if you have MySQL or other stuff running on Windows, the WSL side can talk to it automatically on the same ports on localhost. I actually have a mix of some stuff running on Windows and some things running on WSL (just because the scripts to start some of our processes are Linux and that's the "easiest" approach).

roelof21:02:18

oke, I will try it out

roelof21:02:25

@seancorfield thanks, now everything works well

grierson22:02:47

Can you pass a defrecord that implements a defprotocol into a function in another namespace and still call the functions/methods?

noisesmith22:02:53

@grierson yes - this is how much of clojure.core is implemented - the key is that the function in the other namespace needs to call the methods as defined by the protocol

noisesmith22:02:18

the methods donā€™t belong to the record, they belong to the namespace with the protocol in it

noisesmith23:02:27

@grierson one general rule that might help here is that unless your form starts with a . (and thus an interop special form), the thing to call is always the thing beside the paren, and that is the ā€œobject in chargeā€ of what happens - so when you use the function the protocol defines, thatā€™s the driver, and it needs to be referenced via its own namespace