Я знаю, что (по крайней мере, в какой-то момент) следующее недопустимо на Фортране из-за псевдонимов
program main
integer :: x, y
! compilers assume a and b to be distinct
y = f(x, x)
contains
integer function f(a, b) result(c)
integer, intent(in out) :: a, b
a = 1
b = 2
c = a ! compiler can optimize to c = 1
end function
end program main
Но справедливо ли следующее?
program main
integer :: x(3)
x = [1, 2, 3]
x = square_me(x)
contains
function square_me(a) result(squared)
integer, intent(in out) :: a(3)
integer :: squared(3)
squared = a ** 2
a(1) = 0 ! nasty side-effect
end function
end program main
Он работает в gfortran, но я не уверен, соответствует ли он стандартам.
Я знаю, что побочные эффекты в функциях — не очень хорошая идея. Я имею дело с более чем 100 тысячами строк устаревшего кода, который любит использовать функции, возвращающие целочисленный код в стиле C, и изменять аргументы, поэтому этот вопрос касается именно стандарта.
Какими бы ни были опасения, я бы настоятельно не советовал использовать функции с побочными эффектами, это просто напрашивается на проблемы. В таких случаях используйте подпрограммы. Сохраняйте свои функции в чистоте.
@IanBush Комментарий «неприятный побочный эффект» должен был передать эту идею :)
@francescalus Я был обеспокоен тем, что компилятор попытается поделиться ссылками на возвращаемую x
и результирующую переменную squared
. Другими словами, я знаю, что сначала оценивается правая часть, но когда речь идет о массивах, я менее уверен в том, что говорит стандарт (в частности, я наблюдал много статического распределения в этой программе).
Неважно, было ли это предназначено для передачи идеи. Совету @IanBush следует прислушаться. Что касается вашего первого примера, это неверный Фортран. Компилятор может делать все, что захочет, включая установку c = 1
. Ваш второй пример не предполагает псевдонимов.
@Стив -1. Есть много веских причин задавать вопросы, когда вы знаете, что что-то плохо, но все равно нуждаетесь в ответе. «Просто не делайте этого» бесполезно для тех, кто пытается интерпретировать, редактировать и улучшать код, созданный десятилетиями.
Конечно. Также важно правильно сформулировать вопрос. Второй пример кода не имеет никакого отношения к псевдонимам.
@ Адам, я понимаю, почему ты спрашиваешь, и даже если язык не идеален, мне кажется, это разумный вопрос, ведь одна из причин спрашивать - это научиться. Но цель моего предыдущего комментария состоит в том, чтобы донести до кого-то, кто смотрит на это новичком, что, хотя, при осторожном подходе, подобные вещи могут быть разрешены, это очень плохая идея.
Если бы я все еще не участвовал в забастовке избирателей, я бы обязательно проголосовал за этот и подобные вопросы. Цель вопроса ясна, и любое заблуждение, вызванное (неправильным) использованием терминологии, полностью соответствует теме вопросов и ответов на этом сайте.
@francescalus, намерение ясно? Вопрос в заголовке касается псевдонимов. Название вводит в заблуждение. Фактически речь идет о функциях с побочными эффектами.
@steve, мы с тобой знаем ответ, и мы с тобой не задали бы вопрос. Ответом на точный вопрос, заданный в заголовке, вполне может быть «нет», но, возможно, это будет ужасный ответ. Побочные эффекты и псевдонимы настолько тесно связаны, что, если мы отклоняем какой-либо вопрос, который сбивает их с толку, мы упускаем почти любую возможность уточнить его. Точно задать вопрос об этом случае — значит усомниться в этом.
@francescalus, я не предлагаю отклонять вопрос. Я предлагаю исправить название, чтобы оно отражало реальность. Если кто-то ищет ответы о побочных эффектах, я сомневаюсь, что он будет использовать «псевдоним» в качестве поискового запроса.
@steve, лучше?
@steve Теперь я понимаю, что название довольно глупо с учетом информации, которую я здесь узнал, но чтобы дать ему немного перспективы: Фортран (относительно) уникален тем, что аргументы передаются по ссылке, и поскольку Фортран «возвращает» результаты по присваивая результирующей переменной (имя функции или что-то еще), я думал, что возможно, что результаты также «возвращаются по ссылке» - я недостаточно хорош в стандартах, чтобы выяснить это самостоятельно, поэтому я подумал, что второй пример может быть недействительным для псевдонимов.
@francescalus, намного лучше. Хотя отмечу, что правая часть полностью оценивается перед назначением левой, поэтому побочный эффект не может вызвать проблемы в коде y = f(x,x)
. Фортран 2023, 10.1.4, вероятно, более важен для выражения в правой части, т. е. y = f(x,x) + x
. В данном случае побочный эффект может испортить последнее дополнение (см. примечание 1). Обратите внимание: Фортран позволяет переупорядочить оценку, например y = x + f(x,x)
, где x
инициализирует аккумулятор, а затем f(,x,x)
вычисляется и добавляется в аккумулятор.
Ни одна из основных программ недействительна.
Под так называемыми правилами псевдонимов в Фортране обычно подразумеваются те ограничения, которые применяются к объектам во время выполнения процедуры. Однако в операторе присваивания оценка правой части полностью выполняется до того, как будет затронута левая часть.
Вместо этого вторую основную программу ломает ограничение на побочные эффекты функций.
Побочный эффект ограничен (F2018, 10.1.4) тем, что, за исключением некоторых случаев, здесь не применимых:
если ссылка на функцию вызывает определение или отмену определения фактического аргумента функции, этот аргумент или любые связанные с ним объекты не должны появляться где-либо еще в том же операторе.
Присваивание a(1)
вызывает определение фактического аргумента x
, поэтому x
может не появляться где-либо еще в операторе присваивания (включая левую часть).
Существует несколько других (возможно, неожиданных) ограничений на побочные эффекты в функциях. Скажем так: избегайте побочных эффектов в функциях, если можете, если только вы действительно не знаете правила и не можете быть уверены, что все, кто использует вашу функцию, также действительно знают правила.
Получается, что функции могут (но, конечно, не должны) выполнять побочные эффекты со своими аргументами, пока эти аргументы не встречаются в операторе несколько раз? (либо цель назначения, либо что-то вроде z = foo(x) + foo(x)
) АКА без назначения a
, это действительно?
Есть эффекты, которые продолжаются за пределами утверждения, в котором возникает побочный эффект. Они слишком тонкие для комментариев и выходят за рамки этого вопроса, но подпадают под правило «даже если вы знаете правила, не предполагайте, что другие люди знают». Действительно, побочные эффекты в функциях неприятны.
Я бы, может быть, даже зашел так далеко, что сказал, что вопрос SO, спрашивающий: «Каковы ограничения на побочные эффекты в функциях Фортрана?» будет закрыт как слишком широкий.
Какой аспект вас беспокоит? (Я могу догадаться, но в откровенности нет никакого вреда.)