Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

suggestions for experimental_io open() #125

Closed
urbanjost opened this issue Jan 26, 2020 · 5 comments
Closed

suggestions for experimental_io open() #125

urbanjost opened this issue Jan 26, 2020 · 5 comments
Labels
topic: utilities containers, strings, files, OS/environment integration, unit testing, assertions, logging, ...

Comments

@urbanjost
Copy link

Two possible changes for consideration:

As IOSTAT returns numbers that are programming-environment specific the OPEN statement should
return IOMSG and print it when the user has asked to have the IOSTAT value returned. The message provided by the compiler is often a lot easier to understand than the implementation-specific numbers.

Perhaps it has settled down, but at one time there was a lot of variation in what happened when a blank filename was used on an OPEN. Some systems opened a file with a default name like 'file.10'. I think that particular error should be trapped by the code, or perhaps open a SCRATCH file (I wrote a similar routine in the past where that is what happened, so I have a bias there)

The M_io.f90 module was something I mostly used for prototyping quick utilities except for READ_LINE and SWALLOW. Used to use NOTOPEN a lot before NEWUNIT= was added to OPEN.
But I find it interesting that several discussions in stdlib are about similar routines; just proving we
all are reinventing the wheel all the time -- hopefully stdlib will ultimately eliminate most of that.t

My routine most equivalent to your open() experiment is fileopen(). I played with it a few too many times so it does cute things like allowing '>', '<', '>>' as substitutes for 'r','w','a' for a shell-like feel
that I mostly did as an experiment that several people liked; but in retrospect it should have been kept clean and simple and as much like other common languages as possible; so I like open() so far; but surprised no one felt unconfortable with calling it open instead of fopen since there is already a Fortran directive called OPEN.

The contents of M_io.f90 (definitely not the most evolved module, but it was good for Q&D work):

950 fileclose (3m_io) - [M_io] A simple close of a sequential file(LICENSE:PD)
951 filedelete (3m_io) - [M_io] A simple close of an open file with STATUS='DELETE'(LICENSE:PD)
952 fileopen (3m_io) - [M_io] A simple open of a sequential file(LICENSE:PD)
953 uniq (3m_io) - [M_io] append a number to the end of filename to make a unique name if name exists(LICENSE:PD)
954 rd (3m_io) - [M_io] ask for string from standard input with user-definable prompt(LICENSE:PD)
955 print_inquire (3m_io) - [M_io] Do INQUIRE on file by name/number and print results(LICENSE:PD)
956 notopen (3m_io) - [M_io] Find a FUN/LUN (Fortran-unit-number) that is not in use(LICENSE:PD)
957 M_io (3m_io) - [M_io] Fortran I/O module (LICENSE:PD)
958 read_all (3m_io) - [M_io] read a line from specified LUN into allocatable string up to line length limit(LICENSE:PD)
959 read_line (3m_io) - [M_io] read a line from specified LUN into allocatable string up to line length limit cleaning up input line(LICENSE:PD)
960 read_table (3m_io) - [M_io] read file containing a table of numeric values(LICENSE:PD)
961 slurp (3m_io) - [M_io] read a file into a character array(LICENSE:PD)
962 swallow (3m_io) - [M_io] read a file into a character array line by line(LICENSE:PD)
963 get_tmp (3m_io) - [M_io] Return the name of the scratch directory(LICENSE:PD)
964 scratch (3m_io) - [M_io] Return the name of a scratch file(LICENSE:PD)
965 splitpath (3m_io) - [M_io] split a Unix pathname into components(LICENSE:PD)
966 dirname (3m_io) - [M_io] strip last component from filename(LICENSE:PD)

@jvdp1
Copy link
Member

jvdp1 commented Jan 26, 2020

Thank you @urbanjost for this post. I have some comments below.

Two possible changes for consideration:

As IOSTAT returns numbers that are programming-environment specific the OPEN statement should
return IOMSG and print it when the user has asked to have the IOSTAT value returned. The message provided by the compiler is often a lot easier to understand than the implementation-specific numbers.

