-
Notifications
You must be signed in to change notification settings - Fork 17
Overloading () #119
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
Comments
I'm not so sure about such expressions as the lhs of an assignment (and actually I'm not sure what "1:5" would mean as an argument), but I've often wished for this to improve readability/expressiveness. For example, I currently have stuff similar to this type, abstract :: func
contains
procedure(eval) , deferred :: eval
end type
abstract interface
real function eval(this, x)
import func
real, intent(in) :: x
end function
end interface
class(func) :: f
a = f%eval(0.0) It would be much clearer imo to be able to write |
Unless a strong use case is presented, I would personally oppose. Fortran
is not C++. It already has arrays. If someone wants to build an object
wrapper around an array, or implement string as a derived type (as opposed
to intrinsic implementation) I suggest using C++ as a better suited
language.
Dictionaries, strings and arrays should be built into language.
pt., 20 gru 2019 o 16:30 Neil Carlson <notifications@github.com> napisał(a):
… I'm not so sure about such expressions as the lhs of an assignment (and
actually I'm not sure what "1:5" would mean as an argument), but I've often
wished for this to improve readability/expressiveness. For example, I
currently have stuff similar to this
type, abstract :: funccontains
procedure(eval) , deferred :: eval
end type
abstract interface
real function eval(this, x)
import func
real, intent(in) :: x
end function
end interface
class(func) :: f
a = f%eval(0.0)
It would be much clearer imo to be able to write f(0.0). This just
syntactic sugar I think, so I wouldn't expect it to be difficult to
implement.
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
<#119?email_source=notifications&email_token=AC4NA3I5DFQSTWWBXYILQK3QZTQI5A5CNFSM4J5X4262YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEHNHFFA#issuecomment-567964308>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AC4NA3MP2DRZ245AULZYMW3QZTQI5ANCNFSM4J5X426Q>
.
|
I think this could be useful, but we would need to separate function calls from indexing. Function calls would be trivial enough to define. Something like the following: module example
type :: callable
contains
procedure :: called_proc
generic :: operator(()) => called_proc
end type callable
contains
real function called_proc(self, arg1, arg2, arg3)
class(callable), intent(in) :: self
integer, intent(in) :: arg1, arg2
real, intent(in) :: arg3
called_proc = arg3 ** (arg1 + arg2)
end function called_proc
end module example The procedure that is called could be any function or subroutine which is valid as a type-bound procedure. Indexing could be implemented in a similar manner, but would need some way to distinguish itself. Leaving that issue aside for the moment, we could do the following: module example2
type :: indexed
contains
procedure :: index_proc
generic :: operator(()) => index_proc
end type indexed
contains
real function index_proc(self, arg1, arg2, arg3)
class(indexed), intent(in) :: self
integer, intent(in) :: arg1, arg2, arg3
called_proc = arg3 ** (arg1 + arg2)
end function index_proc
end module example2 The functionn called for indexing would need to accept scalar integer arguments of The issue becomes how to distinguish between these two distinct use cases. Some different approaches:
Personally, I think the first of these makes the most sense. |
Well, the fact of the matter is that these aren't built in and I can see this operator being accepted more quickly than such a standard template library being approved and implemented. A use-case I could potentially see for overloaded indexing would be for handling non-rectangular or periodic grids. Potentially unstructured meshes too, maybe? A use case for overloading procedure-calling would be to allow |
This is just syntactic sugar for a type-bound function that could return a pointer, yes? |
@klausler For the LHS case, maybe ... or maybe some additional kind of assignment operator? @gronki @cmacmackin Right, we don't have strings, and I'm not that optimistic that we will ever have them. So, give us this, and we can write our own string class in the proposed standard library. No matter how amazing a string class we can write now, it will always be clunky since to use the slice notation, we have to expose the underling character string: This would be amazing: type(string) :: s1, s2, s3
...
s3 = s1(1:2) // s(10:20) This is not amazing: type(string) :: s1, s2, s3
...
s3 = s1%str(1:2) // s%str(10:20) |
@klausler the issue with returning pointers is it requires that whatever is being pointed to is a valid target. Currently derived type components can not have the |
I have wished to have this several times. An equivalent feature of Python is the ability to overload the I like the idea of @cmacmackin to have attributes for module quadratic_mod
type, public :: quadratic
real :: a, b, c
contains
procedure, callable :: eval
generic :: operator(()) => eval
end type
contains
real function eval(this,x)
class(quadratic),intent(in) :: this
real,intent(in) :: x
eval = this%a+x*(this%b+x*this%c)
end function
end module
program main
use quadratic_mod
type(quadratic) :: f = quadratic(1.0,2.0,3.0) ! 1 + 2*x + 3*x**2
real :: y
y = f(x)
end program What I wonder is, whether such a functors could then be passed on to some other routine, e.g. a numerical integration routine with a fixed interface such as: abstract interface
real function f(x)
real, intent(in) :: x
end function
end interface
function integrate(a,b,f)
real, intent(in) :: a, b
procedure(func) :: f
...
end funcion without having to rely upon an adaptor class/module. |
Thanks @pbrady I thought you already opened some issues for this, but I couldn't find it. |
@nncarlson It's interesting that I use the same pattern for creating potential energy functions, i.e. a function object (derived from an abstract one) that is given system-specific data + potential routines. An appealing point of this approach (to me) is that each function object has its own data internally. One use case might be to pass such a function object (with an overloaded ()) to generics that can accept both procedures and functors. For example, "callablle(func) :: f" instead of "procedure(func) :: f"...? (But I also feel that this kind of thing could make the learning cost of Fortran higher, so care may be necessary to keep the syntax relatively straightforward...) |
I think that there are two independent proposals here, which I would separate as:
I think both proposals would make the language more intuitive, but I think the two should be evaluated separately, on their own merits. If both were implemented, I see no reason to limit the slice syntax to only be useable with the function object syntax. |
I'm bringing back this discussion following what's been under discussion here. I think having an Here's one simple example I have in mind:
I haven't thought about all the implications on sliced array indexing/ stride/etc. but if there's an Actually, a compiler may like more the My two cents, |
On the usage standpoint, imagine all array-based syntax to be enabled by that, like:
etc. |
@perazz, you should be able to get a nice symmetric matrix syntax with the new features in C++23 such as the multidimensional |
I haven't fully thought this through yet, but what if we had the ability to overload
()
for a derived type in various contexts? That could be used for some interesting things.Such as dictionaries:
or a string class:
The text was updated successfully, but these errors were encountered: