calc-eval-format
何らかの計算結果をソース内で定数とする場合、コメントに計算式を残しておきたいことがあります。calc-eval
を使うと再利用できて便利ではあるのですが、ちょっと見栄えが悪いです。
(kill-new (calc-eval
(format "sqrt((%f - %f)^2 + (%f - %f)^2)"
1 2 3 4)))
さらに変数が多くなった場合、式との対応が分かりづらくなります。そこで以下のように書けるようにしました。ちなみにcalc-eval
自身にもformat-stringと同じ機能はあったりします。詳しくはinfo:Calc#Calling Calc from Your Programs
(calc-eval-format "sqrt((a - b)^2 + (c - a)^2)"
a = 1
b = 2
c = 3)
式をクオートされた文字列ではなく、以下のようにそのまま書きたかったのですがいたらず。
(calc-format eval sqrt((a - b)^2 + (c - a)^2)
with a = 1
b = 2
c = 3)
loop
マクロの実装を見ればなんとかなるかもと思ったのですが、たいへんそうだったので今後の課題です。
(defmacro calc-eval-format (expr-str &rest vars)
(let ((expr (gensym))
(result (gensym)))
`(let ((case-fold-search nil))
(setq ,expr ,expr-str)
(loop for sym in '(,@vars) by #'cdddr
for eq-sym in (cdr '(,@vars)) by #'cdddr
for val in (cddr '(,@vars)) by #'cdddr
do
(unless (and (symbolp sym)
(numberp val)
(eq '= eq-sym))
(error "Wrong format of variables"))
(setq ,expr (replace-regexp-in-string
(concat "\\<" (symbol-name sym) "\\>")
(number-to-string val)
,expr t)))
(setq ,result (calc-eval ,expr))
(if (stringp ,result)
(kill-new ,result)
(if (listp ,result)
(kill-new (cadr ,result))
,result)))))