sci 2023-11-07

Is there a way to get the metadata of a function in SCI - specifically the line where the function is defined - from the "Host of the SCI" (My ClojureScript-Application)?

Yes:

(-> (sci/eval-string* my-ctx "#'namespace/function") meta)

And is there also a way when having stored the function in an atom at the "Host of SCI"?

why would you do that?

Because I define functions in my SCI-Input from which the user can select the function they want to run now

SCI-input? I don't get it, can you maybe write/show some code?

Like I have

(register-it #(println "hello"))

(register-it #(println "you"))

(register-it #(println "wonderful"))

(register-it #(println "world"))

And then the user can switch between the registered functions via a selection

And now I want to mark the currently running function in my editor

so you create anonymous functions and then store them in an atom?

and the above is done by evaluating register-it within SCI?

register-it is a sci-macro

ok, you can look at the &form argument in the macro, the location information is on there

(defn ^:sci/macro foo [&form &env x y z])

Ah, so I just store it in another macro?

you don't need another macro probably, you could do it like this

(defn register-it [&form _env fn-form]
  (let [loc (meta fn-form)]
  `(swap! function-store (with-meta ~fn-form ~{:line (:line loc) :column (:column loc)})))) 

and then the function becomes a function with location metadata

Uh, that works?

And thanks for your help!

be aware that a function with metadata isn't directly callable from JS though, don't know if that is a problem

(this could be fixable in CLJS I think but doesn't work currently)

if that is a problem you could decide to store the location metadata as a JS field on the function and get it back using aget

assuming you are in JS...

And is there a way to get the line when I take a list rather than a function in the macro?

The expression is already a list

The #(...) form expands in the reader, what the macro sees is the last expression here:

cljs.user=> `#(inc %)
(fn* [p1__6__7__auto__] (cljs.core/inc p1__6__7__auto__))

which is a list

Yeah, but what if I dont get an anonymous function but just a list with the expression the user wan't

Is there also a way to get the line then?

Have you actually tried this? I think I already explained it :)

I tried it with (println (meta (list 'fn* [] code))), where code is the list I get in my macro

so you want the user to write an expression without the surrounding fn form?

Sure, the list contains the metadata

Same approach

It doesn't work on non-lists

It is a list but the code above prints nil. Any idea why?

because you are not inside of a macro, you are printing the metadata of the evaluated list which is nil

But it works inside the returned code?

And is it importand if I use fn or fn*?

Got it, thanks

👍 1