当前位置: 首页 > 工具软件 > OpenCI > 使用案例 >

常见的Lisp和Travisci管理预算的简单方法

平羽
2023-12-01

I really don’t like spreadsheets, even the ones provided by the excellent org-mode which I use for other purposes.

我真的不喜欢电子表格,甚至不喜欢我用于其他目的的出色组织模式提供的电子表格。

For one, they are too obsessed with location and order. I would like to re-order items within my household budget at any moment due to pure whimsy and not have things break. There is probably a way to do this with spreadsheets, but there is certainly an easier way with code.

首先,他们太迷恋位置和秩序。 我想在任何时候都出于纯粹的异想天开而在家庭预算范围内重新订购商品,并且不会出现任何问题。 可以使用电子表格执行此操作,但是使用代码当然可以更轻松。

Which brings me to another point: as a programmer, I’m more comfortable with code than spreadsheets. I not only get to see how my household budget has changed over the years through git commits, I can easily check previous builds with TravisCI to see the actual numbers generated by my budget.

这又使我想到了另一点:作为一名程序员,我对代码的理解比对电子表格的适应性更高。 我不仅可以看到多年来通过git commits改变了我的家庭预算,而且我可以轻松地使用TravisCI检查以前的版本,以查看我的预算产生的实际数字。

And like all Lisps, Common Lisp represents “code as data”, an attribute referred to as homoiconicity. This leaves open the door of possibility for my budget to eventually write its own code. Additionally, using SLY or SLIME allows me to hack my budget live in a REPL, as opposed to being stuck with the “write — compile — debug” loop most programming environments force upon you.

与所有Lisps一样, Common Lisp表示“代码即数据”,这是一种被称为谐音性的属性。 这为我的预算最终编写自己的代码敞开了大门。 另外,使用SLYSLIME使我可以在REPL中掌握预算,而不是被大多数编程环境强加给您的“写入-编译-调试”循环所困扰。

And lastly, you can do this for completely free with a private GitHub repo and TravisCI.

最后,您可以使用私有GitHub存储库和TravisCI完全免费地执行此操作。

To get started, first write some brief code in a file called finances.lisp:

首先,请在名为finances.lisp的文件中编写一些简短的代码:

(defparameter *monthly-income* 1000)
(defparameter *index-by-category* (make-hash-table))
(defparameter *index-by-card* (make-hash-table))(defun add-liability (label amount category card)
(if (gethash category *index-by-category*)
(setf (gethash category *index-by-category*) (+ amount (gethash category *index-by-category*)))
(setf (gethash category *index-by-category*) amount))
(if (gethash card *index-by-card*)
(setf (gethash card *index-by-card*) (+ amount (gethash card *index-by-card*)))
(setf (gethash card *index-by-card*) amount)))(defun print-budget ()
(format t "~%Budget by category~%~%")
(let ((total 0))
(loop for k being each hash-key of *index-by-category*
do (setf total (+ total (gethash k *index-by-category*))))
(loop for k being each hash-key of *index-by-category*
do (format t "~A: ~$ (~$%)~%"
k
(gethash k *index-by-category*)
(* 100 (/ (gethash k *index-by-category*) *monthly-income*))))
(format t "LEFTOVER: ~$ (~$%)~%"
(- *monthly-income* total)
(* 100 (/ (- *monthly-income* total) total))))
(format t "~%Card totals~%~%")
(loop for k being each hash-key of *index-by-card*
do (format t "~A: ~$ ~%" k (gethash k *index-by-card*))))

The first function (add-liability) just indexes my budget totals into hash tables by category (*index-by-category*) and payment card (*index-by-card*). The second function (print-budget) organizes and prints the data from the hash tables in a user-friendly manner.

第一个功能( add-liability )仅按类别( *index-by-category* )和支付卡( *index-by-card* )将我的预算总额索引到哈希表中。 第二个功能( print-budget )以用户友好的方式组织并打印哈希表中的数据。

Now, adding items to my budget is as simple as passing the name as a string, the cost as a number, the category and payment card as symbols; these symbols don’t need to be defined in advance, just make up a symbol whenever you want to use it. Again, this is added to finances.lisp:

现在,将项目添加到我的预算中非常简单,只需将名称作为字符串,将费用作为数字,将类别和支付卡作为符号即可; 这些符号不需要预先定义,只要您想使用它就可以组成一个符号。 再次,这被添加到finances.lisp

(add-liability "Cellphone" 50 :bills :amex)
(add-liability "Internet" 50 :bills :discover)
(add-liability "Rent" 400 :home :debit)(print-budget)

Then I have a very short .travis-ci.yml file that runs the above script on every git commit using the fast and portable CLISP interpreter:

然后,我有一个非常短的.travis-ci.yml文件,该文件使用快速且可移植的CLISP解释器在每个git commit上运行上述脚本:

language: generic
before_install:
- sudo apt-get install clisp
script:
- clisp finances.lisp

Once I have enabled TravisCI to access my GitHub repo, after each git commit is pushed to GitHub, a TravisCI build triggers with an output like:

一旦启用TravisCI来访问我的GitHub存储库 ,将每个git commit推送到GitHub后,就会触发TravisCI构建,其输出如下:

Budget by categoryHOME: 400 (40%)
BILLS: 100 (10%)
LEFTOVER: 500 (50%)Card totalsAMEX: 50 (5%)
DISCOVER: 50 (5%)
DEBIT: 400 (40%)

Lastly, I add a TravisCI build badge to my project so that I can ensure it is passing and so that I can easily click on it from the README.md on GitHub.

最后, 我在项目中添加了TravisCI构建徽章,以确保它可以通过,并可以轻松地从GitHub上的README.md单击它。

One idiosyncratic aspect of my workflow is that I oftensly-eval-buffer with C-x c whatever script I am working on instead of gently evaluating or REPL’ing a few lines at a time. I just find this quicker for resetting state and finalizing the source file; I reserve the REPL for explorative programming and general testing. Meaning, I’d rather sly-eval-buffer my finances.lisp which will reset my two hash maps (*index-by-category* and *index-by-card*) and auto-refill their entries instead of slowly adding and removing liabilities one at a time in a REPL.

我的工作流的一个特殊方面是,我经常使用Cx c sly-eval-buffer ,而不管我正在处理什么脚本,而不是每次轻轻地评估或REPL几行。 我发现可以更快地重置状态并完成源文件的确定。 我将REPL保留用于探索性编程和常规测试。 意思是,我宁愿sly-eval-buffer我的finances.lisp ,这将重置我的两个哈希映射( *index-by-category**index-by-card* )并自动重新填充其条目,而不是缓慢地添加和在REPL中一次清除债务。

A more Lisp-y solution might be to allow for the code to add or remove a liability by name, as opposed to just indexing the cost by category and payment card. That will be left as an exercise to the interested reader.

更加Lisp-y的解决方案可能是允许代码按名称添加或删除负债,而不是仅按类别和支付卡索引成本。 这将留给有兴趣的读者练习。

翻译自: https://medium.com/@enzuru/a-simple-way-to-manage-your-budget-with-common-lisp-and-travisci-d9daf6c83d9d

 类似资料: