nodgui 和 SBCL(?): 如何从一开始就避免类型错误“绑定 STREAM 时,值 NIL 不是 STREAM 类型”?

问题描述 投票:0回答:1

当我开始尝试 Common Lisp GUI 编程包时,我总是在很早的阶段就遇到问题。我正在将 SBCL 2.1.1 和 2.3.8 与 Debian“Bullseye”一起使用,目前,我想通过 LTk 示例了解其用法。

(with-nodgui())中的hello world例子是没有问题的。然而,如果谈到“第一个(真实的)例子”,从

开始
(wm-title *tk* "Feet to Metres")

我最终在调试器中遇到了本文主题中提到的情况(在 Slime 中,例如在 shell 中)。

您可以很容易地认识到我与专家相反,因为此类错误消息总是压倒我寻找起点寻找原因的能力。

当我尝试编译以下不带 WM-TITLE 的 LET 形式的示例时

(let ((content (make-instance 'frame)))
  (...))

错误消息保持不变。

您可以给我提示如何避免吗?这对我来说是一份提前的圣诞礼物。

(通过尝试 CLisp,我几乎要“交叉检查”SBCL 的刚性是否存在问题。但我必须意识到,因此我必须参与一些用于设置 CLisp 的初始配置工作,因为它没有”不想快速加载:nodgui 开箱即用,更不用说找到 ASDF ...而且我真的(!)不想打开一个新的烦人的[一个posteriori微小]问题区域。我只是想要按照示例来设计我想要的 GUI,而不是在不知道为什么的情况下最终进入调试器 - 让我哭泣......并且我想使用 SBCL 来做到这一点)

致以诚挚的问候

P.S.:关注回溯可能会有所帮助 - 但不幸的是,在这个级别上不适合我。

Backtrace:
  0: ((FLET SB-THREAD::WITH-RECURSIVE-LOCK-THUNK :IN FLUSH-WISH))
  1: ((FLET "WITHOUT-INTERRUPTS-BODY-11" :IN SB-THREAD::CALL-WITH-RECURSIVE-LOCK))
  2: (SB-THREAD::CALL-WITH-RECURSIVE-LOCK #<FUNCTION (FLET SB-THREAD::WITH-RECURSIVE-LOCK-THUNK :IN FLUSH-WISH) {53B59E7B}> #<SB-THREAD:MUTEX "Anonymous recursive lock" taken owner=worker> T NIL)
  3: ((FLET "WITHOUT-INTERRUPTS-BODY-11" :IN SB-THREAD::CALL-WITH-RECURSIVE-LOCK))
  4: (SB-THREAD::CALL-WITH-RECURSIVE-LOCK #<FUNCTION (FLET SB-THREAD::WITH-RECURSIVE-LOCK-THUNK :IN NODGUI::SEND-WISH) {7F325273612B}> #<SB-THREAD:MUTEX "Anonymous recursive lock" taken owner=worker> T NIL..
  5: (NODGUI::SEND-WISH "wm title . {Feet to Metres}")
      Locals:
        #:ITEM = "wm title . {Feet to Metres}"
  6: ((:METHOD WM-TITLE (WIDGET T)) #<WIDGET {10079B22E3}> "Feet to Metres") [fast-method]
      Locals:
        TITLE = "Feet to Metres"
        NODGUI::W = #<WIDGET {10079B22E3}>
  7: (SB-INT:SIMPLE-EVAL-IN-LEXENV (WM-TITLE *TK* "Feet to Metres") #<NULL-LEXENV>)
  8: (EVAL (WM-TITLE *TK* "Feet to Metres"))
  9: ((LAMBDA NIL :IN SWANK:INTERACTIVE-EVAL))
 10: (SWANK::CALL-WITH-RETRY-RESTART "Retry SLIME interactive evaluation request." #<FUNCTION (LAMBDA NIL :IN SWANK:INTERACTIVE-EVAL) {1008258DAB}>)
 11: (SWANK::CALL-WITH-BUFFER-SYNTAX NIL #<FUNCTION (LAMBDA NIL :IN SWANK:INTERACTIVE-EVAL) {1008258D8B}>)
      Locals:
        FUN = #<FUNCTION (LAMBDA () :IN SWANK:INTERACTIVE-EVAL) {1008258D8B}>
        PACKAGE = NIL
 12: (SB-INT:SIMPLE-EVAL-IN-LEXENV (SWANK:INTERACTIVE-EVAL "(wm-title *tk* \"Feet to Metres\")") #<NULL-LEXENV>)
 13: (EVAL (SWANK:INTERACTIVE-EVAL "(wm-title *tk* \"Feet to Metres\")"))
 14: (SWANK:EVAL-FOR-EMACS (SWANK:INTERACTIVE-EVAL "(wm-title *tk* \"Feet to Metres\")") "COMMON-LISP-USER" 38)
      Locals:
        BUFFER-PACKAGE = "COMMON-LISP-USER"
        CONDITION = #<TYPE-ERROR expected-type: STREAM datum: NIL>
        FORM = (SWANK:INTERACTIVE-EVAL "(wm-title *tk* \"Feet to Metres\")")
        ID = 38
        OK = NIL
        RESULT = NIL
 15: ((LAMBDA NIL :IN SWANK::SPAWN-WORKER-THREAD))
      [No Locals]
 16: (SWANK/SBCL::CALL-WITH-BREAK-HOOK #<FUNCTION SWANK:SWANK-DEBUGGER-HOOK> #<FUNCTION (LAMBDA NIL :IN SWANK::SPAWN-WORKER-THREAD) {539F452B}>)
 17: ((FLET SWANK/BACKEND:CALL-WITH-DEBUGGER-HOOK :IN "/home/old/jochen/Desktop/Arbeit/Akademisch/Forschung/Grundlagen/Lisp/slime-4-atom/slime/swank/sbcl.lisp") #<FUNCTION SWANK:SWANK-DEBUGGER-HOOK> #<FUNC..
 18: (SWANK::CALL-WITH-BINDINGS ((*STANDARD-INPUT* . #<SWANK/GRAY::SLIME-INPUT-STREAM {10018609B3}>)) #<FUNCTION (LAMBDA NIL :IN SWANK::SPAWN-WORKER-THREAD) {539F47DB}>)
 19: ((LAMBDA NIL :IN SWANK::SPAWN-WORKER-THREAD))
 20: ((FLET SB-UNIX::BODY :IN SB-THREAD::RUN))
 21: ((FLET "WITHOUT-INTERRUPTS-BODY-174" :IN SB-THREAD::RUN))
 22: ((FLET SB-UNIX::BODY :IN SB-THREAD::RUN))
 23: ((FLET "WITHOUT-INTERRUPTS-BODY-167" :IN SB-THREAD::RUN))
 24: (SB-THREAD::RUN)
 25: ("foreign function: call_into_lisp_")
 26: ("foreign function: funcall1")
common-lisp tk-toolkit sbcl
1个回答
0
投票

也许这就是你加载所有东西的方式。让我们从头开始:

  • 快速加载“nodgui”。这取代了“require”行。
  • 让我们创建一个“使用”nodgui 的包。这取代了“use-package”行。
(defpackage :feet-to-meter
  (:use :cl :nodgui))
  • 我们将把代码写入我们的包中,并提供所有 nodgui 函数和变量。
(in-package :feet-to-meter)
  • 我将代码粘贴到函数中:
(defun feet-to-meter ()
  (with-nodgui ()
    (wm-title *tk* "Feet to Metres")         ; 1
    (let ((content (make-instance 'frame)))  ; 2
      (configure content :padding "3 3 12 12") ; 3
      (grid content 0 0 :sticky "nsew")
      (grid-columnconfigure *tk* 0 :weight 1)
      (grid-rowconfigure *tk* 0 :weight 1)

      (let* ((feet-entry (make-instance 'entry :master content :width 7)) ; 4
             (metres-label (make-instance 'label :master content :text "")))
        (flet ((calculate ()            ; 5
                 (let ((feet (read-from-string (text feet-entry))))
                   (setf (text metres-label)
                         (if (numberp feet)
                             (/ (round (* 0.3048 feet 10000.0)) 10000.0)
                             "")))))
                                        ; top row has the entry widget and explanatory label to its right
          (grid feet-entry 1 2 :sticky "we" :padx 5 :pady 5) ; 6
          (grid (make-instance 'label :master content :text "feet")
                1 3 :sticky "w" :padx 5 :pady 5)
                                        ; middle row has three labels
          (grid (make-instance 'label :master content :text "is equivalent to")
                2 1 :sticky "e" :padx 5 :pady 5)
          (grid metres-label 2 2 :sticky "we" :padx 5 :pady 5)
          (grid (make-instance 'label :master content :text "metres")
                2 3 :sticky "w" :padx 5 :pady 5)
                                        ; last row has the button on right
          (grid (make-instance 'button :master content ; 7
                                       :text "Calculate"
                                       :command #'calculate)
                3 3 :sticky "w" :padx 5 :pady 5)

          (focus feet-entry)            ; 8
          (bind *tk* "<Return>" (lambda (evt) (calculate))))))
    ))
  • 尝试一下:

    英尺到米>(英尺到米)

© www.soinside.com 2019 - 2024. All rights reserved.