Closed septcolor closed 2 years ago
@septcolor , Toward your first item, how about using the scientific format instead which is already supported?
real :: x
namelist / dat / x
character(len=:), allocatable :: s
s = "&dat x=1e6 /"
read( s, nml=dat )
print *, "x = ", x
end
C:\temp>gfortran p.f90 -o p.exe
C:\temp>p.exe x = 1000000.00
As to your second suggestion, it appears a bridge too far. As you pointed out, you already have the problem with the repeat count (*) that makes the multiplication operation complicated. And that's just the beginning of complexity.
You might consider an expression evaluator library instead that you integrate with your codes and which then parse string "data" to evaluate the expressions.
Hi @FortranFan ,
(Edit: I have just updated the original post and title, such that it focuses only on large integers (which is one of my "pain points" for namelist input.)
Thanks much for your suggestion. I've just tried your snippet, but noticed that x
is real
(and yes, in this case the scientific notation works!). However, if the namelist variable is integer
, it results in a runtime error (at least for Gfortran-10), as follows...
integer :: x
namelist / dat / x
character(len=:), allocatable :: s
s = "&dat x=1e6 /"
read( s, nml=dat )
print *, "x = ", x
end
$ gfortran-10 test.f90 && ./a.out
Fortran runtime error: Cannot match namelist object name e6
And I agree that the namelist input has a lot of "weird" rules (maybe for historical reasons), so I wonder if there could be some way to entirely work around those limitations, while keeping the convenience of namelist input.
RE expression evaluators, that would be one approach if I really want math expressions in the input files. But one of the most appealing points of namelist (to me) is that it can fill values directly in the specified components of a given derived type. I usually set up "parameter type" objects and read all parameters, e.g., as
subroutine X_readpar( par ) !! where X is some tag/name/etc
type(Xpar_t) :: par
namelist / Xinp / par
...
read( file, nml = Xinp )
...
and the caller passes par
as a component of a parent type
call X_readpar( xobj % par ) !! where obj is an instance of type X, for example
Probably, this kind of "direct filling" of type components cannot be done via 3rd-party expression evaluators. Another approach is to use external input libraries like TOML, which may read in values into some dictionary object inside Fortran. However, in this case I have to copy necessary type components again from the dictionary to the derived-type object manually, which is just too tedious (to me) if the number of parameters is large... (One method may be to use such a dictionary directly inside the program, but I guess the code becomes more verbose everywhere, probably, as compared to just using the type components.)
I have been using namelist input files extensively in my codes. While they are very useful, one weak point is that integer assignment allows only this kind of "raw" notation
(here,
par
is some parameter object). Very often, the number of steps like above is rather large, which is often not very readable. I tried using the usual notation likebut it interferes with the special meaning of
*
in the namelist and results in a runtime error. So I wish some other syntax would be available, e.g.,or
If the symbols like
*
or^
are not acceptable, some kind of "math" string (e.g. m"...") may be useful for internal conversion (from math strings to integer in this case).Apart from the specific syntax, I hope I can also write
nsteps = 2 * 10^7
rather thannsteps = 20000000
, because I need to count the number of zeros every time with mouse cursor.(Edit) Because the math evaluation like
sqrt()
seems like too far as a request, I deleted it from the original post. My intention is not a "general" expression evaluator, but just the above kind of large integers (at the moment).