-
Notifications
You must be signed in to change notification settings - Fork 7
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
Callback function design #16
Comments
Generally speaking, these are the options I'm aware of:
(It would be nice to add some bullet points with their respective strengths and weaknesses.) The second part of the problem is how to pass any parameters of the function. A few approaches are outlined on fortran90.org in the section Type-casting in callbacks. Roughly speaking, if we stay within Fortran (no raw C pointers), the options I can recall are:
The last two of these will require the consumer to use a Edit 1: are Fortran procedures only distinguished by TKR, or can it also specialize based upon the callbacks with different interfaces? Edit 2: ironically, I think this issue was less of a problem in the old days of punch-cards and external subprograms. At that time you would always need to compile your code anyway. Switching to a different callback function or algorithm, just amounted to replacing a deck of cards. The name of the callback procedure would be hard-coded in the algorithm code. |
I think we should be able to implement several callback mechanism in A few notes:
|
I'm on the same page. Generally, I find that composition (i.e. procedure pointer in a derived type) involves a bit less effort compared to inheritance. For most serious problems, the overhead from the indirect referencing should be negligible compared to the function evaluation. I also don't mind having a single select type (a small detail I would like to clarify is whether a In my old NLopt wrapper, instead of an unlimited polymorphic object for parameters, I expected consumers to extend an abstract derived type: type, abstract :: nlopt_func_data
end type But the unlimited polymorphic class involves slightly less effort and is also less restrictive, i.e. the same derived type that encapsulates problem parameters can be easily reused across various problems (optimization, differential equations, etc.). |
I noticed C23 is planning to introduce a pointer type for pairing code and data (https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2787.pdf). It looks very similar to the type you are using in nlopt-f: nlopt-f/src/nlopt_callback.f90 Line 75 in 83d21e7
Admittedly, I don't yet have a full understanding of the proposed C enhancement, but I'm wondering if Fortran should have a similar built-in (language-level) callback+context abstraction. |
Instead of having to use host association to adapt the callback interface, maybe something like this procedure(minpack_func_plus_context), delegate(context) :: f
! context is a named dummy argument of the new procedure callback,
! of type minpack_context
procedure(minpack_func), closure :: fold
! the old interface
type(minpack_context) :: mydata
fold => delegate(f,mydata)
! or maybe a spin on the old statement function syntax:
fold(x) => f(x,mydata)
call minpack_hybr(fold, ...) This would be equivalent to call minpack_hybr(fold, ...)
contains
real function fold(x)
real, intent(in) :: x
fold = f(x,mydata) ! f and mydata available through host association
end function The language is pretty close already when you look at the derived type, and the use of |
The callbacks for this bindings are implemented in an ad hoc fashion, with the primary aim to closely match the NLopt API in a Fortran-friendly way. However, this might not be the best/only way to define a callback. A better target for designing the callback for the objective function should be to provide an uniform experience compared to other optimization libraries.
The callback is for this project is defined in
src/nlopt_callback.f90
. Note that this callback design creates an issue with object lifetimes (see #13).Related:
The text was updated successfully, but these errors were encountered: