sci

DerTev 2023-11-07T15:52:19.112979Z

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)?

borkdude 2023-11-07T15:59:35.842959Z

Yes:

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

DerTev 2023-11-07T16:11:36.503049Z

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

borkdude 2023-11-07T16:12:11.872819Z

why would you do that?

DerTev 2023-11-07T16:14:35.377689Z

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

borkdude 2023-11-07T16:15:04.327989Z

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

DerTev 2023-11-07T16:16:31.537899Z

Like I have

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

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

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

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

DerTev 2023-11-07T16:16:51.174529Z

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

DerTev 2023-11-07T16:17:09.642679Z

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

borkdude 2023-11-07T16:17:49.676179Z

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

DerTev 2023-11-07T16:18:06.780579Z

Yes

borkdude 2023-11-07T16:18:28.155969Z

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

DerTev 2023-11-07T16:18:37.980409Z

Yes

DerTev 2023-11-07T16:18:47.691589Z

register-it is a sci-macro

borkdude 2023-11-07T16:19:07.626369Z

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

borkdude 2023-11-07T16:19:44.132849Z

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

DerTev 2023-11-07T16:19:45.993459Z

Ah, so I just store it in another macro?

borkdude 2023-11-07T16:21:32.143189Z

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)})))) 

borkdude 2023-11-07T16:21:53.319889Z

and then the function becomes a function with location metadata

DerTev 2023-11-07T16:23:01.763029Z

Uh, that works?

DerTev 2023-11-07T16:23:02.664669Z

Cool

DerTev 2023-11-07T16:23:08.327709Z

And thanks for your help!

borkdude 2023-11-07T16:23:15.798469Z

no problem

borkdude 2023-11-07T16:23:36.461679Z

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

borkdude 2023-11-07T16:23:52.182249Z

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

borkdude 2023-11-07T16:24:28.071389Z

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

borkdude 2023-11-07T16:24:34.797119Z

assuming you are in JS...

DerTev 2023-11-07T16:30:05.670569Z

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

borkdude 2023-11-07T16:30:44.658299Z

The expression is already a list

borkdude 2023-11-07T16:31:26.248899Z

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__))

borkdude 2023-11-07T16:31:33.824549Z

which is a list

DerTev 2023-11-07T16:34:22.993969Z

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

DerTev 2023-11-07T16:34:33.545459Z

Is there also a way to get the line then?

borkdude 2023-11-07T16:34:56.332019Z

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

DerTev 2023-11-07T16:37:45.905999Z

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

borkdude 2023-11-07T16:40:16.988189Z

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

DerTev 2023-11-07T16:40:40.980869Z

Yes

borkdude 2023-11-07T16:43:23.895069Z

Sure, the list contains the metadata

borkdude 2023-11-07T16:43:28.503359Z

Same approach

borkdude 2023-11-07T16:43:38.586029Z

It doesn't work on non-lists

DerTev 2023-11-07T16:57:23.892909Z

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

borkdude 2023-11-07T16:59:25.058569Z

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

DerTev 2023-11-07T16:59:56.369579Z

But it works inside the returned code?

DerTev 2023-11-07T17:00:26.454599Z

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

DerTev 2023-11-07T17:08:09.349699Z

Got it, thanks

👍 1