-
Notifications
You must be signed in to change notification settings - Fork 182
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
Implement non-fancy functional string type #320
Conversation
- support all intrinsic operators for character variables (llt, lgt, lle, lge, len, len_trim, trim, adjustl, adjustr, index, scan, verify, repeat, char, ichar, iachar) - support derived type IO (formatted and unformatted) - implement assignment from character values - implement constructing string from character values
Thank you, I think this will be a very nice addition. I learned something new. If you define and import, say, Why did you implement the operators as module procedures instead of type bound methods? Currently, you need to explicitly import the operators from the module if you want to use them:
But if they were type-bound, they'd come with the type. Another advantage is that they would work with types that extend I also suggest adding an option to assign a
If you agree, let me know if you'd like me to add the implementation and tests for it to this PR. One thing that may be a non-goal for this PR, but I think useful, is a function (type-bound or otherwise) that returns a raw Fortran character string without having to assign it. This will allow |
None of the operators is defined for a polymorphic object so far, therefore they cannot be type-bound. Also the
I did want to explore a string class at some point (maybe we can call it
There is the usual tie between fixed length characters and deferred length characters, you can only define one interface but not both. You can either have a pure subroutine assign_char_string(lhs, rhs)
character(len=:), allocatable, intent(inout) :: lhs
type(string_type), intent(in) :: rhs
end subroutine assign_char_string Or you can have an elemental subroutine assign_char_string(lhs, rhs)
character(len=*), intent(inout) :: lhs
type(string_type), intent(in) :: rhs
end subroutine assign_char_string The best option in my opinion was to drop this case entirely and use the automatic left-hand-side reallocating by explicitly returning the character sequences from the |
Have a look at the |
Excellent, I didn't put two and two together and realize that this also implements |
Is
Well, operators being type-bound is an implementation detail. The UI would still be functional. The 2nd argument (run-time resolution) is valid, IMO. So it's important to note that this choice would be a compromise between performance (compile-time resolution of operators) and UI (having to import operators explicitly). As long as this module exports only its type and the procedure interfaces that work on it, I'd be happy to recommend users just doing |
See https://j3-fortran.org/doc/year/18/18-007r1.pdf#subsubsection.573, no mention about any deprecation here or elsewhere in this document. To my knowledge, |
This is a good general rule we can adopt in a future Fortran style guide. Particularly in the case when the procedures overload intrinsic functions and provide equivalent functionality. |
I agree on the fact that it should be a general rule, but I don't know if we have a majority on this. Maybe @milancurcic wants to consider this case-by-case, considering his pre-clause above (as long as...). He might not be alone. For example, I did raise a related issue while reviewing the string list PR (together with other observations) where the namespace was polluted with a |
I just asked about this on Discourse. But I'm still unclear what are you trying to do with |
It's the only surefire method I know to make a type non-extendible, that's the reason I'm applying it here. But maybe there is a better way. The problem is that extending another class from the Designing an abstract base class that can support the full functionality of the intrinsic deferred length character is not easy, also it is not a lightweight object anymore. I will upload a |
@awvwgk okay, all good, I understand now. I agree with this design choice. 👍 |
An idea: What do you think about calling this |
IMO, being explicit rather than implicit should be preferred, similar like we prefer character(len=:), allocatable :: str
type(string_type) :: str
type(str_type) :: str |
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.
Nice work. Thank you @awvwgk .
For the specs, I suggest to explicitely mention program demo_....
and end program demo_...
.
While it is correct like that, it might be confusing for beginners who would read these specs.
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 haven't managed to go through the implementation yet (not that I expect any wrongdoing), but I left a few comments in the specs.
The module defines an assignment operations, `=`, to create a string type | ||
from a character scalar. |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
Co-authored-by: Ivan Pribec <[email protected]> Co-authored-by: Jeremie Vandenplas <[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.
Thank you, I'm happy with this PR!
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.
+1 to merge.
Ready to go from my side. |
@jvdp1 do you have any unresolved comments? If not I suggest we go ahead and merge this later today. |
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.
Sorry for the delay. It is ok from my side. It can be merged. Thank you @awvwgk for this work!
Thanks a lot your comments and the review. I already pushed the follow up for the non-fancy string type: an abstract base class for string objects (see #333), which basically provides the same functionality as the string type but in an object-oriented rather than a functional way. |
This patch proposes a non-fancy string type, which basically provides the same functionality as a deferred length character but can be used in an
elemental
rather than apure
way. The idea was to have a scaffold for the string type in stdlib which can be extended later but already provides everything we are used to have from the deferred length character without the rough edges, like not being able to read into an unallocated deferred length character variable or being unable to have arrays.Related issues
Goals
string_type
)llt
,lgt
,lle
,lge
,len
,len_trim
,trim
,adjustl
,adjustr
,index
,scan
,verify
,repeat
,ichar
,iachar
)char
function, which also allows to return astring_type
as fixed length character variableNon-goals (for this patch)
FPM project
To ease review I created an fpm project at https://github.com/awvwgk/stdlib_string, which I will keep in sync with this patch. It also provides the API documentation and the specs at https://awvwgk.github.io/stdlib_string.