This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-09-21
Channels
- # 100-days-of-code (6)
- # aleph (26)
- # beginners (129)
- # boot (5)
- # calva (3)
- # cider (5)
- # cljs-dev (16)
- # cljsrn (4)
- # clojure (204)
- # clojure-dev (36)
- # clojure-italy (23)
- # clojure-nl (4)
- # clojure-spec (221)
- # clojure-uk (60)
- # clojurescript (68)
- # datomic (47)
- # emacs (4)
- # figwheel-main (50)
- # fulcro (29)
- # graphql (10)
- # hyperfiddle (19)
- # lein-figwheel (3)
- # leiningen (20)
- # liberator (3)
- # off-topic (89)
- # onyx (15)
- # pedestal (1)
- # portkey (2)
- # re-frame (3)
- # reagent (6)
- # ring-swagger (1)
- # rum (12)
- # shadow-cljs (10)
- # uncomplicate (4)
- # vim (5)
what is the most idiomatic way to conditionally call a function?
@diego.vid.eco Can you provide a bit more context?
something like (if something call-this else-call-this)
perhaps with different arguments
Sounds like if
is what you want then.
(which is why it seemed to be a confusing question)
Is there a reason you think (if something call-this else-call-this)
might not be idiomatic @diego.vid.eco?
how do I pass the arguments?
If they have different arguments
(if something
(call-this with its args)
(else-call-this with different argument values))
ok, in the docs I did not see any examples calling functions
Function calls are just expressions like everything else.
If you had two functions that you wanted to chose between but call with the exact same arguments, you might do this instead
(let [f (if something a-function another-function)]
(f some argument values))
Does that help?
Quick question… In the project.clj
file what is the :url
value for? For example: :url "
. Can I put my git repo url there, or my blog post url there? Or does it expect something else?
whatever the “home page” is for your project, so github is probably best for a lib
@alexmiller Okay thanks!
Is there a way to know in which order the repl loads the clojure files when it gets started? I am using proto-repl, and am getting a strange startup error ":error-while-loading no.en.core Could not locate no/en/core__init.class or no/en/core.clj on classpath." I do not try to load a "no/en" namespace anywhere in my project.
I guess this is the order it processes the files. But I do neither have a "no.en.core", nor a "user" namespace in my src folder.
user
is just the default namespace for a REPL.
FWIW, I turn OFF the three reload options for proto-repl -- I find them far more trouble than they're worth. That will probably stop this issue.
no.en.core
looks to be coming from this library https://github.com/r0man/noencore
Hard to tell why that's failing to load -- it's probably a transitive dependency of something else you're depending on.
thanks @seancorfield
(there's a lot of magic in thi.ng.strf.core
as well that I would want to avoid)
Hi. Why is (contains? [:a] :a)
false, please? But a keyword in a vector seems to stay as that keyword: (= ([:a] 0) :a)
is true...
contains?
is probably one of the most misunderstood Clojure functions. It checks associative collections for the presence of a "key". Vectors are associative on their index, not their contents.
You'll see that (contains? [:a] 0)
is true while (contains? [:a] 1)
is false -- because the "keys" in the vector [:a]
are just 0 (there is no 1-th element).
Does that help @peter.kehl?
Ah, I forgot.... Thank you.
(I have invoked (doc contains?)
but I haven't read it properly...)
@cr No, some?
is arity 1 and just tests whether its argument is nil or not.
Nope, that takes a predicate and a collection and won't help you with a vector of keywords either.
(some (partial = :a) [:a])
would work tho'
(i.e., you can't do (some [:a] :a)
or (some :a [:a])
)
How about (some #{:a} [:a :b :c])
Yes, that's another possibility.
Using sets as functions is not universally popular though
Given the way spec is leading people, I think sets-as-predicates will become more popular/idiomatic.
Thanks everyone. And to @timo.freiberg for some
with a set as a predicate. That's what I needed, along with returning :a
instead of true
- thanks @seancorfield for point it out.
Is the definition of multi-stage programming this: https://en.wikipedia.org/wiki/Multi-stage_programming ?
yeap runtime code gen is possible due to quotations and executing that code is possible due to eval, right
@mfikes, @coinedtalk or whoever might be interested, for the english list function discussed a couple of days back, if we can do away with the oxford comma, we can also write:
(defn english-list [[f s & _ :as xs]]
(if (not s)
f
(apply str (concat (interpose ", " (butlast xs)) [" and " (last xs)]))))
thread is a function that spins up a Thread and runs your function on it, returning the result on a channel
thread is intended to be mostly “like future”, but returns the result on a channel rather than as a value
(<!! (a/thread (inc 1)))
@(future (inc 1))
Nearly identical semantics, though for simple stuff @
and future
is handy.Why does (doc empty?)
suggest: Please use the idiom (seq x)
rather than (not (empty? x))
?
Yes, (not (empty? x))
is a little less efficient, because (source empty?)
shows (empty? x)
implemented as (not (seq coll)))
. However, (not (empty? x))
tells my intent, but (seq x)
hides it (less obvious => more mental energy wasted when reading the code later).
If you used Clojure for a while, do you really read that usage of (seq x)
naturally?
@peter.kehl To me, it feels a bit clumsy. One is a question and the other a statement? I don’t get it. Regardless, I have learned to read it just by encountering it repeatedly, and do remember to use it when I feel like negating empty?
. I sometimes catch myself inverting code to avoid seq
in favor of empty?
though.
I suppose (def not-empty? seq)
is an option if you find it impossible to swallow, but I’m not sure it’s good form.
there's also not-empty
whcih returns the original object, or nil if it was empty, for any seqable? type
@peter.kehl Yeah, using seq
to mean not empty is truly a preferred idiom, unfortunately not as clear, but, alas, that's what it is.
Thank you @henrik, @noisesmith and @mfikes.
Is there any macro or special form to prevent re-binding symbols? Ideally an alternative to let
that would warn/fail if re-binding an already bound symbol (or if re-binding an existing variable/function), please?
there's defonce
which silently does nothing if the var already exists
(according to @gfredericks , defonce rhymes with Beyonce)
@peter.kehl If your reason for asking is to detect mistakes in your code like using a let
to rebind the value of map
, forgetting you did that, and then calling the locally bound map
inside the let form hoping to get clojure.core/map
, but instead getting the local one, Eastwood can warn about such shadowing. It isn't always an error to do that, but it looks suspicious. https://github.com/jonase/eastwood
eastwood doesn't warn about using the same let binding twice in one block though (and I'd argue it shouldn't because it's a common pattern to do so intentionally)
@peter.kehl I've slowly gotten used to reading (seq xs)
naturally. I had to sort of grin and bear it at first.
is there any simple implementation of disjoint-set data structure in clojure? this one is just too much https://github.com/jordanlewis/data.union-find/blob/0.1.0/src/jordanlewis/data/union_find.clj
@noisesmith Yes, Eastwood's warning for such code tries to catch the thing that is most often an error, without warning about common usage patterns (even if those common usage patterns might also be bugs).
@denisgrebennicov I haven't used any of them, but a Google search of "clojure union find" (without the quotes) turns up several libraries and a blog post or two. Some of them may be simpler than the one you linked.
https://clojuredocs.org/clojure.core/type reads:
;; Checking a macro
user=> (type fn)
user$fn
user=> (type clojure.core/fn)
java.lang.Exception: Can't take value of a macro...
However, in clj 1.9.0 both expressions fail (though not with java.lang.Exception
but with java.lang.RuntimeException
) with the same error description. Can that be a mistake in the doc, or did the implementation of fn
change from a function to a macro?The example is misleading -- it omits the definition for fn
in the user
namespace.
In the first (type fn)
the fn
in intended to mean "any function in the user
namespace"
It really could just omit that piece altogether (since it shows type
on a function above -- foo
).
There. Example updated to remove the confusing part. @peter.kehl
(I forgot that anyone with a GitHub account could just edit the examples!)
In Clojure 1.10, the error message has improved:
user=> (type clojure.core/fn)
Syntax error compiling at (1:1).
Cause: Can't take value of a macro: #'clojure.core/fn
Thanks @seancorfield.
Talking of types: What's a good way to tell if something is a function? Anything that works without namespace import (other than clojure.test/function?
), please?
Thanks @ghadi. (Unsure how to use class
in general, since its result varies: (class inc)
returns clojure.core$inc. ifn?
is good.
@peter.kehl what that result shows is that the "function" we call clojure.core/inc is an instance of a class called core$inc in the package clojure - if you checked, you'd find that this class implements IFn
=> (instance? clojure.lang.IFn inc)
true
and now that I check for myself, that is precisely what ifn? is doing
So this is how I make test my code with clojure.test:
(deftest some-test
(testing "function X should do Y"
(let [arg1 ...
arg2 ...
arg3 ...
expected {...}
result (my-fun arg1 arg2 arg3}]
(is (= expected result)))))
Is this a good practice? I find it is easy and simple to test single functions, but more difficult for testing larger functions or functions that mutate state or do IO"more difficult for testing larger functions" -- maybe break those functions up and test the subfunctions instead?
(and perhaps test the overall function by mocking those subfunctions via with-redefs
)
As for mutating state/doing I/O -- one approach there is to separate out the "function" from the "side effect" as much as possible and write tests for the function part. Testing side effecting code is always harder because you need to set up the appropriate "execution environment" before the test (and you should restore the state of the world if possible after the test).
Does anyone have a working spec for specs? Hopefully covering spec objects, predicates, keywords, regexes and all the other forms that are valid args to e.g. (s/valid? ...)
@polymeris It would be a very loose spec since it can be so many things. "predicate" covers anything that can be treated like a function -- including sets, for example.
ifn?
would cover most function-like things (functions, sets, and also keywords which can behave like predicates!)
:foo
is a perfectly reasonable predicate. :foo/bar
is too -- it doesn't have to be a registered spec... Not quite sure how s/valid?
would handle that
Ah, if s/valid?
is passed a keyword it requires that it is a registered spec!
Also, have been using orchestra, so decided to check if they had implemented a spec for spec, and as it turns out "TODO: Spec for specs" heheheh
So you'd have to check for keyword?
first (and call s/get-spec
) and then check ifn?
or s/spec?
or s/regex?
I guess.
Oh, be careful: s/regex?
is not a string regex -- it's a spec regex!
So you'd need to test for (partial instance? java.util.regex.Pattern)
I think?
So it's... (s/or :kw-spec (s/and keyword? s/get-spec) :predicate ifn? :spec s/spec? :spec-regex s/regex? :str-regex (partial instance? java.util.regex.Pattern))
... anything else needed in there? 🙂
You are correct. Looks like the default case (once s/valid?
has checked for keywords and specs is to require something that can be cast to IFn
, i.e., ifn?
.