(newbie) Listiness

Started by mark5009, October 24, 2014, 11:40:52 PM

Previous topic - Next topic

mark5009

Hi.  Newbie here.  I am trying to understand what is happening here.  



My expectation is that bar should contain (() 1 2 3 4 5) (which is what

I am after, but it doesn't.  Can someone fill me in on where my thinking

is a little broken?  I want to construct a list of the individual items of

foo in bar.



Thanks .. mark.



> (set 'foo '(1 2 3 4 5))
(1 2 3 4 5)
> (set 'bar (cons))
()
> (dolist (it foo) (println it))
1
2
3
4
5
5
> (dolist (it foo) (list bar it))
(() 5)

bairui

#1
Hi, Mark,



The dolist iterates the list one element at a time. Because you're not printing in that loop, the interpreter is silently throwing away each internal result. Finally the result of the whole loop (its final evaluation) is shown by the interpreter, which is (() 5), as you would expect.



For your stated goal of (() 1 2 3 4 5) you could merely do (cons bar foo)



-- bairui

mark5009

#2
Thanks for your reply, bairui.  My problem is I am not being very clear.



Here is the real issue.  Say I have a file I want to read:



# stuff to ignore
123:avc
234:vvc
# more to ignore and the following blank line as well

# and there is the last stuff
999:xxc


I want to end up with something like:



> (set 'foo-file "/tmp/foo.tmp")
> (set 'contents (slurp-in-file foo-file)

> contents
((123 "avc")(243 "vvc")(999 "xxc"))


Basically your typical read-in-a-file scenario for sysadmin work.

I am just not sure of the syntax involved in going through the file

a line at a time, throwing away the crud, then parsing the line.

I know newlisp can do it because I can make each part do its thing.

It is just the putting it all together that I am having a problem with.



TIA, mark.

saulgoode

#3
I'm sure there are Newlispers here who will be able to provide a much better solution (probably with just a single function), but nonetheless perhaps some of the following might spawn some ideas for you.



-----------------

> (set 'in-string (read-file "tmp/foo.tmp"))

"# stuff to ignoren123]

> (set 'all-lines (parse in-string "n"))

("# stuff to ignore" "123]

> (set 'non-empty-lines (clean = all-lines)) ; monadic = compares to empty string

("# stuff to ignore" "123]

> (define (comment? s) (starts-with s "#"))

> (set 'lines (clean comment? non-empty-lines))

("123]

> (define (split-at-colons s) (parse s ":"))

> (set 'contents (map split-at-colons lines))

(("123" "avc") ("234" "vvc") ("999" "xxc"))

rrq

#4
Well, I'd follow saulgoode's approach, but exercise the PCRE engine more, as in:
(define (slurp-in-file file)
  (map (fn (line)
        (and (regex "([0-9]*):(.*)" line 0) (list (int $1) $2)))
      (clean empty? (parse (read-file file) "\s*(#[^n]*)?n" 0))))

Thus, an initial chunking that consumes end-of-of line comments as well as trailing spaces of lines, providing a mix of data lines and empty lines as separate strings, and then, after cleaning out the empty lines, a secondary parts extraction for each line making the first parts into integers.



Note that bad data lines turn up as nil data elements, without a direct trace-back to the source, but maybe the "and" clasue changed to an "if" clause could deal with that.

mark5009

#5
Thanks, guys!  That is most helpful.



 .. mark.

tomtoo

#6
This way also seems to work...

(set 'a (parse (read-file "foo.tmp") "n"))
(dolist (item a)
(unless (or (starts-with item "#")(empty? item))
(push item box -1)))
(dolist (item box)
(set 'z (parse item ":"))
(push (cons (int (first z))(last z)) bag -1))