Skip to content

Instantly share code, notes, and snippets.

@jdz
Created February 13, 2020 14:00
Show Gist options
  • Save jdz/13c002e186f2e7f45f3912eb007c65b2 to your computer and use it in GitHub Desktop.
Save jdz/13c002e186f2e7f45f3912eb007c65b2 to your computer and use it in GitHub Desktop.
Something's fishy
(in-package #:cl-user)
(eval-when (:load-toplevel :compile-toplevel :execute)
(unless (find-package "WHO")
(require "cl-who")))
(defun test ()
(values
(who:with-html-output-to-string (html nil :prologue nil :indent nil)
(:span (who:str "whatever")))
(who:with-html-output-to-string (html nil :prologue nil :indent nil)
(:span (who:fmt "~A" "whatever")))))
;;; SBCL HEAD (e4e6b433b):
;;;
;;; CL-USER> (test)
;;; "<span>whatever</span>"
;;; "<span></span>"
;;;
;;; Expected (works on SBCL 2.0.0):
;;;
;;; CL-USER> (test)
;;; "<span>whatever</span>"
;;; "<span>whatever</span>"
@jdz
Copy link
Author

jdz commented Feb 13, 2020

OK, macroexpansions of the two cases differ in that the who:str case adds additional LET binding:

           (WRITE-STRING "<span>" HTML)
           (LET ((CL-WHO::*INDENT* NIL))
             NIL
             (LET ((#:RESULT567 "whatever"))
               (IF #:RESULT567
                   (PRINC #:RESULT567 HTML))))
           (WRITE-STRING "</span>" HTML)

As opposed to the who:fmt case:

           (WRITE-STRING "<span>" HTML)
           (LET ((CL-WHO::*INDENT* NIL))
             NIL
             (FORMAT HTML "~A" "whatever"))
           (WRITE-STRING "</span>" HTML)

@jdz
Copy link
Author

jdz commented Feb 13, 2020

It seems both check-type and outer let is needed to trigger this:

(defun reduced-test ()
  (values
   (with-output-to-string (out)
     (check-type out stream)
     (let ((out out))
       (princ "whatever" out)))
   (with-output-to-string (out)
     (let ((out out))
       ;; Moving this type check up the tree makes this work.
       (check-type out stream)
       (format out "~A" "whatever")))))

@jdz
Copy link
Author

jdz commented Feb 13, 2020

Even shorter test cases:

(defun works ()
  (with-output-to-string (out)
    (check-type out stream)
    (let ((out out))
      (format out "~A" "whatever"))))

(defun doesnt-work ()
  (with-output-to-string (out)
    (let ((out out))
      (check-type out stream)
      (format out "~A" "whatever"))))

@jdz
Copy link
Author

jdz commented Feb 13, 2020

Another case:

(defun doesnt-work ()
  (with-output-to-string (out)
    (let ((out out))
      (check-type out stream)
      (princ "princ" out)
      (format out "~A" "format"))))

;;; returns "princ"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment