Page 1 of 1

Formatting of println output

Posted: Fri Apr 21, 2006 9:14 am
by cormullion
Just puzzled by the way newLISP outputs things.

Code: Select all

(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:

Code: Select all

((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?

Posted: Fri Apr 21, 2006 10:42 am
by HPW
pretty-print is your friend:
> (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))

Posted: Fri Apr 21, 2006 10:47 am
by HPW
Or do you want:

Code: Select all

> (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)

Posted: Fri Apr 21, 2006 11:10 am
by Lutz
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

Code: Select all

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

Code: Select all

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

Or try

Code: Select all

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

Doing a

Code: Select all

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

Lutz

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

Posted: Fri Apr 21, 2006 11:40 am
by cormullion
Thanks. I hadn't thought of pretty-print.

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

Posted: Fri Apr 21, 2006 11:40 am
by Dmi
I done something like this for my not-yet-released newlisp-console:

Code: Select all

(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)

Posted: Fri Apr 21, 2006 12:27 pm
by Lutz
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

Posted: Fri Apr 21, 2006 12:30 pm
by HPW
PS - Why does println do what it does, though?. :-)
I uses simply the default settings:

Code: Select all

(pretty-print)         => (64 " ") ;; default setting
It should print a long list and reach that default boundry.

Posted: Fri Apr 21, 2006 1:40 pm
by cormullion
HPW wrote: 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!

Posted: Fri Apr 21, 2006 2:24 pm
by Dmi
Lutz wrote: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:

Code: Select all

((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.

Posted: Fri Apr 21, 2006 2:28 pm
by Lutz
Pretty printing in newLISP is optimized for saving/sourceing contents with "save" or "source", saving content with 'set' statements:

Code: Select all

> (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.

Code: Select all

> (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