reddit / emacs

Understand what is happening in the code

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.