scicloj / wolframite

An interface between Clojure and Wolfram Language (the language of Mathematica)
https://scicloj.github.io/wolframite/
Mozilla Public License 2.0
56 stars 2 forks source link

[Enhancement] Include custom aliases in generated wolfram ns #61

Closed holyjak closed 4 months ago

holyjak commented 4 months ago

Issue: wl/init! / wl/eval make it possible to teach Wolfram about custom aliases, but they only work in the symbolic form, i.e. (list '<the symbol> args...). It would be more convenient to have function vars for this as we do for the built-in aliases such as *, so that the user could do (w/<the symbol> args...).

Fix: Extend write-ns! to take a map of opts, including aliases, and write these to the file.

Fixes #59 partly.

light-matters commented 4 months ago

Having trouble getting this to work. I'll post a more detailed comment soon, but I can write a file that doesn't get used at the moment...

holyjak commented 4 months ago

To test:

clj -Sdeps '{:deps {s/w {:local/root "/Users/holyjak/Projects/external/scicloj/wolframite/target/wolframite-1.0.0-SNAPSHOT.jar"} org.clojure/clojure {:mvn/version "1.12.0-alpha12"}}}'

user=> (require '[wolframite.core :as wl] '[wolframite.impl.wolfram-syms.write-ns :as wns])
user=> (wl/init!)
user=> (wns/write-ns! "/tmp/wolf1.clj")
nil
user=> (load-file "/tmp/wolf1.clj")
#'wolframite.wolfram/fn

This works for me.

Noteworthy: the file and the ns it declares may be out of sync, as it is in this case. But the write should still work, and so the load.

Or:

(wns/write-ns! "/tmp/wolf2.clj" {:aliases '{** Times}})
(load-file "/tmp/wolf2.clj")
(require '[wolframite.wolfram :as w2]) ; BEWARE: filename vs ns name mismatch :'(
user=> (wl/eval (w2/** 2 3) {:aliases '{** Times}}) ;; BEWARE: must pass aliases also to init! or eval
6
light-matters commented 4 months ago

Ah, I think I understand what's happening now. It was a combination of wrong assumptions, but this might be useful for the sake of other users who are as dim as me.

I naturally (and wrongly) assumed that using write-ns! would remove the need to also pass the aliases to init!. I also wrongly assumed (though quickly realised my mistake) that init! could be rerun with different arguments without changing the REPL.

Other things to note:

holyjak commented 4 months ago

As always, users never read docs(trings) ;-)

namespace name should be generated from the path (different filename will not have different namespace)?

Ideally yes, but I'd leave that for later. Ppl can always refactor this.

default run on import will not work unless you have the same directory structure

WDYM?

light-matters commented 4 months ago

As always, users never read docs(trings) ;-)

Lol, guilty. In my slight defense, I read the doc entry on the README and the first line of the docstring... :)

default run on import will not work unless you have the same directory structure

WDYM?

I mean that if you use wolframite as a library and import it then a default run of write-ns! will almost always fail with an error (assuming that you don't have wolframite as a parent directory). I'm thinking that the default arg is only good for wolframite developers unless we want to automatically create the parent directory using fs?

([] (write-ns! "src/wolframite/wolfram.clj"))
...
holyjak commented 4 months ago

Perhaps we should rather drop the no-arg arity and force users to supply a path?

light-matters commented 4 months ago

Perhaps we should rather drop the no-arg arity and force users to supply a path?

I think that's probably the cleanest for now. I do like the idea of having a sensible default, but if we're going for usability then the namespace should be automatically chosen (discussed above) and probably we shouldn't have to specify the aliases twice. These seem like a job for another version though.

light-matters commented 4 months ago

I'll make a commit and then merge.