justrajdeep · 2022-05-12 16:20
[removed]
ieure · 2022-05-12 17:05
This is more of a Common Lisp question than Emacs Lisp, since `cl-loop` has CL semantics.
> (cl-loop
Begin a loop…
> for i from a to b
…which binds `i` to successive integers in the range a…b on each pass through the loop.
> (mod i 3)
Return the modulus (remainder) of dividing i by 3. It evaluates to `0` if `i` is evenly divisible by `3`. Equivalent to `i % 3` in many other languages.
> (zerop (mod i 3))
Predicate function: return `t` if its argument is `0`, and `nil` otherwise.
> if (zerop (mod i 3))
Conditional: Only evaluate the next action if the expression evaluates to a truthy value, which occurs when `i` is evenly divisible by `3`.
> collect "fizz"
Accumulate the literal text `fizz` into the implicit loop accumulator, which is a list.
> and collect i into fizz
Also, collect the loop index into the list bound to `fizz`. The loop creates the binding when it sees this; it's not declared. The `and` makes this part of the previous action, so both only eval if `i` is evenly divisible by `3`.
> if (zerop (mod i 5)) collect "buzz" and collect i into buzz
Same as the previous line, but only for values of `i` evenly divisible by 5.
> unless
Guard, equivalent to `when (not …)`. Don't eval the following action unless the guard sexp evals to `nil`.
> (append fizz buzz)
Concatenate lists `fizz` (which contains all numbers evenly dividable by 3) and `buzz` (…by 5).
> (memq i (append fizz buzz))
Returns non-`nil` if `i` is present in either `fizz` or `buzz`.
> collect (number-to-string i)
Collect the string representation of the loop index into the implicit loop accumulator. This is the action following `unless`, so it only collects if `i` isn't in `fizz` or `buzz`.
> collect "\n"
Unconditionally collect a newline character into the implicit loop accumulator.
The loop returns the implicit accumulator, so the whole expression evaluates to a list of strings of either, "fizz", "buzz", "fizzbuzz", or the loop index, followed by a newline.
ieure · 2022-05-12 17:43
Adding, this isn't a particularly efficient approach. The `fizz` and `buzz` lists needlessly collect *every* 3/5 divisible number, but you only need to know if the *current* `i` is divisible. Also, concatenating the lists makes `memq` unnecessarily slow, since it has to traverse **all of** `fizz` before considering a single `buzz`. You could save both time and memory complexity by storing the fizziness/buzziness of `i` in one or two vars instead of lists.
jsled · 2022-05-12 18:38
This has been removed, as posts must relate to emacs.