Define interactive functions
Last week I wrote a simple function in Common Lisp, to calculate whether I should sold a national debt or not. The function takes 6 parameters, which I found a little difficult to use. But it's also not worth to add a command line arguments parsing library and write a formal *ui* for it. So inspired by Emacs interactive function, I wrote a very simple macro which defines functions that can be called interactively:
(defun prompt-ask (&rest args) (apply #'format *standard-output* args) (force-output) (read *standard-input*)) (defmacro define-interactive (name arg-specs &body body) (let ((arg-list (loop for (arg-name prompt) in (mapcar #'(lambda (spec) (destructuring-bind (sym prompt) (if (atom spec) (list spec (symbol-name spec)) spec) (list sym (format nil "~a: " prompt)))) arg-specs) collect `(,arg-name (prompt-ask ,prompt))))) `(defun ,name (&optional ,@arg-list) ,@body)))
With this macro, I defined my debt calculation function as:
(define-interactive suggest ((parvalue "票面总值") (rate "利率(%)") (rate-for-interest "每年兑息的再投资利率(%)") (years "剩余期限中的年数") (days "剩余期限中的天数") (current-value "现值")) (let* ((rate (/ rate 100)) (rate-for-interest (/ rate-for-interest 100)) (years (+ years (/ days 365.0))) (year-interest (* parvalue rate)) (total-expected (+ parvalue (loop for i from (floor years) downto 0 sum (* year-interest (expt (1+ rate-for-interest) i))))) (minimal-next-rate (if (>= current-value total-expected) 0 (loop for i from 0.0005 upto 0.5 by 0.001 for money = (* current-value (expt (1+ i) years)) when (> money total-expected) do (return i) finally (return nil))))) (format t "持有到期预期收入: ~,2f~%现在卖出需要的下一个最少利率是: ~,2f%~%" total-expected (* 100 (or minimal-next-rate 100))) (values)))
Now we have a function 'suggest' which takes 6 optional parameters, and ask user input for the unspecified ones:
GZ-UTIL> (suggest) 票面总值: 150000 利率(%): _
You can still call it non-interactively by specifying all parameters.
The idea and code is so simple that may not worth a blog post, but I do feel happy when writing it. So here we have a blog for it anyway :)
---------------------
Published on 2024-12-25
The content for this site is licensed under: