2014-01-31 4 views
2

서브 루틴에서 함수 호출을 일반화하려고합니다. 그래서 내 아이디어는 이런 것입니다Fortran - 서브 루틴에서 익명 함수를 반환하십시오.

if (case1) then 
    call MainSubroutine1(myFun) 
elseif (case2) 
    call MainSubroutine2(myFun) 
end if 

do i = 1,4 
    data = myFun(i) 
end do 

저는 이것이 일종의 모호하다는 것을 알고 있습니다. 그러나 이것이 가능한지 확실하지 않습니다.

, 당신을 감사


편집 1/31/14 오전 7시 57분


내가이 표현한 막연한 방법에 대한 죄송합니다. @haraldki와 비슷한 것을 생각하고 있었지만 MainSubroutine1과 MainSubroutine2 내에서 익명의 함수를 정의하고 그 정의를 메인 코드로 전달할 수 있기를 바랬습니다.

이것은 myFun이 다른 확장 된 분포 (Gaussian 및 Fermi-Dirac)에 의존하고 있기 때문에 발생합니다. ' 상수가있는 함수 만 호출하는 기능을 갖고 싶지 않습니다.

이것이 가능합니까?

다시 한 번 감사드립니다.

+0

정확히 무엇이 질문입니까? 이 코드는 나에게 맞는 것 같습니다. 서브 루틴 내에서 함수 포인터를 할당하고 전달할 수 있습니다. – haraldkl

+2

내가 보는 유일한 문제는'myFun'이 ** 서브 루틴 안에 ** ** 정의되어 있고'case1'과'case2'가 모두 false 인 경우'data'가 정크 값으로 채워지는 것입니다. –

+2

서브 루틴이'myFun' 함수를 선택하기를 원합니까? 귀하의 질문은 명확하지 않습니다. @haraldki에 의해 작성된 것처럼 그렇게하고 싶다면 함수 포인터를 사용할 수 있습니다. 예 : http://stackoverflow.com/questions/8612466/how-to-alias-a-function-name-in-fortran –

답변

1

당신은 단순히 질문에 대한 답 : 아니, 당신은 익명 함수를 반환 할 수 없습니다. @VladimirF가 코멘트에서 말한 것처럼, Fortran에는 익명의 함수가 없기 때문입니다. 그러나 코멘트가 말한 것처럼, 프로 시저 포인터는 꽤 지나치지 않습니다.

엄청난 추측은 익명의 기능 요구 사항을 피하는 방법으로 유용 할 것으로 기대됩니다.

난 당신이

subroutine MainSubroutine1(fptr) 
    procedure(func), pointer, intent(out) :: fptr 
    ! Calculate parameterization for your "anonymous" function 
    fptr => anon_parameterized 

contains 
    real function anon_parameterized(i) 
    integer, intent(in) :: i 
    ! Use the parameterization 
    anon_parameterized = ... 
    end function 
end subroutine 

그런 짓을하려는 것으로 추정하고 내부 일에 대한 포인터를 전달하는 것과 같은 이러한 내부 아니라는 것을

subroutine MainSubroutine1(fptr) 
    procedure(func), pointer, intent(out) :: fptr 
    fptr => Gaussian 
end subroutine 

real function Gaussian(i) 
    integer, intent(in) :: i 
    ! Calculate parameterization 
    Gaussian = Gaussian_parameterized(i, ...) 

contains 
    function Gaussian_parameterized(i, ...) 
    integer, intent(in) :: i 
    !... other intent(in) parameters 
    end function 
end subroutine 

참고 싶지 않아 다른 곳에서는 아직 (F2008 기능으로) 잘 구현되지 않았고 까다 롭습니다. 호스트 연결을 얻으려면 포인터를 내부 프로 시저에 전달하면 겁이납니다.

내 추론이 옳다면 모듈 변수를 사용하여 매개 변수화를 저장할 가능성이 있으며 최종 "매개 변수화 된"호출은 MainSubroutine1 내부가 아닐 수도 있습니다.

그러나, 당신은 당신이 함수 호출과 함께 파라미터를 전달하는 전달 고려할 수있는 경우 모듈 변수 방지 할 수 있습니다 :

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

if (case1) then 
    call MainSubroutine1(myFun) 
else if (case2) 
    call MainSubroutine2(myFun) 
end if 
if (.not.associated(myFun)) STOP ":(" 

data = myFun(1, par1, par2) 

아,하지만 당신은 비 매개 변수 것을 확실히 모른다 매개 변수화 된 함수 myFun이 필요하므로 인터페이스가 모두 손상되었습니다. 그렇지 않니?

그러면 다형성이 생깁니다.

module dists 

    type, abstract :: par_type 
    end type par_type 

    type, extends(par_type) :: par_gaussian 
    real :: mu=5.2, sigma=1.2 
    end type par_gaussian 

    type, extends(par_type) :: par_fermi_dirac 
    real :: eps=11.1, mu=4.5 
    end type par_fermi_dirac 

    abstract interface 
    real function func(i, pars) 
     import par_type 
     integer, intent(in) :: i 
     class(par_type), intent(in) :: pars 
    end function func 
    end interface 

contains 

    real function gaussian(i, pars) 
    integer, intent(in) :: i 
    class(par_type), intent(in) :: pars 

    select type (pars) 
    class is (par_gaussian) 
     print*, "Gaussian", pars%mu, pars%sigma 
     gaussian = pars%mu+pars%sigma 
    end select 
    end function gaussian 

    real function fermi_dirac(i, pars) 
    integer, intent(in) :: i 
    class(par_type), intent(in) :: pars 

    select type (pars) 
    class is (par_fermi_dirac) 
     print*, "Fermi-Dirac", pars%eps, pars%mu 
     fermi_dirac = pars%eps+pars%mu 
    end select 
    end function fermi_dirac 

    subroutine sub1(fptr, pars) 
    procedure(func), pointer, intent(out) :: fptr 
    class(par_type), intent(out), allocatable :: pars 

    fptr => gaussian 
    allocate(par_gaussian :: pars) 

    end subroutine sub1 

    subroutine sub2(fptr, pars) 
    procedure(func), pointer, intent(out) :: fptr 
    class(par_type), intent(out), allocatable :: pars 

    fptr => fermi_dirac 
    allocate(par_fermi_dirac :: pars) 

    end subroutine sub2 

end module dists 

program prog 

    use dists 
    implicit none 

    class(par_type), allocatable :: pars 
    procedure(func), pointer :: myfun 

    call sub1(myfun, pars) 
    print*, myfun(i, pars) 

    call sub2(myfun, pars) 
    print*, myfun(i, pars) 

end program prog 

그건 모두 추측입니다.

+0

함수를 올바르게 반환하려면 포인터를 반환하지 않아도됩니다. 바이트 배열 (쉘 코드)을 반환 할 수 있습니다. 호출자는 쉘 코드가 자체 포함되어있는 한이 함수의 모든 종속성을 인수로 전달해야합니다. 그러나 "함수"가 순수하고 엄격한 입출력 유형을 갖고 부작용이 없다면 "미리 어셈블"하고 사전 어셈블 된 쉘 코드 배열을 반환하는 함수를 가르쳐서는 안됩니다. – Dmitry