Last active
June 21, 2019 02:35
-
-
Save y2q-actionman/184b9dd9973c0559e810f9b66002b047 to your computer and use it in GitHub Desktop.
repl 変数使えば anaphora いらんやん
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(in-package :cl-user) | |
(defmacro with-repl-variables (&body body) | |
"BODY 中の式を、REPL 変数の `*', `+', `/', `-' 等を bind しながら順次実行する。" | |
(let ((form-results (gensym))) | |
`(let ((* *) (** **) (*** ***) | |
(+ +) (++ ++) (+++ +++) (- -) | |
(/ /) (// //) (/// ///)) | |
,@(loop for form in body | |
collect | |
`(let* ((- ',form) | |
(,form-results (multiple-value-list ,form))) | |
(shiftf +++ ++ + -) | |
(shiftf /// // / ,form-results) | |
(shiftf *** ** * (first ,form-results)) | |
(values-list ,form-results)))))) | |
;;;; | |
(defun example1 (string) | |
(with-repl-variables | |
string | |
(coerce * 'list) | |
(remove-duplicates *) | |
(format t "~&String '~A' contains: ~{~C~^ ~}~%" | |
*** *) | |
**)) | |
#| | |
CL-USER> (example1 "Hello, World!") | |
String 'Hello, World!' contains: H e , W o r l d ! | |
(#\H #\e #\, #\ #\W #\o #\r #\l #\d #\!) | |
|# | |
#+() | |
(defun example2 () | |
;; Clojure の threading macro の代替として `*' を使う | |
;; https://clojuredocs.org/clojure.core/-%3E | |
(with-repl-variables | |
"a b c d" | |
(string-upcase *) | |
(substitute #\A #\X *) | |
(split-sequence:split-sequence #\space *) | |
(first *))) ; => "A" | |
;;;; | |
(defun test-with-repl-variables () | |
(assert | |
(equal (with-repl-variables | |
(values 'a1 'a2) | |
'b | |
(values 'c1 'c2 'c3) | |
(list * ** ***)) | |
'(C1 B A1))) | |
(assert | |
(equal (with-repl-variables | |
(values 1 2 3) | |
/) | |
'(1 2 3))) | |
(assert | |
(= (with-repl-variables | |
(floor 22 7) | |
(+ (* (car /) 7) (cadr /))) | |
22)) | |
(assert | |
(equal (with-repl-variables | |
(+ 0 1) | |
(- 4 2) | |
(/ 9 3) | |
(list + ++ +++)) | |
'((/ 9 3) (- 4 2) (+ 0 1)))) | |
(assert | |
(equal (with-output-to-string (*standard-output*) | |
(with-repl-variables | |
(format t "Evaluating ~S" -))) | |
"Evaluating (FORMAT T \"Evaluating ~S\" -)")) | |
t) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(in-package :cl-user) | |
(defmacro with-repl-variables! (&body forms) | |
"`with-repl-variables' に前の式を '!' で再評価する機能を足したもの。" | |
`(symbol-macrolet ((!!! (!!!)) (!! (!!)) (! (!))) | |
(flet ((!!! ()) | |
(!! ()) | |
(! ())) | |
(declare (ignorable (function !) (function !!) (function !!!))) | |
(with-repl-variables!-internal ,@forms)))) | |
(defmacro with-repl-variables!-internal (&body forms) | |
"`with-repl-variables!' の下請け" | |
;; `with-repl-variables' と違い、 `let*' での再bindのみで実装してみた。 | |
(let ((form1 (first forms)) | |
(form-results (gensym))) | |
`(let* ((- ',form1) | |
(,form-results (multiple-value-list ,form1)) | |
(+++ ++) (++ +) (+ -) | |
(/// //) (// /) (/ ,form-results) | |
(*** **) (** *) (* (first ,form-results))) | |
(flet ((!!! () (!!)) | |
(!! () (!)) | |
(! () ,form1)) | |
(declare (ignorable (function !) (function !!) (function !!!))) | |
,(if (rest forms) | |
`(with-repl-variables!-internal ,@(rest forms)) | |
`(values-list ,form-results)))))) | |
;;;; | |
(defun test-with-repl-variables! () | |
(assert | |
(equal (with-repl-variables! | |
(values 'a1 'a2) | |
'b | |
(values 'c1 'c2 'c3) | |
(list * ** ***)) | |
'(C1 B A1))) | |
(assert | |
(equal (with-repl-variables! | |
(values 1 2 3) | |
/) | |
'(1 2 3))) | |
(assert | |
(= (with-repl-variables! | |
(floor 22 7) | |
(+ (* (car /) 7) (cadr /))) | |
22)) | |
(assert | |
(equal (with-repl-variables! | |
(+ 0 1) | |
(- 4 2) | |
(/ 9 3) | |
(list + ++ +++)) | |
'((/ 9 3) (- 4 2) (+ 0 1)))) | |
(assert | |
(equal (with-output-to-string (*standard-output*) | |
(with-repl-variables! | |
(format t "Evaluating ~S" -))) | |
"Evaluating (FORMAT T \"Evaluating ~S\" -)")) | |
(assert | |
(equal (let ((tmp 0)) | |
(with-repl-variables! | |
(incf tmp) | |
! | |
!) | |
tmp) | |
3)) | |
t) |
もし lexical variable を使うなら、 with-repl-variables!-internal のように let の連鎖にしたほうがよいのだが。
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
+
の symbol-macrolet 版を!
にするとかは思いつく