Fork me on GitHub
#beginners
<
2022-08-16
>
lassemaatta06:08:11

any tips (or known issues) on how to resolve reflection warnings when you're calling overloaded static java methods?

lassemaatta06:08:35

for reference https://docs.geotools.org/stable/javadocs/org/geotools/geometry/jts/JTS.html#transform-org.locationtech.jts.geom.Geometry-org.opengis.referencing.operation.MathTransform- the javadoc of the function in question. note that there exists another overloaded variant of the transform function

lassemaatta06:08:21

even with type hints I still get call to static method transform on org.geotools.geometry.jts.JTS can't be resolved (argument types: org.opengis.geometry.Geometry, org.opengis.referencing.operation.MathTransform) .

delaguardo07:08:06

how do you call it? maybe type hints is in the wrong position

lassemaatta07:08:42

I suspected that as well, which is why I separated the invocation to a separate function, pretty much just (defn- do-transform ^Geometry [^Geometry geom ^MathTransform transform] (JTS/transform geom transform)) . Also, I would assume that the types reported by the warning would be unknown if the type hints were misplaced.

lassemaatta07:08:42

I also checked whether the argument classes in the overloaded methods had the same base class or something like that (not sure if that's even valid in java), but it seems that's not the case

delaguardo09:08:23

hm… Geometry is an interface. Not sure if it is ok to use as a typehint.

lassemaatta09:08:16

the clojure https://clojure.org/reference/java_interop#typehints show an example of (^java.util.List [a & args]), which is an interface

delaguardo09:08:40

yeah, true. then scratch my assumption )

delaguardo09:08:37

it turns out that probably Geometry is something different

org.geotools.geometry.jts.JTS/transform
 [org.locationtech.jts.geom.Geometry org.opengis.referencing.operation.MathTransform]
 [org.locationtech.jts.geom.Envelope org.locationtech.jts.geom.Envelope org.opengis.referencing.operation.MathTransform int]
 [org.locationtech.jts.geom.Envelope org.opengis.referencing.operation.MathTransform]
 [org.locationtech.jts.geom.Coordinate org.locationtech.jts.geom.Coordinate org.opengis.referencing.operation.MathTransform]
Not documented.

For additional documentation, see the Javadoc.

Definition location unavailable.
I thought it is defined in the same package but looks like it is not

delaguardo09:08:16

adding (org.locationtech.jts.geom Geometry) into imports removes reflection warning

lassemaatta09:08:00

ah, there's multiple Geometry classes, great harold

lassemaatta09:08:25

thanks a lot for figuring this out 👍

rolt09:08:34

using clojure.reflect/reflect is a great tool for stuff like this

Yehonathan Sharvit08:08:48

Someone asked me during a workshop a beginner question that I couldn’t answer. What is the meaning of the convention for function names that start with a dash e.g. -main?

lassemaatta08:08:27

this was actually just discussed on #clojure, see https://clojurians.slack.com/archives/C03S1KBA2/p1660303106364409

💯 2
Alex Miller (Clojure team)11:08:26

It's actually more than that, for -main in particular. When using gen-class, there is an option to set a prefix for the methods that should be static in the generated class, and the default prefix is “-“. So if you make a namespace that you want to be compiled to a callable main, it has to be called -main (or you can set the gen-class option for static prefixes and use that, but almost no one ever does). See https://clojure.org/reference/compilation or the gen-class docstring.

👍 1
1
Yehonathan Sharvit11:08:25

Why would we ever want a function in a namespace not to be compiled to as static method?

Alex Miller (Clojure team)11:08:47

If you're extending an interface or concrete class

Yehonathan Sharvit11:08:17

Yes. But when I use defn, shouldn’t it always be compiled into a static method?

Alex Miller (Clojure team)12:08:57

Yes, but gen-class can also make non-static methods to extend classes or implement interfaces, see the docstring or look at examples on clojuredocs

didibus17:08:30

Gen class generates a single Java class with multiple methods in it. Every function in your namespace starting with - implement a method on it

didibus17:08:46

I'm not sure what Alex meant about the static, but gen-class can create static methods, normal methods, and constructor methods, and for all of those the implementating function in the namespace is looked up using the - prefix. The prefix doesn't indicate that the method has to be static, it indicates which functions should be used as the implementation for which methods of the gen-class irregardless if it's a constructor method, a normal method or a static method.

Yehonathan Sharvit18:08:00

Thank your for the clarification @U0K064KQV

Daniel Amber09:08:45

