Как вы ИСПОЛЬЗУЕТЕ данные модуля Fortran 90

Допустим, у вас есть модуль Fortran 90, содержащий множество переменных, функций и подпрограмм. Какому соглашению вы следуете в своем заявлении USE:

  1. явно объявляйте, какие переменные / функции / подпрограммы вы используете с синтаксисом , only :, например USE [module_name], only : variable1, variable2, ...?
  2. Вставить одеяло USE [module_name]?

С одной стороны, предложение only делает код более подробным. Однако это заставляет вас повторяться в коде, и если ваш модуль содержит множество переменных / функций / подпрограмм, все начинает выглядеть неуправляемым.

Вот пример:

module constants
  implicit none
  real, parameter :: PI=3.14
  real, parameter :: E=2.71828183
  integer, parameter :: answer=42
  real, parameter :: earthRadiusMeters=6.38e6
end module constants

program test
! Option #1:  blanket "use constants"
!  use constants
! Option #2:  Specify EACH variable you wish to use.
  use constants, only : PI,E,answer,earthRadiusMeters
  implicit none

  write(6,*) "Hello world.  Here are some constants:"
  write(6,*) PI, &
       E, &
       answer, &
       earthRadiusInMeters
end program test

Обновление. Надеюсь, кто-то скажет что-то вроде «Фортран? Просто перекодируйте его на C #!», чтобы я мог проголосовать против вас.


Обновить

Мне нравится ответ Тима Уиткомба, который сравнивает USE modulename Фортрана с from modulename import * Python. Тема, которая раньше была на Stack Overflow:

  • «импортировать модуль» или «из импорта модуля»

    • In an answer, Mark Roddy mentioned:

      не используйте 'from module import *'. Для любого разумно большого набора кода, если вы «импортируете *», вы, скорее всего, закрепите его в модуле, и его невозможно будет удалить. Это связано с тем, что трудно определить, какие элементы, используемые в коде, поступают из «модуля», что делает его восточным, чтобы добраться до точки, где, по вашему мнению, вы больше не используете импорт, но в этом чрезвычайно сложно быть уверенным.

  • Каковы практические правила импорта Python?

    • dbr's answer contains

      не делайте из x import * - это затрудняет понимание вашего кода, поскольку вы не можете легко увидеть, откуда появился метод (из x import *; из y import *; my_func () - где определяется my_func?)

Итак, я склоняюсь к консенсусу явного указания всех элементов, которые я использую в модуле, через

USE modulename, only : var1, var2, ...

И как упоминает Стефано Борини,

[если] у вас настолько большой модуль, что вы чувствуете себя обязанным добавить ТОЛЬКО, это означает, что ваш модуль слишком велик. Раздели это.


person Pete    schedule 06.08.2009    source источник
comment
Одна из проблем с Fortran заключается в том, что при импорте из модулей вы всегда будете помещать все в глобальное пространство имен, как в Javascript. В python вы можете сделать это из foo.bar import *, но также и из foo import bar. В фортране у вас нет выбора. Каждый раз, когда вы используете USE, вы выполняете импорт * и включаете все в глобальное пространство имен. Это одна из самых серьезных проблем с Fortran 9X.   -  person Stefano Borini    schedule 07.08.2009
comment
@StefanoBorini: означает ли это последнее предложение, что проблема решена в более поздних версиях fortran?   -  person naught101    schedule 24.06.2014


Ответы (7)


Это вопрос баланса.

Если вы используете только несколько вещей из модуля, имеет смысл добавить ТОЛЬКО, чтобы четко указать, что вы используете.

Если вы используете много элементов из модуля, за указанием ONLY будет следовать много элементов, поэтому это не имеет смысла. Вы в основном выбираете то, что используете, но на самом деле вы зависите от этого модуля в целом.

Однако, в конце концов, лучшая философия такова: если вас беспокоит загрязнение пространства имен и у вас настолько большой модуль, что вы чувствуете себя обязанным добавить ТОЛЬКО, это означает, что ваш модуль слишком велик. Раздели это.

Обновление: Фортран? просто перекодируйте его на python;)

person Stefano Borini    schedule 06.08.2009
comment
Это полезный эвристический метод определения размера моего модуля ?. - person Tim Whitcomb; 07.08.2009

Раньше я просто делал use modulename - затем, по мере роста моего приложения, мне становилось все труднее и труднее находить источник функций (не обращаясь к grep) - в другом коде, плавающем в офисе, по-прежнему используется одна подпрограмма. для каждого файла, который имеет свой собственный набор проблем, но значительно упрощает использование текстового редактора для перемещения по коду и быстрого отслеживания того, что вам нужно.

После того, как я испытал это, я стал использовать _2 _..._ 3_, когда это возможно. Я также начал подбирать Python и рассматривать его так же, как from modulename import *. Модули дают вам много замечательных вещей, но я предпочитаю строго контролировать свое глобальное пространство имен.

person Tim Whitcomb    schedule 06.08.2009
comment
Мне нравится ваша аналогия с импортом модулей Python - хорошие мысли! - person Pete; 06.08.2009
comment
Точно. Я использую только явное использование импорта ... только как в Python, которое я использую только из ... импорта. Я считаю, что это правильный подход. - person Ondřej Čertík; 25.02.2012

Не совсем отвечаю на вопрос здесь, просто добавляю другое решение, которое я нашел полезным в некоторых обстоятельствах, если по какой-либо причине вы не хотите разделить свой модуль и начать получать конфликты пространств имен. Вы можете использовать производные типы для хранения нескольких пространств имен в одном модуле.

Если существует некоторая логическая группировка переменных, вы можете создать свой собственный производный тип для каждой группы, сохранить экземпляр этого типа в модуле, а затем вы можете импортировать только ту группу, которая вам может понадобиться.

Небольшой пример: у нас есть много данных, некоторые из которых вводятся пользователем, а некоторые являются результатом различных инициализаций.

module basicdata
   implicit none
   ! First the data types...
   type input_data
      integer :: a, b
   end type input_data
   type init_data
      integer :: b, c
   end type init_data

   ! ... then declare the data
   type(input_data) :: input
   type(init_data) :: init
end module basicdata

Теперь, если подпрограмма использует данные только из init, вы импортируете только это:

subroutine doesstuff
   use basicdata, only : init
   ...
   q = init%b
end subroutine doesstuff

Это определенно не универсальное решение, вы получаете дополнительную многословность из синтаксиса производного типа, и тогда это, конечно, вряд ли поможет, если ваш модуль не является сортом basicdata, указанным выше, а скорее allthestuffivebeenmeaningtosortoutразновидностью. В любом случае, мне посчастливилось получить код, который таким образом легче вписывается в мозг.

person TorbjornB    schedule 11.03.2011

Главное преимущество ИСПОЛЬЗОВАНИЯ ТОЛЬКО для меня состоит в том, что он позволяет избежать загрязнения моего глобального пространства имен ненужными мне вещами.

person ire_and_curses    schedule 06.08.2009

Согласившись с большинством ранее приведенных ответов, use ..., only: ... - это правильный путь, используйте типы, когда это имеет смысл, примените Python думает, насколько это возможно. Другое предложение - использовать соответствующие соглашения об именах в импортированном модуле вместе с операторами private / public.

Например, библиотека netcdf использует nf90_<some name>, что ограничивает загрязнение пространства имен на стороне импортера.

use netcdf  ! imported names are prefixed with "nf90_"

nf90_open(...)
nf90_create(...)
nf90_get_var(...)
nf90_close(...)

аналогично, оболочка ncio для этой библиотеки использует nc_<some name> (nc_read, _9 _...).

Важно отметить, что с такими проектами, где use: ..., only: ... становится менее актуальным, вам лучше контролировать пространство имен импортируемого модуля, устанавливая соответствующие атрибуты private / public в заголовке, чтобы читателям было достаточно беглого взгляда на него, чтобы оценить, какой уровень «загрязнения», с которым они сталкиваются. Это в основном то же, что и use ..., only: ..., но на стороне импортированного модуля - таким образом, он должен быть записан только один раз, а не при каждом импорте).

