Fork me on GitHub
#clojure
<
2020-04-23
>
seancorfield00:04:48

Ah, yes. Thank you!

pfeodrippe04:04:21

Hi, is there any way to keep metadata after using clojure.walk/post-walk? I've tried the code below, but it returns nil

(meta (walk/postwalk
       (fn [v]
         (if (meta v)
           (with-meta v
             (meta v))
           v))
       (with-meta '(1 2 3)
         {:ar 2})))

pfeodrippe05:04:41

Well, it appears that a small change in post-walk gives me what I want

(defn postwalk
  [f form]
  (let [form' (clojure.walk/walk (partial postwalk f) f form)]
    (if (meta form)
      (with-meta form' (meta form))
      form')))

dpsutton05:04:00

i think https://github.com/ztellman/riddley solves this as well

👍 4
souenzzo20:04:31

also #specter

pfeodrippe20:04:47

Gracias, @U2J4FRT2T o/ It's a very nice library

Kurt Sys08:04:27

I'm trying to build a native image to take a screenshot in clojure. The code is not that hard, but compiling to native images seems to fail. Or rather, I can build an image, but when running it, I get this exception:

Exception in thread "main" java.lang.IllegalArgumentException: AWT is currently not supported on Substrate VM
        at java.awt.Toolkit.getDefaultToolkit(Toolkit.java:37)
        at hosa$_main.invokeStatic(hosa.clj:14)
        at hosa$_main.doInvoke(hosa.clj:8)
        at clojure.lang.RestFn.invoke(RestFn.java:397)
        at clojure.lang.AFn.applyToHelper(AFn.java:152)
        at clojure.lang.RestFn.applyTo(RestFn.java:132)
        at hosa.main(Unknown Source)

Kurt Sys08:04:05

This is my deps.edn:

{:paths ["src/main/clojure"]
 :aliases {:native-image
           {:main-opts ["-m clj.native-image hosa"
                        "--initialize-at-build-time"
                        "--initialize-at-run-time=java.awt.*"
                        ;; optional native image name override
                        "-H:Name=hosa"]
            :jvm-opts ["-Dclojure.compiler.direct-linking=true"]
            :extra-deps
            {clj.native-image
             {:git/url ""
              :sha "7708e7fd4572459c81f6a6b8e44c96f41cdd92d4"}}}}
 }

Kurt Sys08:04:39

in my code, I added type hints (without them, I couldn't build the native image):

(ns hosa
  (:gen-class)
  (:import [java.awt GraphicsDevice GraphicsEnvironment Rectangle Robot Toolkit]
           .File
           java.awt.image.BufferedImage
           javax.imageio.ImageIO))

(defn -main [& _]
  (let [^Rectangle screen-rectangle (Rectangle. (.getScreenSize
                                                 ^Toolkit (Toolkit/getDefaultToolkit)))
        ^BufferedImage capture (.createScreenCapture ^Robot (Robot.) screen-rectangle)]
    (ImageIO/write ^BufferedImage capture "bmp" ^File (File. "printscreen.bmp"))
    ))

Kurt Sys08:04:27

So, the question actually would be: how to add AWT to the substrate VM? (I get the same result with the --no-server option)

yenda09:04:37

@kurt.sys the exception starts with AWT is currently not supported on Substrate VM so I would say you just can't

Kurt Sys09:04:38

yeah... There's currently no workaround?

Kurt Sys09:04:08

(I'm trying JavaFX, but that also doesn't seem to be supported - well, probably not a clj question anymore)

hindol09:04:20

I have found this: https://github.com/gluonhq/substrate Seems to support JavaFX on Graal.

Kurt Sys09:04:21

Yeah... I'm trying to make it work. I seem to be able to add javafx, but for some reason, to get a saveable image from a javafx image, one still needs java.awt. So far, no native image to take screenshots, I suppose.

vlaaad10:04:42

javafx uses their own fork of graalvm IIRC

vlaaad11:04:16

there are download links to their fork

Kurt Sys11:04:32

Right. That might almost be ok, except: 1. having a javafx WriteableImage can apparently only be written when it's converted to a java.awt.BufferedImage, and the latter is depending on java.awt, which is not supported for native images 2. the main target would be win-images, which is not available.

otwieracz11:04:41

Hi How can I, with clojure.data.zip.xml/xml1-> navigate to text of first children inside tag? Imagine case where I have something like:

<names>
  <name>
    otwieracz
    <comment>
      ...
    </comment>
  </name>
  ...
</names>

otwieracz11:04:36

I'd like to access otwieracz, so something more or less reassembling: (xml1-> xml :names :name first text)

otwieracz11:04:40

but this does not work

jsn11:04:40

I don't think your first means what you think it means. I think one way to do it is to replace it with clojure.zip/down

Setzer2211:04:52

can I create a multidimensional array of doubles with double-array? There's only the two following signatures:

[size-or-seq]
 [size init-val-or-seq]
But if I try using make-array, I cannot use double as the type. I need this to interop with a library that is expecting a double[][] as one of its parameters

jsn12:04:10

Did you read make-array doc string?

jsn12:04:10

or is it for boxed only? I don't know then.

p-himik12:04:55

The resulting type is the same as it would be in Java.

Setzer2213:04:25

I ended up with this:

(defn make-2d-double-array [dim1 dim2]
  (into-array (repeatedly dim1 #(double-array (repeat dim2 0)))))

Setzer2214:04:14

I'd still prefer a solution not involving the creation of a lazy seq just for the sake of having something to feed into-array, but this is enough for my use-case

borkdude12:04:12

Should next.jdbc be considered the successor to clojure.java.jdbc or will both be maintained indefinitely? Say if I were adding one of these to babashka, is next.jdbc preferred?

Alex Miller (Clojure team)12:04:18

next.jdbc is the active code base

murtaza5212:04:32

(read-string "#:db{:ident :class-desc/10-major-varies-by-season}") the above throws an error. Why is this valid :a/b-10 and this invalid :a/10-b?

Alex Miller (Clojure team)12:04:11

It’s a long story, but the symbols can’t start with numbers

Alex Miller (Clojure team)12:04:28

Keywords are “like symbols” in this respect

Alex Miller (Clojure team)12:04:25

This is really the Clojure reader, not edn

Alex Miller (Clojure team)12:04:52

But there are some long standing now grandfathered in bugs that does allow it in keywords

Alex Miller (Clojure team)12:04:15

But you’re seeing one of the cases where it will be marked invalid

murtaza5212:04:49

its edn data that I am trying to read, its invalid for that too ?

Alex Miller (Clojure team)12:04:15

Yes, code derived from there

plins12:04:00

hey, just discovered ^:const like

(def ^:const pi 3.14)
when I should use it ? always?

Alex Miller (Clojure team)13:04:37

probably almost never

👍 16
Alex Miller (Clojure team)13:04:03

you should use it for true compile-time constants that should be compiled into code that uses it

Saurabh Jain14:04:41

Hello, getting the below error..

Saurabh Jain14:04:06

Applying task run to [-m tap-mssql.core --config /builds/config/config.json --discover]  Applying task javac to nil  Running javac with [@/tmp/.leiningen-cmdline13379584158302418975.tmp]  Applying task compile to nil  All namespaces already AOT compiled.

Saurabh Jain14:04:14

Any help would be highly appreciated

Nico14:04:11

does clojure have a go-to markdown parsing library? I'm looking to parse markdown into hiccup if I can but HTML if not.

dpsutton14:04:15

there's https://github.com/yogthos/markdown-clj . some rough edges like it parses a line at a time so the markdown must be a bit tidier than the spec allows

Nico14:04:46

thanks, I'll check it out

potetm14:04:58

I looked into this at length a while back. I would recommend https://github.com/atlassian/commonmark-java

Nico14:04:07

are there some examples of using that from clojure?

Nico14:04:18

(I've never really used the java interop that much before)

potetm18:04:47

@nihilazo I have suffered so you don’t have to

(let [^Parser mdparser (-> (Parser/builder)
                           (.extensions [(StrikethroughExtension/create)
                                         (HeadingAnchorExtension/create)])
                           (.build))
      ^HtmlRenderer md (-> (HtmlRenderer/builder)
                           (.nodeRendererFactory (code-border-render-factory))
                           (.build))
      d (.format DateTimeFormatter/ISO_DATE
                 (LocalDate/now))]
  (html5
    [:main
     [:section
      [:time {"datetime" d} d]
      (.render md
               (.parse mdparser
                       (slurp "./path/to/file.md")))]]))

potetm18:04:48

An example where I integrate some markdown into a hiccup template.

kwladyka15:04:04

you can try convert markdown -> HTML -> hiccup

kwladyka15:04:22

I saw some libraries to convert HTML into hiccup

Amir Mohammad15:04:28

And you can use hiccup for template rendering in clojure

emccue15:04:02

@nihilazo Translating a bit of what is on their docs

emccue15:04:07

Parser parser = Parser.builder().build();
HtmlRenderer renderer = HtmlRenderer.builder()
        .attributeProviderFactory(new AttributeProviderFactory() {
            public AttributeProvider create(AttributeProviderContext context) {
                return new ImageAttributeProvider();
            }
        })
        .build();

Node document = parser.parse("![text](/url.png)");
renderer.render(document);
// "<p><img src=\"/url.png\" alt=\"text\" class=\"border\" /></p>\n"

emccue15:04:48

(let [parser (-> (Parser/builder) (.build))
      renderer (-> (HtmlRenderer/builder)
                   (.attributeProviderFactory 
                     (reify AttributeProviderFactory
                         (create [this context]
                            (ImageAttributeProvider.))))
                   (.build))
      document (.parse parser "![text](/url.png)")]
  (.render renderer document))
    

emccue15:04:53

and since this is somewhat fun

emccue15:04:57

class IndentedCodeBlockNodeRenderer implements NodeRenderer {

    private final HtmlWriter html;

    IndentedCodeBlockNodeRenderer(HtmlNodeRendererContext context) {
        this.html = context.getWriter();
    }

    @Override
    public Set<Class<? extends Node>> getNodeTypes() {
        // Return the node types we want to use this renderer for.
        return Collections.<Class<? extends Node>>singleton(IndentedCodeBlock.class);
    }

    @Override
    public void render(Node node) {
        // We only handle one type as per getNodeTypes, so we can just cast it here.
        IndentedCodeBlock codeBlock = (IndentedCodeBlock) node;
        html.line();
        html.tag("pre");
        html.text(codeBlock.getLiteral());
        html.tag("/pre");
        html.line();
    }
}

emccue15:04:35

(defn indented-code-block-node-renderer [context]
  (let [html (.getWriter context)]
    (reify NodeRenderer
      (getNodeTypes [_]
        [IndentedCodeBlock])
      (render [_ node]
        (doto html
           (.line)
           (.tag "pre")
           (.text (.getLiteral node))
           (.tag "/pre")
           (.line))))))

Nico15:04:19

thanks again

hindol15:04:54

Isn't CommonMark PegDown based? It can get stuck on some edge cases. I researched about the same a few months back and found FlexMark-java better.

hindol15:04:41

I barely started to wrap flexmark: https://github.com/hindol/flexmark-clj Don't use this library, but maybe you can see how to do interop.

emccue15:04:17

personal opinion don't ever look for clojure wrappers

8
💯 8
emccue15:04:00

look for good java libraries or native clojure things

emccue15:04:20

and then evaluate if the clojure wrappings of those java things are worth it

emccue15:04:33

if it just changes (.doThing (ThingDoer.) to (do-thing! (thing-doer))

emccue15:04:40

you haven't gained much

emccue15:04:57

but you have gained a vector for dependency rot

☝️ 8
ghadi15:04:39

learning the basic Java interop pays off dividends

ghadi15:04:51

just to reemphasize the point being made: there is a variety in Clojure libraries that wrap the underlying Java things. Some add a lot of leverage, some don't

hindol15:04:01

Yeah, that's not a wrapper per se. I was trying to structurally parse a Markdown and the only library I found did Markdown -> HTML -> Hiccup. So, I wrote my own that will go from Markdown to Flexmark's tree of nodes to Clojure data structures.

roklenarcic15:04:12

Why is url-encode doing all that by hand… but form-encode is using java’s URLEncoder

roklenarcic15:04:28

(form-encode* [unencoded encoding]
    (URLEncoder/encode unencoded encoding))

roklenarcic15:04:12

but URL encode is doing its own substitutions (which are using regexes and thus probably not very fast)

lukasz16:04:50

I had to look into something similar a couple of weeks ago - URLEncoder is not quite the same as URIEncode from Javascript, and not 100% the same as usual form/multipart encoding. I wouldn't worry about regex performance, usually that's not the bottleneck in request processing, especially if you're doing database calls etc

potetm18:04:47

@nihilazo I have suffered so you don’t have to

(let [^Parser mdparser (-> (Parser/builder)
                           (.extensions [(StrikethroughExtension/create)
                                         (HeadingAnchorExtension/create)])
                           (.build))
      ^HtmlRenderer md (-> (HtmlRenderer/builder)
                           (.nodeRendererFactory (code-border-render-factory))
                           (.build))
      d (.format DateTimeFormatter/ISO_DATE
                 (LocalDate/now))]
  (html5
    [:main
     [:section
      [:time {"datetime" d} d]
      (.render md
               (.parse mdparser
                       (slurp "./path/to/file.md")))]]))

nikolavojicic19:04:29

Is there a way to (set! *warn-on-reflection* true) for all namespaces in src and test directories? I use :global-vars {*warn-on-reflection* true} in defproject but that shows me warnings for deps also, e.g. a lot of CIDER warnings at startup.

andy.fingerhut19:04:20

There is of course the technique of editing all files in your project's src and testdirectories to add that single line to all of them. I do not know a way in Leiningen to do it another way. You could try asking in #leiningen channel to see if anyone there knows another way.

nikolavojicic19:04:57

Does that affect performance in production? You can set :global-vars for :dev profile in Leiningen to avoid that.

andy.fingerhut19:04:07

No more than the time it takes to print the warning messages, I believe.

nikolavojicic19:04:23

Ah yes, it happens only at compile time. No penalty.

andy.fingerhut19:04:24

The Clojure compiler must always determine when compiling Clojure code whether it can make a JVM interop call without using reflection, or whether it needs to use the reflection API. The main difference that I know between setting *warn-on-reflection*to true, versus not, is the printing of the warning messages when it detects that it must use reflection.

punit-naik19:04:19

Hi guys, I was compiling my project but got an error which I never have previously seen: Error building classpath. Could not transfer artifact com.taoensso:encore:jar:2.117.0 from/to clojars (): Range Not Satisfiable (416) Please help me resolve this if you have faced this before 🙏

defndaines20:04:37

Today in typos: If you call

(let [state (atom {})]
  (count @atom))
That is @atom instead of @state, you get the following stacktrace …
java.lang.ClassCastException: class clojure.core$atom cannot be cast to class java.util.concurrent.Future (clojure.core$atom is in unnamed module of loader 'app'; java.util.concurrent.Future is in module java.base of loader 'bootstrap')
 at clojure.core$deref_future.invokeStatic (core.clj:2298)
    clojure.core$deref.invokeStatic (core.clj:2320)
    clojure.core$deref.invoke (core.clj:2306)

😬 4
antonmos21:04:06

brutal 🙂