Fork me on GitHub

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.


So there's no way to prevent ::bugged from being checked right?


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

Lennart Buit07:01:43

Well, I could imagine that you sometimes don’t care about what is in ::bugged

Lennart Buit07:01:54

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.

Lennart Buit07:01:32

Yeah, I was merely stating why I would maybe want to have such an option

Lennart Buit07:01:17

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


On the other hand, unqualified keywords works the opposite


(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


How do you guys exit the clojure repl from clj or clojure ?


Me too, but I thought I was doing something hacky. [Edit] Thanks


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?


yes thats just a namespaced keyword


but deps can be "inherited" from system configs


so you can also define an alias in ~/.clojure/deps.edn


if you want something that is generic and not specific to a project


@U05224H0W So in this case there's likely a deps.edn file along the lines of:

  {:dev/rebel ...}}


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 you'll see the edge repo has no app dir


probably got reorgnized. maybe that is the main dir now?


Ya but docs didn't update. Thanks I get it.


@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?

Alex Miller (Clojure team)13:01:40

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.


but that can become confusing, since last is probably used often


Is there a variation of or in which the first non-nil value (e.g. false) is returned?


#(first (drop-while nil? %)) Bind it to a suitable name and there's your function.


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

👍 5

yeah, or (first (filter some? ...)), but I wanted to avoid first filter 😉


what about (some (complement nil?) ...)


user=> (some (complement nil?) [false])


(some identity …) should work


nope, same problem 😜


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


@saikyun you can try (:refer-clojure :exclude [last]) in your ns form


@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


oh, huh. I wonder why the deque defines its own interface then


but you cannot extend-type ISeq, because it’s not a protocol


I'll try changing that then 🙂


is ISeq different from Sequable?


ISeq has first, next and rest. Seqable has a seq function that tells how to turn something into a seq

Alex Miller (Clojure team)14:01:15

An ISeq is a sequence. Seqable is something that can return a sequence when asked (via seq)


hmm, I think I understand why they define their own last


(last [this]
    (array-last (if (and (zero? (alength suffix))
                         (identical? empty-deque child)
                         (identical? empty-deque substack))


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


it seems to use a mutable array internally


thanks for the help 🙂


and thanks for the link @alexmiller


I’m using 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?

Geoffrey Gaillard17:01:02

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?


that is a hash collision


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:


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).


a set could contain some java instance of Foo with an unstable hashcode in theory


unstable across process executions I mean


Sure, that falls outside of my qualification of "Clojure values" that I slipped in above 🙂


all in all relying on hash sounds like a bad idea imho


but that's just me


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. 


from the javadoc


so an unstable hashcode is illegal


Whatever happened with that hash function that was discovered that had a very small amount of collisions?


ah? is that something that changed? I recall reading the opposite


@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.


also is that true for execution in runtime from vendor A to vendor B?


@mpenet notice the difference between "during an execution" and "need not remain consistent from one execution to another"


maybe that's what you were talking about?


I need to read this again 😛


oh yeah that's what I meant


gotcha then you were correct


sorry for the noise :)


no worries

Geoffrey Gaillard17:01:24

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.


replikativ has something like that I think


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.


but it has other tradeoffs


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?

Geoffrey Gaillard17:01:03

Sorry about that, thank you for the reminder

👍 5

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


a hash is not great, maybe a bloom filter gets closer, but still has issues

Geoffrey Gaillard17:01:42

If there is no perfect solution, an acceptable solution might be way enough.

Geoffrey Gaillard17:01:12

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?

Geoffrey Gaillard17:01:03

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

Geoffrey Gaillard17:01:25

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?

Geoffrey Gaillard18:01:47

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.

👍 5

@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

Geoffrey Gaillard19:01:21

Thank you! Will look into it


i'm currently happily using clj-uuid for a V5 implementation:

Geoffrey Gaillard20:01:43

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 ' — where 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


you are thinking of the reverse


yes i figured the same, reify is in the opposite direction of my issue 🙂


Because of type erasure in the JVM there's no way to ensure


"don't pass it non-strings"


my guess is it is more a question of providing intellisense


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


but that is just dynamic typing right?


clojure is a dynamic language, no getting around it


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


type erasure happens in the jvm


nah, it happens in the java compiler


java the language has generics


Also, ^String doesn't actually mean the parameter is a string


the jvm doesn't


clojure will still make the function signature Object, and do local casts to string where necessary


type hints are not type declarations


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


there are huge issues with that as well


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 🙂


and stop aot compiling your clojure code


(after you write a stub with whatever types in 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


sure, I mean, you write a facade in java and invoke clojure like that


i'm not struggling with invoking itself 🙂


expose your java facade then with whatever types you want


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 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 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))))


type hinting is purely local to function boundaries


type hints are not type declarations, type hints are not propagated


there is nothing like a type inference algorithm going on behind the scenes


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

Alex Miller (Clojure team)22:01:58

(except long and primitive double type hints)


Thanks for the info. Then 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 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.