This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-04-24
Channels
- # announcements (8)
- # aws (12)
- # babashka (84)
- # beginners (380)
- # calva (56)
- # clj-kondo (52)
- # cljdoc (4)
- # cljs-dev (327)
- # cljsrn (4)
- # clojure (154)
- # clojure-italy (5)
- # clojure-nl (3)
- # clojure-uk (21)
- # clojurescript (52)
- # conjure (133)
- # cursive (64)
- # datomic (33)
- # emacs (22)
- # fulcro (35)
- # graalvm (24)
- # graphql (1)
- # kaocha (1)
- # leiningen (1)
- # off-topic (24)
- # onyx (2)
- # pathom (10)
- # re-frame (3)
- # reagent (3)
- # reitit (3)
- # shadow-cljs (48)
- # spacemacs (12)
- # tools-deps (98)
- # xtdb (7)
@U07S8JGF7 can you expand on what do you imply by shadow function vars
Meaning: Ordinarily, the symbol map
would refer to clojure.core/map
, but because you re-bound it in a let
, it now refers to {:foo :bar}
.
Sound advice, but if it was in response to the (count @atom)
code snippet earlier and the associated error message, there was no name shadowing occurring there.
They used atom
in an expression when they should have used state
, that is true, but they never shadowed the definition of atom
oh, right, it’s related in that: If you often shadow atom
you’re more likely to make this mistake.
Is there an interface in the standard library that represents associativeish things like maps, but doesn’t include vectors? I’ve seen clojure.lang.Associative
but that doesn’t fit the bill. clojure.lang.IKVReduce
might be a good proxy for what I’m looking for? What is clojure.lang.MapEquivalence
?
@jake142 Are you looking for a way to test things for being "map-like" or are you looking to implement something that is associative?
This is what I’m doin’. It didn’t work with clojure.lang.Associative
, since vectors extend that but don’t return a [[][]]
structure after the call to into
(It would be interesting if you could extend a protocol based upon more than one class…)
I’m being a bit lazy I guess, it would probably be more robust to dispatch off of clojure.lang.IKVReduce
and rewrite my function to use reduce-kv
rather than map
.
What are the Java classes that are auto-imported? I know Math is, what are the other ones?
Everything in java.lang
Well, everything old. Hasn’t been updated in a while
Prob java 5 or something
If you know of an example of some class matching java.lang.x.y, you could try using it in a REPL without the full prefix and see what happens.
I don't happen to know such a class off the top of my head.
user=> (sort (filter #(re-find #"^java.lang" %) (map #(.getName %) (vals (ns-imports *ns*)))))
("java.lang.AbstractMethodError" "java.lang.Appendable" "java.lang.ArithmeticException" "java.lang.ArrayIndexOutOfBoundsException" "java.lang.ArrayStoreException" "java.lang.AssertionError" "java.lang.Boolean" "java.lang.Byte" "java.lang.CharSequence" "java.lang.Character" "java.lang.Class" "java.lang.ClassCastException" "java.lang.ClassCircularityError" ...
Easy enough to look 🙂user=> (sort (filter #(re-find #"^java\.lang\..*\." %) (map #(.getName %) (vals (ns-imports *ns*)))))
()
No triple-dotted entriesjava.lang.Character.Subset
is Java syntax for what I believe is an inner class of java.lang.Character
. I will put a sample REPL session in a thread on this message to show some results I found
Clojure 1.10.1
user=> Character
java.lang.Character
user=> java.lang.Character
java.lang.Character
user=> java.lang.Character.Subset
Syntax error (ClassNotFoundException) compiling at (REPL:0:0).
java.lang.Character.Subset
user=> java.lang.Character$Subset
java.lang.Character$Subset
user=> Character$Subset
Syntax error compiling at (REPL:0:0).
Unable to resolve symbol: Character$Subset in this context
Wow, I found an inner class inside of an inner class, too:
user=> java.lang.ProcessBuilder$Redirect$Type
java.lang.ProcessBuilder$Redirect$Type
Full list of class names in java.lang inside of JDK 8 here: https://docs.oracle.com/javase/8/docs/api/java/lang/package-summary.html
apparently
I'm concluding that from experiments, not from some kind of first principles of full knowledge of Clojure's implementation.
These two are auto-imported:
user=> (sort (filter #(re-find #"^java\.lang\..*\$" %) (map #(.getName %) (vals (ns-imports *ns*)))))
("java.lang.Thread$State" "java.lang.Thread$UncaughtExceptionHandler")
user=>
😓 might ignore those for now 😛, I'm trying to add completion for java as well to anakondo, but inner classes are bit weird
That made me curious about what is imported that isn't java.lang.*
user=> (sort (filter #(not (re-find #"^java.lang" %)) (map #(.getName %) (vals (ns-imports *ns*)))))
("clojure.lang.Compiler" "java.math.BigDecimal" "java.math.BigInteger" "java.util.concurrent.Callable")
user=>
Don't think we'd want them to show up until someone typed $ and that's more work for me
So there's a triple-dotted one! java.util.concurrent.Callable
Interesting, I wonder what's the logic, are they coming from just the clojure.core refer, or like, why is there so many lol
The Big classes are basically extended parts of the numerics in lang
Functions implement Callable
Iirc Compiler is in there almost by accident
Not at a computer to check but it’s all explicit in the code
I don't know if I should have them all completed, or I should just pick the most common ones
> The Big classes are basically extended parts of the numerics in lang > What does this mean?
The numeric types are in java.lang.Integer java.lang.Long etc and extended by java.math.BigInteger etc
@seancorfield Just the command I was looking for.
Probably someone explained that already but I can't find it. Why it executes code inside when?
(when (Boolean. "false") "SHOULDN'T GO THERE")
I could not find the in-code explanation but the behaviour is documented for if
:
> Note that `if` does not test for arbitrary values of java.lang.Boolean, only the singular value `false` (Java’s `Boolean.FALSE`), so if you are creating your own boxed Booleans make sure to use `Boolean/valueOf` and not the Boolean constructors.
https://clojure.org/reference/special_forms#if
So, I guess the answer is "because!" and "don't do that!". 😬
I have a strong suspicion (but haven't measured) that if every if/when/cond in Clojure supported checking for a new boxed Boolean false value as taking the false branch, it would have a measurable performance slowdown effect on Clojure execution.
Joy of Clojure has a part about that
> (false? (Boolean. “false”)) > => false
dont create booleans like this
use boolean
you want to parse boolean
> ;; Simply defined: Everything except false and nil is logically true in Clojure.
I know, but I've just wanted to say that boolean
is not the right answer. It looks like you should use Boolean/valueOf
.
(true? (Boolean/parseBoolean "false"))
My point was you should not create Boolean
every time
for performance reasons clojure already has true
and false
created
and it compares are objects identical
I am not following you
what then you are asking?
But I think it is not consistent, that when
works only with Boolean.TRUE and true?
works for everything.
not following
The question was about when
and why it doesn't work properly for (Boolean. "false")
. Then next line was about that true?
handles it properly.
@U1V7K1YTZ I'm sure you mean well but answering a "why?" question with "don't do that!" can be a bit aggressive.
sorry for it did not mean it aggressive
my point is - one should not create new Boolean
because clojure compares with already created instance of true
agreed, that's absolutely valid. the discussion here seems to be more about that only false
and nil
are falsey in if
/`when` but a lot more things are falsey in true?
and that that seems inconsistent.
well, true?
is only checks if it Boolean.TRUE, right?
if/when if it is truthy
(hope I spelled that correclty)
I do not understand the statement "but a lot more things are falsey in true?
and that that seems inconsistent". Do you have an example?
Oh, perhaps you mean that if
treats (Boolean. true)
as true, but true?
returns false for that input?
Yeah, I believe everything is consistent if you avoid/ignore values created from the Boolean
constructor. The Java docs for the Boolean
constructor also have a big bold warning that it is rarely appropriate to use: https://docs.oracle.com/javase/8/docs/api/java/lang/Boolean.html#Boolean-boolean-
I really struggle to but this into good words. 🙂
I think it's about the mental model that one has about if
. Is (if condition then else)
the same as:
(if (true? condition) then else)
Or is it:
(if (or (nil? condition) (false? condition)) else then)
If you assume the first one (like @U0DN426JG), you are surprised that (Boolean. "false")
passes the check.I understand it can be surprising.
user=> (false? (Boolean. "false"))
false
then this is also should be surprising 🙂My only consoling words are: it rarely arises as an issue that affects your code's behavior. I agree it can make it all the more surprising in those occasions when it might arise, which if I understand correctly, are most often when interacting with Java libraries that box boolean values.
I found it surprising enough when I first came across it many years ago that I spent time writing a a fair amount about it on http://ClojureDocs.org: http://clojuredocs.org/clojure.core/if
clojure treats as falsey only nil
and Boolean/FALSE
(checked with identity, not equality), everything else is truthy
It seems reasonable from the performance perspective as @andy.fingerhut said.
Yeah, don't ever create a new instance of Boolean using the constructor. If you must, use Boolean/valueOf. Then identity check works.
154: public static Boolean valueOf(String s)
155: {
156: return "true".equalsIgnoreCase(s) ? TRUE : FALSE;
157: }
https://github.com/stathissideris/spec-provider (https://github.com/metosin/malli can also do it)
Let's say I have a data structure that represents lines on a 2-D plane. Some of these lines overlap and can be joined together. I want to take pairs of lines, compare them, join them into one line or return them both unjoined. I need to repeat this process until all lines that can be joined have been joined. The trick is that this won't reduce to just one line. I also need to immediately remove the two lines that were joined from the list of lines and insert the joined line, or not. I've come up with a solution that's very stateful and it feels very wrong. I know that the process is complete when the "before" and "after" versions are the same, e.g. nothing was found to have overlapped. It's also not generic at all. Is there some pattern that I don't know about that could help with this?
This is vague, I know, but you could have some kind of data structure, call it a line-set, that represents "a set of joined lines", which could be as little as one line by itself. Then you could represent the state at every point of your computation as a set of line-sets. A line-set could be represented by a Clojure set, perhaps, and the top level set could be, too.
Joining two line-sets is removing those two line-sets from the top level set, taking a union of them, then putting that new line-set back into the top level set.
Thanks. I hadn't thought of sets. Ideally I'd like to come up with something that's as simple as (reduce-as-much-as-possible does-pair-of-things-match-fn combine-pair-of-things-fn list-of-things)
Currently the combine-fn
is required to return a specific and stateful data structure. I thought about transducers that just work on pairs but couldn't make that work
I had a play for my own learning, may or may not be helpful, still does feel quite stateful in a way but I haven't figured out anything nicer yet:
;; Assumes
;; if (combinable? a b) and (combinable? b c)
;; then (combinable? (combine a b) c)
(defn combine
[combinable? combine-fn xs x]
(loop [combination x remainder xs]
(let [{combinables true
others false} (group-by (partial combinable? combination) remainder)]
(if (seq combinables)
(recur (reduce combine-fn combination combinables)
others)
{:combination combination
:remainder remainder}))))
(defn combine-all
[combinable? combine-fn xs]
(loop [[x & more] xs result nil]
(if x
(let [{:keys [combination remainder]} (combine combinable? combine-fn more x)]
(recur remainder (conj result combination)))
result)))
Was testing a little with some 1d ranges and seems to work well:
(combine-all
(fn [{amin :min amax :max}
{bmin :min bmax :max}]
(and (<= bmin amax)
(>= bmax amin)))
(fn [{amin :min amax :max}
{bmin :min bmax :max}]
{:min (min amin bmin)
:max (max amax bmax)})
[{:min 0 :max 1}
{:min 1.5 :max 2}
{:min 2.5 :max 3}
{:min 1 :max 1.5}])
=> ({:min 2.5, :max 3} {:min 0, :max 2})
(cheshire.core/parse-string "3blowup")
-> 3 instead of an error is an incredibly surprising behavior to us. anyone know how to make this consider the string as a whole and not just whatever fragment it can parse?
Have you tried parse-string-strict? I can't test right now but might do what you want
So my program takes configuration via command line arguments or environment variables. Is there away to set either of those in deps.edn aliases?
command line - yes via :main-opts
env - no (not actually possible in java)
it would be theoretically possible for the clj script itself to do that but nothing for that exists now
System properties can be set programmatically, so that's a possibility instead of env vars.
Hi, is there anyone who has been work or experience with "vase"? Is it good for large application?
sometimes my nREPL grinds to a halt (editor tooling starts failing, the repl itself seems slow). Any thoughts on what’s going on/what I’m doing wrong?
if you are running the repl from a terminal, you can use Ctrl-\
to see all stack traces of all threads, there might be a clue hidden in that output
you could also connnect a performance profiler like yourkit or visualvm to the jvm
thanks, i’ll give it a shot
If I have a vector of functions that I want to compose, it seems like the obvious choice would be to use comp
It occurred to me that (apply comp fns)
and (reduce comp fns)
would both technically work... is there a good reason to prefer one over the other?
comp already uses reduce1 (something clojure.core uses internally before reduce is bootstrapped from other functions) to its varargs
I think apply is easier to read - there's less for me to look at (not that there's a big difference here)
I see apply and just check the fn, with reduce there's more to look at, generally
TIL you can transpose a 2D matrix by using apply map vector|list
, e.g.:
(apply map vector [[1 2 3]
[4 5 6]
[7 8 9]])
=>
([1 4 7]
[2 5 8]
[3 6 9])
I feel stupid, can someone explain to me how this works?@ag did you know that map
can work on multiple collections, eg (map + [1] [2])
It's nicely explained in SO comment: > This works because (apply mapv vector m) is the same as (mapv vector (m 0) (m 1) ...). map/mapv accepts function (vector) in this case and any number of collections. If more than one collection is provided then map will apply the function (vector) to the first items in those collections, then to the second items, etc
On that topic, what are other useful things in clojure.core
and friends that people keep forgetting?
other stuff that takes multiple args:
• fn returned from every-pred
• fn returned from some-fn
• fn returned from juxt
oh good ones - also fnil
for up to 3 args
oh thats interesting, with juxt your f
s and g
s do need to share an arity
I didn’t realise because in my mind, juxt was always for functions of one argument :’)
idiom:
(def debug-data (atom []))
(defn debug [x] (swap! debug-data conj x))
(add-tap #'debug)
note the usage of the var, so that redef of debug can happen without losing the ability to remove the tap