#fortran #fortran90
#fortran #fortran90
Вопрос:
Я борюсь с кратким названием, но это не так сложно. У меня есть функция, которая возвращает структуру (производный тип), и я ищу простой способ ссылаться только на часть структуры при вызове функции (без копирования / указания на другую структуру).
program main
real :: xx = 1.
real :: yy = 2.
! works fine but what I want is to be
! able to return %tx and %ts separately
print *, " tax ", tax(xx,yy)
! just guessing at possible syntax here, but neither works
print *, " tax ", tax%tx(xx,yy)
print *, " tax ", tax(xx,yy)%tx
contains
function tax(x,y)
real :: x, y
type tTax
real :: tx, ty
end type tTax
type(tTax) :: tax
tax%tx = x * 100.
tax%ty = y * 100.
end function tax
end program main
Я ограничен набором функций f90 / f95, но не стесняйтесь также включать ответы f2003.
И я действительно ищу здесь что-то простое, если оно существует. В противном случае, это просто будет лучше делать как подпрограмму (если альтернативой является сохранение ее как функции, но добавление указателей, интерфейсов и т. Д.).
Я также попытался заставить функцию возвращать 2-мерный массив вместо структуры и столкнулся с той же основной проблемой — это работает, но я могу печатать только весь массив, а не какие-либо разделы массива сами по себе.
Мне было трудно даже угадать синтаксис, поскольку ()
он используется как для функций, так и для разделов массива в fortran (в отличие от таких языков, как python, которые используются []
для индексации, поэтому вполне естественно смешивать функции и индексы, например, что-то вроде tax(xx,yy)[1,:]
).
Ответ №1:
Вы можете создать пользовательский конструктор, перегрузив имя производного типа данных возвращаемой функцией.
Широкое использование конструкции стандарта Fortran 2003 associate
позволяет получить доступ к компонентам определенного типа без копирования или обращения к указателям, подверженным утечке памяти.
Есть ли какая-то особая причина, по которой вы ограничиваете себя Fortran 2003; большая часть Fortran 2008 поддерживается большинством популярных компиляторов.
Следующий код
module mymod
! Explicit typing only
implicit none
! Declare derived data type
type tTax
real :: tx, ty
end type tTax
! User-defined constructor
interface tTax
module procedure tax
end interface tTax
contains
function tax(x, y) result (return_value)
real, intent (in) :: x, y
type (tTax) :: return_value
return_value%tx = x * 100.0
return_value%ty = y * 100.0
end function tax
end module mymod
program main
use mymod
! Explicit typing only
implicit none
real :: xx = 1.0, yy = 2.0
type(tTax) :: foo
print *, " tax ", tax(xx,yy)
print *, " tax ", tTax(xx, yy)
! Invoke the user-defined constructor
foo = tTax(xx, yy)
! Fortran 2003's associate construct
associate( amp;
tx => foo%tx, amp;
ty => foo%ty amp;
)
print *, " tax ", tx, ty
end associate
end program main
выдает
gfortran -Wall -o main.exe mymod.f90 main.f90
./main.exe
tax 100.000000 200.000000
tax 100.000000 200.000000
tax 100.000000 200.000000
Комментарии:
1. Спасибо, 1. Как я догадался в вопросе, fortran выполняет эту дополнительную работу, так что с практической точки зрения я могу просто использовать подпрограмму, поскольку она немного проще — и на данный момент у меня нет достаточно нового компилятора, чтобы протестировать его в любом случае. 😉 Но это круто, спасибо!
2. Я знаю, что без f2003 я не могу использовать
associate()
в main, но должен ли модуль сам компилироваться для меня? Мой компилятор f90 жалуется на тип и интерфейс, оба из которых используют имя tTax, но скомпилирует любой из них отдельно (конечно, main в этих случаях не работает). Если бы я мог просто использовать foo%tx в main, а не tx, это было бы достаточным решением с моей точки зрения.3. @VladimirF или jlok: есть ли какой-нибудь простой ответ на мой комментарий прямо здесь? Или это стоит задать как отдельный вопрос?
4. @JohnE, Вероятно, отдельный вопрос. Это недостаточно ясно из вашего описания. Возможно, старый компилятор, возможно, неправильный код.
Ответ №2:
Проблема не в символах круглых скобок, а в том, разрешено ли вам ссылаться на компонент или элемент выражения или нет.
И в Fortran вам это не разрешено. Вы можете использовать только синтаксис % или индексацию массива () для имен переменных или констант или для ассоциированных имен.
Комментарии:
1. Верно, это было мое рабочее предположение, но я всегда надеюсь на какой-то синтаксический сахар в стиле python, хотя это, похоже, противоречит духу fortran. 😉
2. @JohnE Вот ссылка на Python Fortran Rosetta Stone fortran90.org/src/rosetta.html
3. @jlokimlin да, это хорошо, хотя и интересно, что для моей проблемы он обрабатывает подпрограммы fortran как эквивалент python / numpy! Моя проблема здесь, очевидно, в том, что я пытаюсь заставить функцию fortran работать как функцию python, и, возможно, я просто изо всех сил пытаюсь сделать fortran более похожим на python.