Open light-matters opened 6 months ago
Something like this seems to work (outputs {-y "Minus[y]", -x "Minus[x]"}) :
(def expression '(+ -x -x -y -5 -2 (- x 10 5) (** x 2)))
(defn strip-ns [form]
(walk/postwalk (fn [form]
(if (qualified-symbol? form)
(symbol (name form))
form))
form))
(defn replacement-map
"Creates a replacement map for negative symbols, such that they are reasonably interpreted by Wolfram.
TODO:
- Extend the idea to deal with other custom replacements (e.g. greek/hebrew symbols.) .
"
[expression]
(let [syms (->> expression
strip-ns
(into '())
(tree-seq list? seq)
(remove (some-fn list? nil?))
(filter #(when (symbol? %)
(->> %
str
(re-matches #"-.+"))))
distinct)
syms-base (map (fn [sym] (-> sym str char-array rest (#(apply str %)) symbol)) syms)]
(zipmap syms (map (fn [sym] (format "Minus[%s]" sym)) syms-base))))
(replacement-map expression)
(replacement-map `(+ -x -x -y -5 -2 (- x 10 5) (** x 2)))
Last two s-exps show that it works for quoted and backticked expressions.
Would it make more sense to actually do the replacement during the expression walk? This would require a fairly fundamental change to how wolframite usually works, but it would be powerful to have user-specified replacement functions.
At the moment, we can pass the generated replacement map to ->wl and it will get passed down the line, e.g.
(->wl '(+ -x -x -y -5 -2 (- x 10 5) (** x 2))
{:aliases {'-x '(Minus x)
'-y '(Minus y)
'** 'Power}})
produces
#object[com.wolfram.jlink.Expr 0x23a65a14 "Plus[Minus[x], Minus[x], Minus[y], -5, -2, Subtract[x, 10, 5], Power[x, 2]]"]
Something like this seems to work ...
@light-matters Not sure these comments have anything to do with supporting negative symbols, as in -E4
??
This could likely be implemented easily by extending wolframite.base.convert/convert
impl. for :symbol
, where we currently throw if the symbol does not match #"[^a-zA-Z0-9$\/]"
- we could check that it is alphanum. and starts with -
and replace that with Minus[...]
.
But this is not something Wolfram itself supports so IMO this is beyond v1. Notice that after #58 we will support (w/- E4)
.
Hm, what is E4
anyway? It does not seem Wolfram knows this? Is this meant for fn args, as in (w/Map (w/fn [x] -x) [1 2])
??
Something like this seems to work ...
@light-matters Not sure these comments have anything to do with supporting negative symbols, as in
-E4
??
-E4 is symbolically equivalent to -x,-y etc. unless I misunderstand what you're meaning. I suppose it might have made more sense to use E4 as an example.
This could likely be implemented easily by extending
wolframite.base.convert/convert
impl. for:symbol
, where we currently throw if the symbol does not match#"[^a-zA-Z0-9$\/]"
- we could check that it is alphanum. and starts with-
and replace that withMinus[...]
.But this is not something Wolfram itself supports so IMO this is beyond v1. Notice that after #58 we will support
(w/- E4)
.Hm, what is
E4
anyway? It does not seem Wolfram knows this? Is this meant for fn args, as in(w/Map (w/fn [x] -x) [1 2])
??
Wolfram does support this, as I can evaluate "-x + 10" in Mathematica, but beyond v1 sounds right for us. As you say, (w/- E4) mostly solves the issue for now (it is better than having to write "(- 0 symbol)" just to make 'symbol' negative.
(wl/eval (w/- 'E4))
(wl/eval '(- E4))
both work as expected.
E4 is just an arbitrary symbol, e.g. 'equation4' or 'e' or 'x'. This was probaly a bad example, but just happened to be the thing I was working with when I reported the issue!
Would it be worth making it easier to pass negative symbols, e.g. '-E4 instead of '(- 0 E4).
At the moment, this will be interpreted as a non-alphanumeric symbol.