Formatting of println output

Started by cormullion, April 21, 2006, 02:14:05 AM

Previous topic - Next topic

cormullion

Just puzzled by the way newLISP outputs things.


(println (set 'l (map list (randomize (sequence 1 20)) (sequence 1 20))))


always prints the first 10 elements on one line, then prints the rest of the elements one per line:


((1 1) (10 2) (3 3) (16 4) (7 5) (12 6) (11 7) (17 8) (19 9) (18
  10)
 (8 11)
 (13 12)
 (6 13)
 (14 14)
 (4 15)
 (9 16)
 (15 17)
 (2 18)
 (5 19)
 (20 20))


Why is this?

HPW

#1
pretty-print is your friend:


Quote> (pretty-print 7)

(7 " ")

> (silent(println (set 'l (map list (randomize (sequence 1 20)) (sequence 1 20)))))

((19 1)

 (7 2)

 (3 3)

 (10 4)

 (12 5)

 (17 6)

 (15 7)

 (20 8)

 (2 9)

 (1 10)

 (11 11)

 (18 12)

 (9 13)

 (6 14)

 (13 15)

 (5 16)

 (14 17)

 (4 18)

 (16 19)

 (8 20))
Hans-Peter

HPW

#2
Or do you want:



> (silent(map println (set 'l (map list (randomize (sequence 1 20)) (sequence 1 20)))))
(16 1)
(9 2)
(2 3)
(19 4)
(11 5)
(14 6)
(6 7)
(13 8)
(10 9)
(3 10)
(7 11)
(15 12)
(4 13)
(8 14)
(5 15)
(18 16)
(1 17)
(20 18)
(12 19)
(17 20)
Hans-Peter

Lutz

#3
Pretty printing in newLISP is optimized for saving/sourceing contents with "save" or "source", saving content with 'set' statements, and it works well for user defined functions when entering the function name on the interactive command line.



Whe you put your list into a variable and then do a


(save "myfile" 'var) you will get a


(set 'var ....) statement in "myfile" file which is well formatted.



Or try (save "everything") and get a well formatted file of all your newLISP contents you have in memory in a file.



Doing a (load "everything") will bring you back where you were.



Lutz



ps: and as HPW suggests, fine tune pretty printing using 'pretty-print'

cormullion

#4
Thanks. I hadn't thought of pretty-print.



PS - Why does println do what it does, though?. :-)

Dmi

#5
I done something like this for my not-yet-released newlisp-console:
(define (sys-cols) 80)

(define (format-expr lst cols indent , curline shift lstart lend)
  "format the nested list to simply indented wrapped string list"
  "use (indent (format-expr ...)) then for more fine wrap"
  (setq curline "" lstart true shift 0)
  (unless cols (setq cols (sys-cols)))
  (unless indent (setq indent 2)) ; indent step
  (let (outbuf (indent-wrap lst))
    (new-curline)
    outbuf))

; inner to indent-wrap
(define (new-curline value)
  (if (and curline (not (empty? curline)) (push-end curline outbuf)))
  (set 'curline (append (dup " " shift) (unless value "" value))
       'lstart true))

; supply string-like converter. needed workaround for t etc.
(define (string-value s)
  (if (string? s) (append """
                          (replace "n" (replace """ (replace "\"
                            s "\\") "\"") "\n")
                          """)
                  (string s)))

; if s-expr fit the line, we write it
; else we'll write subexpressions until they fill the line
(define (indent-wrap lst , lbuf)
  (let (outbuf '() s (string-value lst))
    (if (< (+ (length curline) 1 (length s)) cols)
      (write-buffer curline (append
                              (unless (or (empty? curline) lstart) " " "")
                              s))
      (unless (list? lst)
        (new-curline s)
        (begin
          (new-curline "(")
          (inc 'shift indent)
          (set 'lbuf (length outbuf))
          (dolist (l lst)
            (if lend (new-curline))
            (set 'lend nil)
            (set 'outbuf (append outbuf (indent-wrap l))))
          (write-buffer curline ")")
          (set 'lend (> (length outbuf) lbuf))
          (dec 'shift indent))))
    (set 'lstart nil)
    outbuf))

use: (format-expr lst)
WBR, Dmi

Lutz

#6
How does pretty print work?



There is a set of rules when to break the line and how much indenting steps to fill in before each line.



The rules count the the level and balance of open braces and watch if the  stuff printed comes from a user-defined function. Certain primitives like i'if', 'dotimes', 'dolist', 'while', 'until' have an iternal flag telling when to break the line, this way braking after the parameter list or condition.



When saving lists formattting is optimized for 'save' and 'source'.



DMI's program does something similar, but I haven't looked into it enough to explain the differences.



Lutz

HPW

#7
QuotePS - Why does println do what it does, though?. :-)


I uses simply the default settings:



(pretty-print)         => (64 " ") ;; default setting


It should print a long list and reach that default boundry.
Hans-Peter

cormullion

#8
Quote from: "HPW"
It should print a long list and reach that default boundry.


I see that it does that for the first line, but then it doesn't take any notice for the remaining lines...



Not a problem - a curiousity!

Dmi

#9
Quote from: "Lutz"DMI's program does something similar, but I haven't looked into it enough to explain the differences.

Lutz

My one is mainly for printing the "data" lists. It trying to fill each line until possible, then do a line break with indenting (if it needed to reflect the structure).

The cormullion's example will be printed like this:
((17 1) (12 2) (14 3) (3 4) (10 5) (9 6) (11 7) (1 8) (8 9) (7 10) (16 11)
  (6 12) (4 13) (18 14) (19 15) (2 16) (15 17) (13 18) (5 19) (20 20))

It can also pretty indent a code too, for ex:

(join (format-expr indent-wrap) "n")

but there is no sufficient euristics for smart line breaking according with lisp code etc. - only the list structure is checked for indenting and bracket closing.
WBR, Dmi

Lutz

#10
Pretty printing in newLISP is optimized for saving/sourceing contents with "save" or "source", saving content with 'set' statements:



> (set 'l (map list (randomize (sequence 1 20)) (sequence 1 20)))
((7 1) (6 2) (18 3) (19 4) (14 5) (13 6) (3 7) (12 8) (9 9) (16 10)
 (4 11)
 (2 12)
 (8 13)
 (15 14)
 (5 15)
 (11 16)
 (10 17)
 (17 18)
 (1 19)
 (20 20))
> (save "list" 'l)
true

> !cat list
(set 'l '(
  (7 1)
  (6 2)
  (18 3)
  (19 4)
  (14 5)
  (13 6)
  (3 7)
  (12 8)
  (9 9)
  (16 10)
  (4 11)
  (2 12)
  (8 13)
  (15 14)
  (5 15)
  (11 16)
  (10 17)
  (17 18)
  (1 19)
  (20 20)))

>


Note that 'cat' is a shell command the '!' has to come immedeately before it and in the first column and initiates the shell. Of course you also could open the file "list" in an editor.



Only a completely flat list will fill each line to the end.



> (set 'l (sequence 1 100))
(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
 92 93 94 95 96 97 98 99 100)
> (save "list" 'l)
true
> !cat list
(set 'l '(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
  23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
  44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
  65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
  86 87 88 89 90 91 92 93 94 95 96 97 98 99 100))

>


It is impossible to make a pretty print algorithm, which gets it right all the time. Remember that LISP has the same syntax for data and program. The current algorithm is optimized for displaying program text and does a reasonable well job on data, when using 'save' and 'source' for ouput.



Lutz