Fork me on GitHub
#clojure
<
2023-12-28
>
agorgl10:12:15

Hello all! I'm writing a script that will generate clojure ffi bindings by parsing an include header. I'm at the stage where I have all the parsed data that I need from the header, and now looking on how to transform them to clojure forms. How would you approach this problem to produce nicely formatted forms? Make string templates with placeholders? Syntax quoting and unquotes with pretty printing? For example, lets say you have the data:

{:name "strlen", :symbol "strlen", :params [::mem/c-string], :ret ::mem/long}
And you want to produce (on stdout/file or whatever) this kind of output:
(defcfn strlen
  "strlen" [::mem/c-string] ::mem/long)
How would you do it? P.S. The output will eventually be copied to a clj file and will be tweaked by hand if needed, I'm just trying to minimize the manual steps that may be needed after code generation.

clyfe10:12:06

I would use clojure.spec and core.match to transform the structures like https://github.com/clyfe/clara-eav/blob/master/src/clara_eav/dsl.clj#L123-L126 and format the output with cljfmt.

iperdomo10:12:59

somehow related , there is jnr-ffi project to call native code - related talk - https://www.youtube.com/watch?v=Lf-M1ZH6KME#t=5m15s

agorgl10:12:11

Yeah, I'm targeting coffi as my ffi bridge

ericdallo12:12:09

This was probably discussed somewhere but why the ArityException message can't show what is the expected number of args and not only the wrong passed ones?

clojure.lang.ArityException: Wrong number of args (1) passed to: foo.bar/fn-8293
....

5
ericdallo12:12:50

In the past years I saw lots of that exception hehe and in big codebases or lots of anon fns that makes harder understand what is the real var, and having the expected args would help so much

p-himik12:12:36

> lots of anon fns that makes harder understand what is the real var Does the exception not have the line number?

ericdallo12:12:22

Most of the time I think so, but I always find myself failing in corner cases where it's not enough or not present, like this one:

clojure.lang.ArityException: Wrong number of args (1) passed to: com.github.clojure-repl.intellij.configuration.repl-client/-createTemplateConfiguration/fn--8209
	at clojure.lang.AFn.throwArity(AFn.java:429)
	at clojure.lang.AFn.invoke(AFn.java:32)
	at com.github.clojure_repl.intellij.configuration.repl_client.proxy$com.intellij.execution.configurations.RunConfigurationBase$ff19274a.getState(Unknown Source)
	at com.intellij.execution.impl.statistics.RunConfigurationTypeUsagesCollector.collectRunConfigurationFeatures(RunConfigurationTypeUsagesCollector.java:136)
	at com.intellij.execution.impl.statistics.RunConfigurationTypeUsagesCollector.getMetrics(RunConfigurationTypeUsagesCollector.java:96)

p-himik12:12:20

Mm, can't really say anything without the source code. But I'm 95% certain that Alex will ask you to create a post at http://ask.clojure.org or vote there for an existing one, if it does exist. :)

p-himik12:12:05

Ah, proxies are fun. The error seems to be in getState though - according to the docs, it doesn't accept any arguments at all.

Noah Bogart12:12:10

I believe that because of the way clojure is implemented, it’s not possible to know the potential arities of all functions ahead of time

ohno 1
Noah Bogart12:12:54

For example, adding metadata to functions will convert them to RestFns, which have no arity info at all: https://github.com/clojure/clojure/blob/08a2d9bdd013143a87e50fa82e9740e2ab4ee2c2/src/jvm/clojure/lang/AFunction.java#L28

ericdallo12:12:46

@UEENNMX0T but isn't that a corner case? I suppose most of the time we have this info, right?

p-himik12:12:32

@UKFSJSM38 Ah, huh. Where does the error come from then?

ericdallo12:12:44

From my running Intellij, so it's based on the version of Intellij I'm using, and it's that branch I linked 232.8660

p-himik12:12:29

So different versions have different arities of the method that you're trying to use?

ericdallo12:12:18

It could be that, but checking the Intellij source code that method has no breaking changes on different versions AFAICS

Noah Bogart12:12:34

@UKFSJSM38 yes but how to know when you’re in an edge case?

Noah Bogart12:12:35

If you make a normal 2 arg function, add metadata, and then the ArtyException says “expected 0, received 0”, you’re gonna scratch your head

ericdallo12:12:05

hahah yeah, makes sense... that's sad

1
p-himik12:12:00

That particular case can probably be solved by altering RestFn.

1
Noah Bogart12:12:21

I believe there are others but they’re not coming to mind. I agree that it’s sad.

magnars12:12:13

You should feel free to use keywords directly. If you are worried about namespacing, then using namespaced keys are a good way to go.

💯 1
p-himik12:12:16

Depending on the context, you might prefer one of: • Plain keywords by themselves • Plain keywords with helper functions (helpful when you always need e.g. get-in and assoc-in on a path from constraints-paths) which then would be explicitly required • Fully qualified keywords which can be used with a namespace alias