Skip to content

Instantly share code, notes, and snippets.

@ehaliewicz
Last active October 12, 2015 08:27
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ehaliewicz/3998890 to your computer and use it in GitHub Desktop.
Save ehaliewicz/3998890 to your computer and use it in GitHub Desktop.
A flip-flop operator for lisp
(defmacro flip-flop (left right)
"Evaluates to false until the left test is satisfied. Then evaluates to true until the right test is satisfied, etc."
;; create a collision-safe name for our state variable
(let ((state-var (gensym)))
;; create a toplevel variable to keep state of flip-flop
`(progn
(defvar ,state-var nil))
(if ,state-var
;; prog1 binds the result of the first form to a variable, evaluates the
;; second form, and returns the result of the first form
(prog1
,state-var
(if ,right
(toggle ,state-var)))
(if ,left
(toggle ,state-var)))))
(defmacro toggle (&rest args)
"Toggle a generalized boolean."
`(progn
,@(mapcar #'(lambda (a) `(toggle2 ,a))
args)))
(define-modify-macro toggle2 () not)
;; in Perl for 1..20 { .say if $_ == 9 ff $_ == 13; } # 9 10 11 12 13
;; in ruby 20.times { |i| puts i if i == 9 .. i == 13 }
;; in Lisp
(dotimes (i 20)
(if (flip-flop (= i 9) (= i 13))
(print i)))
=> 9 10 11 12 13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment