let and set

Started by jeremyc, December 07, 2006, 11:11:40 AM

Previous topic - Next topic

jeremyc

Excuse my newbie question, but I am unsure how to handle this properly?



let creates a variable in a local sense. set set's it as a global, correct? Please look at the following function.



(define (read-segment fh)
  (let ((buf "") (ch (char (read-char fh))))
    (while (!= ch "~")
      (push ch buf -1)
      (set 'ch (char (read-char fh))))
    (parse buf "*")))


My question is, how am I suppose to update ch each time around? If ch is defined else where, my set 'ch will overwrite it's value, correct?



What this function does is reads 1 segment at a time from an edi file which looks like:



NAME*JOHN*DOE~ADDRESS*123 MAIN ST.*SMALLTOWN*COLORADO*USA~


etc.... All segments are on one line, there is no n in the entire file, be it 2k or 500k in size :-(



Thanks,



Jeremy

Lutz

#1
The variables 'buf' and 'ch' will have their newly assigned values inside the 'let' and in all functions called from 'let', but assume their previous value after it. Basically the 'let' or any other 'define' function shadows the contents of variables in the higher scope with the definition in the local scope. Here is an example to illustrate this:


(set 'x 123)

(define (report)
(println "->" x))

(report)

(let (x "hello") (report))

(report)


running this program gives the following output:


->123
->hello
->123


In your case this means that any value 'ch' had before calling (read-segment ..) will be restores when (read-segment ...) has returned.



Read also the chapter about dynamic scoping here:

http://newlisp.org/downloads/newlisp_manual.html#scoping">http://newlisp.org/downloads/newlisp_ma ... ml#scoping">http://newlisp.org/downloads/newlisp_manual.html#scoping



Lutz

cormullion

#2
Quote from: "jeremyc"let creates a variable in a local sense. set set's it as a global, correct?


don't think so - 'set' changes the value of a symbol. Inside a function a local symbol hides a global one with the same name. So you can use 'set' inside a function to change the value of a local symbol. But if it's not local, set will change the global one.



Life is more interesting with contexts, of course. :-)

Lutz

#3
Yes Cormullion, or in other words:



'set' sets the variable to a new value in the current scope. 'let' creates a new scope and then sets the value of the variable in that scope. when 'let' finishes the previous scope is restored.



Lutz



ps: sometimes people talk about: environment instead of: scope.

cormullion

#4
By the way, if it's only 500K, it could be worth doing it in one go:


(set 'f (parse (read-file "/Users/me/Desktop/data.txt") "~"))

Should only take a second or so...

jeremyc

#5
Quote from: "cormullion"By the way, if it's only 500K, it could be worth doing it in one go:


(set 'f (parse (read-file "/Users/me/Desktop/data.txt") "~"))

Should only take a second or so...


I will be processing a hundred or so files a day, and many times I need to just read the first segment of the file. (that tells me where the file came from and where it's going). So, reading just the first segment of any file, time reports it takes 0.009s ... so, for reading just the first segment, I'll stick with my method, but for parsing the whole file, your method of using parse looks pretty simple! The largest EDI File I've ever delt with was 1.5mb. That's *very* rare. I'll give it a shot through the parse method and see.



Thanks!



Jeremy

Lutz

#6
... you could also try 'read-buffer' with wait string:


(read-buffer fh 'buff 10000 "~")
(parse (chop buff)  "*")


You do this until 'buff' comes back with 'nil' at the end of the file.



Lutz