Fork me on GitHub
#clojure
<
2022-04-17
>
pinkfrog06:04:56

How can I attach metadata to a symbol in the def form?

pinkfrog06:04:16

(def credential (with-meta 'crendetial {:type :ratom}))
works. But I really like the following to work:
(def credential ^{:type :ratom} 'crendetial)

vemv07:04:18

'^{:type :ratom} credential works!

👍 1
Søren Sjørup08:04:02

Is there a library that defines, these?

(defn less? [a b] (neg? (compare a b)))
(defn less-equal? [a b] (not (pos? (compare a b))))

pavlosmelissinos08:04:29

So something like < and <= that also work on non-numbers? Why do you need these predicates? Where would you use them?

Søren Sjørup08:04:05

I use them on characters currently, but I’ve had other uses for them. They’re analogous to least and greatest from medley.

pavlosmelissinos08:04:22

I'm not aware of any library that offers these but I feel that maybe it's an XY problem. > I use them on characters currently Yes but to what end? I mean maybe there's a better way to solve your actual problem without resorting to manual comparisons. E.g. to sort arbitrary data it would be better to https://clojure.org/guides/comparators

Søren Sjørup08:04:41

I’m writing a interval set for character ranges, for instace i have. a function:

(defn in [x [a b]]
  (and (less-equal? a x) (less-equal? x b)))
to test if a character is within an interval.

pavlosmelissinos09:04:31

So you have a set of discrete values and a character and you want to do a membership check. I would: 1. build the set of characters based on the interval bounds 2. run (charset x) That way if charset is #{\b \d \c \e} and x is \e the result will be truthy, if charset is #{\b \d \c}, the result will be falsey.

Søren Sjørup09:04:28

Thank you. I want to avoid representing each character as this is for a regex engine and a interval set could potentially represent all characters.

pavlosmelissinos09:04:34

Oh alright, I assumed ASCII 🙂 I think your solution is fine for bigger character sets. (Still, I'm not sure how meaningful Unicode ordering is, like should a smile emoji be greater than the plus sign emoji?)

Søren Sjørup09:04:31

I haven't tried but I would assume regex character classes us codepoint ordering.

Kevin10:04:37

Hey, I'm trying to rewrite some Java code to Clojure but bumping into some issues (maybe this can't be done in Clojure?). Basically I have a Go Library which I'm trying to import and call in Clojure. This works with the following Java code:

public interface GoTest extends Library {
        long Add(long x, long y);
    }

    public static GoTest GO_TEST;

    static {
        String lib = System.getProperty("user.dir") + "/bin/foo.so";
        GO_TEST = (GoTest) Native.loadLibrary(lib, GoTest.class);
    }
I'd like to avoid Java if possible. I wrote the following piece of Clojure:
(import '(com.sun.jna Library Native))

  (definterface GoTest
    (Add [this x y]))

  (extend GoTest Library)

  (defn load-library []
    (let [lib (str (System/getProperty "user.dir") "/bin/foo.so")]
      (Native/loadLibrary lib GoTest)))
but I get the following error:
Interface (GoTest) of
   library=/home/user/clojure-go/bin/foo.so does not
   extend Library
Any ideas? Or is this just not possible in Clojure?

p-himik10:04:51

Not sure whether it'll work but try

(definterface GoTest
  (Add ^long [this ^long x ^long y]))

Kevin10:04:54

Same result, sadly

p-himik10:04:35

Oh, wait, you have extends in the Java code.

Kevin10:04:03

Is that unsupported in Clojure?

p-himik10:04:21

Indeed, definterface by itself doesn't have that ability. But you can use gen-interface.

p-himik10:04:17

Oh, and also - my bad for not realizing this - methods you specify in definterface don't accept this. So also remove this from there.

Kevin10:04:06

Let me try out gen-interface

Kevin10:04:56

Awesome! This works:

(gen-interface :name "clojure_go.core.GoTest"
                 :extends [com.sun.jna.Library]
                 :methods [[Add [Long Long] Long]])

Kevin10:04:12

Thanks for the tip 😄

borkdude15:04:40

@UG9U7TPDZ you could also consider implementing a golang pod so you can call it through the babashka.pods library which also works in the JVM. No native stuff :)

Kevin15:04:59

Interesting idea :thinking_face: But you would have a communication bottleneck I think. But maybe that would be really minimal

Kevin15:04:16

The reason I want to call Go is for performance

borkdude15:04:30

it depends on if you have: 1. many function calls 2. big sized arguments (as they are serialized) So if the overhead of the function call serialization is small compared to the actual work happening in Golang per function call then it would be a good fit. E.g. the sqlite3 pod and file watcher pod fall into this category

borkdude15:04:11

but if you add two numbers, and want the result then that's probably not a good fit

Kevin15:04:43

Right, for my usecase this might actually be a good fit. Not sure how I'd implement this though. Also I haven't gotten my own example working in GraalVM yet lol

Kevin15:04:49

But I'll think about this, thanks

borkdude15:04:22

there has to be no graalvm involved. you can look at the existing babashka pods in golang here: https://github.com/babashka/pod-registry

borkdude15:04:43

@UG9U7TPDZ Another option might be to use #coffi and project Panama on JVM 17

borkdude15:04:45

or dtype.next

Kevin15:04:47

Coffi also looks interesting, trying that out now

phronmophobic19:04:01

If you're targeting graalvm, then I think dtype.next is the best option. I don't think coffi works with graalvm. If it does, that would be good to know!

borkdude19:04:13

But does @UG9U7TPDZ target graalvm native? I haven't read that he did... Please don't leave us in suspense!

Kevin19:04:23

Yeah I'm targetting graalvm (eventually)

borkdude19:04:38

> The reason I want to call Go is for performance I'm not sure if I understand that one. Go in general shouldn't be more performant than Java, or is it?

phronmophobic19:04:54

I'm happy to answer any questions. clojure <-> c interop unlocks a lot of potential!

phronmophobic19:04:58

although I agree with @U04V15CAJ that if the goal is performance, I'm not sure calling go from clojure will give you any better results than either calling java or optimizing your clojure code.

Kevin19:04:50

I was under the impression that Go did have a bit of an edge in terms of performance from the benchmarks I've seen, but maybe that's a bit misleading

borkdude19:04:27

Measure for your specific problem and in the typical scenario you're using it. Performance is hard to speak about in general is usually very contextual.

borkdude19:04:42

E.g. the JVM JIT may outperform Go when you run the program long enough

pinkfrog13:04:53

import-vars of potemkin exposes values and macros, is it possible to expose a namespace?

Noah Bogart13:04:19

You want to import all vars (defs, functions, and macros) from one namespace into another and then export them as if they are defined in the second namespace?

Noah Bogart13:04:04

If that's the case, then i would recommend against it lol

☝️ 2
pinkfrog14:04:42

In ns a , i’d like to import ns b and define b as a.b. so that, from ns c, it can access a.b by importing ns a only.

Noah Bogart14:04:26

Oh hmm. I don’t think that's possible. Why not just require ns b from within ns c? Namespace aren't private or hidden, so if ns a can require it, so can ns c.

potetm14:04:18

I will say tho: The reason I know this is I purposefully circumvent it in my code because it messes with cursive symbol resolution.

emccue22:04:45

If you were to make a runtime basis, but it did not include flags - just dependency and repository information - what would you call that?

didibus23:04:39

Is there a way to tell iterate to end? Or I guess a lazy-seq in general? Does returning reduced work for that?

didibus23:04:51

Say I wanted an iterate that generate the numbers from 1 to 10 and stopped

p-himik23:04:03

So you want to stop iterate nor from the consumer but from the f itself?

didibus23:04:26

Ya, kind of what (take 5) does where it stops after 5

didibus23:04:36

I wonder how take does that

didibus23:04:44

I found a workaround:

(->> (iterate (fn [x] ...))
     (take-while (complement reduced?)))

didibus23:04:30

That lets me return a reduced from the iterate fn and it'll stop. But I'm still curious, like how does take-while short-circuits the infinite seq to make it finite?

p-himik23:04:55

The implementation is rather trivial.

didibus23:04:24

Hum... right so with lazy-seq, nil short-circuits, but I guess nothing can make iterate short-circtuits so you need to wrap it and not poll it anymore

p-himik23:04:26

That's right.

didibus23:04:06

That answers my question haha, seems you can't short-circuit iterate, but wrapping it is pretty trivial and solves my issue cleanly enough

hiredman23:04:11

There is the new function, maybe iteration? That includes a stop condition