Fork me on GitHub
#clojure
<
2023-08-24
>
Luis Cerritos00:08:28

Hi. Team. I have a situation with my code. I am doing the following: • The mainly NS is having the -main function which is executed as (-main) after the declaration • The situation is when creating the uberjar with a build.clj with the following code:

(defn uber [_]
      (clean nil)
      (b/copy-dir {:src-dirs ["resources"]
                   :target-dir class-dir})
      (b/compile-clj {:basis basis
                      :src-dirs ["src"]
                      :class-dir class-dir})
      (b/uber {:class-dir class-dir
               :uber-file uber-file
               :basis basis
               :main 'finicity-order-generator.core
               ;; required for building in macOS
               :exclude ["LICENSE"]})
      (println (format "Uberjar %s built at %s" uber-file (.format (LocalDateTime/now) formatter))))
It is running the -main function at the moment the clojure -T:build uber is executed. I don’t want to get it executed in that moment. Any idea if I can stop running the function when the uber is created.

dpsutton00:08:25

The build tooling won’t invoke any functions. Are you sure you don’t have any spots where you call it? Including in user.clj maybe?

Sam Ferrell00:08:47

Don't call (-main) in the file

Sam Ferrell00:08:43

It'll be invoked when you run the jar with something like java -cp foo.jar clojure.main -m foo.core

Luis Cerritos00:08:29

I am calling the (-main) in the file due part of the logic I am implementing an AWS Lambda and I need to run some context when the lambda starts.

dpsutton00:08:16

Well requiring that file will invoke that function. So it will run during building as well

Luis Cerritos00:08:50

Correct. Every time the file is required it will executed, correct?

Luis Cerritos00:08:05

What about if using AOT?

Luis Cerritos00:08:20

Do you think it could fix the issue?

dpsutton00:08:36

That compiles the namespace which will compile all top level forms. Including the call to main

Luis Cerritos00:08:56

Sorry… Without AOT.

seancorfield00:08:41

If you remove the call to compile-clj you will need to add "src" to the :src-dirs in your copy-dir call, but that should produce a source-based uberjar. You will also need to set :main to clojure.main (since it must be a compiled main class) and then you will need to pass -m finicity-order-generator.core to the JAR when you run it:

java -jar path/to/the.jar -m finicity-order-generator.core

mx200008:08:43

Is there some kind of gui/entity editor for clojure.spec?

tatut09:08:07

you mean like creating (s/def ::foo (s/keys :req [::bar ::baz])) forms in a visual editor? not text?

mx200009:08:48

Yes, I have asked this before in malli group. For example to create a combobox /textfield/etc depending on keys.

tatut09:08:11

oh, you mean like generating a gui form based on a spec?

tatut09:08:30

I’m not aware of any ready ones, but I haven’t looked. You can certainly make one as you can get the specs as data with s/describe but I think specs are missing lots of information you would need in a GUI

mx200009:08:09

I am working on it already, you saw my post in datomic group.

tatut09:08:14

like layout and order, proper human readable validation messages, so you would need something extra in any case

mx200009:08:04

Maybe it might be interesting for other people once I finish and open source it

tatut07:08:25

would it integrate with existing editors/IDEs?

tatut07:08:07

or rather some other ui toolkit to integrate it with existing apps

mx200009:08:35

I am using scene2d ui from libgdx because it's already included and integrated very nice with libgdx, also quite simple and powerful. Full access to graphics context and configurable. https://libgdx.com/wiki/graphics/2d/scene2d/scene2d-ui

tatut09:08:25

I don’t know if libgdx is used much outside of games

mx200009:08:53

Probably not at all.

Olav Fosse09:08:38

Hello I’m trying to call a method, but it throws an IllegalArgumentException. To me it seems like this method exists. Any pointers would be appreciated 🐛

;; Calling the `add` method on `layers` passing `layer` as an argument
;; throws an exception:

(.add layers layer)
;; => Execution error (IllegalArgumentException) at geotools-crs/eval66608 (REPL:34).
;;    No matching method add found taking 1 args for class org.geotools.map.MapContent$LayerList

;; So I list the methods called `add` on `layers`:

(->> (cr/reflect layers) :members (filter #(= (:name %) 'add)))
;; => ({:name add,
;;      :return-type void,
;;      :declaring-class org.geotools.map.MapContent$LayerList,
;;      :parameter-types [int org.geotools.map.Layer],
;;      :exception-types [],
;;      :flags #{:public}}
;;     {:name add,
;;      :return-type boolean,
;;      :declaring-class org.geotools.map.MapContent$LayerList,
;;      :parameter-types [org.geotools.map.Layer],
;;      :exception-types [],
;;      :flags #{:public}}
;;     {:name add,
;;      :return-type boolean,
;;      :declaring-class org.geotools.map.MapContent$LayerList,
;;      :parameter-types [java.lang.Object],
;;      :exception-types [],
;;      :flags #{:public :bridge :synthetic}}
;;     {:name add,
;;      :return-type void,
;;      :declaring-class org.geotools.map.MapContent$LayerList,
;;      :parameter-types [int java.lang.Object],
;;      :exception-types [],
;;      :flags #{:public :bridge :synthetic}})

;; Here we see one method taking a `org.geotools.map.Layer` as input,
;; this is the method I think I'm calling:

{:name add,                                             
 :return-type boolean,                                  
 :declaring-class org.geotools.map.MapContent$LayerList,
 :parameter-types [org.geotools.map.Layer],             
 :exception-types [],                                   
 :flags #{:public}}

;; Here I confirm that the argument i'm passing is of the expected
;; type:
(instance? org.geotools.map.Layer layer)
;; => true

;; So why does (.add layers layer) tell me there is no matching
;; method?
(.add layers layer)
;; => Execution error (IllegalArgumentException) at geotools-crs/eval66626 (REPL:87).
;;    No matching method add found taking 1 args for class org.geotools.map.MapContent$LayerList

oyakushev09:08:21

Just guessing here, maybe it is because there is another overload of add that takes an Object as an argument, and since Clojure compiler can't guess which one you want to invoke, it generates IAE during reflection?

oyakushev09:08:45

Try doing (.add layers ^org.geotools.map.Layer layer) and see if it's still the same

Olav Fosse09:08:10

I tried that, but I got the same result

(.add layers ^org.geotools.map.Layer layer)
;; => Execution error (IllegalArgumentException) at geotools-crs/eval66642 (REPL:91).
;;    No matching method add found taking 1 args for class org.geotools.map.MapContent$LayerList
adding a type hint to the first argument too worked though 🎉
(.add ^org.geotools.map.MapContent$LayerList layers ^org.geotools.map.Layer layer)
;; => true
Thanks a lot!

👍 2
furiel12:08:02

Hello, I have trouble extending a type with a protocol which has a function with multiple arities. Could help me figure out what I am missing? Interestingly, the 3-arity version works. I have only trouble with the 2-arity variant. proto.clj

(ns proto)

(defrecord Record [])

(defprotocol Protocol
  (func [this param1] [this param1 param2]))
app.clj
(ns app
  (:require [proto])
  (:import (proto Record)))

(extend-type Record
  proto/Protocol

  (func [this param1] (func this param1 :param2))
  (func [this param1 param2] [param1 param2]))

(comment
  (proto/func (proto/->Record) :a :b) ; works => [:a :b]
  (proto/func (proto/->Record) :a) ; Wrong number of args (2) passed to: app/eval9854/fn--9855
  ,,,)

igrishaev12:08:01

it must have been

(func [this param1] (proto/func this param1 :param2))

igrishaev12:08:48

when redirecting, you must specify not func but namespace/func since it comes not from the current namespace but from somewhere else

furiel12:08:35

Ah good point, I missed that. Unfortunately, it did not solve to problem. That is probably the next issue I would have faced if I could get the arities working. I got the same error. It turns out if I completely remove the implementation, that still does not work:

(extend-type Record
  proto/Protocol

  (func [this param1])
  (func [this param1 param2] [param1 param2]))

furiel12:08:43

So the execution does not get to the point to start executing the body.

furiel08:08:42

Bumping this in case someone has an idea what the problem is. I do not know how to debug this further.

2
furiel09:08:32

Aaah got it. The syntax is different. I managed to get it working by:

(extend-type Record
  proto/Protocol

  (func
    ([this param1] (proto/func this param1 :param2))
    ([this param1 param2] [param1 param2])))

Lucas Jordan18:08:15

I think maybe I found a bug in clojure (or at least a core libraries) (clojure.edn/read-string (str {(keyword "bad;keyword") 5})) this produces the exception EOF while reading I can’t decide if the blame lies with keyword or read-string. Since this seems work: (type (keyword "bad;keyword")) => clojure.lang.Keyword I would love some feedback before I start filling out forms. Anyone else think this is a bug?

Joshua Suskalo18:08:11

This is an example of clojure's "garbage in, garbage out" philosophy. Calling keyword on an unreadable keyword produces undefined behavior.

Joshua Suskalo18:08:29

In this case the result is a keyword which, once printed, cannot be read back in.

Lucas Jordan18:08:32

yeah, I agree with that

Lucas Jordan18:08:01

should a keyword be able to be created that is invalid edn?

Lucas Jordan18:08:11

or maye edn should be able to ‘escape’ it somehow?

Alex Miller (Clojure team)18:08:23

I think what would be desirable here is a way to print data guaranteed as valid edn

Alex Miller (Clojure team)18:08:40

and that is something that is on our radar as it comes up a lot

clojure-spin 6
💯 1
Lucas Jordan18:08:06

as a note, this also fails differently but sorta the same (clojure.edn/read-string (str {(keyword "badkeyword") 5}))`

Lucas Jordan18:08:18

@U064X3EF3 that makes sense to me

seancorfield19:08:35

There is quite a bit of code out in the wild that relies on being able to create "illegal" keywords (i.e., that aren't valid according to Clojure's description of what a keyword is and are therefore "unreadable"). There are also a few things that are not technically legal keywords but the reader does still accept them (e.g., :1) and, again, there's code out there in the wild that relies on that working.

Alex Miller (Clojure team)19:08:24

creating unreadable keyword objects is not a problem, but printing them is

2
Alex Miller (Clojure team)19:08:25

the even more general problem right now is that printing is an open global system when it would often be useful to create scoped modifications of printing in different contexts. if such a thing existed, you could create a set of printing rules for printing edn, or printing somewhere else and use them both at the same time in a clojure runtime. I think a separate concern is how you would want to be notified of something that cannot be printed - that starts to feel instead more like validation. this space is complex and deeply woven into lots of real code, but is a real common problem. I continue to lobby Rich to work on it. :)

❤️ 5
frozenlock19:08:27

About :1: IIRC, it wasn't working initially in clojurescript. It has been patched since then to have the same behavior as in clojure. Wouldn't it mean that it's a valid keyword?

Joshua Suskalo19:08:24

To me it sounds like it could be useful to have the ability to have a dynamic scope with-methods which includes local overrides to specific methods on a multimethod, similar to with-redefs but thread-local.

Alex Miller (Clojure team)20:08:23

That is one of many possible solution spaces

valerauko02:08:45

I recall having a (def ctx (keyword "@context")) when dealing with JSON-LD

jasonjckn05:08:26

Considering we're already supporting code that has invalid keywords for the indefinite future, we might consider relaxing the constraints of what symbols are allowed, which would be backwards compatible

jasonjckn05:08:45

Then maybe a compiler flag to warn, and/or assert in dev builds when you use illegal chars. Although i'm sure this topic has been talked about ad nauseam already .

jasonjckn05:08:51

I'm definitely guilty of not using the strictly valid keywords, even with full consciousness of it 😕 E.g. reading in weird JSON at system boundary, and keywordizing