Replies: 9 comments
-
I tried the same script in sbl without problem, so I think this might be a problem with the Medley cl:loop not handling nested iterations. (Whether in the sacla implementation or my result of loading that into Medley, I don't know.) I didn't see a simple fix, so I'd suggest an issue. I got with-hash-table-iterator working but with-package-iterator is harder and I might put it on the shelf. |
Beta Was this translation helpful? Give feedback.
-
I opened issue #1614. Since the two |
Beta Was this translation helpful? Give feedback.
-
I would have to think about this more than I can do on a phone, but I think that
may not be legal. In particular this is because the syntax is
and (And yes, that's stupid but this is So if that is the case this is just not legal CL, even though the error message is not helpful here. However as I said I am reading all this on a phone. |
Beta Was this translation helpful? Give feedback.
-
it's easy enough to turn and sbcl supports it, but it's a DWIMish kind of thing to fix up non-conforming code. |
Beta Was this translation helpful? Give feedback.
-
CodeI rewrote the (define-condition malformed-log-entry-error (error)
((text :initarg :text :reader text)))
(defun well-formed-log-entry-p (text)
(not (search "MALFORMED" text)))
(defclass log-entry ()
((message :initarg :message :accessor message)))
(defun parse-log-entry (text)
(if (well-formed-log-entry-p text)
(make-instance 'log-entry :message text)
(error 'malformed-log-entry-error :text text)))
(parse-log-entry "Well formed")
(parse-log-entry "MALFORMED")
(defun create-log-file (file)
(with-open-file (s file :direction :output :if-exists :supersede)
(dotimes (i 10)
(format s "~&Log message ~a~%" i))
(format s "~&MALFORMED~%")))
(create-log-file "pclchap19.log")
(defun parse-log-file (file)
(with-open-file (in file :direction :input)
(do* (result
(text (read-line in nil nil) (read-line in nil nil))
(entry (handler-case (parse-log-entry text)
(malformed-log-entry-error () nil))
(handler-case (parse-log-entry text)
(malformed-log-entry-error () nil))))
((not text) (nreverse result))
(when entry (push entry result)))))
(parse-log-file "pclchap19.log")
(defun skip-log-entry (c)
(invoke-restart 'skip-log-entry))
(defun parse-log-file (file)
(with-open-file (in file :direction :input)
(do* (result
(text (read-line in nil nil) (read-line in nil nil))
(entry (restart-case (parse-log-entry text)
(skip-log-entry () nil))
(restart-case (parse-log-entry text)
(skip-log-entry () nil))))
((not text) (nreverse result))
(when entry (push entry result)))))
(parse-log-file "pclchap19.log")
(defun analyze-entry (entry)
(format t "~&Analyzing entry: ~a~%" entry))
(analyze-entry "This is an entry")
(defun analyze-log (log)
(dolist (entry (parse-log-file log))
(analyze-entry entry)))
(analyze-log "pclchap19.log")
(defun find-all-logs ()
(list "pclchap19.log"))
(defun log-analyzer ()
(dolist (log (find-all-logs))
(analyze-log log)))
(log-analyzer)
(defun log-analyzer ()
(handler-bind ((malformed-log-entry-error
#'(lambda (c)
(invoke-restart 'skip-log-entry))))
(dolist (log (find-all-logs))
(analyze-log log))))
(log-analyzer)
(defun log-analyzer ()
(handler-bind ((malformed-log-entry-error #'skip-log-entry))
(dolist (log (find-all-logs))
(analyze-log log))))
(log-analyzer)
(defun skip-log-entry (c)
(let ((restart (find-restart 'skip-log-entry)))
(when restart (invoke-restart restart))))
(defun parse-log-entry (text)
(if (well-formed-log-entry-p text)
(make-instance 'log-entry :message text)
(restart-case (error 'malformed-log-entry-error :text text)
(use-value (value) value)
(reparse-entry (fixed-text) (parse-log-entry fixed-text)))))
(parse-log-entry "Well formed")
(parse-log-entry "MALFORMED") ; error raised instead of RESTART-CASE
(defun log-analyzer ()
(handler-bind ((malformed-log-entry-error
#'(lambda (c)
(use-value
(make-instance 'malformed-log-entry :text (text c))))))
(dolist (log (find-all-logs))
(analyze-log log))))
(log-analyzer) IssuesEvaluating the expressions pointed out a couple of issues. The first is there doesn't seem to be any way of interactively invoking restarts or using values from the debugger, not even in the break window's middle-click menu. The other issue is an undefined function error which is likely a bug in the code and not a Medley problem. Session transcriptNow let's go over the code and the issues in the transcript of the test session. The first group of expressions worked fine, including the intentionally unhandled error: 2/8> (define-condition malformed-log-entry-error (error)
((text :initarg :text :reader text)))
MALFORMED-LOG-ENTRY-ERROR
2/9>
2/9> (defun well-formed-log-entry-p (text)
(not (search "MALFORMED" text)))
WELL-FORMED-LOG-ENTRY-P
2/10>
2/10> (defclass log-entry ()
((message :initarg :message :accessor message)))
LOG-ENTRY
2/11>
2/11> (defun parse-log-entry (text)
(if (well-formed-log-entry-p text)
(make-instance 'log-entry :message text)
(error 'malformed-log-entry-error :text text)))
PARSE-LOG-ENTRY
2/12>
2/12> (parse-log-entry "Well formed")
#<LOG-ENTRY 124,140174>
2/13>
2/13> (parse-log-entry "MALFORMED")
Serious condition MALFORMED-LOG-ENTRY-ERROR occurred.
2/14>
2/14> (defun create-log-file (file)
(with-open-file (s file :direction :output :if-exists :supersede)
(dotimes (i 10)
(format s "~&Log message ~a~%" i))
(format s "~&MALFORMED~%")))
CREATE-LOG-FILE
2/15>
2/15> (create-log-file "pclchap19.log")
NIL
2/16>
2/16> (defun parse-log-file (file)
(with-open-file (in file :direction :input)
(do* (result
(text (read-line in nil nil) (read-line in nil nil))
(entry (handler-case (parse-log-entry text)
(malformed-log-entry-error () nil))
(handler-case (parse-log-entry text)
(malformed-log-entry-error () nil))))
((not text) (nreverse result))
(when entry (push entry result)))))
PARSE-LOG-FILE
2/17>
2/17> (parse-log-file "pclchap19.log")
(#<LOG-ENTRY 124,140170> #<LOG-ENTRY 124,140164> #<LOG-ENTRY 124,140160> #<LOG-ENTRY 124,140154> #<LOG-ENTRY 124,140150> #<LOG-ENTRY 124,140144> #<LOG-ENTRY 124,140140> #<LOG-ENTRY 124,140134> #<LOG-ENTRY 124,140130> #<LOG-ENTRY 124,140124>)
2/18>
2/18> (defun skip-log-entry (c)
(invoke-restart 'skip-log-entry))
SKIP-LOG-ENTRY
2/19>
2/19> (defun parse-log-file (file)
(with-open-file (in file :direction :input)
(do* (result
(text (read-line in nil nil) (read-line in nil nil))
(entry (restart-case (parse-log-entry text)
(skip-log-entry () nil))
(restart-case (parse-log-entry text)
(skip-log-entry () nil))))
((not text) (nreverse result))
(when entry (push entry result)))))
New FUNCTIONS definition for PARSE-LOG-FILE.
PARSE-LOG-FILE
2/20> The next call broke into the debugger. The 2/20> (parse-log-file "pclchap19.log")
In EVAL:
Serious condition MALFORMED-LOG-ENTRY-ERROR occurred.
2/21: ^ The next few expressions worked as expected: 2/22> (defun analyze-entry (entry)
(format t "~&Analyzing entry: ~a~%" entry))
ANALYZE-ENTRY
2/23>
2/23> (analyze-entry "This is an entry")
Analyzing entry: This is an entry
NIL
2/24>
2/24> (defun analyze-log (log)
(dolist (entry (parse-log-file log))
(analyze-entry entry)))
ANALYZE-LOG
2/25> Then a call to 2/25> (analyze-log "pclchap19.log")
In EVAL:
Serious condition MALFORMED-LOG-ENTRY-ERROR occurred.
2/26: ^ The next couple of expressions worked as expected: 2/27> (defun find-all-logs ()
(list "pclchap19.log"))
FIND-ALL-LOGS
2/28>
2/28> (defun log-analyzer ()
(dolist (log (find-all-logs))
(analyze-log log)))
LOG-ANALYZER
2/29> But the call to 2/29> (log-analyzer)
In EVAL:
Serious condition MALFORMED-LOG-ENTRY-ERROR occurred.
2/30: ^ The next group of expressions worked fine: 2/31> (defun log-analyzer ()
(handler-bind ((malformed-log-entry-error
#'(lambda (c)
(invoke-restart 'skip-log-entry))))
(dolist (log (find-all-logs))
(analyze-log log))))
New FUNCTIONS definition for LOG-ANALYZER.
LOG-ANALYZER
2/32>
2/32> (log-analyzer)
Analyzing entry: #<LOG-ENTRY 124,140120>
Analyzing entry: #<LOG-ENTRY 124,140114>
Analyzing entry: #<LOG-ENTRY 124,140110>
Analyzing entry: #<LOG-ENTRY 124,140104>
Analyzing entry: #<LOG-ENTRY 124,140100>
Analyzing entry: #<LOG-ENTRY 124,140074>
Analyzing entry: #<LOG-ENTRY 124,140070>
Analyzing entry: #<LOG-ENTRY 124,140064>
Analyzing entry: #<LOG-ENTRY 124,140060>
Analyzing entry: #<LOG-ENTRY 124,140054>
NIL
2/33>
2/33> (defun log-analyzer ()
(handler-bind ((malformed-log-entry-error #'skip-log-entry))
(dolist (log (find-all-logs))
(analyze-log log))))
New FUNCTIONS definition for LOG-ANALYZER.
LOG-ANALYZER
2/34>
2/34> (log-analyzer)
Analyzing entry: #<LOG-ENTRY 124,140044>
Analyzing entry: #<LOG-ENTRY 124,140040>
Analyzing entry: #<LOG-ENTRY 124,140034>
Analyzing entry: #<LOG-ENTRY 124,140030>
Analyzing entry: #<LOG-ENTRY 124,140024>
Analyzing entry: #<LOG-ENTRY 124,140020>
Analyzing entry: #<LOG-ENTRY 124,140014>
Analyzing entry: #<LOG-ENTRY 124,140010>
Analyzing entry: #<LOG-ENTRY 124,140120>
Analyzing entry: #<LOG-ENTRY 124,140114>
NIL
2/35>
2/35> (defun skip-log-entry (c)
(let ((restart (find-restart 'skip-log-entry)))
(when restart (invoke-restart restart))))
New FUNCTIONS definition for SKIP-LOG-ENTRY.
SKIP-LOG-ENTRY
2/36>
2/36> (defun parse-log-entry (text)
(if (well-formed-log-entry-p text)
(make-instance 'log-entry :message text)
(restart-case (error 'malformed-log-entry-error :text text)
(use-value (value) value)
(reparse-entry (fixed-text) (parse-log-entry fixed-text)))))
New FUNCTIONS definition for PARSE-LOG-ENTRY.
PARSE-LOG-ENTRY
2/37>
2/37> (parse-log-entry "Well formed")
#<LOG-ENTRY 124,140104>
2/38> The 2/38> (parse-log-entry "MALFORMED")
Serious condition MALFORMED-LOG-ENTRY-ERROR occurred.
2/39> Finally, the call to 2/39> (defun log-analyzer ()
(handler-bind ((malformed-log-entry-error
#'(lambda (c)
(use-value
(make-instance 'malformed-log-entry :text (text c))))))
(dolist (log (find-all-logs))
(analyze-log log))))
New FUNCTIONS definition for LOG-ANALYZER.
LOG-ANALYZER
2/40> (log-analyzer)
In IL:ERROR:
Undefined car of form
TEXT
2/41: ^ |
Beta Was this translation helpful? Give feedback.
-
there is a problem #821 which describes the situation. The decision of when to break and when to just stop is "empirical" and the numbers were made for a different time. Secondly, once you are in a BREAK window, the "OK" command will prompt you for the "proceed" case. This doesn't explain the "undefined function TEXT" problem, but might reduce the number problems found during testing. |
Beta Was this translation helpful? Give feedback.
-
The fixI rerun the tests and the debugger's Session transcriptNIL
2/8> (define-condition malformed-log-entry-error (error)
((text :initarg :text :reader text)))
MALFORMED-LOG-ENTRY-ERROR
2/9>
2/9> (defun well-formed-log-entry-p (text)
(not (search "MALFORMED" text)))
WELL-FORMED-LOG-ENTRY-P
2/10>
2/10> (defclass log-entry ()
((message :initarg :message :accessor message)))
LOG-ENTRY
2/11>
2/11> (defun parse-log-entry (text)
(if (well-formed-log-entry-p text)
(make-instance 'log-entry :message text)
(error 'malformed-log-entry-error :text text)))
PARSE-LOG-ENTRY
2/12>
2/12> (parse-log-entry "Well formed")
#<LOG-ENTRY 124,140174>
2/13>
2/13> (parse-log-entry "MALFORMED")
Serious condition MALFORMED-LOG-ENTRY-ERROR occurred.
2/14>
2/14> (defun create-log-file (file)
(with-open-file (s file :direction :output :if-exists :supersede)
(dotimes (i 10)
(format s "~&Log message ~a~%" i))
(format s "~&MALFORMED~%")))
CREATE-LOG-FILE
2/15>
2/15> (create-log-file "pclchap19.log")
NIL
2/16>
2/16> (defun parse-log-file (file)
(with-open-file (in file :direction :input)
(do* (result
(text (read-line in nil nil) (read-line in nil nil))
(entry (handler-case (parse-log-entry text)
(malformed-log-entry-error () nil))
(handler-case (parse-log-entry text)
(malformed-log-entry-error () nil))))
((not text) (nreverse result))
(when entry (push entry result)))))
PARSE-LOG-FILE
2/17>
2/17> (parse-log-file "pclchap19.log")
(#<LOG-ENTRY 124,140170> #<LOG-ENTRY 124,140164> #<LOG-ENTRY 124,140160> #<LOG-ENTRY 124,140154> #<LOG-ENTRY 124,140150> #<LOG-ENTRY 124,140144> #<LOG-ENTRY 124,140140> #<LOG-ENTRY 124,140134> #<LOG-ENTRY 124,140130> #<LOG-ENTRY 124,140124>)
2/18>
2/18> (defun skip-log-entry (c)
(invoke-restart 'skip-log-entry))
SKIP-LOG-ENTRY
2/19>
2/19> (defun parse-log-file (file)
(with-open-file (in file :direction :input)
(do* (result
(text (read-line in nil nil) (read-line in nil nil))
(entry (restart-case (parse-log-entry text)
(skip-log-entry () nil))
(restart-case (parse-log-entry text)
(skip-log-entry () nil))))
((not text) (nreverse result))
(when entry (push entry result)))))
New FUNCTIONS definition for PARSE-LOG-FILE.
PARSE-LOG-FILE
2/20>
2/20> (parse-log-file "pclchap19.log")
In EVAL:
Serious condition MALFORMED-LOG-ENTRY-ERROR occurred.
2/21: OK
1 (SKIP-LOG-ENTRY) - Restart type: SKIP-LOG-ENTRY
2 (ABORT) - Unwind to ERRORSET
No - don't proceed
Proceed how? Restart type: SKIP-LOG-ENTRY
(#<LOG-ENTRY 124,140120> #<LOG-ENTRY 124,140114> #<LOG-ENTRY 124,140110> #<LOG-ENTRY 124,140104> #<LOG-ENTRY 124,140100> #<LOG-ENTRY 124,140074> #<LOG-ENTRY 124,140070> #<LOG-ENTRY 124,140064> #<LOG-ENTRY 124,140060> #<LOG-ENTRY 124,140054>)
2/22> (defun analyze-entry (entry)
(format t "~&Analyzing entry: ~a~%" entry))
ANALYZE-ENTRY
2/23>
2/23> (analyze-entry "This is an entry")
Analyzing entry: This is an entry
NIL
2/24>
2/24> (defun analyze-log (log)
(dolist (entry (parse-log-file log))
(analyze-entry entry)))
ANALYZE-LOG
2/25>
2/25> (analyze-log "pclchap19.log")
In EVAL:
Serious condition MALFORMED-LOG-ENTRY-ERROR occurred.
2/26: OK
1 (SKIP-LOG-ENTRY) - Restart type: SKIP-LOG-ENTRY
2 (ABORT) - Unwind to ERRORSET
No - don't proceed
Proceed how? Restart type: SKIP-LOG-ENTRY
Analyzing entry: #<LOG-ENTRY 124,140050>
Analyzing entry: #<LOG-ENTRY 124,140044>
Analyzing entry: #<LOG-ENTRY 124,140040>
Analyzing entry: #<LOG-ENTRY 124,140034>
Analyzing entry: #<LOG-ENTRY 124,140030>
Analyzing entry: #<LOG-ENTRY 124,140024>
Analyzing entry: #<LOG-ENTRY 124,140020>
Analyzing entry: #<LOG-ENTRY 124,140014>
Analyzing entry: #<LOG-ENTRY 124,140010>
Analyzing entry: #<LOG-ENTRY 124,140004>
NIL
2/27> (defun find-all-logs ()
(list "pclchap19.log"))
FIND-ALL-LOGS
2/28>
2/28> (defun log-analyzer ()
(dolist (log (find-all-logs))
(analyze-log log)))
LOG-ANALYZER
2/29>
2/29> (log-analyzer)
In EVAL:
Serious condition MALFORMED-LOG-ENTRY-ERROR occurred.
2/30: OK
1 (SKIP-LOG-ENTRY) - Restart type: SKIP-LOG-ENTRY
2 (ABORT) - Unwind to ERRORSET
No - don't proceed
Proceed how? Restart type: SKIP-LOG-ENTRY
Analyzing entry: #<LOG-ENTRY 124,140000>
Analyzing entry: #<LOG-ENTRY 124,140044>
Analyzing entry: #<LOG-ENTRY 124,140050>
Analyzing entry: #<LOG-ENTRY 124,140034>
Analyzing entry: #<LOG-ENTRY 124,140040>
Analyzing entry: #<LOG-ENTRY 124,140024>
Analyzing entry: #<LOG-ENTRY 124,140030>
Analyzing entry: #<LOG-ENTRY 124,140014>
Analyzing entry: #<LOG-ENTRY 124,140020>
Analyzing entry: #<LOG-ENTRY 124,140004>
NIL
2/31> (defun log-analyzer ()
(handler-bind ((malformed-log-entry-error
#'(lambda (c)
(invoke-restart 'skip-log-entry))))
(dolist (log (find-all-logs))
(analyze-log log))))
New FUNCTIONS definition for LOG-ANALYZER.
LOG-ANALYZER
2/32>
2/32> (log-analyzer)
Analyzing entry: #<LOG-ENTRY 124,140010>
Analyzing entry: #<LOG-ENTRY 124,140044>
Analyzing entry: #<LOG-ENTRY 124,140000>
Analyzing entry: #<LOG-ENTRY 124,140034>
Analyzing entry: #<LOG-ENTRY 124,140050>
Analyzing entry: #<LOG-ENTRY 124,140024>
Analyzing entry: #<LOG-ENTRY 124,140040>
Analyzing entry: #<LOG-ENTRY 124,140014>
Analyzing entry: #<LOG-ENTRY 124,140030>
Analyzing entry: #<LOG-ENTRY 124,140004>
NIL
2/33>
2/33> (defun log-analyzer ()
(handler-bind ((malformed-log-entry-error #'skip-log-entry))
(dolist (log (find-all-logs))
(analyze-log log))))
New FUNCTIONS definition for LOG-ANALYZER.
LOG-ANALYZER
2/34>
2/34> (log-analyzer)
Analyzing entry: #<LOG-ENTRY 122,46774>
Analyzing entry: #<LOG-ENTRY 122,46770>
Analyzing entry: #<LOG-ENTRY 122,46764>
Analyzing entry: #<LOG-ENTRY 122,46760>
Analyzing entry: #<LOG-ENTRY 122,46754>
Analyzing entry: #<LOG-ENTRY 122,46750>
Analyzing entry: #<LOG-ENTRY 122,46744>
Analyzing entry: #<LOG-ENTRY 122,46740>
Analyzing entry: #<LOG-ENTRY 122,46734>
Analyzing entry: #<LOG-ENTRY 124,140010>
NIL
2/35>
2/35> (defun skip-log-entry (c)
(let ((restart (find-restart 'skip-log-entry)))
(when restart (invoke-restart restart))))
New FUNCTIONS definition for SKIP-LOG-ENTRY.
SKIP-LOG-ENTRY
2/36>
2/36> (defun parse-log-entry (text)
(if (well-formed-log-entry-p text)
(make-instance 'log-entry :message text)
(restart-case (error 'malformed-log-entry-error :text text)
(use-value (value) value)
(reparse-entry (fixed-text) (parse-log-entry fixed-text)))))
New FUNCTIONS definition for PARSE-LOG-ENTRY.
PARSE-LOG-ENTRY
2/37>
2/37> (parse-log-entry "Well formed")
#<LOG-ENTRY 124,140000>
2/38>
2/38> (parse-log-entry "MALFORMED")
Serious condition MALFORMED-LOG-ENTRY-ERROR occurred.
2/39> After evaluating Here is a transcript of this part of the session and a couple of screenshots: 2/41> (SETQ IL:HELPTIME -1)
-1
2/42>
2/42> (parse-log-entry "MALFORMED")
In EVAL:
Serious condition MALFORMED-LOG-ENTRY-ERROR occurred.
2/43: OK
1 (USE-VALUE) - Use a different value
2 (REPARSE-ENTRY) - Restart type: REPARSE-ENTRY
3 (ABORT) - Unwind to ERRORSET
No - don't proceed
Proceed how? Use a different value
NIL
2/44> REDO
In EVAL:
Serious condition MALFORMED-LOG-ENTRY-ERROR occurred.
2/45: OK
1 (USE-VALUE) - Use a different value
2 (REPARSE-ENTRY) - Restart type: REPARSE-ENTRY
3 (ABORT) - Unwind to ERRORSET
No - don't proceed
Proceed how? Use a different value�? [confirm] �?
[confirm] �? [confirm] �? [confirm]
NIL
2/46> REDO
In EVAL:
Serious condition MALFORMED-LOG-ENTRY-ERROR occurred.
2/47: OK
1 (USE-VALUE) - Use a different value
2 (REPARSE-ENTRY) - Restart type: REPARSE-ENTRY
3 (ABORT) - Unwind to ERRORSET
No - don't proceed
Proceed how? Use a different value�? [confirm]
NIL
2/48> REDO
In EVAL:
Serious condition MALFORMED-LOG-ENTRY-ERROR occurred.
2/49: OK
1 (USE-VALUE) - Use a different value
2 (REPARSE-ENTRY) - Restart type: REPARSE-ENTRY
3 (ABORT) - Unwind to ERRORSET
No - don't proceed
Proceed how? Use a different value�? [confirm] �?
[confirm] The only remaining issues are the undefined |
Beta Was this translation helpful? Give feedback.
-
From the Medley 1.0 release notes on page 225 of the PDF:
This may be why |
Beta Was this translation helpful? Give feedback.
-
i'm not sure it was a 'feature'. Sounds more like "we couldn't implement it in time" but I'm not sure. |
Beta Was this translation helpful? Give feedback.
-
Chapter 19. Beyond Exception Handling: Conditions and Restarts
This is the continuation of the work on issue #609. To evaluate the compatibility of Medley Common Lisp with ANSI Common Lisp I'm testing on Medley the code of Peter Seibel's book Practical Common Lisp.
Issues
While working on chapter 19 I bumped into an error hinting at a missing
loop
feature. Before rewriting the code withoutloop
or reporting an issue I want to make sure there's indeed a problem withloop
.Code
This is the first part of the code I'm evaluating at a XCL Exec, which adds some definitions and calls missing from the chapter:
Session transcript
And here is a session leading to an unprocessed
loop
form tail error:Are there any problems with this code? Is this a
loop
issue?Beta Was this translation helpful? Give feedback.
All reactions