This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-02-08
Channels
- # aleph (2)
- # aws (1)
- # beginners (172)
- # boot (15)
- # cider (17)
- # clara (7)
- # cljs-dev (22)
- # cljsrn (12)
- # clojars (3)
- # clojure (110)
- # clojure-dev (5)
- # clojure-italy (13)
- # clojure-sanfrancisco (5)
- # clojure-spec (3)
- # clojure-uk (31)
- # clojurescript (110)
- # community-development (2)
- # cursive (16)
- # datomic (19)
- # docs (4)
- # emacs (49)
- # fulcro (24)
- # jobs (5)
- # keechma (2)
- # lein-figwheel (41)
- # leiningen (10)
- # luminus (4)
- # lumo (24)
- # mount (24)
- # numerical-computing (1)
- # off-topic (16)
- # om (4)
- # onyx (6)
- # parinfer (9)
- # planck (8)
- # re-frame (7)
- # reagent (6)
- # shadow-cljs (125)
- # sql (5)
- # test-check (9)
- # unrepl (6)
- # yada (5)
` (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") ) `
def
should be used at the root level. You are using it inside a function, that's not right.
You might want to use let
instead.
(let [name value] ...)
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
@suryapjr You should read this https://lambdaisland.com/blog/29-12-2017-the-bare-minimum-clojure-mayonnaise
Wow you guys make me wish I went to #beginners when I started out
Of course, brave clojure was more than enough to get the ball rolling
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.
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.
@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
@seancorfield noted !!
Mornin' @roelof
@seancorfield almost time to sleep for you ?
It's only half past ten. Early!
We're watching Doctor Who (but happy to answer any beginner questions!).
oke, it;s here half past 7 in the morning. Very busy to get my daugther to school and with breakfast
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.
Unfortunately, no, there's not much in that area...
Rich has talked about tests as "guard rails" and between Rich and Stu there's an emphasis on the REPL, rather than tests.
@raheel here's a good one about setting up test-fixtures for clojure.test: https://stuartsierra.com/2016/05/19/fixtures-as-caches
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.
No one likes clojure.test
even tho' it's the greatest common denominator.
@seancorfield and what is your oponion then about midje ?
- 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)
@roelof I'm opinionated but I think Midje is terrible
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.
It's a completely non-idiomatic DSL on top of Clojure.
oke, I wonder if I make my first project which test framework Im wanted to use . There is midje, speclij, Expectations
@rymndhng clojure.test
s creator doesn't like it š But it's a lowest common denominator so it has that going for it.
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
1 question is: how guilty should i feel that I am writing less tests with the REPL based development?
I only feel guilty when my app unexpectedly does not work.
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?
@roelof I'd recommend either clojure.test
or expectations.clojure.test
š
@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"))
@raheel As long as you're capturing your REPL experiments in a (comment ...)
I wouldn't feel guilty about anything.
You'll see this pattern of using comment
even in clojure š i.e https://github.com/clojure/clojure/blob/f572a60262852af68cdb561784a517143a5847cf/src/clj/clojure/parallel.clj#L216-L250
yep, you can also use it as a basic regression test when you make changes to the namespace
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))
so we can evaluate each form
We can start and stop any of our myriad applications in the REPL like this.
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.Everything is all about sending forms to the REPL...
comment
means the code is never loaded in dev / test / production -- but you can still evaluate it in the REPL...
Development should be all about evaluating forms ... š
@seancorfield wierd, first you say clojure.test is not good and if I ask for a recommendation you say first clojure.test
I thought this one : https://semaphoreci.com/community/tutorials/testing-clojure-web-applications-with-kerodon could also work
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.)))
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
I discovered that. There seems to be a memfn
fn that can be used to do something similar for java interop.
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?
lein deps :tree
should give you a clue, usually it is about adding some exclusions for some dependencies
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"]
Thanks! That code snippet you gave didn't quite work out but I now know how to proceed solving this issue.
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"]
:the_horns:
@bmaddy Thank you! I'll try that
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.
Could I use the same trick to read a lot of data from a external api which can read some 3800 images
@nickstares0 the ScheduledThreadPoolExecutor API is pretty simple, it comes with the JVM, and clojure functions can be used directly as Runnable / Callable
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
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
ok, thanks! I'll try this out
after executing future-cancel the task stopped printing
I also should have included (.shutdown tpe)
in the above example - returns nil, cleans up resources
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)
Hello, im following this book : "web development with clojure" I made the guestbook as described in the book
but as soon as I do lein run
I see this error message : No :main namespace specified in project.clj.
@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.
@seancorfield thanks for the explanation
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.
oke, can I use Expectations to test web pages or can I then better use another library @seancorfield
What do you mean by "test web pages"?
I am not sure what you mean by "test the pages of the website"...
clojure.test
(and Expectations) are about unit testing.
@roelof Normally, you'd test functions (although you can use them to write assertions about anything).
It sounds to me like you want to interact with your running application at the browser level?
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
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.
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).
oke, first I try to follow the "web development with clojure" book and ran into problems
but as soon as I try to run it I see a error message that there is no :main
in the project file
here is the whole source : https://github.com/RoelofWobben/guestbook
@roelof do you have a -main
function defined in one of your namespaces that starts and runs the web server and application?
Your project.clj
has
:main guestbook.core
but you have no matching namespace for that.:main guestbook.core
from http://www.luminusweb.net/docs
wierd, the tutorial says to do this : lein new luminus guestbook +h2
and the book says the same : lein new luminus guestbook +h2
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
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
Likely a problem that you have a space in the file system path: web development
-- Windows doesn't like that.
That will break a lot of tools.
@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.
Windows has never been a particularly well-supported platform for a lot of Clojure projects.
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
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
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.
Then you can use Atom on the Windows side and Linux for command line stuff. That's how I work on Windows.
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 ?
Do I understand you well, @seancorfield
No need to mount. The C: drive is auto-mounted as /mnt/c
in WSL @roelof
(I'd expect /mnt/d
etc for other partitions -- but I only have a C: drive on my Win10 laptop)
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).
@seancorfield thanks, now everything works well
Can you pass a defrecord
that implements a defprotocol
into a function in another namespace and still call the functions/methods?
@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
the methods donāt belong to the record, they belong to the namespace with the protocol in it
@noisesmith Thanks.
@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