let and set

Notices and updates
Locked
jeremyc
Posts: 33
Joined: Wed Dec 06, 2006 3:33 am

let and set

Post by 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.

Code: Select all

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

Code: Select all

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
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Post by Lutz »

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:

Code: Select all

(set 'x 123)

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

(report)

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

(report)
running this program gives the following output:

Code: Select all

->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_ma ... ml#scoping

Lutz

cormullion
Posts: 2038
Joined: Tue Nov 29, 2005 8:28 pm
Location: latiitude 50N longitude 3W
Contact:

Re: let and set

Post by cormullion »

jeremyc wrote: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
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Post by Lutz »

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
Posts: 2038
Joined: Tue Nov 29, 2005 8:28 pm
Location: latiitude 50N longitude 3W
Contact:

Post by cormullion »

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

Code: Select all

(set 'f (parse (read-file "/Users/me/Desktop/data.txt") "~"))
Should only take a second or so...

jeremyc
Posts: 33
Joined: Wed Dec 06, 2006 3:33 am

Post by jeremyc »

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

Code: Select all

(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
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Post by Lutz »

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

Code: Select all

(read-buffer fh 'buff 10000 "~")
(parse (chop buff)  "*")
You do this until 'buff' comes back with 'nil' at the end of the file.

Lutz

Locked