This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-08-30
Channels
- # announcements (1)
- # babashka (28)
- # beginners (68)
- # cider (12)
- # clj-kondo (5)
- # clojure (37)
- # clojure-spec (4)
- # core-async (5)
- # cursive (3)
- # data-science (1)
- # datomic (70)
- # fulcro (18)
- # graalvm (1)
- # joker (1)
- # luminus (2)
- # malli (11)
- # off-topic (21)
- # shadow-cljs (3)
- # spacemacs (11)
- # test-check (3)
- # vrac (8)
i'm making a bingo game and i want to randomly call one of the remaining numbers. currently i am doing (rand-nth (into [] (difference possible-numbers called-numbers)))
is there a better way?
That seems fairly reasonable to me, although I'd probably use vec
instead of into []
#clojure-dev might be better
I'm reading through the source (trying to implement my own HAMT) and I'm curious about some decisions
So for example, here invoke
is declared a number of times for different argument counts:
https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/AFn.java#L27
What's the reasoning behind this? Is it just for efficiency, so the arguments don't need to be counted?
I do not know if counting would be the main inefficiency -- Java would actually create a run-time Java array of Object
if you used Object... args
instead of the technique used here. I would guess maybe some JVMs might be able to autoamatically do some of what is done here manually in Java, but perhaps not.
Given that it is coded like this, probably JVM JITs typically do not do that kind of transformation for you.
For the (very likely most) JVM JITs that do not do this, imagine calling a function that takes two args. With two Object
args, that is pushing two Object
references on the stack. With Object
array, it is creating a Java array object, and writing the two Object
references into its first and second elements. A lot more memory allocation for the Object... args
version.
Well, not a lot more allocation for a single call, but in a loop with a million of them ...
I'm assuming that any non-negligible overhead in the core datastructures is pretty much worth eliminating anyway
That isn't even an allocation in the data structure implementation -- that is on every Clojure function call.
Is this line a bug then? Shouldn't it be 20 + args.length
instead of 21
?
https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/AFn.java#L140
If it was considered important to give the exact number of args for all cases where you tried to pass over 20, and wanted to see a precise number that were actually passed in the exception, then yes.
Perhaps that is not considered important, given that most people switch to passing collections long before the number of args ever gets close to that.
Mmm, thinking about it some more I realise the arity error here is really a reference to the unimplemented function
If that's the case, is it also why the final count is hard-coded, despite taking a variable number of args? https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/AFn.java#L140
(I'm assuming Object... args
is a variable-length args list, been a while since I coded Java)
Object... args
under the covers is a Java array of Object
, yes with variable length at run time.
How can I typehint a Java interop function that has signatures like
function remove (int i) {}
function remove (String s) {}
//clojure code like
(defn remove [k] (remove k))
is defprotocol/defmulti probably what im after here?
do you want to support both?
if so, the most expedient thing is probably to type check and use different hints in both branches
yes I need to support both signatures.
So validating all function specs is a thing (orchestra), but that requires speccing out existing functions. What if I want to validate all keyword specs instead? Validating all :foo/bar
values during runtime. Is that a thing?
I'm not sure what you mean by that @deadghost -- could you elaborate?
@seancorfield Suppose I'm at the REPL and suppose :foo/bar
is spec'd as int?
:
• I eval {:foo/bar "1"}
in the REPL, I want it to tell me nope that's not a valid :foo/bar
• I eval a fn with {:foo/bar "1"}
as an argument, I want it to tell me nope, that's not a valid :foo/bar
• I eval a function and it returns {:foo/bar "1"}
, I want it to tell me nope, that's not a valid :foo/bar
• Stretch goal: I eval a function that uses a {:foo/bar "1"}
internally, and I want it to tell me nope, that's not a valid :foo/bar