I think it is a good idea to use iomsg to help the users. However, I would suggest to not print iomsg per default when iostat is asked. For some applications, I just need to know if iostat is equl to 0 or not.

Perhaps it has settled down, but at one time there was a lot of variation in what happened when a blank filename was used on an OPEN. Some systems opened a file with a default name like 'file.10'. I think that particular error should be trapped by the code, or perhaps open a SCRATCH file (I wrote a similar routine in the past where that is what happened, so I have a bias there)

I don't think such a behavior is possible with the stdlib open (at least I could not reproduce it). For example,
u=open(' ','wt',iostat=io)
will return a io status = 2 because the open statement does not accept blank filenames.

but surprised no one felt unconfortable with calling it open instead of fopen since there is already a Fortran directive called OPEN.

There has been some discussions about the name in #71.

951 filedelete (3m_io) - [M_io] A simple close of an open file with STATUS='DELETE'(LICENSE:PD)

See #14 (this comment and others) for some discussions on this topic.

960 read_table (3m_io) - [M_io] read file containing a table of numeric values(LICENSE:PD)

Is it similar to stdlib loadtxt?

961 slurp (3m_io) - [M_io] read a file into a character array(LICENSE:PD)

It might be a nice extension to stdlib loadtxt.

@jvdp1 jvdp1 added the topic: utilities containers, strings, files, OS/environment integration, unit testing, assertions, logging, ... label Jan 26, 2020
@urbanjost
Copy link
Author

http://www.urbanjost.altervista.org/LIBRARY/libGPF/download/tmp/html/BOOK_M_io.html

describes the M_io.f90 module. The routines have similar functionality to the IO routines being created in io_experimental. The loading of tables keeps reparsing in mine; I think parsing the top line and counting the number of variables and then using standard I/O as done in io_experimental is probably far more efficient.

I literally meant in open() to detect a blank filename and then do a standard Fortran OPEN on a scratch file as an alternative to generating an error. The compilers I tried where I tried a blank filename do not act like the filename parameter was not present which was a problem I saw in the past that made me think you should trap for a blank filename yourself instead of depending on the compiler to flag it as an error, but maybe no compiler does that anymore. It was a confusing difference in the past between compilers.

I was trying to move the GPF (General Purpose Fortran) collection from my own site to github but was having a lot of problems with getting the automatically generated documents to work in github and then stdlib started so I have not done much with it lately, but it is a lot easier to read the online
documents from GPF download

@certik
Copy link
Member

certik commented Jan 27, 2020

Regarding the blank filename, I would not silently open a temporary file, but rather give an error. As in Python:

In [1]: a = open()                                                              
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-1-7d12777c4d26> in <module>
----> 1 a = open()

TypeError: open() missing required argument 'file' (pos 1)

In [2]: a = open("")                                                            
---------------------------------------------------------------------------
FileNotFoundError                         Traceback (most recent call last)
<ipython-input-2-1b5b4ce920cc> in <module>
----> 1 a = open("")

FileNotFoundError: [Errno 2] No such file or directory: ''

For temporary files, we should create a different function, e.g., Python has mkstemp. I just opened #126 for that.

@jvdp1
Copy link
Member

jvdp1 commented Jan 27, 2020

Regarding the blank filename, I would not silently open a temporary file, but rather give an error.

I agree with @certik. And it is already what should happen with the stdlib open.

@urbanjost
Copy link
Author

I have a similar routine to stdlib::open called fileopen, and it uses a null filename to open a scratch file and looking thru my usage of the routine the first and second most common usage where "fileopen('filename') and fileopen('','rwb') so thought I would mention it; no strong feelings on what a blank name should do; especially since what testing I could do does not show any modern compilers that opened an explicit blank filename as a "default" system-dependent name; although a lot do open a named file called something like "file.NNN" where NNN is the LUN; even some open the file as "file.-NNN" when newunit= is used. The negative sign seems a bit ugly. Maybe it is obvious but part of the style guide could be to always either use a named file or status='scratch' but to not use this "feature" of most programs to open default filenames.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
topic: utilities containers, strings, files, OS/environment integration, unit testing, assertions, logging, ...
Projects
None yet
Development

No branches or pull requests

3 participants