• Re: Is there a better way to read multiple values from a string

    From B. Pym@Nobody447095@here-nor-there.org to comp.lang.lisp on Wed Jul 2 10:53:00 2025
    From Newsgroup: comp.lang.lisp

    Pascal J. Bourguignon wrote:

    I have a strings like "0 2 0 1". The number of values may vary, but they all can be read using READ

    Right now I do the following
    (loop
    :for (x pos) = (multiple-value-list
    (read-from-string first-line nil nil :start (or pos 0)))
    :while x
    :collect x)


    Is there a more idiomatic way to read all the tokens in the string and return them as a list?

    (with-input-from-string (in string)
    (loop :for n = (read in nil nil)
    :while n :collect n))

    If we are allowed to use a collector, then the loop
    becomes much shorter. Compare:

    (loop :for n = (read in nil nil) :while n :collect n))
    (until (eof-object? (bag (read))))

    Gauche Scheme:

    (define bag (mlistbag))

    (with-input-from-string "0 4 2 5"
    (lambda()
    (until (eof-object? (bag (read))))))

    ;; Remove the eof-object.
    (drop-right (bag) 1)
    ===>
    (0 4 2 5)

    Given:

    (define (mbag init func :optional (pass-through #f))
    (let ((val init) (func func) (pass-through pass-through))
    (lambda args
    (if (null? args)
    val
    (begin
    (set! val
    ;; A "kons" may have been supplied.
    ((if (null? (cdr args)) func (cadr args))
    (car args) val))
    (if pass-through
    (car args)
    val))))))

    (define (mlistbag :optional (pass-through #t))
    (let ((bag (mbag '() cons pass-through)))
    (lambda args
    (if (null? args)
    (reverse (bag))
    (apply bag args)))))

    --- Synchronet 3.21d-Linux NewsLink 1.2
  • From B. Pym@Nobody447095@here-nor-there.org to comp.lang.lisp,comp.lang.scheme on Wed Jul 2 15:48:19 2025
    From Newsgroup: comp.lang.lisp

    B. Pym wrote:

    Pascal J. Bourguignon wrote:

    I have a strings like "0 2 0 1". The number of values may vary, but they all can be read using READ

    Right now I do the following
    (loop
    :for (x pos) = (multiple-value-list
    (read-from-string first-line nil nil :start (or pos 0)))
    :while x
    :collect x)


    Is there a more idiomatic way to read all the tokens in the string and return them as a list?

    (with-input-from-string (in string)
    (loop :for n = (read in nil nil)
    :while n :collect n))

    If we are allowed to use a collector, then the loop
    becomes much shorter. Compare:

    (loop :for n = (read in nil nil) :while n :collect n))
    (until (eof-object? (bag (read))))

    Gauche Scheme:

    (define bag (mlistbag))

    (with-input-from-string "0 4 2 5"
    (lambda()
    (until (eof-object? (bag (read))))))

    ;; Remove the eof-object.
    (drop-right (bag) 1)
    ===>
    (0 4 2 5)

    Given:


    A better way.


    ;; Remove the eof-object.
    (bag 1 'drop)
    ===>
    (0 4 2 5)

    Given:

    (define (mbag init func :optional (pass-through #f))
    (let ((val init) (func func) (pass-through pass-through))
    (lambda args
    (if (null? args)
    val
    (let ((x (car args)))
    (if (null? (cdr args))
    (begin
    (set! val (func x val))
    (if pass-through
    x
    val))
    (let ((kons (cadr args)))
    (if (or (eq? 'drop kons) (eq? 'DROP kons))
    (do ((n x (- n 1)))
    ((zero? n) (if (eq? 'drop kons) (reverse val) val))
    (set! val (cdr val)))
    (begin
    (set! val (kons x val))
    (if pass-through
    x
    val))))))))))

    (define (mlistbag :optional (raw #f) (pass-through #t))
    (let ((bag (mbag '() cons pass-through)))
    (lambda args
    (if (null? args)
    (if raw
    (bag)
    (reverse (bag)))
    (apply bag args)))))
    --- Synchronet 3.21d-Linux NewsLink 1.2