diff --git a/docs/contrib/flow.rst b/docs/contrib/flow.rst new file mode 100644 index 0000000..be868db --- /dev/null +++ b/docs/contrib/flow.rst @@ -0,0 +1,60 @@ +========== +Flow +========== + +.. versionadded:: 0.10.1 + +The ``flow`` macros allow a programmer to direct the flow of his program with +greater ease. + + +Macros +====== + +.. _case: +.. _switch: + +case +----- + +``case`` allows you to decide based on the value of a variable. + + +Usage: `(case variable val1 (body1) val2 (body2) ...)` + +Example: + +.. code-block:: hy + + (require hy.contrib.flow) + + (defn bmi-commenter [bmi] + (case bmi + 10 (print "The bmi was 10, wow.") + 20 (print "20? Really?") + 30 (print "Was it 30? Ok...") + (print "I don't even know."))) + + +switch +----- + +``switch`` allows you to run code based on the value of a variable. +A final extra body allows for a default case. + + +Usage: `(switch var (cond1) (body1) (cond2) (body2) ... )` + +Example: + +.. code-block:: hy + + (require hy.contrib.flow) + + (defn bmi-commenter [bmi] + (switch bmi + (<= 18.5) (print "you are underweight!") + (<= 25.0) (print "apparently normal") + (<= 30.0) (print "a little too heavy, but ok") + (print "You are a whale!"))) + diff --git a/docs/contrib/index.rst b/docs/contrib/index.rst index eda11f2..ebed64f 100644 --- a/docs/contrib/index.rst +++ b/docs/contrib/index.rst @@ -10,3 +10,4 @@ Contents: anaphoric loop multi + flow diff --git a/hy/contrib/flow.hy b/hy/contrib/flow.hy new file mode 100644 index 0000000..ae70362 --- /dev/null +++ b/hy/contrib/flow.hy @@ -0,0 +1,24 @@ +;; Additional flow macros + + +(defmacro/g! switch [variable &rest args] + (setv g!comp (car args)) + (setv g!body (car (cdr args))) + (setv g!rest (cdr (cdr args))) + (setv g!cond `(~(car g!comp) ~variable ~@(cdr g!comp))) + (if g!rest + (if (cdr g!rest) + `(if ~g!cond ~g!body (switch ~variable ~@g!rest)) + `(if ~g!cond ~g!body ~@g!rest)) + `(if ~g!cond ~g!body))) + +(defmacro/g! case [variable &rest args] + (setv g!value (car args)) + (setv g!body (car (cdr args))) + (setv g!rest (cdr (cdr args))) + (setv g!cond `(= ~variable ~g!value)) + (if g!rest + (if (cdr g!rest) + `(if ~g!cond ~g!body (case ~variable ~@g!rest)) + `(if ~g!cond ~g!body ~@g!rest)) + `(if ~g!cond ~g!body)))