2011-12-23 16 views
22

No estoy seguro si el título está bien puesto. Sugerencias bienvenidas.Cómo alias un nombre de función en Fortran

Esto es lo que quiero hacer. Verifique una condición y luego decida qué función usar en un bucle. Por ejemplo:

if (a < 0) then 
    loop_func = func1 
else 
    loop_func = func2 
endif 

hacemos lo siguiente loop_func como un puntero al escribir mi bucle. Ambas funciones toman exactamente las mismas entradas, y son diferentes los enfoques para abordar el problema en función del valor de a. Esto me permitirá tener solo un bloque de código, en lugar de dos bloques casi idénticos. Esto también podría aplicarse a las subrutinas.

¿Alguna idea de cómo esto podría implementarse?

Gracias.

Respuesta

31

Sí, Fortran tiene punteros de procedimiento, por lo que en efecto se puede alias un nombre de función. Aquí hay un ejemplo de código que asigna al puntero de función "f_ptr" una función u otra. A partir de entonces, el programa puede usar "f_ptr" y la función seleccionada será invocada.

module ExampleFuncs 

    implicit none 

contains 

function f1 (x) 
    real :: f1 
    real, intent (in) :: x 

    f1 = 2.0 * x 

    return 
end function f1 


function f2 (x) 
    real :: f2 
    real, intent (in) :: x 

    f2 = 3.0 * x**2 

    return 
end function f2 

end module ExampleFuncs 


program test_func_ptrs 

    use ExampleFuncs 
    implicit none 

    abstract interface 
     function func (z) 
     real :: func 
     real, intent (in) :: z 
     end function func 
    end interface 

    procedure (func), pointer :: f_ptr => null() 

    real :: input 

    write (*, '(/ "Input test value: ")', advance="no") 
    read (*, *) input 

    if (input < 0) then 
     f_ptr => f1 
    else 
     f_ptr => f2 
    end if 

    write (*, '(/ "evaluate function: ", ES14.4)') f_ptr (input) 

    stop 

end program test_func_ptrs 
+0

¿Para qué dialecto es esto? – wallyk

+0

Hmm ... tan '=>' es una especie de operador de asignación para punteros, y 'procedure (func)' es algún tipo de declaración para procedimientos, como 'tipo (mytype)' es para tipos derivados. Supongo que 'null()' se usa para la inicialización y es equivalente a 0. Como puedes ver, soy un principiante en esto.Y sí, Fortran es el primer lenguaje de programación que estoy aprendiendo correctamente. –

+0

Algunas preguntas. ¿Para qué es la 'interfaz'? ¿Es esa la manera de especificar un procedimiento (una vez más, como tipo derivado), y para garantizar que lo que señala el puntero es del "tipo" correcto? Además, tiene una 'parada' antes del final de su programa. ¿Es esa la mejor práctica, y debería incluirla también en mi código? –

2

La mayoría de las implementaciones de Fortran no tienen una forma estándar de manipular punteros de función o punteros de procedimiento. Sin embargo, Fortran 2003 y posteriores tienen algo. (Véase página 6 del this.)

Para la situación dada, esto va a funcionar bastante bien en su lugar:

function func1 (p1, p2, etc) 
... as you have it already 
end 

function func2 (p1, p2, etc) 
... as you have it already 
end 

function funcselect (a, p1, p2, etc) 
    if (a < 0) then 
      x = func1 (p1, p2, etc) 
    else 
      x = func2 (p1, p2, etc) 
    endif 
end 

A continuación, sólo llamar funcselect con el parámetro extra en vez de lo que habría hecho con loop_func .

+0

¿Pero no tendrá que comprobar el programa cada vez que llame a la función? Estoy tratando de evitar eso. –

+0

@SamuelTan: Sí, pero eso no es nada de qué preocuparse. En cualquier procesador moderno, son solo unos pocos ciclos de CPU: un puñado de nanosegundos. – wallyk

+2

No estoy de acuerdo con la afirmación "Fortran no tiene una forma estándar de manipular punteros de función o punteros de procedimiento". Los indicadores de procedimiento son parte del estándar de lenguaje Fortran 2003. –

Cuestiones relacionadas