-
Notifications
You must be signed in to change notification settings - Fork 174
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
Add format_string routine to format other types to strings #444
Add format_string routine to format other types to strings #444
Conversation
1. src/stdlib_strings_format_string.fypp 2. src/tests/string/test_strings_format_string.f90 3. stdlib_strings.fypp%format_string interface modify: 1. doc/spec/stdlib_strings.md%format_string(doc) 2. stdlib_strings.f90 -> stdlib_strings.fypp(rename) 3. src/Makefile.manual%format_string(make) 4. src/tests/string/Makefile.manual%format_string(make) 5. src/CMakelists.txt%format_string(cmake) 6. src/CMakelists.txt%format_string(cmake) note: make test passed. cmake test passed
string = '*' | ||
!!\TODO: *? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For a meaningful number of asterisks in the output we must be able to parse format strings and determine the width of the field we are writing into. Just writing a single asterisk until we are able to do so in stdlib sounds like a good compromise for now. What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is OK, just writing a single asterisk until we are able to do so in stdlib
.😜
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Checking a failed formatter should be simple, currently I'm using starts_with(format_string(var, "(...)"), "*")
. This is not fail-safe as it would match a formatter like '("*", g0)'
as well. Using format_string
should imply that we trade some of the versatility of the internal IO approach for having a function.
How about returning an empty string on failure? This would be clearly distinct from a too narrow formatter?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is mainly to remind the users: an empty string may not be effectively fed back to the user, this is a format_string
failure.
- We need to notify the user more clearly that this has failed;
- The string output after failure is simple enough;
- Does not hinder the effective operation of the main process of our
Fortran
program.
clean the implementation of format_string
fix: 1. src/stdlib_strings.fypp%format_string interface comments 2. src/stdlib_strings_format_string.fypp update: 1. src/tests/string/test_strings_format_string.f90 2. doc/specs/stdlib_strings.md note: make passed cmake passed
I added a suggestion as PR against yours (see St-Maxwell#1) for expanding the unit testing and providing better error reporting in case of a mismatch in the formatted strings. |
Expand unit testing for more cases
Looks like our choice of default formatter with For
|
Links
It seems that the standard says that the width is determined by the processor, but it is actually determined by the compiler on |
Processor is standard-speak for compiler. |
…4 (comment)) fix: 1. src/tests/string/test_strings_format_string.f90 2. romove the `buffer` variable in `format_string_c${kind}$` update: 1. doc/specs/stdlib_strings.md%format_string note: make passed cmake passed
…Maxwell/stdlib into zoziha/feature/format_string
🤔I'm wondering if there are some compiler options of Intel compiler that can prevent applying edit descriptor on mismatching type of values. And if exist, we can add them into |
I opened #446 to discuss handling smart behaviour in compilers. I think we want consistent results which are independent of the compiler, but we also don't want to set too many special flags when compiling, because some of them (like Eventually, not using the internal IO but have our own implementation of format descriptors would be the preferred solution, as it makes as most independent of the actual details of compiler extensions. |
I support implementing a procedure converting floating-point numbers to strings in stdlib in the future. I found Grisu or Ryū algorithm might be the choice. Unfortunately I'm not able to implement it. This needs the help from the community. |
How about
|
@zoziha, concerning the following point
see #399. IMO, also |
Sorry for my absence in recent discussion because I was busy in my project. I like |
Yes, 512 is a bit long, we can decide a certain length, it can be 128. And it is stated in the docs (stdlib_strings.md).
If I try to cancel the
If
If it is renamed
If |
This comment has been minimized.
This comment has been minimized.
We rejected I'm still fine with naming it Whatever name we arrive with in the end, I'm still in favor of moving this patch forward. |
…module):format_to_string(interface)`. #### Works 1. merge `to_string` and `format_to_string` to `stdlib_strings`, make the name `to_string` 2. redrect the used keyword `to_string` in `stdlib_string_type` 3. add `stdlib_string_type_constructor.fypp` to avoid the ring dependence in `stdlib_strings` and `stdlib_string_type`. 4. other clean works.
Thanks, I canceled the idea (see comment) merge I completed this task in another branch (see implementation). It's true that the task is a bit heavy. A note(see stdlib_string_type_constructor.fypp) |
I merged |
logical :: stat | ||
character(len=:), allocatable :: msg | ||
|
||
if (merge(partial, .false., present(partial))) then |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
In a nutshell, these are now specific functions that go in addition to the previously existing |
If there are no objections, I'll merge this tomorrow. |
Thanks a lot, @zoziha! |
src/stdlib_strings_to_string.fypp
Outdated
character(len=buffer_len) :: buffer | ||
integer :: stat | ||
|
||
write(buffer, optval(format, "(g0)"), iostat=stat) value |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I apologize for the last minute suggestion. What do you think about the following:
write(buffer, optval(format, "(g0)"), iostat=stat) value | |
write(buffer, "(" // optval(format, "g0") // ")", iostat=stat) value |
Whether the format dummy is present or not, this encloses the format string in an extra set of parentheses. This makes the function slightly more flexible. For example, you can now do:
print *, to_string(1.2345, 'f4.2') ! prints '1.23'
which would previously not work. I don't know why Fortran requires parentheses around format strings, but it's always been one of those little annoying things to me. And if you already have an outer set of parentheses, the semantics don't change. I think this allows for a better UI.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have to admit, a format string without parenthesis looks slightly off to me. But I have no strong feelings about this either way.
The only issue I could see, is that it might be surprising for a new user if the intrinsic transfer routines require a different syntax than the standard library. But maybe this is a good thing as well and could be used to suggest a simplification of format strings in the next Fortran standard.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, if we decide to do this we should document it clearly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Without parentheses, it looks more concise. I think it's good, as long as we explain it in the document: We use parentheses by default inside to_string
to help users write less.
I will confirm the feasibility of this writing later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just made a suggestion in #444 (comment).
doc/specs/stdlib_strings.md
Outdated
|
||
- `value`: Shall be an `integer/real/complex/logical` scalar. | ||
This is an `intent(in)` argument. | ||
- `format`: Shall be a `character(len=*)` scalar like `'(F6.2)'`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@zoziha @awvwgk Suggestion for docs improvement, to go together with #444 (comment).
- `format`: Shall be a `character(len=*)` scalar like `'(F6.2)'`. | |
- `format`: Shall be a `character(len=*)` scalar that contains the edit descriptor to format `value` into a string, | |
for example `'(F6.2)'` or `'(f6.2)'`. `to_string` will automatically enclose `format` in a set of parentheses, | |
so passing `F6.2` or `f6.2` as `format` is possible as well. |
I tried to change the corresponding content of This is user-friendly and a practical change. @milancurcic Thanks a lot! |
Indeed, Fortran allows formats like this: |
modify:
note:
make test passed.
cmake test passed