Fork me on GitHub
#clojure
<
2018-12-16
>
andy.fingerhut00:12:24

I am not aware of anything in the Clojure/Java compiler uses metadata on the function object for, but neither do I have exhaustive knowledge there. Yes, when you use defn to define a function and put metadata after 'defn' and before the symbol naming the function, the metadata goes on the Var created, not on the function object created.

lilactown00:12:01

yeah. the original reason I asked, was because I was trying to compare it to CLJS

lilactown00:12:16

in CLJS, we can’t access metadata on the var at runtime

lilactown00:12:10

like you said, I wonder if further attention will be given to these corner cases now. I’ve seen Rich talking quite a bit in #rebl about how to handle serializing functions to go between REBL and e.g. a CLJS or remote CLJ app

andy.fingerhut00:12:46

People like Rich, David Nolen and Mike Fikes know way more about the detailed differences between Clojure/Java and ClojureScript than I do, and the reasons for them, but my limited understanding is that some of them go pretty deep into the nature of the ClojureScript compiler and the target.

andy.fingerhut00:12:38

The #cljs-dev and #rebl channels are probably more target-rich environments for answering such questions.

lilactown00:12:59

yep I’ve been yakking away in #cljs-dev too 🙂

lilactown00:12:57

just wanted to gather info on how metadata was handled in general before I started making noises about how it could behave in CLJS

andy.fingerhut00:12:41

I would be surprised if there are any significant differences in the handling of metadata on immutable Clojure collections between CLJ and CLJS -- the answers are probably pretty clear there. On vars and function objects, I dunno so much there.

didibus00:12:44

I guess its not obvious to me why AFunction even implements IObj. But, since it also implements Comparator and Serializable, my guess is that it has to be related with the idea that functions can be serialized and sent over a wire, and thus compared for equality and thus also have meta.

didibus00:12:32

I think in CLJS, Vars only exists at compile time, they are full on Clojure Vars, but get compiled into JS variables. Which gets rid of the metadata, since JS vars don't have meta.

andy.fingerhut00:12:24

serializing two functions with identical textual definitions over a wire, and expecting them to be = on the other end after being created independently in memory on the other side, either requires remembering/caching the source text and comparing those to each other, or solving the halting problem. The first is way more likely to happen in practice, but I don't know what plans people might have in mind there for REBL.

andy.fingerhut00:12:53

Even comparing the textual definitions of two functions and seeing they are the same doesn't really mean they are necessarily equal, if one has direct linking call to a second function that was redefined between the deserializing of the two identical source texts. i.e. (defn foo [x] (my-fn x)) deserialized at two different times, with a redefinition of my-fn in between them, should those be = or no?

andy.fingerhut00:12:32

(I am thinking in terms of a Clojure/Java interactive session here -- I don't know whether any of that applies in the CLJS world, since I haven't used it enough to be familiar with the operational environments possible)

didibus00:12:36

Well, there is a field called methodImplCache lol, now I'm just speculating, but whats that for?

andy.fingerhut00:12:09

From a quick scan of the relevant Clojure/Java source mentioning it, it looks related to the implementation of protocols

andy.fingerhut00:12:27

i.e. speeding up protocol calls in the common case.

didibus00:12:31

I have to admit, I wish Rich Hickey had a little bit more comments in his code 😋 Hard to figure out the intent of RestFn, AFunction, etc.

didibus00:12:34

I guess RestFn is just the concrete implementation for all nornal Fns, why is it called Rest, I can't find another Fn concrete class, kinda confusing

andy.fingerhut00:12:52

That seems unlikely to happen, unless someone besides Rich Hickey writes such comments and publishes them separately. Someone years back did start work on a 'literate code' document for Clojure source code -- I don't know how far they got, or how accurate their comments might have been. Given current state of affairs, folks who have dug into implementation like Alex Miller, Nicola Mometto (bronsa here), and several others are the best options for learning such things.

didibus00:12:37

Haha ya, I'm still hoping someone will drop a book eventually specifically about the Clojure/ClojureScript implementation.

andy.fingerhut00:12:14

Other possible sources of info, although perhaps more time consuming, would be some of the Clojure/conj talks over the years that focus in internal implementation details (check ClojureTV YouTube channel), and doing searches on such names in the Google Clojure group message archive.

didibus00:12:46

So, FnLoaderThunk implementation of withMeta ignores the argument

didibus00:12:55

public IObj withMeta(IPersistentMap meta){
	return this;
}

didibus00:12:57

The only thing that I see adding the passed in meta is a call to AFunction withMeta, whoch returns a new RestFn with the meta attached. But I think only PersistentList makes use of this.

didibus00:12:19

But, I'm clearly wrong, since anonymous fn definitly support adding meta and return it

didibus00:12:04

The interesting bit is that with-meta returns an AFunction, whereas an fn call returns the type of the fn class

Alex Miller (Clojure team)00:12:48

You should not consider = to be a useful operation on functions

didibus00:12:43

@alexmiller Any reason why functions implement IObj? Is there any particular use of meta on functions?

Alex Miller (Clojure team)00:12:12

I believe it is sometimes used in the compiler to hold type tags

didibus00:12:11

Right, so very limiter use for the compiler itself. I think its fair to say as a user, you should threat fns like they don't support meta.

Alex Miller (Clojure team)00:12:57

Generally you should put them on vars or symbols

Daouda05:12:55

hey folks, can i consider this (doall (map @profiles connections-ids)) under side effect of @profiles?

andy.fingerhut05:12:52

I am not sure I understand your question. @profiles is the same as (deref profiles), and I am guessing from the context that profiles is an atom that you use to point to a function you want to call via map?

👍 8
andy.fingerhut05:12:23

The expression @profiles does not cause any side effects by itself, only dereferences the atom profiles

andy.fingerhut05:12:34

(or whatever stateful thing profiles happens to be, if not an atom)

andy.fingerhut05:12:42

That deref operation will happen only 1 time while executing that expression, not once for each element of the sequence connection-ids

✔️ 4
jaide06:12:18

Does profiles deref to a function, {map}, :keyword, or #{set}?

Daouda06:12:31

(def profiles
  "Profiles runtime database"
  (atom (hash-map)))

Daouda06:12:07

i use it like a my profile repository

Daouda06:12:48

profiles i meant

andy.fingerhut06:12:54

So with the comments I gave above, do you still have a question about 'side effects'? I don't see any side effects possible if profiles is an atom that points at a hash map.

Daouda06:12:31

@andy.fingerhut no, you've been very clear

Daouda06:12:41

thank you very much

andy.fingerhut06:12:54

sure, no problem.

jaide06:12:08

Also, entirely up to you but (atom (hash-map)) could become (atom {})

✔️ 4
Daouda06:12:28

you right @jayzawrotny, i just noticed that with your observation (= (hash-map) {})

jaide06:12:04

(every? #(apply = %) [[(hash-map :a 1)  {:a 1}]
                      [(hash-set :a :b) #{:a :b}]
                      [(list :a :b)     '(:a :b)]
                      [(vector :a :b)   [:a :b]]])

👍 4
jaide06:12:42

Of course, wanted to reinforce the relationship between constructor functions and literal syntax.

Daouda06:12:03

@jayzawrotny that was nice from you, every piece of information is important for me right now

metal 4
Daouda07:12:32

hey folks, i am refactoring a code here i went from this:

Daouda07:12:42

(defn get-profile-connection-suggestion!
  "Take an id and return a list of the connections suggestion"
  [id]
  (info "Calling get-profile-connection-suggestion! Suggestion list generation for ID: ", id)
  (let [profile (get-profile! id)
        connections-ids (get-profile-connections-ids profile)
        ids-connection-of-connection (mapcat get-profile-connections-ids (map @profiles connections-ids))
        all-possible-suggestions (map @profiles ids-connection-of-connection)
        public-possible-suggestions (map :id (filter :visibility all-possible-suggestions))
        final-suggestions-list (frequencies (remove (set (conj connections-ids id)) public-possible-suggestions))]
    (doall (map (fn [[id count]]
                  (get-profile! id))
                (sort-by val > final-suggestions-list)))))

Daouda07:12:12

(->> prof
    :connections
    (map @toy-data)
    (mapcat get-profile-connections-ids)
    (map @toy-data)
    (filter :visibility)
    (map :id)
    (remove (set (conj (:connections prof) 2)))
    (frequencies)
    (sort-by val >)
    (map (fn [[id count]]
                  (get @toy-data id))))

Daouda07:12:16

can you see if i am doing something wrong, or something i could improve in the code?

Daouda07:12:41

prof = profile and @toy-data = all profiles

tomjack07:12:28

(let [toy-data @toy-data] ...)

👍 4
Daouda07:12:27

that helped @U0Q8JHZAM, thanks 🙂

tomjack07:12:03

it doesn't really matter if you know the thing is not changing, it's just dogma 🙂

Daouda07:12:04

what is dharma ?

tomjack07:12:58

def 2 🙂

tomjack07:12:57

> Programs are easier to understand/test when functional value calculation is independent of identity/value association.

tomjack07:12:45

(here, I never need to think about what happens if toy-data atom is swapped while your code is running, if you only deref once)

Daouda07:12:41

hahaaaaaaaaaannnnn now i got the point hehehehehehehe

Daouda07:12:48

it took me long but i got it

Daouda07:12:53

hehehehehehehee

Daouda07:12:16

thank you very much:pray:

jaide07:12:13

Generally nothing sticks out to me, I do think some of those can be grouped together into more specific functions though. As a practice, that can make the intention of the code more clear and help focus on the domain instead of the implementation.

👍 4
Daouda07:12:39

i got it @jayzawrotny, i am always trying to do that

Daouda07:12:40

another question

Daouda07:12:59

(defn get-profiles!
  "Return all profiles"
  []
  (info "Calling get-profiles! to get all profiles")
  (-> profiles deref vals))

Daouda07:12:39

is it correct to mark this function has having side effect?

andy.fingerhut08:12:57

I believe no. I am having difficulty thinking of any use of deref that would cause a change in state of the system. I am guessing someone more awake than I am could come up with an example of that, but not if profiles is an atom pointing at an immutable value.

Daouda08:12:48

but profiles can change in case a new profile is added

Daouda08:12:02

so get-profiles! result can be different according to when it will be called

jaide08:12:45

So does (rand), I think the ! is more often to denote writes

jaide08:12:15

Like reset!, swap!, set!, and compare-and-set!

Daouda08:12:42

what about get a value that my changed?

jaide08:12:05

(rand) will return a new value each call

Daouda08:12:10

let's say a person, can change is name, of something else

jaide08:12:19

Same with (time)

Daouda08:12:39

hummmmmmmmm

Daouda08:12:49

really tricky for me

Daouda08:12:55

i get lost all the time

Daouda08:12:57

hehehehehehe

jaide08:12:45

All good, it was a pattern I didn’t understand until recently myself.

jaide08:12:54

Another note is that something like swap! returns the value it was passed in, the ! helps show that it does more than what we get from the return value.

🙏 4
Daouda08:12:37

understood 🙂

mitchelkuijpers14:12:36

I have been fighting with a macro for the last hour, I am trying to generate a interface with the help of gen-interface for a list of domain objects. Because I have some constraints I have to have a class file so that some bytecode scanner can inspect the generated interfaces and can find any annotations on them. But I cannot get for the life of me annotations to work within a macro which generates a list of interfaces:

(defmacro generate-interfaces []
  (let [db-types (get-types)]
    (into (for [{:type/keys [PascalCaseName] :as db-type} db-types]
            (let [iname (with-meta (symbol (str interface-ns (name PascalCaseName)))
                                   {Deprecated true})
                  imethods (mapv (fn [{:field/keys [PascalCaseName type]}]
                                   [(with-meta (symbol (str "get" (name PascalCaseName)))
                                               {Deprecated true
                                                Retention RetentionPolicy/RUNTIME})
                                    []
                                    (cond
                                      (:type/enum type) (symbol "String")
                                      (= (:type/nature type) :primitive) (symbol (str
                                                                                  "java.lang."
                                                                                  (name (:type/PascalCaseName type))))
                                      :default (symbol (str
                                                        interface-ns
                                                        (name (:type/PascalCaseName type)))))])
                                 (:field/_parent db-type))]
              (println iname)
              (println (meta iname))
              `(gen-interface
                :name ~iname
                :methods ~imethods)
              ))
          `(do))))
Note I am just playing around with the Deprecated macro for easy testing, anyone have any hints? And I have it working without my own macro btw like this:
(gen-interface
 :name
 "nl.avisi.atlascrm.domain.Foo"
 :methods
 [[^{java.lang.Deprecated true}
    getId
   []
   java.lang.Id]
  [^{java.lang.Deprecated true}
  getLabel
   []
   java.lang.String]
  [^{java.lang.Deprecated true}
  getOrder
   []
   java.lang.Float]])

mitchelkuijpers14:12:19

This is one the generated class files:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package nl.avisi.atlascrm.domain;

public interface Foo {
    String getType();

    Section getSections();
}

mitchelkuijpers14:12:31

No annotations 😞

mitchelkuijpers14:12:56

And the little test example without my macro around it generates:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package nl.avisi.atlascrm.domain;

public interface Foo {
    @Deprecated(true)
    Id getId();

    @Deprecated(true)
    String getLabel();

    @Deprecated(true)
    Float getOrder();
}

thegeez16:12:48

@U060GQK8U perhaps have the (with-meta ..) call in the output code of the macro instead of already on the symbol in the output of the macro:

thegeez16:12:57

(defmacro generate-interfaces []
  (let [db-types ["Foo" "Bar"]
        interface-ns "ns-prefix"]
    (into []
          (for [type-name db-types]
            (let [iname# `(with-meta (symbol ~(str interface-ns "/" type-name))
                           {Deprecated true})]
              (println iname#)
              (println (meta iname#))
              `(assoc {}
                      :meta (meta ~iname#)
                      :name ~iname#)
              )))))

  ;; (let [res (generate-interfaces)]
  ;;   (mapv (comp meta :name) res)) => [{java.lang.Deprecated true} {java.lang.Deprecated true}]

mitchelkuijpers16:12:48

@U06D9RGQM That is good idea let me try that

mitchelkuijpers16:12:08

Doesn't seem to work, I now even tried a simpler version:

(defmacro very-simple-test []
  `(definterface
    ~(with-meta (symbol "Foo") {Retention RetentionPolicy/RUNTIME})))

(definterface ^{Retention RetentionPolicy/RUNTIME} Foo2)

(very-simple-test)
When I compile this Foo2 has the annotation and Foo doesn't

Alex Miller (Clojure team)16:12:28

Off the top of my head, no idea

Alex Miller (Clojure team)16:12:41

File a jira if you don’t figure it out

mitchelkuijpers16:12:03

I will thank you

thegeez17:12:14

I think the problem is symbols from macros lose their metadata, the definterface is downstream from that

Dustin Getz15:12:59

Why does (seq nil) return nil but (str nil) return ""

Dustin Getz15:12:43

Probably to prevent NPEs in platform code?

jjttjj16:12:51

not sure if this is a reason, but string has variable arity, so what should (str "a" "b" nil "c") return

Dustin Getz16:12:47

nil pun it to ""

Dustin Getz16:12:06

(assoc nil :a 1) works fine

Alex Miller (Clojure team)16:12:41

There’s no correlation or relationship between seq and str

Alex Miller (Clojure team)16:12:58

Seq returns either a seq view with at least one element or nil

Dustin Getz16:12:13

yes i know but design wise i thought it is interesting thought that str does not nil pun

Alex Miller (Clojure team)16:12:14

str is string concatenation and always returns a string

Alex Miller (Clojure team)16:12:53

Nil punning is a collection thing. Strings are values, not collections.

andy.fingerhut16:12:23

In this case, the doc string for str explicitly says what it does for nil, and that it concatenates.

Alex Miller (Clojure team)16:12:28

They can produce a sequence view, but they’re not collections

Dustin Getz16:12:53

We write this a lot (if (blank->nil label) (a LOT)

valtteri20:12:31

I’ve found not-empty handy. It returns nil for empty string.

Alex Miller (Clojure team)16:12:57

Some apps may want to treat blank strings as nil, but that’s an app thing, not a Clojure thing

Alex Miller (Clojure team)16:12:36

clojure.string/blank? exists to blur that line too

Dustin Getz16:12:38

I see, so there isn't a touch point to do the nil punning, like there is for collections (seq)

andy.fingerhut16:12:44

By 'touch point' do you mean 'a function that can be overridden, or a configuration knob that can be changed, to modify the language's behavior'? Sorry if that phrase has a standard meaning I'm not aware of.

Alex Miller (Clojure team)16:12:15

I don’t think they have any relation

Alex Miller (Clojure team)16:12:31

Nil pinning is primarily about seqs, it’s not a general thing

Dustin Getz16:12:35

No, i mean that when you work with collections, there is a thing you always want to do which is iterate them, and seq kind of means "turn this thing into an interator"

andy.fingerhut16:12:58

It is true that many many Clojure functions call seq, which does give them a common behavior in this regard.

Dustin Getz16:12:01

When working with strings, the string just is a simple value and its done, there is no further common operation where clojure.core could do the nil pun

Dustin Getz16:12:26

seq is very much by design, clojure.core data operations fit together brilliantly around it

Alex Miller (Clojure team)16:12:59

Related is that collections are polymorphic on nil, but I’m not sure lispers would consider that to be the same thing as nil punning

Dustin Getz16:12:18

"polymorphic on nil" not sure what you mean

Alex Miller (Clojure team)16:12:40

You can invoke collection functions on nil

Dustin Getz16:12:44

(assoc nil :a 10)

Dustin Getz16:12:19

Right, they lift nil to the empty value of "the thing you want it to be"

Alex Miller (Clojure team)16:12:11

I would say all of the collection ops are polymorphic - they have different behavior based on type, and nil is one of those cases

Alex Miller (Clojure team)16:12:26

So I don’t see that as special, just another case

Alex Miller (Clojure team)16:12:49

Nil punning traditionally I believe refers to treating empty lists and nils the same

Dustin Getz16:12:03

static public Associative assoc(Object coll, Object key, Object val){
	if(coll == null)
		return new PersistentArrayMap(new Object[]{key, val});
	return ((Associative) coll).assoc(key, val);
}
Is there a better example than assoc to demonstrate this? Conj i guess

Alex Miller (Clojure team)16:12:16

All of this is imo unrelated to strings at all

WhoNeedszZz16:12:27

"It is called punning because you can use it to mean different things in different contexts. In Clojure, nil, as a value, is nearly void of meaning." (pulled from an article)

Alex Miller (Clojure team)16:12:48

I don’t agree with a lot of stuff in that article

Dustin Getz16:12:15

It seems to me that nil means empty in many cases, string being the exception, but i have not seen this idea from alex or rich

WhoNeedszZz16:12:23

To be fair I didn't read all of the way down

Alex Miller (Clojure team)16:12:32

Yeah, wouldn’t agree with that

Alex Miller (Clojure team)16:12:11

nil is a case that is given utility in different polymorphic operations

WhoNeedszZz16:12:30

Well we have Alex here, so what is the canonical meaning of nil?

Alex Miller (Clojure team)16:12:53

I view it as I said above

Alex Miller (Clojure team)16:12:12

Don’t try to assign it some special global meaning

Alex Miller (Clojure team)16:12:30

The approach is entirely pragmatic

WhoNeedszZz16:12:40

So then what the article was saying was in the right direction at least - that it depends on the context

Dustin Getz16:12:11

"The places where Clojure does not do this [nil as mzero] seem to be the places where Clojure inherits the platform behavior for pragmatism and speed" is this accurate ?

Alex Miller (Clojure team)16:12:43

I think it’s missing the point

Alex Miller (Clojure team)16:12:45

Which is that by assigning a useful meaning to nil in polymorphic ops, we can write simpler more obvious code with fewer conditionals

Alex Miller (Clojure team)16:12:55

I can examine a piece of code, analyze where nils may occur, and make my code do what I want, usually without any nil checks

mitchelkuijpers16:12:08
replied to a thread:I have been fighting with a macro for the last hour, I am trying to generate a interface with the help of `gen-interface` for a list of domain objects. Because I have some constraints I have to have a class file so that some bytecode scanner can inspect the generated interfaces and can find any annotations on them. But I cannot get for the life of me annotations to work within a macro which generates a list of interfaces: (defmacro generate-interfaces [] (let [db-types (get-types)] (into (for [{:type/keys [PascalCaseName] :as db-type} db-types] (let [iname (with-meta (symbol (str interface-ns (name PascalCaseName))) {Deprecated true}) imethods (mapv (fn [{:field/keys [PascalCaseName type]}] [(with-meta (symbol (str "get" (name PascalCaseName))) {Deprecated true Retention RetentionPolicy/RUNTIME}) [] (cond (:type/enum type) (symbol "String") (= (:type/nature type) :primitive) (symbol (str "java.lang." (name (:type/PascalCaseName type)))) :default (symbol (str interface-ns (name (:type/PascalCaseName type)))))]) (:field/_parent db-type))] (println iname) (println (meta iname)) `(gen-interface :name ~iname :methods ~imethods) )) `(do)))) Note I am just playing around with the Deprecated macro for easy testing, anyone have any hints? And I have it working without my own macro btw like this: (gen-interface :name "nl.avisi.atlascrm.domain.Foo" :methods [[^{java.lang.Deprecated true} getId [] java.lang.Id] [^{java.lang.Deprecated true} getLabel [] java.lang.String] [^{java.lang.Deprecated true} getOrder [] java.lang.Float]])

Doesn't seem to work, I now even tried a simpler version:

(defmacro very-simple-test []
  `(definterface
    ~(with-meta (symbol "Foo") {Retention RetentionPolicy/RUNTIME})))

(definterface ^{Retention RetentionPolicy/RUNTIME} Foo2)

(very-simple-test)
When I compile this Foo2 has the annotation and Foo doesn't

Dustin Getz16:12:13

(+ 1 (bigint 1)) is polymorphic but (+ 1 nil) is NPE (why not ground nil to zero?)

Dustin Getz16:12:36

Platform efficiency is a reason

WhoNeedszZz16:12:49

@alexmiller Can you expand a bit on that last bit?

Alex Miller (Clojure team)16:12:13

There are different “domains” and different choices made

Dustin Getz16:12:16

same with (if (blank->nil label)); (if "") is true

Alex Miller (Clojure team)16:12:24

I’m talking about collections primarily

Alex Miller (Clojure team)16:12:47

Math is it’s own domain with its own set of choices

Dustin Getz16:12:49

Yeah, I recognize I am trying to unify something that Rich probably specifically chose not to unify

Alex Miller (Clojure team)16:12:24

Java interop is another, where npes are most commonly seen

Dustin Getz16:12:47

yea java interop is imperative, nothing really to be done to avoide npe in imperative code

Dustin Getz16:12:12

have to just be careful

Alex Miller (Clojure team)16:12:41

I apply a different level of code reading with interop, and make more use of things like some->

Dustin Getz16:12:32

I think the beauty of nil punning is that if you constrain yourself to the little Clojure data processing world of clojure.core on clojure data structures, NPEs simply never happen. When people talk about needing Maybe types on boundaries, they are often talking about interop and not data processing biz logic, a misunderstanding that causes lots of conflict

Alex Miller (Clojure team)16:12:29

Yeah. I marvel at being able to write a chunk of code, look at it, and know it’s safe from npes, but also handles all the edge cases

Dustin Getz16:12:21

Thanks for digging in with me Alex, I am going to clean this up and post it on r/clojure

Alex Miller (Clojure team)16:12:22

I can even give you an example...

Alex Miller (Clojure team)17:12:03

Is a gnarly of bit of code handling a wide variety of optional and missing data

Alex Miller (Clojure team)17:12:27

And it employs lots of Clojure tricks to make it both safe and concise

Alex Miller (Clojure team)17:12:35

Destructuring, cond->, polymorphic nils, etc

jaide17:12:22

What’s the process for creating a clojure lib README? Is there a recommended template somewhere?

andy.fingerhut17:12:54

I don't think there is a template that they all use. The 'contrib' libraries that are part of http://github.com/clojure/&lt;libname&gt; mostly use a common template that you could look at, but maybe not all of it would be relevant for your case.

👌 4
jaide18:12:37

What about an example of a .travis.yml that uses clojure.tools.deps and the clj cli?

andy.fingerhut19:12:08

Sorry, I do not have any examples of that handy.

jaide21:12:04

That’s ok, I couldn’t find any in the wild either. Ended up adding a project.clj using the standard lein test route.

ztellman18:12:51

if you're using Aleph in production, we'd like to hear about it: https://github.com/ztellman/aleph/issues/450

koala punch21:12:05

hi, anyone else having problems with latest compojure-api lein template?

koala punch21:12:18

says no :main namespace specified when i do lein new compojure-api

cfleming21:12:20

I’m writing a deftype which implements an interface which contains overloaded methods. I have to type hint the params and return type of those methods, and I don’t know how to hint the method return to be a primitive int.

cfleming21:12:37

I’m getting: IllegalArgumentException: Mismatched return type: calcWidthInPixels, expected: int, had: java.lang.Object

cfleming21:12:59

The interface methods are default int calcWidthInPixels(@NotNull Inlay inlay) {...} and default int calcWidthInPixels(@NotNull Editor editor) {...}.

cfleming21:12:35

Currently I’m trying:

(deftype InlineRenderer [text]
  EditorCustomElementRenderer
  (calcWidthInPixels ^"I" [this ^Inlay inlay]
    ...))

cfleming21:12:40

But that’s not working.

hiredman21:12:26

have you tried ^int ?

cfleming21:12:28

Yes, with no luck.

hiredman21:12:29

I also don't end up having to do this much, but if I recall the last time I did, I think I type hinted the symbol of the method name, not the argument vector

hiredman21:12:27

(^int calcWidthInPixels [...] ...)

cfleming21:12:55

Oh, yes, that works - I would never have expected that.

cfleming21:12:19

TIL, also that ^void is a thing.

koala punch21:12:48

i fixed my thing, the docs were wrong

koala punch21:12:55

its lein ring server, not lein run

hiredman21:12:18

type hinting on the arg vector is kind of the newer (but many releases old way to do it), most places that support type hinting first did it on the name, but one new feature introduced doing it on the vector (I think invokePrim) and people started expecting it to match that, so hinting of the vector has sort of been slowly spiraling outwards from there

cfleming21:12:36

Yeah, but I thought the name was more in cases where the hint would end up on the var, i.e. def-like things. I’d assumed deftype had always used the arg vector hint, or at least that it would work in recent versions.

jaide21:12:35

Is it doable\reasonable to push to github -> travis ci tests -> publish to clojars?

ghadi22:12:52

@jayzawrotny that would involve putting your signing keys within the CI system

jaide22:12:16

Hah yeah that would be a terrible idea.

ghadi22:12:22

Clojure itself does that, but it's not a great practice

👍 4