Fork me on GitHub
#clojure
<
2020-08-30
>
ozzloy04:08:52

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?

seancorfield04:08:02

That seems fairly reasonable to me, although I'd probably use vec instead of into []

Jcaw11:08:44

Is this the right channel to ask questions about Clojure's implementation?

jaihindhreddy13:08:19

#clojure-dev might be better

Jcaw13:08:44

Mmm, not sure if I should pollute that one though

Jcaw11:08:35

I'm reading through the source (trying to implement my own HAMT) and I'm curious about some decisions

Jcaw11:08:01

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?

andy.fingerhut15:08:44

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.

andy.fingerhut15:08:51

Given that it is coded like this, probably JVM JITs typically do not do that kind of transformation for you.

Jcaw15:08:17

I guess it could be defensive

Jcaw15:08:21

Cover all JVMs

andy.fingerhut16:08:17

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.

andy.fingerhut16:08:47

Well, not a lot more allocation for a single call, but in a loop with a million of them ...

Jcaw16:08:52

That makes sense

Jcaw16:08:06

I'm assuming that any non-negligible overhead in the core datastructures is pretty much worth eliminating anyway

Jcaw16:08:21

So even if it's a small allocation it makes sense to avoid it

andy.fingerhut16:08:52

That isn't even an allocation in the data structure implementation -- that is on every Clojure function call.

Jcaw16:08:26

Yeah ok that makes more sense

Jcaw16:08:40

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

andy.fingerhut16:08:19

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.

andy.fingerhut16:08:42

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.

Jcaw16:08:37

Mmm, thinking about it some more I realise the arity error here is really a reference to the unimplemented function

Jcaw16:08:55

So it's important that it's a static number

Jcaw11:08:03

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

Jcaw11:08:18

(I'm assuming Object... args is a variable-length args list, been a while since I coded Java)

andy.fingerhut15:08:16

Object... args under the covers is a Java array of Object, yes with variable length at run time.

👍 3
Chester ONeill17:08:57

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

Chester ONeill17:08:00

is defprotocol/defmulti probably what im after here?

Alex Miller (Clojure team)18:08:03

do you want to support both?

Alex Miller (Clojure team)18:08:58

if so, the most expedient thing is probably to type check and use different hints in both branches

Chester ONeill20:08:26

yes I need to support both signatures.

deadghost23:08:26

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?

seancorfield23:08:29

I'm not sure what you mean by that @deadghost -- could you elaborate?

deadghost23:08:47

@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

deadghost23:08:26

In short, I'd like the :foo/bar spec enforced as close to everywhere as possible