【问题标题】:translate-pathname behaves strangetranslate-pathname 的行为很奇怪
【发布时间】:2012-12-28 12:34:14
【问题描述】:

在这个问题之后:Strange symbols in filespec when calling load 我尝试了路径名的运气,但是,如您所见,失败了。以下是错误示例,我无法解释:

此代码不起作用:

(defun test-process-imgae-raw ()
  (cl-gd:with-image-from-file
      (test #P"digit-recognition:digit-7.png")
    (process-image-raw test)))

这也不行:

(defun test-process-imgae-raw ()
  (cl-gd:with-image-from-file
      (test "digit-recognition:digit-7.png")
    (process-image-raw test)))

但是这段代码可以:

(defun test-process-imgae-raw ()
  (cl-gd:with-image-from-file
      (test (translate-logical-pathname "digit-recognition:digit-7.png"))
    (process-image-raw test)))

这也是如此:

(defun test-process-imgae-raw ()
  (cl-gd:with-image-from-file
      (test (translate-logical-pathname #P"digit-recognition:digit-7.png"))
    (process-image-raw test)))

这里是“翻译”:

(setf (logical-pathname-translations "DIGIT-RECOGNITION")
      `(("**;*.*" "/home/wvxvw/Projects/digit-recognition/**/*.*")))

这是我得到的错误:

Pathname components from SOURCE and FROM args to TRANSLATE-PATHNAME
did not match:
  :NEWEST NIL
   [Condition of type SIMPLE-ERROR]

Restarts:
 0: [RETRY] Retry SLIME REPL evaluation request.
 1: [*ABORT] Return to SLIME's top level.
 2: [ABORT] Abort thread (#<THREAD "repl-thread" RUNNING {1003800113}>)

Backtrace:
  0: (SB-IMPL::DIDNT-MATCH-ERROR :NEWEST NIL)
  1: (SB-IMPL::TRANSLATE-COMPONENT :NEWEST NIL :NEWEST T)
  2: (TRANSLATE-PATHNAME #P"DIGIT-RECOGNITION:DIGIT-7.PNG.NEWEST" #P"DIGIT-RECOGNITION:**;*.*" #P"/home/wvxvw/Projects/digit-recognition/**/*.*")
  3: (TRANSLATE-LOGICAL-PATHNAME #P"DIGIT-RECOGNITION:DIGIT-7.PNG.NEWEST")
  4: (SB-IMPL::QUERY-FILE-SYSTEM #P"DIGIT-RECOGNITION:DIGIT-7.PNG" :TRUENAME NIL)
  5: (PROBE-FILE #P"DIGIT-RECOGNITION:DIGIT-7.PNG")
  6: (CREATE-IMAGE-FROM-FILE #<unavailable argument> NIL)
  7: (TEST-PROCESS-IMGAE-RAW)

我正在尝试阅读有关 translate-pathname 的 Hyperspec 部分,但我完全无法理解它所说的内容,无论是从它显示的示例中。更别说它了,我什至无法理解,如果你按照你设置的任何规则来转换一个字符串,怎么可能会出错,到目前为止,这只是一种方式的转换......

我正在尝试阅读此函数的 SBCL 源代码,但它们确实很长,并且尝试以这种方式找出问题需要花费大量时间。

tl;dr 从用户代码调用的translate-logical-pathname 怎么可能产生与从系统代码调用该函数产生的不同的东西?这不仅是不可移植的,而且完全被破坏了。

编辑:

向左侧的模式添加一个星号,但不在右侧解决了这个问题。但是为什么有必要这样做的目的或逻辑超出了我的范围。

(setf (logical-pathname-translations "DIGIT-RECOGNITION")
      `(("**;*.*.*" "/home/wvxvw/Projects/digit-recognition/**/*.*")))

这允许像digit-recognition:foo.bar.newest 这样的路径名成功,就像digit-recognition:foo.bar 一样,但是为什么这个星号是一个要求超出我的范围。另外,为什么系统函数感觉有权将路径名更改为它所给定的其他名称?.. 但为了不让你感到困惑,with-image-from-file 将仅适用于已由translate-logical-pathname 扩展的路径,它赢了否则不行。

EDIT2:

好的,这似乎是cl-gd 的问题,而不是尝试扩展文件名,而是从字面上理解。这段取自create-image-from-file 的代码可能最好地回答了我的问题:

(when (pathnamep file-name)
  (setq file-name
          #+:cmu (ext:unix-namestring file-name)
          #-:cmu (namestring file-name)))
(with-foreign-object (err :int)
  (with-cstring (c-file-name file-name)
    (let ((image (ecase %type
                   ((:jpg :jpeg)
                     (gd-image-create-from-jpeg-file c-file-name err))

即而不是做(namestring file-name) 它必须做(namestring (trnaslate-logical-pathname file-name))。呃……

【问题讨论】:

    标签: common-lisp


    【解决方案1】:

    另一种方法是使用TRUENAME,它返回真实的文件名。通常这不会有什么不同。

    映像具有文件版本的文件系统(如 VMS 的文件系统,...)。如果您有一个逻辑路径名foo:bar;baz.png.newest,那么它可能会转换为/myfiles/images/baz.png~newest(再次假设它具有版本号)。这仍然不是一个真正的物理文件。如果这样的 Lisp 系统试图打开文件,它必须查看文件系统以实际确定最新的文件。那可能是/myfiles/images/baz.png~42

    因此,如果您想将真实的物理文件名传递给外部工具(如 C 库),扩展逻辑路径名可能不够,但可能需要计算 truename - 真正的物理文件。

    处理文件版本的能力来自于文件版本在 ITS、VMS 或各种 Lisp Machine 操作系统等操作系统中非常普遍(参见 Versioning file system)的时代。

    主要的实际问题是,对于各种 CL 实现,没有用于路径名操作的通用测试套件,因此实现在许多细微的细节上存在差异(尤其是当您需要处理来自不同操作系统的不同文件系统时) )。另外,真实的文件系统有复杂性——例如 Mac OS X 中的文件名在处理变音符号时使用特殊的 unicode 编码。

    【讨论】:

    • @wvxvw:某些函数(例如PROBE-FILE)可能会在末尾添加版本组件。那么*.* 可能不匹配,但*.*.*
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-23
    • 1970-01-01
    相关资源
    最近更新 更多