Universal read_data function



On 05/28/2011 01:31 PM, Edwin Woollett wrote:
> On May 27, Volker van Nek wrote:
> ---------------------------------------
> If you want to read general Maxima expressions
> containing blanks and commas it makes sense
> to me to use the default ";" or "$" as separators.
> E.g.
>
> (%i1) string: "(x:1,y:2,x+y); block([fpprec:24],bfloat(%pi)); foo;"$
>
> (%i2) strings: split(string,";");
> (%o2)       [(x:1,y:2,x+y),  block([fpprec:24],bfloat(%pi)),  foo]
>
> (%i3) map(parse_string, strings);
> (%o3)   [(x : 1, y : 2, y + x), block([fpprec : 24], bfloat(%pi)), foo]
>
> (%i4) ''%;
> (%o4)                [3, 3.14159265358979323846264b0, foo]
> ----------------------------------------------------------
> Thanks for the great suggestion.
> Having a read_data function which allows the
> user to pass on to split any desired data
> separator string makes a lot of sense.
>
> My new (and improved?) version of read_data
> has the syntax:
>
> read_data (filename, data-sep-string, mult).
>
> Using the minimal form:  read_data(filename) assumes an arbitrary 
> mixture of commas
> and space data separators, convenient for
> many applications, but will not allow
> string data items containing spaces, since
> the default simple version converts all
> commas to spaces.
>
> Using read_data (filename, ",")
>  or read_data (filename, ";")
> assumes all data items are using the
> same data separators as indicated.
>
> The code sets the third optional
> arg to true , but can be set to false
> for use by split.
>
> ---------------------------------
> Maxima 5.24.0 http://maxima.sourceforge.net
> using Lisp GNU Common Lisp (GCL) GCL 2.6.8 (a.k.a. GCL)
> Distributed under the GNU Public License. See the file COPYING.
> Dedicated to the memory of William Schelter.
> The function bug_report() provides bug reporting information.
>                                  2011-05-28
>
>
> (%i1) (display2d:false,fpprintprec:8)$
> (%i2) load(readwrite);
> (%o2) "c:/work2/readwrite.mac"
>
> (%i3) printfile ("ndata1.dat")$
> 2.3e9 "Abc"
>
> (%i4) read_data ("ndata1.dat");
> (%o4) [[2.3E+9,"Abc"]]
> (%i5) read_data ("ndata1.dat"," ");
> (%o5) [[2.3E+9,"Abc"]]
>
> (%i6) printfile ("ndata2.dat")$
> 2 , 4.8, -3/4, "xyz", -2.8e-9
>
> 3 22.2  7/8 "abc" 4.4e10
>
> (%i7) read_data ("ndata2.dat");
> (%o7) [[2,4.8,-3/4,"xyz",-2.8E-9],[3,22.2,7/8,"abc",4.4E+10]]
>
> (%i8) printfile ("ndata3.dat")$
> 2.0; -3/7; (x:1,y:2,x+y); block([fpprec:24],bfloat(%pi)); foo
>
> (%i9) read_data ("ndata3.dat",";");
> (%o9) [[2.0,-3/7,(x:1,y:2,y+x),block([fpprec:24],bfloat(%pi)),foo]]
> (%i10) ev(%);
> (%o10) [[2.0,-3/7,3,3.1415926b0,foo]]
>
> (%i11) printfile ("ndata4.dat")$
> 2.0; -3/7; (x:1,y:2,x+y); block([fpprec:24],bfloat(%pi)); "my error"
>
> (%i12) read_data ("ndata4.dat",";");
> (%o12) [[2.0,-3/7,(x:1,y:2,y+x),block([fpprec:24],bfloat(%pi)),"my 
> error"]]
> (%i13) ev(%);
> (%o13) [[2.0,-3/7,3,3.1415926b0,"my error"]]
>
> (%i14) printfile ("ndata5.dat")$
> 1 0
>
> 2 -1/3
>
> 3 -1/2
>
> 4 -3/5
>
> 5 -2/3
> (%i15) read_data ("ndata5.dat");
> (%o15) [[1,0], [2,-1/3], [3,-1/2], [4,-3/5], [5,-2/3]]
>
> (%i16) printfile ("ndata6.dat")$
> 1, 2/3, 3.4, 2.3e9, "file ndata6.dat"
>
> "line two" , -3/4 , 6 , -4.8e-7 , 5.5
>
> 7/13, "hi there", 8, 3.3e4, -7.3
>
> 4,-3/9,"Jkl", 44.6, 9.9e-6
>
> (%i17) read_data("ndata6.dat",",");
> (%o17) [[1,2/3,3.4,2.3E+9,"file ndata6.dat"],
>                ["line two",-3/4,6,-4.8E-7,5.5],
>                [7/13,"hi there",8,33000.0,-7.3],
>                [4,-1/3,"Jkl",44.6,9.9E-6]]
>        (%i18) fundef (read_data);
>
> (%o18) read_data ([%v]) :=                  block 
> ([%s,%r,%l,%filename,%dsep,%mult:true,
>                               %mix:false],
>                 %filename:part(%v,1),
>                 if not stringp(%filename)
>                     then (disp(" file name must be a Maxima string "),
>                           return(false)),
>                 if not file_search(%filename)
>                     then (disp(" file not found "),return(false)),
>
>                 if length(%v) = 1 then %mix:true
>                     else (if length(%v) = 2 then %dsep:part(%v,2)
>                               else (%dsep:part(%v,2),%mult:part(%v,3))),
>
>                 %s:openr(%filename),%r:[],
>                 while (%l:readline(%s)) # false do
>                       if %mix
>                           then %r:cons(
>                                   map(parse_string,
>                                       split(ssubst(" ",",",%l))),%r)
>                           else %r:cons(
>                                   
> map(parse_string,split(%l,%dsep,%mult)),
>                                   %r),
>                 close(%s),reverse(%r))
>                                 
> -------------------------------------------------
>
> Ted Woollett
>
> _______________________________________________
> Maxima mailing list
> Maxima at math.utexas.edu
> http://www.math.utexas.edu/mailman/listinfo/maxima
>
Hi Ted:

I tried your latest Universal read_data function on the same file I used 
with the one I last presented and it chokes no matter what separator I 
use. This is what I think your function is (in case I copied it 
incorrectly):

read_data ([%v]) := block(
   [%s,%r,%l,%filename,%dsep,%mult:true,%mix:false],
   %filename:part(%v,1),
   if not stringp(%filename) then
     (
       disp(" file name must be a Maxima string "),
       return(false)
     ),
   if not file_search(%filename) then
     (
       disp(" file not found "),
       return(false)
     ),
   if length(%v) = 1 then
     %mix:true
   else
   (
     if length(%v) = 2 then
       %dsep:part(%v,2)
     else
     (
       %dsep:part(%v,2),
       %mult:part(%v,3)
     )
   ),
   %s:openr(%filename),
   %r:[],
   while (%l:readline(%s)) # false do
     if %mix then
       %r:cons(map(parse_string, split(ssubst(" ",",",%l))),%r)
     else
       %r:cons(map(parse_string,split(%l,%dsep,%mult)),%r),
   close(%s),
   reverse(%r)
);

My data file (with embedded CRs, LFs, and spaces,  which probably don't 
show up in this message, but I can attach it if necessary):
2.3e9 "Abc"
10.3
14.4
read_data1(%filename):=block([%s,%r],if notfile_search(%filename) then 
(disp(" file not found "),return(false)) 
,%s:openr(%filename),%r:[],while (l:readline(%s))#false do 
%r:cons(map(parse_string,split(l)),%r),reverse(%r))
12.6
14.5

If I use a space separator I get:
stdin:2:incorrect syntax: Premature termination of input at $.

If I use a ","  or ";" separator I get:
stdin:11:incorrect syntax: Abc is not an infix operator

Maybe I'm making the data file more complex than it should be, but if 
you're calling it a universal read data function, It should be bullet proof.

Paul