Arc Forumnew | comments | leaders | submitlogin
1 point by waterhouse 5134 days ago | link | parent

Here are a bunch of printing functions, which I frequently use in combination.

Function: (prsn . args) : Prints the elements of args separated by spaces, then prints a newline. Extremely handy for debugging: add in (prsn a b c) when you want to see the state of a,b,c. Equivalent to the built-in prs, except this also prints a newline.

  (def prsn args (apply prs args) (prn))
Function: (pad x wanted-len (o side 'left) (o pad-char #\space)) : Coerces x to a string, then adds enough pad-char characters on the left or right side to make x be wanted-len long. Returns the resulting string. If x is longer than wanted-len, this will throw an error.

Very handy for printing out a table of data, especially in conjunction with prsn. Also good for, e.g., printing out dates which you want to be constant-length. Look at this beautiful table:

  arc> (for i 6 15 (prsn (pad i 2) (pad fib.i 3) (pad (fib:* 2 i) 6)))
   6   8    144
   7  13    377
   8  21    987
   9  34   2584
  10  55   6765
  11  89  17711
  12 144  46368
  13 233 121393
  14 377 317811
  15 610 832040
  nil

  (def pad (x wanted-len (o side 'left) (o pad-char #\space))
    (zap string x)
    (let padding (newstring (- wanted-len len.x) pad-char)
      (case side
        left (string padding x)
        right (string x padding))))
Of course, in that demonstration, I found those values 3 and 6 by experiment and having 'pad throw errors until I increased wanted-len enough. This may suck for you; therefore, here is a function to print out a whole grid:

Function: (grid xses (o strict nil)) : Prints out xses, which should be a list of lists, in a grid; that is, it pads each element enough that all elements in each column are the same width. If strict is t, then all columns will be the same width. Works even if lists are different length. Note that my definition uses 'pad and 'prsn. Illustration with Pascal's triangle, first without strict, then with:

  arc> (grid:accum a (for n 0 10 (a:accum b (for k 0 n (b:choose n k)))))
  1
  1  1
  1  2  1
  1  3  3   1
  1  4  6   4   1
  1  5 10  10   5   1
  1  6 15  20  15   6   1
  1  7 21  35  35  21   7   1
  1  8 28  56  70  56  28   8  1
  1  9 36  84 126 126  84  36  9  1
  1 10 45 120 210 252 210 120 45 10 1
  nil
  arc> (grid (accum a (for n 0 10 (a:accum b (for k 0 n (b:choose n k))))) t)
    1
    1   1
    1   2   1
    1   3   3   1
    1   4   6   4   1
    1   5  10  10   5   1
    1   6  15  20  15   6   1
    1   7  21  35  35  21   7   1
    1   8  28  56  70  56  28   8   1
    1   9  36  84 126 126  84  36   9   1
    1  10  45 120 210 252 210 120  45  10   1
  nil
I love this. Implementation:

  (def grid (xses (o strict nil)) ;dense lines of code for brevity
    (let lens (map [best > (map (fn (xs) (len:string:car:nthcdr _ xs)) xses)]
                   (range 0 (dec:best > (map len xses))))
      (when strict (let u (best > lens) (= lens (n-of len.lens u))))
      (each xs xses (apply prsn (map pad xs lens)))))