英文:
How to define caveman2 routes in multiple files/packages?
问题
I want to have routes defined over multiple files, not just web.lisp. What is the correct way of doing this?
我想在多个文件中定义路由,而不仅仅是在web.lisp中。正确的做法是什么?
I tried writing another file with this code and it works:
我尝试编写另一个文件,并使用以下代码,它可以正常工作:
(in-package :mywebapp.web)
;; for @route annotation
(syntax:use-syntax :annot)
(defroute "/hello" ()
(format nil "Hello World!"))
However, what I thought was the correct approach was to have another package definition and then either import :mywebapp.web
into my new package, or import my new package :mywebapp.controllers.hello
into :mywebapp.web
.
然而,我认为正确的方法是创建另一个包定义,然后要么将 :mywebapp.web
导入到我的新包中,要么将我的新包 :mywebapp.controllers.hello
导入到 :mywebapp.web
中。
Can you please explain to me the correct approach?
你能否向我解释正确的方法?
When I created my own package and imported :mywebapp.web
I got the following error:
当我创建自己的包并导入 :mywebapp.web
时,我收到以下错误消息:
There is no applicable method for the generic function
#<STANDARD-GENERIC-FUNCTION (COMMON-LISP:SETF NINGLE/APP:ROUTE) (1)>
when called with arguments
(#<FUNCTION (LAMBDA (#:PARAMS1141)
:IN
"/project/src/controllers/hello.lisp") {53CE5F6B}>
NIL "/hello").
See also:
The ANSI Standard, Section 7.6.6
However I had imported into the new packages all the same imports as in the .web
package...
但是,我已经将与.web
包中相同的导入内容导入到新包中...
Note that I redacted the path...
请注意,我已经删除了路径...
Thanks!
谢谢!
英文:
I want to have routes defined over multiple files, not just web.lisp. What is the correct way of doing this?
I tried writing another file with this code and it works:
(in-package :mywebapp.web)
;; for @route annotation
(syntax:use-syntax :annot)
(defroute "/hello" ()
(format nil "Hello World!"))
However, what I thought was the correct approach was to have another package definition and then either import :mywebapp.web
into my new package, or import my new package :mywebapp.controllers.hello
into :mywebapp.web
.
Can you please explain to me the correct approach?
When I created my own package and imported :mywebapp.web
I got the following error:
There is no applicable method for the generic function
#<STANDARD-GENERIC-FUNCTION (COMMON-LISP:SETF NINGLE/APP:ROUTE) (1)>
when called with arguments
(#<FUNCTION (LAMBDA (#:PARAMS1141)
:IN
"/project/src/controllers/hello.lisp") {53CE5F6B}>
NIL "/hello").
See also:
The ANSI Standard, Section 7.6.6
However I had imported into the new packages all the same imports as in the .web
package...
Note that I redacted the path...
Thanks!
答案1
得分: 2
在CL-USER包中(在REPL中),我编写了以下表达式,并请求Emacs/Slime对其进行宏展开:
(caveman2:defroute "/hello" ())
结果如下:
(SETF (APPLY #'NINGLE/APP:ROUTE
(CONS
(CAVEMAN2.APP:FIND-PACKAGE-APP #<PACKAGE "COMMON-LISP-USER">)
(LIST "/hello")))
(LAMBDA (#:PARAMS1721) (DECLARE (IGNORABLE #:PARAMS1721))))
这对应于您的错误,因为最终在将apply
与(cons ...)
表达式结合时,代码将调用route
,传递find-package-app
和"/hello"
的结果。
但在您的情况下,find-package-app
的结果是NIL,表示未找到这样的应用程序。我可能预期在这里会有更好的错误消息,但无论如何,解决方法是明确指定应用程序:
(caveman2:defroute (other-package:*app* "/hello") ())
这个宏展开为:
(SETF (APPLY #'NINGLE/APP:ROUTE (LIST OTHER-PACKAGE:*APP* "/hello"))
(LAMBDA (#:PARAMS1723) (DECLARE (IGNORABLE #:PARAMS1723))))
然而,关于这个问题的文档很少,我不得不查看源代码。
基本上,当应用程序被实例化时,*package*
的当前值被捕获并关联到应用程序实例的哈希表中。
英文:
So, in package CL-USER (in the REPL) I wrote the following form and asked Emacs/Slime for its macroexpansion:
(caveman2:defroute "/hello" ())
The result is:
(SETF (APPLY #'NINGLE/APP:ROUTE
(CONS
(CAVEMAN2.APP:FIND-PACKAGE-APP #<PACKAGE "COMMON-LISP-USER">)
(LIST "/hello")))
(LAMBDA (#:PARAMS1721) (DECLARE (IGNORABLE #:PARAMS1721))))
This corresponds to your error, because ultimately when combining apply
with the (cons ...)
forms, the code will be calling route
with the result of find-package-app
and "/hello"
.
But in your case, the result of find-package-app
is NIL, meaning no such app was found. I probably would have expected a better error message here, but anyway the solution is to explicitly specify the application:
(caveman2:defroute (other-package:*app* "/hello") ())
This macroexpands as:
(SETF (APPLY #'NINGLE/APP:ROUTE (LIST OTHER-PACKAGE:*APP* "/hello"))
(LAMBDA (#:PARAMS1723) (DECLARE (IGNORABLE #:PARAMS1723))))
There is however little documentation about that, I had to look at the source code.
Basically when an application is instantiated, the current value of *package*
is captured and associated in a hash-table to the application instance.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论