-
Notifications
You must be signed in to change notification settings - Fork 178
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 functions to convert integer/logical values to character values #336
Conversation
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.
In general I agree with the implementation and tests. I'm not sure about the name char_value
. I think it is too long to be practical in building strings using concatenation, e.g. filename = basename//char_value(timestep)//".txt"
.
I guess the name str
would be the typical name, but it risks clashing with variables. char
cannot be used due to overlap with the intrinsic function.
integer, parameter :: ik = ${kind}$ | ||
logical(ik), intent(in) :: val |
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.
Is this just for improved clarity of the generated code?
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, I didn't like the look with the ${kind}$
preprocessor all over the place
I was thinking about something short, |
How about |
I just wanted to suggest Edit: in analogy, we could have |
I was thinking that there is also |
Should we extend the constructor for the use stdlib_string_type, only : string_type, assignment(=), write(formatted)
use stdlib_ascii, only : to_char
implicit none
type(string_type) :: string
string = to_char(42)
print*, string
print*, string_type(to_char(42))
end Do we want to extend the use stdlib_string_type, only : string_type, assignment(=), write(formatted)
implicit none
type(string_type) :: string
string = 42 ! possibly harmful
print*, string
print*, string_type(42) ! maybe useful
end |
I'd love to allow the above. I agree that allowing the assignment |
IMO |
|
You're right, but the Fortran type name is surprising in general. "Character" is commonly used to refer to a single character, like in a C So the question is whether we should follow an existing, suboptimal convention, or choose the most appropriate and commonly used term. I'd prefer to use |
@ivan-pi I'm confused. This is a snippet of a potential user code, right? So, an stdlib function name clashes with a user snippet? Here's a scenario: User: "I can't use the I totally get that this is a common and convenient pattern for single string variables, but if you use this argument, you're throwing out many perfectly good function names. Is there some other scenario of a name clash? |
I agree that Fortran
I would agree with you if we were planning on changing also the intrinsic name from ADDENDUM: I see the point about the ambiguity of single and multi-char |
@milan, That is precisely the scenario I had in mind. I recall there being a discussion somewhere of how I found two examples where Here are a few Fortran libraries that use
And here are a few libraries which already use
Let's look at what other languages have:
|
I'm not sure if using C is a good counter-argument. Fortran is the older language of the two, and the motivation for using Fortran is partially to avoid the pitfalls of C pointers and tedious array management. Isn't it then better to maintain the same root morpheme which is already part of language? |
Sorry for the confusion with that, I only meant to use C |
I understand your viewpoint. Quoting Computer Hope:
I also amended my list above with the name of the string object in different languages. Fortran is the odd one 😂, which is exactly what would make the name |
@ivan-pi Thank you for the comprehensive review of names in other languages. I think that's very helpful. Regarding the Fortran libraries that use Instead, let's narrow down to a scenario that would cause a name-clash:
3a could be a major nuisance for the user, and 3b is a minor nuisance. Do you agree with my description of the scenario, and is my assessment of the level of nuisance fair? But I think the consistency argument for From your list, 9/15 use some kind of
|
I did take the list of Fortran libraries a notch too far. I merely wanted to demonstrate that Regarding points 3a and 3b when developing new codes, as long as the code is modular, renaming is not a big issue with modern source code editors. In fact when preparing the list I noticed many codes use variables such as One further downside of This has me quite torn now. |
I added Elixir, Erlang, Nim, and Zig to your table. |
Just to throw a few other options on the table:
Addendum: one more (unfriendly) option are separate functions:
Addendum 2: borrow from C and gnuplot
|
Speaking of someone that already uses a STR() function name,one version I have that might be relevant (just uses internal reads) is in M_msg but uses class(*) to allow the There are other versions that use the old ITOA, FTOA, DTOA routines that are used for arrays as they are considerably faster than internal I/O; but I do not think I have a public version. It raises the interesting issue of whether you want the routines to be elemental or not. I find overloading helps make things much more compact, so assuming you have a function like STR, overloading // with that allows you to do things like "MESSAGE='the value is '//10//' and the limit is '//300.4//'.'". Some would probably like to overload + to do that, but I prefer to overload + - / * to convert strings to numbers, and to overload INT(), REAL(), and DBLE() to take character values and assume they are numeric. So that makes for a symmetric set for converting to and from strings and numeric values. I originally overloaded CHAR() to do something other than it does by default but decided that was a bad idea (I actually do not remember what I tried, but I remember I decided it was too confusing). So I did not see anything about overloading '//' or using class(*) variables so thought I would mention that works well for me. |
Any comments about |
Both Java and Javascript support the idiom of using the concatenation operator to build a string using String s = "" + i; If
Addendum: inside the overloaded operator one still needs to use internal I/O or a function like |
FWIW, I find I think ultimately we will need to go with the popular choice. |
Thanks for all the feedback, naming functions is hard, especially with the oddity of the Fortran I also added the integer/logical to character conversion to the constructor of the |
I realize now, both arguments--for Even though "experimental" and can change, it's important to make a good choice here because these are such high impact functions. Let's get more eyes on this. @certik @jvdp1 @everythingfunctional @arjenmarkus @rouson @LKedward @smeskos what do you think? |
Nice and important discussion! IMO the prefix "to_" is needed, as it explains the purpose of the function (like for |
I am in favor of the prefix "to_" as well. Now as far as the rest, I have given it much thought and I am leaning towards "to_string", keeping in mind that it can be used for both characters as well as the string DT. Reasoning: I am inspired by C++ |
I vote for |
With d835ad8 (this PR), it will be |
For derived types the natural choice is to extend the constructor IMO, this way no additional function name is required. |
My preference is for |
From the discussion I conclude that use stdlib_ascii, only : to_string ! returns character(len=*)
use stdlib_string_type, only : string_type, & ! overloaded constructor, returns type(string_type)
& write(formatted), assignment(=)
implicit none
character(len=:), allocatable :: dlc
type(string_type) :: str
! Intrinsic character case
dlc = to_string(7)
print*, dlc, to_string(42)
! Derived type case
str = string_type(7) ! str = to_string(7) works as well due to overloaded assignment(=)
print*, str, string_type(42)
end |
- use fypp in stdlib_ascii to generate functions for all kind values
Co-authored-by: Ivan Pribec <[email protected]>
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.
LGTM 👍
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.
LGTM! Thank you.
Thanks everybody for the feedback. With four approvals I'll go ahead and merge. |
I think that looks good. |
stdlib_ascii
to generate functions for all kind values