cider

Jim Newton 2025-04-25T06:51:27.533539Z

I’d love to have some advice from someone in debugging a subtle problem. I have a macro which expands to a fairly ugly piece of code. The first time that code evaluates, i get an error, because it does indeed have a compilation error. But if I then re-evaluate the same code, I don’t get any such error.

Jim Newton 2025-04-25T06:52:13.441189Z

indeed it is not valid to use ^integer? as a type hint. However, if I re-evaluate the same piece of code, the error is not shown a second time.

Jim Newton 2025-04-25T06:53:40.153949Z

Here is the complete macro expansion. rte-case/clauses-to-dfa is a normal function, not a macro.

(def f
  (let [dfa__51157__auto__ (rte-case/clauses-to-dfa
                            '([0
                               (:cat
                                (rte
                                 (:cat
                                  (and :sigma :sigma)
                                  (and :sigma :sigma)))
                                (and :sigma :sigma)
                                (and :sigma :sigma))]
                              [1
                               (:cat
                                (and :sigma :sigma)
                                (rte
                                 (:cat
                                  (and :sigma :sigma)
                                  (and :sigma :sigma)))
                                (and :sigma :sigma))]
                              [2
                               (:cat
                                (and :sigma :sigma)
                                (and :sigma :sigma)
                                (rte
                                 (:cat
                                  (and Ratio :sigma)
                                  (and :sigma :sigma))))]))]
    (fn [& seq__51158__auto__]
      (let [fns__51159__auto__ [(fn conv-1 [[^integer? a ^integer? b] c d] 12)
                                (fn conv-1 [a [b c] ^integer? d] 13)
                                (fn conv-1 [a b [^Ratio c d]] 14)]
            ind__51160__auto__ (rte/match
                                dfa__51157__auto__
                                seq__51158__auto__
                                :promise-disjoint
                                true)]
        (if ind__51160__auto__
          (apply
           (fns__51159__auto__ ind__51160__auto__)
           seq__51158__auto__)
          (throw
           (ex-info
            "No pattern matching given list"
            {:sequence seq__51158__auto__})))))))

Jim Newton 2025-04-25T06:55:04.876619Z

uhhhh. now it gives an error every time. something really bizarre is happening.

Jim Newton 2025-04-25T06:56:34.619589Z

OK, i’ll keep trying to reproduce the issue. but it’s really strange.

Jim Newton 2025-04-25T07:37:03.588439Z

@alexyakushev, yes I already understand why the error occurs. The thing I don’t understand is why the same situation fails to trigger an error other times. I know how to fix the error when it gets reported. However, if the error fails to be reported, the user of my library will not realize that there is an error.

oyakushev 2025-04-25T08:02:05.067549Z

This is related https://clojurians.slack.com/archives/C03S1KBA2/p1745523078201339

Jim Newton 2025-04-25T08:08:12.415989Z

That’s a bit strange (long (foo 1)) is that really a type hint or a type conversion?

oyakushev 2025-04-25T08:08:31.225869Z

Conversion

Jim Newton 2025-04-25T08:08:46.824469Z

indeed, not a type hint at all.

Jim Newton 2025-04-25T08:11:32.196859Z

however, the decompiled code is a bit surprising to me. I was under the (apparently false) impression that the type hint instructed the java compiler to create a seperate code path for the case that the argument is of type Long, which would theoretically allow the JVM to do optimizations specific to that type, but there would always be a default code path in case the run-time object is not of type Long

Jim Newton 2025-04-25T06:59:04.079939Z

I discovered something weird about type-hints. A form like the following refuses (justly so) to compile. because integer? is not a valid class name

(fn [a ^integer? b [c d]] nil)
however, the following compiles fine
(fn [a b [^integer? c d]] nil)
is that expected?

Jim Newton 2025-04-25T08:27:32.845199Z

(fn [a ^integer? b [c d]] nil) macroexpands to (fn* ([a ^integer? b p__59939] (let [[c d] p__59939] nil))) but (fn [a [^integer? c d]] nil) macroexpands to (fn* ([a p__59942] (let [[^integer? c d] p__59942] nil))) which further macroexpands to

(fn* ([a p__59942] (let*
                       [vec__59945
                        p__59942
                        ^integer? c
                        (nth vec__59945 0 nil)
                        d
                        (nth vec__59945 1 nil)]
                       nil)))
Looks to me like the ^integer? gets left in the declarations vector of the let* and has no effect on the result.

dpsutton 2025-04-25T12:33:29.271049Z

Ask this in #clojure as this is language level. I’m sure you will get some help there

rolt 2025-04-25T14:21:35.887099Z

Type hints that are not used by the compiler are just ignored. I'm not sure why it's used in your first case, maybe to determine if the function can used primitive argument ?