Hey guys! I posted what I think is a cool tutorial for beginners: https://www.youtube.com/watch?v=0mrguRPgCzI&amp;t=1289s since it involves working with a db, environment variables, namespaces and creating a simple api 🙂

🙌 14
❤️ 3
dabrazhe09:08:42

Is there a way to ensure that the map's keys are in a particular order? I am printing a table with the pprint print-table function and the order is important for me.

rolt09:08:24

you can specify the keys as the first argument to print-table, so you can simply apply your sort there

1
Bart Kleijngeld10:08:04

@U02KYBC5WJY what a lovely coincidence, I just learned this through https://www.youtube.com/watch?v=x24fLxur-2o! Thanks for the good work

🙌 2
dabrazhe11:08:30

sorted-map won't work, it sorts the keys, which actually destroys the order

rolt11:08:17

can you specify the problem you're trying to solve ? maybe with an example ?

dabrazhe11:08:05

Specifying the keys vector in print-tabe works as expected. Thank you, @U02F0C62TC1

👍 1
Kamuela15:08:00

When using every-pred, what's a reasonable technique to negate the result of one of the predicate functions? E.g. I want the opposite of something that returns false. I was thinking of an inline anonymous function that wrapped the resulting value of (not predicate?) but that seems unidiomatic/inelegant

delaguardo15:08:25

there is clojure.core/complement

Chase23:08:24

