# FizzBuzz Macro a small macro for defining FizzBuzz-like functions easily. uses continuation passing to ensure each predicate is only checked once per number. ## usage import the file into your `#lang racket` project ``` (require "fizzbuzz.rkt") ``` from there the functions `mult`, `fizzbuzz` and `define-fizzbuzz` will be avaliable to you. ### mult `(mult x)` creates a predicate that answers whether a number is a multiple of `x` ``` ((mult 5) 15) => #t ((mult 5) 16) => #f ``` ### fizzbuzz `(fizzbuzz x)` is an implementation of fizzbuzz using this program. it returns a string which will be one of: * the string representation of `x` * the string "Fizz" * the string "Buzz" * the string "FizzBuzz" it is defined using `define-fizzbuzz` and `mult` as follows: ``` (define-fizzbuzz fizzbuzz [(mult 3) "Fizz"] [(mult 5) "Buzz"]) ``` ### define-fizzbuzz `define-fizzbuzz` takes a name, and a list of predicate, string pairs, and creates a function that acts as fizzbuzz would for any number of triggers. the order of the pairs will determine the ordering of the strings should more than one be true for a given number, ie. the difference between "FizzBuzz" and "BuzzFizz" is the ordering of the pairs. ## example in order to define the function `bashforkfoobar` which has the following semantics: * if `x` is odd, "Bash" * if `x` is a multiple of 7, "Fork" * if `x - 2` is a multiple of 3, "Foo" * if `x` is 69, "Bar" we can use the following; ``` (define-fizzbuzz bashforkfoobar [odd? "Bash"] [(mult 7) "Fork"] [(lambda (n) ((mult 3) (- n 2))) "Foo"] [(lambda (n) (= n 69) "Bar"]) ``` which when mapped over a range of numbers using `(map bashforfoobar (range 1 101)`; ``` '("Bash" "Foo" "Bash" "4" "BashFoo" "6" "BashFork" "Foo" "Bash" "10" "BashFoo" "12" "Bash" "ForkFoo" "Bash" "16" "BashFoo" "18" "Bash" "Foo" "BashFork" "22" "BashFoo" "24" "Bash" "Foo" "Bash" "Fork" "BashFoo" "30" "Bash" "Foo" "Bash" "34" "BashForkFoo" "36" "Bash" "Foo" "Bash" "40" "BashFoo" "Fork" "Bash" "Foo" "Bash" "46" "BashFoo" "48" "BashFork" "Foo" "Bash" "52" "BashFoo" "54" "Bash" "ForkFoo" "Bash" "58" "BashFoo" "60" "Bash" "Foo" "BashFork" "64" "BashFoo" "66" "Bash" "Foo" "BashBar" "Fork" "BashFoo" "72" "Bash" "Foo" "Bash" "76" "BashForkFoo" "78" "Bash" "Foo" "Bash" "82" "BashFoo" "Fork" "Bash" "Foo" "Bash" "88" "BashFoo" "90" "BashFork" "Foo" "Bash" "94" "BashFoo" "96" "Bash" "ForkFoo" "Bash" "100") ``` ## explanation the macro creates a composition of continuation style passing functions, which will build a string and halt production in order to prevent a number being printed if an identifier has been. the string building functions `myprint`, `skip` and `halt` are quite simple. `skip` and `halt` both take a string and return a string, with `skip` acting as the identity function, and `halt` intead throwing away its argument and returning the empty string (the unit value for this composition). `myprint` takes two strings and returns a string. the first is the message to add to the end of the string being built, and the second (curried) argument works as in `skip` and `halt`. `base` exists as a CPS function that creates (once passed a continuation) a function from string to string, simply applying its continuation to the result of printing the number passed to `base`. it is the first rule in any fizzbuzz function to facilitate the default behaviour. the macro then constructs an additional trigger for each predicate / string pair, which when given a number, returns a CPS function that when given a continuation will take a string, and either pass it unchanged to the continuation, or sandwich the continuation between a `myprint` and a `halt`, such that the halt will prevent the default behaviour. after macro transformations, a trigger with the message `message` and the predicate `predicate` will look as follows: ``` (lambda (n) (lambda (k) (lambda (s) (if (p n) (myprint m (k (halt s))) (k s))))) ``` here, `n` is the number passed to the fizzbuzz function, `k` is the continuation function, and `s` is the string for the final string builder. these are composed starting with `base`, and then each trigger in order to create the final fizzbuzz function. ## author * tA