#:g1: SBCL 1.2.2でのbackquoteの変更

Posted 2014-07-30 15:05:00 GMT

 SBCL 1.2.2でbackquoteについて非互換な変更がありましたが、既存のコードが結構動かなかったりするみたいです。

 例えば、Let Over Lambdaっぽく、マクロのコードウォークが面倒なので安易にflattenするような場合、flattenの結果が、

(*:flatten
 '`(LET ,(MAPCAR #'LIST (LIST) (LIST))
     (PROGN
       (LET ((GS
              (LOOP FOR I IN LETARGS
                    COLLECT (GENSYM))))
         `(MACROLET ((N GS
                       `(PROGN
                          (VALUES
                           @(APPLY #'NCONC
                                   (MAPCAR #'LIST
                                           '(MAPCAR #'CAR
                                             LETARGS)
                                           (LIST @GS))))
                          (GO '#:N))))
            (BLOCK #:B
              (LET LETARGS
                (TAGBODY
                  #:N
                  (RETURN-FROM #:B (PROGN @BODY))))))))))
;=>  (SB-INT:QUASIQUOTE LET ,(MAPCAR #'LIST (LIST) (LIST)) PROGN LET GS LOOP FOR I
;     IN LETARGS COLLECT GENSYM SB-INT:QUASIQUOTE MACROLET N GS SB-INT:QUASIQUOTE
;     PROGN VALUES @ APPLY FUNCTION NCONC MAPCAR FUNCTION LIST QUOTE MAPCAR FUNCTION
;     CAR LETARGS LIST @GS GO QUOTE #:N BLOCK #:B LET LETARGS TAGBODY #:N
;     RETURN-FROM #:B PROGN @BODY)

みたいになったりします。,(MAPCAR #'LIST (LIST) (LIST))って何者だと思っちゃいますが、

(*:cons-tree-map 
 (lambda (x)
   (list x :=> (type-of x)))  
 '`(LET ,(MAPCAR #'LIST (LIST) (LIST))
     (PROGN
       (LET ((GS
              (LOOP FOR I IN LETARGS
                    COLLECT (GENSYM))))
         `(MACROLET ((N GS
                       `(PROGN
                          (VALUES
                           @(APPLY #'NCONC
                                   (MAPCAR #'LIST
                                           '(MAPCAR #'CAR
                                             LETARGS)
                                           (LIST @GS))))
                          (GO '#:N))))
            (BLOCK #:B
              (LET LETARGS
                (TAGBODY
                  #:N
                  (RETURN-FROM #:B (PROGN @BODY))))))))))
;=>  ((SB-INT:QUASIQUOTE :=> SYMBOL)
;     ((LET :=>
;        SYMBOL)
;      (,(MAPCAR #'LIST (LIST) (LIST)) :=> SB-IMPL::COMMA)
;      ((PROGN :=> SYMBOL)
;       ((LET :=>
;          SYMBOL)
;        (((GS :=> SYMBOL)
;          ((LOOP :=> SYMBOL) (FOR :=> SYMBOL) (I :=> SYMBOL) (IN :=> SYMBOL)
;           (LETARGS :=> SYMBOL) (COLLECT :=> SYMBOL) ((GENSYM :=> SYMBOL)))))
;        ((SB-INT:QUASIQUOTE :=> SYMBOL)
;         ((MACROLET :=>
;            SYMBOL)
;          (((N :=> SYMBOL) (GS :=> SYMBOL)
;            ((SB-INT:QUASIQUOTE :=> SYMBOL)
;             ((PROGN :=> SYMBOL)
;              ((VALUES :=> SYMBOL) (@ :=> SYMBOL)
;               ((APPLY :=> SYMBOL) ((FUNCTION :=> SYMBOL) (NCONC :=> SYMBOL))
;                ((MAPCAR :=> SYMBOL) ((FUNCTION :=> SYMBOL) (LIST :=> SYMBOL))
;                 ((QUOTE :=> SYMBOL)
;                  ((MAPCAR :=> SYMBOL) ((FUNCTION :=> SYMBOL) (CAR :=> SYMBOL))
;                   (LETARGS :=> SYMBOL)))
;                 ((LIST :=> SYMBOL) (@GS :=> SYMBOL)))))
;              ((GO :=> SYMBOL) ((QUOTE :=> SYMBOL) (#:N :=> SYMBOL)))))))
;          ((BLOCK :=> SYMBOL) (#:B :=> SYMBOL)
;           ((LET :=>
;              SYMBOL)
;            (LETARGS :=> SYMBOL)
;            ((TAGBODY :=> SYMBOL) (#:N :=> SYMBOL)
;             ((RETURN-FROM :=> SYMBOL) (#:B :=> SYMBOL)
;              ((PROGN :=> SYMBOL) (@BODY :=> SYMBOL))))))))))))

どうもsb-impl::commaというATOM扱いみたいなんですね。
sb-impl::commaは構造体なので、(slot-value x 'sb-impl::expr)で式は取り出せますが、ちょっとこれに対応するのは面倒臭いなという感じです。
redditでも同様の話が出てきています。

 それと手元で起きた別の例では、

`#(,@(list 1 2 3)) ;=>  #((1 2 3))

というのがあります、これは、#(1 2 3)に展開されて合法だった気がするのですが、どうなんでしょう。

まとめ

 他力本願なので今後の流れに注目です。

続き: #:g1: 続・SBCL 1.2.2でのbackquoteの変更

comments powered by Disqus