Fork me on GitHub
#clojure
<
2021-10-20
>
didibus07:10:04

reify might have the worst doc-string of them all: > reify is a macro with the following structure: > (reify options* specs*)

p-himik07:10:02

Huh?

Clojure 1.10.3
user=> (doc reify)
-------------------------
clojure.core/reify
([& opts+specs])
Macro
  reify is a macro with the following structure:

 (reify options* specs*)
  
  Currently there are no options.

  Each spec consists of the protocol or interface name followed by zero
  or more method bodies:

  protocol-or-interface-or-Object
  (methodName [args+] body)*

  Methods should be supplied for all methods of the desired
  protocol(s) and interface(s). You can also define overrides for
  methods of Object. Note that the first parameter must be supplied to
  correspond to the target object ('this' in Java parlance). Thus
  methods for interfaces will take one more argument than do the
  interface declarations.  Note also that recur calls to the method
  head should *not* pass the target object, it will be supplied
  automatically and can not be substituted.

  The return type can be indicated by a type hint on the method name,
  and arg types can be indicated by a type hint on arg names. If you
  leave out all hints, reify will try to match on same name/arity
  method in the protocol(s)/interface(s) - this is preferred. If you
  supply any hints at all, no inference is done, so all hints (or
  default of Object) must be correct, for both arguments and return
  type. If a method is overloaded in a protocol/interface, multiple
  independent method definitions must be supplied.  If overloaded with
  same arity in an interface you must specify complete hints to
  disambiguate - a missing hint implies Object.

  recur works to method heads The method bodies of reify are lexical
  closures, and can refer to the surrounding local scope:
  
  (str (let [f "foo"] 
       (reify Object 
         (toString [this] f))))
  == "foo"

  (seq (let [f "foo"] 
       (reify clojure.lang.Seqable 
         (seq [this] (seq f)))))
  == (\f \o \o))
  
  reify always implements clojure.lang.IObj and transfers meta
  data of the form to the created object.
  
  (meta ^{:k :v} (reify Object (toString [this] "foo")))
  == {:k :v}
nil
user=> 

didibus07:10:31

Ya, it goes into some details, but the summary is: > reify is a macro with the following structure:

didibus07:10:29

It never really explains what its for

p-himik07:10:51

Right. Time to create an http://ask.clojure.org question with a suggested edit? :)

✔️ 3
Alex Miller (Clojure team)12:10:25

There is an active ticket for this already

Alex Miller (Clojure team)12:10:52

CLJ-2488 is screened for Rich to look at in 1.11

🎉 6
Eugen04:04:15

I do hope the docs get improved for this one. I can't figure out how to implement reify for multiple interfaces

Eugen04:04:42

I'm not a junior dev. I have been using clojure on and off for some almost two years, but I can't figure out by reading documentation - how to use reify to implement multiple interfaces. IMO the docs can be improved.

p-himik07:04:01

FWIW I think the docs are rather clear. The only thing I'd add is, perhaps, an example of the above. Although Clojure code itself has such examples - future-call, promise, iteration.

Eugen09:04:28

hi, there was an issue - I tried to add docstring and it does not support it. Once I removed method docstring it worked. I added a note to https://clojuredocs.org/clojure.core/reify about this . hopefully people won't fell for the same trap 🙂

Ben Wiz10:10:20

I am debugging something. I have a TransientHashSet I must inspect. I cannot call persistent! because the library exposing the TransientHashSet expects to continue modifying it. What can I do? If It were a TransientVector I could call nth on it but since it is a set I cannot

Timur Latypoff10:10:50

Do exposed Java methods work for inspection?

Ed10:10:54

https://github.com/clojure/clojure/blob/b8132f92f3c3862aa6cdd8a72e4e74802a63f673/src/jvm/clojure/lang/PersistentHashSet.java#L120 It looks like it extends ATransientSet, so you can call things like .count and .contains ...

Ed10:10:56

but I don't see an easy way to get an iterator without reflection ...

Ed10:10:15

I might well not be looking properly 😜

Ben Wiz10:10:52

Hacky solution

(into []
      (keep-indexed (fn [idx v]
                      (when (even? idx)
                        v)))
      (.-arr ^TransientArrayMap (.-transient_map ^TransientHashSet s)))

1
hiredman15:10:12

No reason you can't persist, inspect, then turn it back into a transient

👍 2
hiredman15:10:11

assuming your inspection is somewhere in the middle of a pipeline or something

Gabriel16:10:35

Hi! Is it intended that sorted-map-by freaks out if the comparator is weird? I'd expect the output to be unstable, but not for it to be downright missing data from the input.

user=> (defn kinda> [a b] (> (max a 2) (max b 2)))
#'user/kinda>
user=> (sorted-map-by kinda> 1 "a", 2 "b", 3 "c")
{3 "c", 1 "b"}

Gabriel16:10:00

ah! thank you 🙂

hiredman16:10:32

that isn't even a comparator issue

hiredman16:10:23

it is a comparator issue, I just get confused about sorted-map-by, because the -by means something different from the by in sort-by

Nazral17:10:01

what is the complexity of count on a vector? O(n)? Or is there something like the length of the vector stored somewhere that allows O(1) ?

phronmophobic17:10:14

you can use counted? to determine if coll implements count in constant time

Nazral18:10:44

perfect thank you !

phronmophobic17:10:27

> (counted? [1 2 3])
true