开始使用大型Lisp“图书馆” (日历计算)

发布于 2025-02-10 03:35:38 字数 995 浏览 1 评论 0 原文

我曾经通过Cadence Design Systems编写小型LISP程序和中型程序。我现在想使用带有日历计算的LISP函数的“库” -Science/Computing General-rest/caldentrical-calcoulation-ultimate-edition-edition-edition-th-edition?格式= hb#bvcwevjdd9zjexq7.97“ rel =“ nofollow noreferrer”>从剑桥大学下载(供个人使用)

我在Windows 10计算机上安装了口红包(以前从未使用过)。 (至少我已经使用了emacs)。我一直在使用Peter Seibel(2005)的实用Common Lisp 作为文本。

我想开始在repl中给单个函数调用,因此我想在repl中“安装”“库”。我将单词放在引号中,因为我不确定要使用的适当的LISP单词。我只是尝试加载文件,但失败了,所以我尝试了

(compile-file "calendar.l")

,并且

; compiling file "c:/Users/card9/lispstick/calendar.l" (written 19 JUN 2022 01:12:02 PM):
; compiling (IN-PACKAGE "CC4")

在另一个缓冲区SLDB [2]中的响应中,

    The name "CC4" does not designate any package.
    [Condition of type SB-Kernel:SIMPLE-PACKAGE-ERROR]The name "CC4" does not designate any package.
    [Condition of type SB-Kernel:SIMPLE-PACKAGE-ERROR]

我的响应是我的问题是我应该对LISP文件进行什么更改日历功能使我可以编译和加载它,或者我应该使用哪些其他方法来访问这些功能?

I used to write small Lisp programs, and medium programs in a derivative, Skill, by Cadence Design Systems. I now want to use the "library" of Lisp functions that comes with Calendrical Calculations and which can be downloaded (for personal use) from Cambridge University.