Any of you regex guru's mind helping me out? I'm looking for a regex that matches on [:{div}. and keep's matching on every . after that too. {div} can be replaced with any html element but I imagine we can just match on a word followed by a .. But I'm not sure if I then need a separate regex to continue that ability as I keep adding css classes

Chase23:08:29

I'm getting autocompletion/docs set up for tailwind when writing in the reagent/hiccup style. My particular solution will only work on nvim w/ coc.nvim but if you are ever looking to do the same for whatever editor/lsp setup you have you can probably start here: https://github.com/tailwindlabs/tailwindcss/discussions/7554 and here: https://github.com/tailwindlabs/tailwindcss-intellisense/issues/400#issuecomment-916973975 to get it sorted out. More specific Clojurescript topic and the difficulty in getting the right regex to make this work: https://github.com/tailwindlabs/tailwindcss/issues/7553#issuecomment-984202139

Chase23:08:20

So if I get the regexes setup correctly (if it even requires two) I would be getting autocompletion after [:div.| and after [:div.text-3xl.font-extrabold.| etc.

Chase00:08:50

I was trying something like this: ":w+\\.(\\w*)" but it's not quite working.

chucklehead01:08:02

maybe something like this if I understand you correctly #"^:([\w\-:]+\.)+"

chucklehead01:08:53

roughly: starts with a :, followed by one or more sequences of alphanumeric characters (that might contain - or : ), terminated by a .

chucklehead01:08:44

may need to remove the ^ depending on how exactly the matching works

Chase02:08:35

Hmmm, doesn't seem to be working. I think I'm not explaining it correctly though. Here is what it looks like to get the autocompletion for the [:div {:class "|" }] style. where | is my cursor and where the autocompletion begins:

"tailwindCSS.experimental.classRegex": [
  ":class\\s+\"([^\"]*)\""
]

Chase02:08:10

It's a json config file so in order to get your suggestion to work (I was getting an invalid escape character error) I changed it to: :([\\w\\-:]+\\.)+ but I'm not getting the matching.

Chase02:08:54

Someone in the #vim channel tried:

":\\w+([^\\s]*)",
 "\\.([^\\.]*)"
And what that gives me is autosuggestions starting at [| and no suggestions at [:div.|

skylize07:08:49

I have absolutely no resemblance to a "guru" on this topic, so I could be way off base. But I don't think you can actually accomplish what you want with Clojure's (or JavaScript's) implementation of regex, without wrapping it in additional control flow (which may nullify choosing regex at all). Given

"[:h1.text.font-extrabold.mt-6]"
You can use this pattern to capture the first class
;; note: (?:thing) is a non-capturing group to avoid capturing parts we don't care about, but need grouped. The non-capturing group is actually redundant here, but important to the next step.

#":[\w-]+(?:\.([\w-]+))"  ;; => ["h1.text" "text"]
In theory, we can use +, *, or ? on the "`.`"+classname group for optionality.
#":[\w-]+(?:\.([\w-]+))*"
This does match on the entire element-with-all-of-its-classnames. But unfortunately, each time we hit * and iterate the search, the prior group capture gets dropped in favor of the newly matched capture. So ultimately you are left with only the final classname in a capture group. And you also get the annoying side effect of finding a match with a captured nil when there are no classnames.
(def pattern #":[\w-]+(?:\.([\w-]+))*")
(re-seq pattern ":h1.text.font-extrabold.mt-6")
 ;;  => ([":h1.text.font-extrabold.mt-6" "mt-6"])

(re-seq pattern ":h1")
 ;;  => ([":h1" nil])
I guess it might be relevant that you could choose to repeat the classname part of the pattern a bunch of times (if you don't mind all the nils), or you can target a numeric index with {0,n}.
#":[\w-]+(?:\.([\w-]+))?(?:\.([\w-]+))?(?:\.([\w-]+))?(?:\.([\w-]+))?(?:\.([\w-]+))?"]
 ;; => [":h1.text.font-extrabold.mt-6" "text" "font-extrabold" "mt-6" nil nil]

#":[\w-]+(?:\.([\w-]+)){0,2}"
 ;; => [":h1.text.font-extrabold" "font-extrabold"]

tomd09:08:04

I think this does what you need?

(let [re #":[\w.-]+\.([\w-]*)"]
    (re-find re "[:div.text-3x1.font-extrabold]"))
  ;; => [":div.text-3x1.font-extrabold" "font-extrabold"]
Edit: simplified

skylize13:08:38

... Unless I am misunderstanding, and what you want is only the entire match. In that case, this is pretty much perfect.

#":[\w-]+(?:\.(?:[\w-]+))*"

(defn elem-with-classes [hiccup]
  (let [re #":[\w-]+(?:\.(?:[\w-]+))*"]
    (re-find re hiccup)))

(elem-with-classes "[:h1.text.font-extrabold.mt-6#example-id]")
 ;; => ":h1.text.font-extrabold.mt-6"

tomd14:08:43

pretty sure @U9J50BY4C is looking to capture the final part (after the final .) in a capture group, like the example he gave:

":class\\s+\"([^\"]*)\""

skylize14:08:41

All in all, I think he has not been super clear about what he actually wants. 😄 So hopefully, if our answers are not on track, he will clarify? ":class\\s+\"([^\"]*)\"" deals with a much more contained case, where you just blindly grab anything and everything inside a pair of quotes, So it's difficult to use as strong example of the target.

🙂 1
Chase15:08:26

Lol, I would guess it's definitely me not explaining it clearly. I don't know how else to explain though, apologies. I don't know how Intellisense/LSP's use regex to trigger autocompletion menus so I probably can't explain what they want either. The link's I provided might help but I don't expect anyone to dig in that much for me. I'll try out these suggestions and see if any work though. Thanks!

Chase15:08:08

Right now, when I write [:div {:class "|"}] I get an autocompletion/docs menu to open up showing me all the tailwind classes where my cursor is (the |). The regex example I showed (`":class\\s+\"([^\"]*)\""`) is what allows for that to happen. I also keep getting that autocompletion when writing multiple classes like [:div {:class "text-3xl font-extrabold |"}] inside the quotations. What I'm also trying to set up is to get that same autocompletion menu to open when I write the shortened css class style in hiccup that lets you write like [:div.{some class name}.{another class name}] where the menu would open up for me after each dot. According to those github issues I linked, the way that the LSP's and Intellisense solves that problem is somehow using a custom regex. I just haven't figured out what the right one is to provide to it. Hopefully that makes more sense.

skylize20:08:07

> when I write [:div {:class "|"}] I get an autocompletion/docs menu to open up ... The regex example I showed (`":class\\s+\"([^\"]*)\""`) is what allows for that to happen. > Based on that, I would try almost exactly what @UE1N3HAJH suggested. Basically trying to keep the pattern as naive as possible, you could slowly build in more accuracy later if needed: Match the colon, then naively match 1+ of any char that could possibly show up between the colon and final dot (I might be missing some), then capture 0+ classname chars. (0+ instead of 1+ so it can trigger immediately after you type the dot, instead of waiting for a first char)

#":[\w-.#>]+\.([\w-]*)"
If that doesn't get you going, I doubt I can be helpful at this stage.

👍 1
Chase20:08:03

That worked!

🎉 1
Chase20:08:47

Thanks folks. Cool stuff. I'll spread this out to the various github issues asking about it.

Chase21:08:26

I imagine any Clojure + Tailwind users will be able to get this working now for their own editors/LSP providers.

skylize22:08:58

Cool. You also get a pattern for ids and nested tags by just replacing \. with # or \>. Might want browse through the docs for hiccup and popular hiccup derivatives in case we're missing any similar sugar.