This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-01-21
Channels
- # announcements (1)
- # architecture (1)
- # beginners (125)
- # boot (6)
- # boot-dev (2)
- # calva (69)
- # cider (38)
- # cljs-dev (3)
- # clojure (212)
- # clojure-austin (7)
- # clojure-australia (1)
- # clojure-denver (2)
- # clojure-europe (3)
- # clojure-gamedev (1)
- # clojure-hamburg (8)
- # clojure-italy (10)
- # clojure-nl (31)
- # clojure-russia (3)
- # clojure-uk (57)
- # clojurescript (56)
- # core-async (3)
- # cursive (15)
- # datascript (1)
- # duct (28)
- # emacs (6)
- # events (1)
- # figwheel-main (11)
- # fulcro (22)
- # luminus (59)
- # lumo (2)
- # onyx (4)
- # overtone (1)
- # re-frame (1)
- # reagent (4)
- # remote-jobs (3)
- # rum (2)
- # shadow-cljs (84)
- # spacemacs (7)
- # speculative (5)
- # vim (1)
- # yada (127)
hey has anybody worked with postal? I can't quite figure out how to set mime content-id header for the attachment (or whether it's possible at all)?
oops. should have gone through the source right away (:content-id for the same mime part map works)
Hi, is this a bug in clojure spec?
(require [clojure.spec.alpha :as s])
(s/def ::foobar keyword?)
(s/def ::bugged keyword?)
(s/def ::form1 (s/keys :req [::foobar]))
(s/def ::form2 (s/keys :req [::bugged]))
(s/explain ::form1 {::foobar :d})
(s/explain ::form1 {::foobar :d ::bugged nil})
The second (s/explain)
fails.Others can answer more authoritatively than I can, but I believe this is expected behavior. ::form1
only requires ::foobar
, and it allows other key/value pairs to be present as well. If one of those other keys that is present has a spec, then its value must satisfy that spec.
If one of those other keys that is present does not have a spec, then its value is not checked to see what it is.
Hmm, I saw this paragraph in the docs, for s/keys
In addition, the values of *all* namespace-qualified keys will be validated
(and possibly destructured) by any registered specs. Note: there is
no support for inline value specification, by design.
I guess a question would be, if the only valid kind of value to associate with the key ::bugged is a keyword, then why do you hope for no error to occur when you give that key a value nil?
And if nil is a valid value to associate with the keyword ::bugged, then maybe you want to change the spec for ::bugged to allow nil
Well, I could imagine that you sometimes don’t care about what is in ::bugged
You know, after some form of transform that you would make a stronger guarantee
Spec certainly lends itself well to doing that by calling the pre-transform and the post-transform things by different keys.
but not sure if that conflicts with other goals you may have.
Yeah, I was merely stating why I would maybe want to have such an option
I don’t think its good or bad about spec to expect each key to have a single (canonical/always applying) spec, its just surprising ^^
Yes, this is something that was surprising to me, and took me a while to figure out if this was a bug with my code, spec
, or of my understanding with spec
(s/def ::form1 (s/keys :req-un [::foobar]))
(s/explain ::form1 {:foobar :d :bugged nil}) ;; Success!
(s/def ::form2 (s/keys :req [::foobar]))
(s/explain ::form2 {::foobar :d ::bugged nil}) ;; fails
Trying to understand aliases invoked via clojure
or clj
could someone please explain what this most likely means clojure -A:dev:build:dev/rebel
.
I see dev
and build
are aliases that should be in deps.edn
but I don't quite get it.
aliases let you selectively add functionality/dependencies. so you just basically combine several aliases to get to the result you want
@U05224H0W and the dev/rebel
that's also an alias in the deps.edn
?
@U05224H0W So in this case there's likely a deps.edn
file along the lines of:
{:aliases
{:dev/rebel ...}}
right?Yes it's that, rebel. Okay, let me state the larger issue. I'm trying to get familiar with this tool edge but to understand it I think I need to figure out yada. Docs on both are however out of sync with the repo.
If one tries to follow https://juxt.pro/yada/manual/index.html#_build_run you'll see the edge repo has no app dir
@lennart.buit if you don’t care, then :opt
instead of :req
or define spec which let ::bugged
be nil
I have a protocol which defines the function last
. how do I refer this function without replacing clojure.core/last
?
Either fully qualify with the namespace where the protocol is defined or alias that namespace and refer to it via the alias
@saikyun you can also use :refer-clojure to exclude last from core and then refer to clojure.core/last when you need it.
Is there a variation of or
in which the first non-nil value (e.g. false) is returned?
yeah, I know how to write a function for it, that wasn’t my question 🙂 the difference between a function and a macro like or is that or short-circuits. of course I could also write my own or.
I'm quite certain this will do the same, drop-while
will yield a lazy seq which will be realized by first
so it should stop the moment you get an actual head of your seq back.
yeah, but then you should first create a lazy-seq of things you already don’t want to evaluate.
e.g.:
(or 1 (throw (Exception. "no")))
(defn some-nil [coll]
(when-let [s (seq coll)]
(if (some? (first s))
(first s)
(recur (next s)))))
=> #'dev/some-nil
(some-nil [nil false true])
=> false
?derived from the source of some
Does not short-circuit
user=> (some-nil [nil false (throw (Exception. "no"))])
Exception no user/eval149 (NO_SOURCE_FILE:7)
What problem are you trying to solve that you need this type of logical operator?
Suppose you’re reading a configuration option where false is a valid option. Then you could have:
(or* (read-from-env …) (read-from-java-opts …) (read-from-file …) (throw. (Exception. "no option provided")))
It’s no problem to write this macro myself, but I already solved it another way
Ah I see
some
is close to that
(some identity …) should work
ugh, right
I can't think of a way of implementing this with some
without an if
expression inside off the back of my head - but if anyone can I'd love to hear it!
okay, so there's no way to somehow say that the protocol just extends last
to include this new datatype?
I'm trying to use name.stadig.deque
to get deques, but for some reason it has separate a function for last
@borkdude sorry if I'm being unclear, I would want to use clojure.core/last
as well. I guess I should've phrased the question as "can I implement last
for more types in clojure jvm?"
I remember reading that some it wasn't possible with some protocols in clojure jvm, but it is in clojurescript or something like that
last is a sequence function. if you implement ISeq that should just work out of the box
ISeq has first, next and rest. Seqable has a seq function that tells how to turn something into a seq
An ISeq is a sequence. Seqable is something that can return a sequence when asked (via seq
)
(last [this]
(array-last (if (and (zero? (alength suffix))
(identical? empty-deque child)
(identical? empty-deque substack))
prefix
suffix)))
so I guess I should just qualify that last. it's just kind of sad that it's conceptually the same last
as clojure.core/last
eit seems that clojure.core/last
works on the deque as well. maybe their own last
is faster or something
and thanks for the link @alexmiller
I’m using clojure.tools.namespace.repl/refresh
but it seems my :after
symbol is not called. I’m not sure why. Should it be in the user namespace or can it live anywhere?
Can I assume that the clojure.core/hash
of too clojure sets are always equal if the sets are equal by value? I have a use case where I'd like to store the hash in a database in order to find a set by its hash. Can too different values have the same hash with this implementation?
There are far more possible sets than there are 32-bit hash values, so there must be collisions. And in practice if you start generating similar random sets, e.g. of integer values, you can find such collisions without a lot of trouble.
Maybe more detail than you care to know, but there are non-Clojure Java sets that have inconsistent hash values, even though they are =
to Clojure sets. If you restrict your attention to Clojure sets of Clojure values, you should avoid those oddities.
depends on what's in the set too, no guarantee that hashCode is stable accross process executions in theory
Article containing even more details, if you are interested: https://clojure.org/guides/equality
Certainly in Clojure, most hashes of Clojure values changed from pre-Clojure-1.6 to Clojure 1.6-and-later, but pretty stable except for that change. But sure, the hash function could change again in a future Clojure version, or perhaps because of changes in Java hash functions on some values that Clojure calls out to (I don't recall implementation details well enough to know whether Clojure even uses any Java hash code any more, for Clojure values).
Sure, that falls outside of my qualification of "Clojure values" that I slipped in above 🙂
Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application.
Whatever happened with that hash function that was discovered that had a very small amount of collisions?
@whoneedszzz Do you mean the hash function that Clojure used before Clojure 1.6? It was replaced.
No, I remember a hash function that was discovered by some person a few years back that promised very few collisions, but I haven't seen use of it
crypto hashes like SHA / MD5 / etc. promise (or strongly hope) very few collisions, but tend to be a little more expensive to calculate than non-cryptographically-strong ones. Do you recall whether the one you heard of was intended to be cryptographically strong?
Found it - Buzhash.
@mpenet notice the difference between "during an execution" and "need not remain consistent from one execution to another"
They are going to contain UUIDs (so java.util.UUID
instances on the JVM), but since the UUIDs are identifying users (or other resources) they are going to repeat a lot since the database contains far less records than the set of 32-bit values.
Thanks you all for the quick answer, and thank you for the article. I shall read it.
Do you know any function/library providing non-colliding hashes (or very low probability, mathematically speaking)? Or an alternative clean way to create a unique identity?
@ggaillard We may be talking all around your question, without solving your problem here. Depending on how long this database will last, relying on someone else's hash function implementation may be a bad idea, since it may change more quickly than the lifetime of your database.
Unless you have an implementation of the hash function that you have source code to that you believe to be stable for longer than your database.
because a hash is a summary they contain fewer bits of information then exist in the value being hashed, collisions will always be at least theoretically possible
you can construct a perfect hash, but you need to know the set of values a head of time
This is getting to be a lot of discussion on this topic. Can you guys please start a thread to keep track?
I've been there wanting to use a set as a key in some database and trying to come up with some scalar value which maps to the set, and there is no satisfying way to do it
If there is no perfect solution, an acceptable solution might be way enough.
If a bloom filter can at least reduce my search space by an order of magnitude I'd be happy with it.
If the set elements are UUIDs or other things with a total order that you can sort them on, would sorting the set elements and using a string representation of that sorted order work?
It would work I guess, but the string might get huge… If I do it this way I need to find out what will be the maximum set size, and I don't know that yet
Let's think of it pragmatically: If I hash the sets, I might get collisions. But even if I get some collisions the probability is still small, so it might be acceptable. But if the hash changes because the implementation changed, I'll get into trouble. So I'll have to find a way to hash a set that won't change over time/machine/process/version. A string might do it, but might get huge. A bloom filter might produce some false positives, but it might be acceptable anyway. I don't know how to persist a bloom filter yet though. You all gave me a lot to think about, and I think I might take the time to refine my requirements and constraints before asking other questions 🙂 Thank you very much!
The string I mentioned would never have collisions, but yes might get too large.
Even if you had a hash function that didn't have collisions, and had a small result, were you planning on storing the full set in the database, in any form at all? If so, what technique were you planning to use? Perhaps storing its elements across different database entries?
I'm using a SQL relational database, and the current use case is to store users and groups of users. So I have a Group (id)
table, a User (id)
table and UserGroup (group_id, user_id)
join table. I want to find as fast as possible a group having an exact set of user. Not a subset nor a superset. SQL got set operations, but don't provide a way to compute set equality in one operation. And with this table design I have to perform a GROUP BY group_id HAVING count(*) = <size of the user set>
, thus iterating with a nested loop at most over all groups.
So I was thinking that hashing the set and storing the hash would gave me direct access…
If you are willing to iterate over all groups that have the same hash, then a decent hash function can help significantly reduce the number of sets you would need to check in a slower way for precise membership equality, often down to 1 candidate, but even if occasionally down to several, would be much faster than checking all with say, the same number of elements.
@ggaillard sort the set and reduce with the v5 uuid constructor fn - that will give you a stable, deterministic hash of your set, with as low a probability of collision as the nsa’s best crypto engineers of the 1990s could devise
Thank you! Will look into it
i'm currently happily using clj-uuid for a V5 implementation: https://github.com/danlentz/clj-uuid#namespaced-v3v5-identifiers
It looks a lot like what replikative/hasch
(posted by mpenet) is doing with (uuid5 (edn-hash <value>))
for this use case
oh, i hadn't seen edn-hash
before - yes, that's similar, although perhaps more general (in that it's designed to do all the hard work of distinguishing your general edn structure before feeding it to a hash fn)
Bumping a previous question — how should I debug a tools.namespace.repl.refresh
invocation not calling my :after
function? I’m calling it like this: (c.t.n.r/refresh :after 'nosco.dev/go)
— where nosco.dev/go
is a no-args function as instructed. The refresh works (I see a bunch of refreshed namespaces printed out) but the function is not called (nor do I see any exception).
hitting an interesting java interop issue at last that i'm having trouble solving 🙂
if you were to declare a java function that expects a biconsumer string-string lambda you would declare it as public void foo (BiConsumer<String, String> aLambda) { .... aLambda.accept("a-string", "another-string"); .... } , something like this ... and whenever other java code tries to invoke it then javac is smart enough to check if that lambda is actually capable of consuming the string string argument pairs
but if i expose a function from clojure ... how do i achieve the same typehint so that java invokers would be aware of the bi-consumer expected ?
so i need at leat to write pure java interfaces for the "hinting layer"
a bit sad 😞
you could write something that reifies the interface that you need without it being too hateful
consider voting for https://dev.clojure.org/jira/browse/CLJ-2365
yes i figured the same, reify is in the opposite direction of my issue 🙂
it's not about runtime checks 🙂 , it's about making life easier for coworker who invokes my clojure function from java
so that he wouldn't feed my code a biconsumer that expects an elephant and a teapot as argument types
well it does look kind of weird that i can say (defn foo [^String a-string] .... ) but not (defn foo [^java.util.List<String> many-strings] ...) ...
but as said, i'm not married to the biconsumer interface, so i can declare my own, more restrictive, it will have to do
clojure will still make the function signature Object, and do local casts to string where necessary
i understand that part
i'm not trying to alter that part either 🙂 ... all i need to do is to define type hints for people invoking the code from java ... so that their intellij could be helpful for them when invoking my code
the classes etc created by clojure may not be visible until you load the clojure code
well the gen-class part etc. i already solved
so i'm generating a nice jar file that has nicely callable functions ... just wanted the parameter types to be more precise
you could create the interface in a java file and then implement the interface in clojure
instead of just java.util.List 🙂
use https://clojure.github.io/clojure/javadoc/clojure/java/api/package-summary.html to invoke clojure from your java
gen-class with :methods and matching -some-method is cleaner when you look from the java side
they won't even know it's clojure they are invoking
i'm not struggling with invoking itself 🙂
was just struggling with the generic part which while being a mimic (since the compiler throws it all away in the end) , is helpful at dev time
at least helpful in the way their intellij will draw a bold red line around the elephant and teapot
I am an old foe of clojure's aot compilation (I've seen it cause real head scratchers) so I am generally of the opinion that the design that leaves it out is best, in this case writing some facade in java (so it gets intellisense and types, maybe even javadocs), and having it call clojure via clojure.java.api seems best
I agree with @hiredman that if you want IntelliJ to provide type hints, you're going to have to write a facade in Java and then call into Clojure behind the scenes. The Java API that Clojure exposes is really nice -- we rely very heavily on it in production and have done for years to integrate Clojure into our legacy apps.
well this piece of code has just one entry point (calling one singe function) and what follows is a bunch of clojure all the way
Is type hinting loses effect at function boundaries? In the code below I would expect that no reflection is needed, but lein check says it does: Reflection warning, core.clj:26:43 - reference to field getDisplayLanguage can't be resolved. Why? Please explain type hinting rules. (I've read https://clojure.org/reference/java_interop#typehints and googled this, but can't see why it is working as it does in this case.) (ns core (:import [java.util Locale Locale$Builder])) (defn get-default ^Locale [] (let [l (Locale/getDefault)] ;; local usage of the result of a static method: ;; no type hint is needed to avoid reflection: (println "gd" (.getDisplayLanguage l)) l)) (defn getd2 [] (let [l (get-default)] ;; local usage of the result of a type hinted return value of an fn: ;; no new type hint is needed to avoid reflection: (println "gd2" (.getDisplayLanguage l)) l)) (defn -main [& _] (let [l (getd2)] ;; indirect usage of the result of a type hinted return value of an fn: ;; type hint is ineffective, reflection is used (println "Hello, type hinting World!" (.getDisplayLanguage l))))
it is helpful to consider clojure in the context of being dynamic and code reload and things being redfined
it is not safe to conclude getd2 will always return a whatever because the current definition defines it as returning a whatever
was a small surprise to me too at some point that clojure typehints dont enforce anything really
i was passing through a completely wrong type and the machine happily hummed along 👼
type hints are just that, hints to the compiler when dealing with interop, if you don't do interop they do nothing
(except long and primitive double type hints)
Thanks for the info. Then https://clojure.org/reference/java_interop#typehints is quite misleading for me, stating that "Once a type hint has been placed on an identifier or expression, the compiler will try to resolve any calls to methods thereupon at compile time. In addition, the compiler will track the use of any return values and infer types for their use and so on, so very few hints are needed to get a fully compile-time resolved series of calls." Now I think this could be used to deduce the behavior you describe above: "Type hints are metadata tags placed on symbols or expressions that are consumed by the compiler."
the docs on the page are maybe correct if you add a modifier like "within a function" somewhere
It's probably worth mentioning that Clojure's "unit of compilation" is a single top-level form -- so when getd2
is compiled, it has no type hint attached to indicate what it might return, and when -main
is compiled that definition of getd2
with no true hint is what it sees being used.
It would be incorrect in a lot of cases for Clojure to automatically tag the return type of a function based on whatever it deduces the type of the last expression in its body to be (which would be the only way the type deduced for l
inside getd2
to be propagated out of the function).
Does that help @771?
Thanks for your explanation, it helps! (Honestly, I thought that type inference is capable of determining the correct type in many cases, e.g. in the case of getd2's return type, and Clojure does it IF it is "hinted" to do so: I thought that once I type hinted something, Clojure respects the explicit intention and avoids reflection in all cases where it can, based on the hint I gave. I understood the http://clojure.org reference (linked previously) in this way too. After the answers I got here I tend to suspect that Rich H. doesn't want to encourage the usage of type hinting, so limits its capabilities.)
Yeah, real world Clojure can get a lot done without type hints -- if you're not worried about the performance of reflection, you almost never need type hints. If you decide to worry about performance due to reflection, it's still most often surprising just how few type hints you really need -- and they tend to be very localized, which I really appreciate.
I agree, I never needed type hints, I "decided to worry about it" :)) just because I am working on a free sw whose usage I don't want to hinder by possible performance bottle necks. I found also that very few type hints were enough to eliminate all reflections -- just I didn't understand why exactly those type hints are needed / why exactly there... And the reference doc didn't help me here.