I installed the Lipstick package (which I have not worked with before) on my Windows 10 computer. (At least I've used Emacs). I've been using Practical Common Lisp by Peter Seibel (2005) as a text.

I want to start by giving individual function calls in the REPL, so I want to "install" the "library" in the REPL. I put the words in quotes because I'm not sure the proper Lisp words to use. I tried to just load the file and that failed, so I tried

(compile-file "calendar.l")

and the response in the REPL buffer was

; compiling file "c:/Users/card9/lispstick/calendar.l" (written 19 JUN 2022 01:12:02 PM):
; compiling (IN-PACKAGE "CC4")

The response in the other buffer, sldb[2], was

    The name "CC4" does not designate any package.
    [Condition of type SB-Kernel:SIMPLE-PACKAGE-ERROR]The name "CC4" does not designate any package.
    [Condition of type SB-Kernel:SIMPLE-PACKAGE-ERROR]

So my question is what changes should I make to the Lisp file with all the calendar functions so I can compile and load it, or alternatively, what other approach should I use to access the functions?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

那一片橙海, 2025-02-17 03:35:39

这既是非常古老的代码,也不写得不好。如果您使用比SBCL不太严格的编译器,您可能会更有可能使其变得更容易工作:我可以编译并加载它在Lispworks和Clozure CL中,但是当试图使SBCL编译时,我最终失去了生存的意愿。

请参阅下面的建议解决方法,可以与SBCL一起使用。

您可以解决的问题:包问题

这些是您将要遇到的第一件事,而此答案的第一个版本仅处理此问题。此代码似乎依靠语义 in In-takage 在1980年代消失(具体来说,似乎, 1989 )!

fix(也许请参见下文)是

(in-package "CC4")
...
(export ...)

或者

(defpackage "CC4"
  (:use "CL")
  (:export ...))

(in-package "CC4")

将导出的名称变成一个字符串(带有上层名称的字符串)的地方, 也许更容易,无临界的符号(##:的前缀名称,因此(导出...'foo ...)变成(:export> export ... export ...## :foo ...) defpackage 表单中)。

一个更轻松的修复程序,涉及对代码的较小编辑,因此可能是优选的,是放置在(包装“ CC4”)之前,表格,此:

(defpackage "CC4"
  (:use "CL"))

另一个修复程序只是为了预先定义避免编辑文件的软件包:请参见下文。

完成此操作后,您至少应该在编译文件时进行一次镜头。如果有效(可能还有其他问题),那么您可以加载它,然后需要说

(use-package "CC4")

defconstant 问题,第一部分

在许多地方使用 defconstant 如果常数的值取决于其他函数,

(defconstant jd-epoch
  ;; TYPE moment
  ;; Fixed time of start of the julian day number.
  (rd -1721424.5L0))

则首先是用 defconstant 定义的事物的值,需要在编译时知道:

如果 defconstant 表单以最高级别的形式出现,则编译器必须识别该名称名称为常数变量。实施可以选择在编译时间,加载时间或两者兼而有之评估价值形式。因此,用户必须确保可以在编译时评估初始值(无论对名称是否出现在文件中),并且始终将其评估为相同的值。

编译文件时并非如此。

解决此问题的修复是要包装所谓的函数以计算合适的 defconstant 表单中的任何值, eval- eval- ,所以

(defun rd (tee)
  ...)

看起来还可以

(eval-when (:compile-toplevel :load-toplevel :execute)
  (defun rd (tee)
    ...))

,但是您可以得到这个:

(defconstant icelandic-epoch
  ;; TYPE fixed-date
  ;; Fixed date of start of the Icelandic calendar.
  (fixed-from-gregorian (gregorian-date 1 april 19)))

现在固定从gregorian gregorian-date 需要用 eval-eval-eval-eval-when 包装,他们致电或参考

好吧,除了追踪代码以查找需要包装的所有功能外,还有两个解决方案。

首先是将 defconstant s更改为 fefparameter s,并希望代码中的任何内容都没有尝试分配或以其他方式陷入变量。这将降低性能,但这可能并不重要。

另一个是做传统的事情,即这样的可怕系统经常在CL的史前史前需要进行:在尝试编译系统之前,加载其解释。这是一个小的包装器文件,它将尝试执行此操作,并且还可以预先定义包:

;;;;; Try to compile & load calendar.l
;;;

(in-package :cl-user)

;;; Define the package to avoid doom
;;;
(defpackage "CC4"
  (:use "CL"))

(let ((source (merge-pathnames (pathname "calendar.l") *load-truename*)))
  ;; Load the source, compile it and load that.
  (load source)
  (load (compile-file source)))

defconstant 第二部分:订购:

如果您查看代码,请在第1596行中找到固定从使用 summer 免费。 summer 定义为第4142行中的常数。因此,这意味着 compile-file 可以做一个不错的工作来编译固定的工作-Icelandic :自由变量需要在编译之前是常数。

但是,首先加载解释的文件也可以解决。

defconstant 第三部分:最终崩溃

这是我放弃SBCL的地方。 SBCL具有 defconstant ) ,我认为以上从规范引用的子句。这意味着像

(defconstant foo '(1 2))

在sbcl 中基本上是不可能的。该链接背后描述了一些解决方法。

好吧,这意味着确实没有机会使用SBCL编译此代码,因为有很多这样的情况,并且在加载解释的版本之后,还有很少的机会编译它,我们需要做。

其他CL实现对此不太严格,并且会很高兴。

放弃了,解决方法

可能有可能使SBCL编译该代码的一些衍生物,但是需要进行大量修改。甚至不那么挑剔的编译器吐出了许多合理的警告。

但是,我的强烈怀疑是,此代码从未被编译。因此,一个解决方法是简单地不尝试编译文件:修改加载程序垫片以:

;;;;; Try to load calendar.l
;;;

(in-package :cl-user)

;;; Define the package to avoid doom
;;;
(defpackage "CC4"
  (:use "CL"))

;;; Don't even try to compile the file
(load (merge-pathnames (pathname "calendar.l") *load-truename*))

这样做,即使SBCL也会加载文件。 SBCL将吐出很多警告,因为它是仅编译器的实现,因此会汇编单个定义。

那么,由此产生的事情是否会工作是另一个问题,但是它 will 负载。


注意:通常,这是一件特别不幸的事情

,这是一件特别不幸的事情:大多数CL代码不是 之类的东西。

This is both very old code and not well written. You would probably stand more chance of making it work easily if you used a less strict compiler than SBCL: I can compile and load it in LispWorks and Clozure CL but I eventually lost the will to live when trying to make SBCL compile it.

See below for a suggested workaround which may work with SBCL.

Something you can fix: the package problems

These are the first things you will run across, and the first version of this answer dealt only with this. This code appears to rely on semantics for in-package which went away in the 1980s (specifically, it seems, 1989)!

The right fix (see below for an easier one perhaps) is to change the

(in-package "CC4")
...
(export ...)

to something like

(defpackage "CC4"
  (:use "CL")
  (:export ...))

(in-package "CC4")

Where the exported names should be turned into either strings (with the string containing the upper-cased name), or, perhaps easier, uninterned symbols (prefix name by #:, so (export ... 'foo ...) turns into (:export ... #:foo ...) in the defpackage form).

An easier fix which involves a smaller edit to the code, and is thus probably preferable, would be to place, before the (in-package "CC4") form, this:

(defpackage "CC4"
  (:use "CL"))

Another fix is just to predefine the package which avoids editing the file: see below.

Once you have done this you should have at least a shot at compiling the file. If that works (there may be other problems) then you can load it and would then need to say

(use-package "CC4")

defconstant problems, part one

There are a number of places where defconstant is used where the value of the constant depends on other functions, the first being

(defconstant jd-epoch
  ;; TYPE moment
  ;; Fixed time of start of the julian day number.
  (rd -1721424.5L0))

But the value of something defined with defconstant needs to be known at compile time:

If a defconstant form appears as a top level form, the compiler must recognize that name names a constant variable. An implementation may choose to evaluate the value-form at compile time, load time, or both. Therefore, users must ensure that the initial-value can be evaluated at compile time (regardless of whether or not references to name appear in the file) and that it always evaluates to the same value.

And this is not the case when compiling the file.

The fix for this is either to wrap the functions called to compute the values of any defconstant form in a suitable eval-when, so

(defun rd (tee)
  ...)

Would become

(eval-when (:compile-toplevel :load-toplevel :execute)
  (defun rd (tee)
    ...))

And this looks OK, but then you get this:

(defconstant icelandic-epoch
  ;; TYPE fixed-date
  ;; Fixed date of start of the Icelandic calendar.
  (fixed-from-gregorian (gregorian-date 1 april 19)))

And now fixed-from-gregorian and gregorian-date need to be wrapped in eval-when as does anything they call or refer to.

Well, other than tracing through the code to find all the functions which need to be wrapped there are two workarounds to this problem.

The first is to change the defconstants to defparameters and hope that nothing in the code tries to assign or otherwise muck around with the variable. This will reduce performance but that probably does not matter.

The other is to do the traditional thing that terrible systems like this often used to require in the prehistory of CL: before you attempt to compile the system, load it interpreted. Here is a little wrapper file which will try to do this, and which also predefines the package:

;;;;; Try to compile & load calendar.l
;;;

(in-package :cl-user)

;;; Define the package to avoid doom
;;;
(defpackage "CC4"
  (:use "CL"))

(let ((source (merge-pathnames (pathname "calendar.l") *load-truename*)))
  ;; Load the source, compile it and load that.
  (load source)
  (load (compile-file source)))

defconstants part two: order

If you look at the code you will find at line 1596 a definition of fixed-from-icelandic which uses summer free. summer is defined as a constant at line 4142. So this means that there is essentially no way that compile-file can do a decent job of compiling fixed-from-icelandic: the free variable needs to be known to be a constant before it's compiled.

This is also resolved by loading the file interpreted first however.

defconstants part three: the final collapse

This is where I gave up with SBCL. SBCL has a very strict interpretation of defconstant, based I think on the clause cited above from the spec. That means that things like

(defconstant foo '(1 2))

Are essentially impossible in SBCL. There are workarounds described behind that link.

Well, that means that there's really no chance of compiling this code with SBCL because there are lots of cases like this, and still less are there chances of compiling it after loading the interpreted version, which we need to do.

Other CL implementations are less strict about this and will be happy.

Giving up, and a workaround

It would probably be possible to get SBCL to compile some derivative of this code, but it would need to be significantly modified. Even less fussy compilers spit out a lot of justified warnings.

However my strong suspicion is that this code has never been compiled. So one workaround would be to simply not try and compile the file: modify the loader shim to be:

;;;;; Try to load calendar.l
;;;

(in-package :cl-user)

;;; Define the package to avoid doom
;;;
(defpackage "CC4"
  (:use "CL"))

;;; Don't even try to compile the file
(load (merge-pathnames (pathname "calendar.l") *load-truename*))

Doing that will let even SBCL load the file. SBCL will spit out a lot of warnings as it compiles individual definitions, since it's a compiler-only implementation.

Whether the resulting thing will then work is another question, but it will load.


A note: it's not usually this bad

This is a particularly unfortunate thing to start with: most CL code is not anything like as awful as this.

錯遇了你 2025-02-17 03:35:39

仅供参考,作为将不大惊小怪的替代方案,我将常见的LISP代码适应了另一个LISP方言,clojure:

我正在与正在以 iCu4x ,用生锈写。能够与代码进行交互式工作将使他们内省和调试其翻译功能并创建测试用例。

原始的CLISP代码不干净,因此改编版的版本仍然需要一些修复程序:使用Clojure的声明创建前向声明来处理排序外 def /code>/ defn s,并修复一两个错字。

FYI, as an alternative that will work without fuss, I adapated the Common Lisp code into another Lisp dialect, Clojure: https://github.com/echeran/calendar-code2

I'm working with teammates who are implementing new calendar systems in ICU4X, which is written in Rust. Being able to work with the code interactively will allow them to introspect and debug their translated functions and create test cases.

The original CLisp code isn't clean, so the adapted version still needed some fixups: using Clojure's declare to create forward declarations to handle out-of-order def/defns, and fixing a typo or two.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文