Еще одна вещь: что касается объектной ориентации и python, разница, на мой взгляд, заключается в том, что fortran на самом деле не поощряет процедуры с привязкой к типу, отчасти потому, что это относительно новый стандарт (например, несовместимый с рядом инструментов , и менее рационально, это просто необычно) и потому, что это нарушает удобное поведение, такое как копирование производного типа без процедур (type(mytype) :: t1, t2 и t2 = t1). Это означает, что вам часто приходится импортировать тип и все предполагаемые процедуры с привязкой к типу, а не только класс. Уже одно это делает код fortran более подробным по сравнению с python, и могут пригодиться практические решения, такие как соглашение об именах префиксов.

ИМО, суть в следующем: выберите свой стиль кодирования для людей, которые будут его читать (включая ваше более позднее себя), как учил python. Лучше всего более подробный use ..., only: ... при каждом импорте, но в некоторых случаях простое соглашение об именах сделает это (если вы достаточно дисциплинированы ...).

person Mahé    schedule 12.12.2015

Да, используйте use module, only: .... Для больших баз кода с несколькими программистами это упрощает выполнение кода всеми (или просто использует grep).

Пожалуйста, не используйте include, вместо этого используйте модуль меньшего размера. Включить - это текстовая вставка исходного кода, которая не проверяется компилятором на том же уровне, что и модуль использования, см .: ФОРТРАН: разница между INCLUDE и модулями. Include обычно затрудняет использование кода людьми и компьютером, что означает, что его не следует использовать. Бывший. из mpi-forum: «Использование включаемого файла mpif.h категорически не рекомендуется и может быть исключено в будущей версии MPI». (http://mpi-forum.org/docs/mpi-3.1/mpi31-report/node411.htm).

person Knut Gjerden    schedule 09.05.2016
comment
Не добавляйте предложения, подобные первому, во втором абзаце. Либо ваш ответ подходит в качестве отдельного ответа, либо нет, и тогда не публикуйте его. Сначала получите репутацию, чтобы публиковать комментарии, это легко. С такими предложениями вы только приглашаете людей голосовать за то, чтобы ваш вопрос был удален. Для таких ответов / комментариев существует особая причина удаления. - person Vladimir F; 09.05.2016
comment
@VladimirF, и это хорошая идея и веская причина для удаления. Я наткнулся на это случайно и, предполагая, что забуду, я решил опубликовать, потому что я считаю, что использование include - это настолько плохая практика, что его следует не рекомендовать, по крайней мере, активно обескураживать. Как правило, это усложняет задачу как для людей, так и для компьютера, поэтому использовать ее не следует. Пример из mpi-forum: Использование включаемого файла mpif.h категорически не рекомендуется и может быть исключено в будущей версии MPI. (mpi-forum.org/docs/mpi-3.1 /mpi31-report/node411.htm). Итак, я дал обоснованный ответ и добавил замечание. Отредактированный пост. - person Knut Gjerden; 10.05.2016
comment
Я согласен. Вы можете вставить эту цитату в ответ. К сожалению, руководство OpenMPI по-прежнему показывает только include mpif.h перед каждым вводом вручную подпрограммы, по крайней мере, в версии 1.8. - person Vladimir F; 10.05.2016

Я знаю, что немного опаздываю на вечеринку, но если вам нужен только набор констант, а не обязательно вычисляемые значения, вы можете сделать как C и создать включаемый файл:

внутри файла, например, constants.for

real, parameter :: pi = 3.14
real, parameter :: g = 6.67384e-11
...


program main
    use module1, only : func1, subroutine1, func2 
    implicit none

    include 'constants.for'
    ...
end program main

Отредактировано, чтобы удалить "real (4)", поскольку некоторые считают это плохой практикой.

person Forrest    schedule 20.11.2014
comment
Пожалуйста, не учите людей плохой привычке использовать real(4), когда исходный вопрос этого не требует. Кроме того, я не могу согласиться с тем, что подход include лучше или даже проще. - person Vladimir F; 21.11.2014
comment
real (4) - это копирование / вставка и сила привычки с моей стороны. Я подумал о вашем другом комментарии, но все равно оставил его. Есть множество способов сделать то же самое. Важно, чтобы люди экспериментировали и находили то, что им нравится. На мой взгляд, включить файл было бы сложнее, если бы он / она не использовал Makefile и не добавлял -I. - person Forrest; 21.11.2014