Я надеюсь, Fortran поддерживать популярный синтаксис как
subroutine mysub(x, val = -1)
integer, optional :: val
или в более Fortran стиле
subroutine mysub(x, val)
integer, optional :: val = -1 !! not SAVE attribute intended
, но это, похоже, не поддерживается (по состоянию на 2016 г.). Поэтому некоторые способы решения проблемы должны выполняться пользователями ...
В моем случае, после проб и ошибок, я устроился на прикрепление один подчеркивания к факультативному фиктивному аргументу, так что делать что-то вроде (*)
subroutine mysub(x, val_)
integer, optional :: val_
integer val
Других люди, кажется, как обратную картину (т. е. фиктивная переменная =>sep
, локальная переменная =>sep_
, см., например, split() в StringiFor). Как видно из this line, самый короткий путь, чтобы установить значение по умолчанию является
val = -1 ; if (present(val_)) val = val_
Но поскольку даже эта линия несколько многословен, я обычно определяют макрос как
#define optval(x,opt,val) x = val; if (present(opt)) x = opt
в общем файле заголовка и использования это, как
subroutine mysub(x, val_, eps_)
integer :: x
integer, optional :: val_
real, optional :: eps_
integer val
real eps
optval(val, val_, -1)
optval(eps, eps_, 1.0e-5)
print *, "x=", x, "val=", val, "eps=", eps
endsubroutine
...
call mysub(100)
call mysub(100, val_= 3)
call mysub(100, val_= 3, eps_= 1.0e-8)
Однако, я считаю, что это еще далеко от элегантности и не больше усилий, чтобы сделать его немного менее подвержены ошибкам (используя нужное имя переменного в тело подпрограммы).
Другой обходной путь для очень «большой» подпрограммы может быть пройти производный тип, который содержит все остальные аргументы ключевого слова. Например,
#define getkey(T) type(T), optional :: key_; type(T) key; if (present(key_)) key = key_
module mymod
implicit none
type mysub_k
integer :: val = -1
real :: eps = 1.0e-3
endtype
contains
subroutine mysub(x, seed_, key_)
integer :: x
integer, optional :: seed_
integer :: seed
getkey(mysub_k) !! for all the remaining keyword arguments
optval(seed, seed_, 100)
print *, x, seed, key% val, key% eps
endsubroutine
endmodule
program main
use mymod, key => mysub_k
call mysub(10)
call mysub(20, key_= key(val = 3))
call mysub(30, seed_=200, key_= key(eps = 1.0e-8)) ! ugly...
endprogram
Это может быть немного близко к тому, что делается на некоторых динамических языков под капотом, но это опять же далеко от элегантности в вышеприведенной форме ...
(*) Я знаю, что часто считаются уродливыми для использования макросов CPP, но IMO зависит от того, как они используются; если они ограничены ограниченным расширением синтаксиса Fortran, я считаю, что разумно использовать (поскольку в Fortran нет объекта метапрограммирования); с другой стороны, вероятно, следует избегать определения зависимых от программы констант или ветвей. Кроме того, я предполагаю, что это будет более мощным, чтобы использовать Python и т.д., чтобы сделать более гибкий препроцессор (например, PreForM.py и fypp и так далее), например, чтобы синтаксис как subroutine sub(val = -1)
Первое решение - это то, что я опубликовал в исходном вопросе - изменение соглашения об именах на самом деле не делает его новым шаблоном. Второе решение - печально недопустимый код, если имеется более одного необязательного аргумента, поскольку fortran не позволяет смешивать объявление и код выполнения - в то время как для одного необязательного аргумента использование макроса, вероятно, недостаточно для того, чтобы оправдать безвестность , – kdb
Привет, потому что нынешние стандарты Fortran не позволяют никакого реального «решения» (как было предложено Владимиром ниже), нет другого способа, кроме как использовать локальную переменную с похожим именем, и я думал, что вы ищете какой-то систематический (менее подверженные ошибкам) обходные пути. RE вторая точка, приведенный выше код действителен (вы можете попробовать), и вы также можете добавить другие обычные необязательные переменные перед ключом. Дело в том, что setkey() должен появиться после всех других объявлений, но это естественно, потому что этот тип аргументов ключевого слова приходит после всех необязательных аргументов. – roygvib
Кроме того, моя цель - просто представить мою практику, никогда не защищать ее использование. Что еще более важно, мое намерение состоит в том, чтобы показать, как текущий синтаксис Fortran ограничен в некоторых частях и принуждает пользователя писать довольно подробный/длинный код. – roygvib