Fork me on GitHub
#clojure
<
2016-11-20
>
amacdougall02:11:14

Anyone have feelings about using defn- my-fn in namespaces and then #'my.awesome.namespace/my-fn in unit tests? Is there a better way to test private functions? Or would you say that if they need to be unit tested, they should not be private? I definitely feel like I might be doing something wrong when my unit test namespace begins with a big block of (def whatever #'namespace.under.test/whatever).

amacdougall02:11:32

...of course, it wouldn't be hard to write a macro to auto-define those references...

noisesmith02:11:43

you can also use ns-resolve (which is frequently misunderstood - it doesn't mean "look up the symbol in this ns" it means "look up the symbol using the same rules you would use in this ns" - which in this case is the right behavior)

noisesmith02:11:35

oh, funny, resolve works here too

hwk02:11:56

@amacdougall : IMHO, unit testing private functions are fine: 1. Functions are marked private because "in general use, you should not call this directly" 2. Private functions have unit tests to make refactoring / debugging easier. There's no clear reason why "this function has a unit test" implies "this function should be public"

amacdougall02:11:00

Interesting. Is #' a reader macro for (ns-resolve ...)?

amacdougall02:11:45

Also, any idea how to test whether something is usable as a function? e.g. functions, sets, keywords... fn? is obviously too limited.

noisesmith02:11:46

#' is a reader macro for var

noisesmith02:11:21

reader macros are easy to verify btw:

user=> '#'foo
(var foo)

amacdougall02:11:41

Oh, neat. I keep learning new things here. Thanks for the advice!

noisesmith02:11:24

another fun example:

user=> '#(+ % %)
(fn* [p1__23067#] (+ p1__23067# p1__23067#))

noisesmith02:11:31

the trick here, if it isn't clear, is that quote prevents eval, but happens after reading, so that you can see the raw form generated by the reader macro

noisesmith02:11:09

it even works recursively

user=> ''()
(quote ())

amacdougall02:11:52

Whoa, that's pretty fascinating. Not necessarily useful, but it helps illustrate what's going on under the hood.

Alex Miller (Clojure team)02:11:21

You can invoke #' directly - they look up their fn and invoke that

Alex Miller (Clojure team)02:11:31

When I'm testing private fns I just use the full var-quote instead of the unqualified symbol

Alex Miller (Clojure team)02:11:58

And I think it's good and fine to test private fns

spacepluk09:11:57

is there any way to do function composition at compile time, so that the implementations get inlined?

metametadata12:11:34

@amacdougall One of the main problems of having tests for private stuff: it creates a barrier to refactoring your code later because it's harder to modify code which is covered by tests. Generally I would not expect the tests to fail after I refactor private stuff. Private functions should be created during refactoring of public functions which you test before refactoring your code:

After successfully doing TDD or Test-Driven Refactoring, your code will not have specific tests for the private methods.

If you are developing new code, you are following TDD. You test-drive the development and no functionality is added without a test. Private methods are only created as the result of a refactoring step. And the path of code going through the private method is already being tested by previously written tests. So, after successfully doing TDD, your code will not have specific tests for the private methods.

If you are improving a legacy code, you should be following Test-Driven Refactoring. In this case, you may provisionally add tests for private methods. Gradually, with the increasing test coverage, the tests for the public methods will cover all the paths, including the paths going through the private methods. At this point, you don't require the tests for private methods anymore. So, after successfully following Test-Driven Refactoring, your code will not have specific tests for the private methods.
Now, it's a whole different discussion on whether one should always test first. And the simplest argument for writing tests first is that it guarantees that your test code really covers the tested behaviour. I've seen numerous times how tests do not cover the intended paths when they were written after the implementation. Thus: if you really feel that private stuff should be tested - extract it into a separate namespace so that it becomes "public" in that namespace. Quoting "Working Effectively with Legacy Code":
"How do I test private methods?” Many people spend a lot of time trying to figure out how to get around this problem, but, as I mentioned in an earlier chapter, the real answer is that if you have the urge to test a private method, the method shouldn’t be private; if making the method public bothers you, chances are, it is because it is part of a separate responsibility. It should be on another class.
As a side note, I also don't use defn- preferring -naming-private-stuff-like-this which makes code more readable and also works for naming private protocol methods, macros, etc.

lxsameer12:11:46

hey folks, I'm looking for a tool to help me generate a project template based on boot. is there any ?

madstap12:11:20

@leonoel What are you trying to achieve? ((first-partial / 3) 1) ;=> 1/3?

leonoel12:11:06

not exactly : (((first-partial /) 2 3) 1) ;=> 1/6

leonoel13:11:56

(((first-partial assoc) :a 1 :b 2) {}) ;=> {:a 1, :b 2}

gfredericks14:11:10

in my emacs/irc client the : b gets rendered as : stuck_out_tongue :

gfredericks14:11:28

it makes code examples more colorful

gabenwithrock14:11:13

Hello world! Can anybody help with error? when i use lein repl i get error: Error: Could not find or load main class lein Exception in thread "Thread-3" clojure.lang.ExceptionInfo: Subprocess failed {:exit-code 1} i'm tried to google that error and couldn't found any solution. Help

gfredericks15:11:09

@gabenwithrock can you share your project.clj?

gfredericks15:11:09

@gabenwithrock if I run lein repl with just that project.clj it starts fine; does that happen for you too?

gabenwithrock15:11:11

nope, same error Error: Error: Could not find or load main class lein Exception in thread "Thread-3" clojure.lang.ExceptionInfo: Subprocess failed {:exit-code 1}

stevenyi16:11:34

@gfredericks What version of Leiningen are you using and what OS? (can you post output of lein --version) Also, maybe try lein upgrade.

gabenwithrock16:11:52

Leiningen 2.7.1 on Java 1.8.0_102 Java HotSpot(TM) 64-Bit Server VM , Windows 10

gabenwithrock16:11:59

Lein updated, nothing has changed

gfredericks16:11:02

@gabenwithrock you mean there was only the project.clj in the directory, right?

gabenwithrock16:11:38

I think, something wrong with environment

roelofw16:11:28

someone who knows if 4clojure is down ?

Prakash16:11:12

its down for me too

roelofw17:11:51

bummer, I have to wait till it comes back

roelofw17:11:33

Another question : Is there a book / tutorials where I can learn to make websites without luminus

stevenyi17:11:34

@gabenwithrock I checked out the git repo and tested with lein repl here. I also am using leiningen 2.7.1, Java 1.8 64-bit, Windows 10. Only thing I can think of is maybe your lein self-install folder has a corrupt download or something in your .m2 local repo is corrupt. Maybe try clearing one or both and let leiningen redownload dependencies from scratch?

Pablo Fernandez17:11:35

I’m starting to use sente and in the handler callback I’m printing some debugging output. Sometimes it goes to the console, sometimes it doesn’t; sometimes it goes when I reload the Clojure source code, sometimes it doesn’t. I tried adding (flush) but it seems to make no difference. Does anybody know what’s going on here?

vitvakatu19:11:55

Hello everybody, I have a problem with clojure on android. Everything works fine, when I use standard lein droid application, but when I tried to use external java library (jsoup) - it fails. Actually, I added only one line to the code: ":import (org.jsoup Jsoup)". Application didn't start anymore

gfredericks20:11:22

@fumlead did you really write it like that without the surrounding parens?

vitvakatu20:11:38

No, of course. Right now, I'm trying to repeat situation with fresh project. Soon I'll write the exact algorithm to repeat problem yourself

vitvakatu20:11:25

Oh, I found the difference in project.clj. The second one (that succeded) has target-version 18, the first - 15. The joke is, that I have tablet with android 4.0.4 and the second project must fail instead of first

hwk22:11:43

is there a nicer way to write (apply vector :foo :bar lst) ? where lst is a sequence -- I'm wondering is there is a way to ~@ splice it into it

hwk22:11:40

`[:foo :bar ~@lst] <-- apparently this can be used outside of amcros too!