Нет переноса скалярных аргументов в массивы в Фортране

Почему Фортран преобразует скалярное выражение в массив в выражении, но не в качестве аргумента процедуры? В частности, почему орган по стандартизации принял такое дизайнерское решение? Только ли из-за двусмысленности процедура должна быть перегружена? Может ли сообщение об ошибке в этой ситуации быть альтернативным подходом?

Например, в приведенном ниже коде последний оператор x = foo(7) выдает ошибку GFortran: Error: Rank mismatch in argument 'a' at (1) (1 and 0).

module m

  public :: foo

  contains

  function foo(a) result(b)
    integer, dimension(:)       :: a
    integer, dimension(size(a)) :: b
    b = a+1
  end function foo

end module m

program p

  use m

  integer, dimension(4) :: x
  integer, parameter, dimension(4) :: y = (/1,2,3,4/)

  x = 7
  x = foo(x)
  x = foo(y)
  x = foo(x + 7)
  x = foo(7)

end program p

Этот вопрос должен был спрашивать о том, почему присваивание массива продвигает источник скалярного значения к целевому массиву; в отличие от функции массива. Я ожидаю, что это просто удобный частный случай. Любые комментарии с благодарностью принимаются в шапках попрошайничества ниже.


person user2023370    schedule 18.10.2011    source источник


Ответы (3)


Если вы хотите, чтобы функция обрабатывала аргументы масштабатора и массива, объявите ее как «элементарную» и с фиктивными аргументами масштабатора. Тогда он сможет обрабатывать фактические аргументы как скейлера, так и массива, включая выражения скейлера. Удовлетворит ли это ваши потребности?

Изменение:

  elemental function foo(a) result(b)
    integer, intent (in)      :: a
    integer :: b
    b = a+1
  end function foo

Возможно, они предоставили способ делать то, что вы хотите, и одного способа было достаточно?

person M. S. B.    schedule 18.10.2011
comment
Это, вероятно, не так широко, как хочет OP, поскольку elemental накладывает много ограничений на то, что может делать функция. - person bdforbes; 18.10.2011
comment
Да, конечно. Большинство встроенных функций элементарны, не так ли? А элементарной функции нужна арность > 1, чтобы преобразовать скаляр в массив. Мой вопрос был бы лучше сосредоточен на операторе присваивания, который будет продвигать скаляр. Но в этом больше смысла: оператор присваивания особенный. В последнее время я смотрю на слишком много APL... - person user2023370; 18.10.2011

Вызов процедур на Фортране с явными интерфейсами (которые вы получаете автоматически при использовании модульных процедур) требует совпадения TKR (тип, вид, ранг). Поскольку массив отличается от скалярного типа, не говоря уже о несоответствии рангов, это недопустимо.

Должна ли процедура быть перегружена из-за неоднозначности?

Это будет проблемой, да.

Может ли сообщение об ошибке в этой ситуации быть альтернативным подходом?

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

person janneb    schedule 18.10.2011
comment
Спасибо, Яннеб. Я ценю ваш ответ, но я действительно ищу почему. - person user2023370; 18.10.2011

Думаю, ответ на этот вопрос достаточно ясен. Давайте немного изменим ваш пример:

module m

  public :: foo

  contains

  function foo(a) result(b)
    integer, dimension(:)       :: a
    integer, dimension(size(a)) :: b
    b = a+1
    a(2) = -777     ! new line; modify one element
  end function foo

end module m

program p

  use m

  integer :: x
  integer, dimension(4) :: y 

  x = 7
  y = foo(x)  ! pass a scalar

end program p

что должно быть x после вызова foo?

Теперь, конечно, вы могли бы изменить семантику передачи аргументов в зависимости от того, является ли это переменной intent(in), но это не то, что проясняет вещи для программистов. .

Если предполагается, что вызов функции каким-то образом «распределяет» по элементам массива, то, как указывает MSB, elemental — это путь. В противном случае нужно просто убедиться, что аргументы соответствуют параметрам.

person Jonathan Dursi    schedule 18.10.2011
comment
Спасибо. Я думал, аргумент будет intent(in). Вот почему я включил аргумент parameter, y. Как вы говорите, elemental это путь. - person user2023370; 19.10.2011