Io 未读字符行为偏离规范?

Io 未读字符行为偏离规范?,io,stream,common-lisp,sbcl,ccl,Io,Stream,Common Lisp,Sbcl,Ccl,在未读字符的公共Lisp HyperSpec页面上,请参见 -它说明了以下两个方面: “未读字符旨在成为允许Lisp读取器和其他 解析器在输入流中执行一个字符的先行查找。“ “在同一个流上连续调用未读字符两次而没有 读取字符的中间调用(或隐式读取字符的其他输入操作) 在那条小溪上。” 我正在研究如何为一个应用程序的CL流添加多字符前瞻支持 我正计划编写解析器,为了确认上述内容,我运行了以下代码: (defun unread-char-test (data) (with-input-from-

未读字符的公共Lisp HyperSpec页面上,请参见
-它说明了以下两个方面:

  • “未读字符旨在成为允许Lisp读取器和其他 解析器在输入流中执行一个字符的先行查找。“

  • “在同一个流上连续调用未读字符两次而没有 读取字符的中间调用(或隐式读取字符的其他输入操作) 在那条小溪上。”

  • 我正在研究如何为一个应用程序的CL流添加多字符前瞻支持 我正计划编写解析器,为了确认上述内容,我运行了以下代码:

    (defun unread-char-test (data)
      (with-input-from-string (stream data)
        (let ((stack nil))
          (loop
             for c = (read-char stream nil)
             while c
             do (push c stack))
          (loop
             for c = (pop stack)
             while c
             do (unread-char c stream)))
        (coerce
         (loop
            for c = (read-char stream nil)
            while c
            collect c)
         'string)))
    
    (unread-char-test "hello")
    ==> "hello"
    
    它不会抛出错误(在SBCL或CCL上,我还没有在其他实现上测试它),但我不知道如何可能有任何读取 在连续调用之间的流上发生的操作(隐式或显式) 到
    未读字符

    这种行为对于多角色前瞻来说是个好消息,只要它是一致的,但为什么呢
    不是抛出了一个错误吗?

    为了回应用户jkiiski的评论,我做了更多的挖掘。我定义了一个与上述类似的函数,但它将流作为参数(以便于重用):

    然后,我在第二个REPL中运行了以下命令:

    (defun create-server (port)
      (usocket:with-socket-listener (listener "127.0.0.1" port)
        (usocket:with-server-socket (connection (usocket:socket-accept listener))
          (let ((stream (usocket:socket-stream connection)))
            (print "hello" stream)))))
    
    (create-server 4000)
    
    在第一份答复中:

    (defun create-client (port)
      (usocket:with-client-socket (connection stream "127.0.0.1" port)
        (unread-char-test stream)))
    
    (create-client 4000)
    
    它确实抛出了我预期的错误:

    Two UNREAD-CHARs without intervening READ-CHAR on #<BASIC-TCP-STREAM ISO-8859-1 (SOCKET/4) #x302001813E2D>
       [Condition of type SIMPLE-ERROR]
    

    我设想,在处理本地文件I/O时,实现将文件的大块读取到内存中,然后
    readchar
    从缓冲区读取。如果正确的话,这也支持这样一种假设,即当从内容在内存中的流中读取时,规范中描述的错误不是由典型的实现引发的。

    我假设当字符串在内存中且未读取时,开发人员在字符串输入流中读取多个字符时不会发出错误信号基本上只是减少当前索引。在CLISP中,这是一个错误
    Two UNREAD-CHARs without intervening READ-CHAR on #<BASIC-TCP-STREAM ISO-8859-1 (SOCKET/4) #x302001813E2D>
       [Condition of type SIMPLE-ERROR]
    
    (with-open-file (stream "test.txt" :direction :output)
      (princ "hello" stream))
    
    (with-open-file (stream "test.txt")
      (unread-char-test stream)))
    ==> "hello"