Хороший способ думать об этом: «Я изменил что-нибудь, что любой более поздний код (включая повторное выполнение этой же функции позже) мог когда-либо видеть, кроме возвращаемого мной значения?»Если это так, это побочный эффект.Если нет, то вы можете знать, что его нет.
Итак, что-то вроде:
let inc_nosf v = v+1
не имеет побочных эффектов, потому что просто возвращает новое значение, которое на единицу больше, чемцелое число v. Таким образом, если вы выполните следующий код на верхнем уровне ocaml, вы получите соответствующие результаты:
# let x = 5;;
val x : int = 5
# inc_nosf x;;
- : int = 6
# x;;
- : int = 5
Как видите, значение x не изменилось.Итак, так как мы не сохранили возвращаемое значение, то ничего действительно не было увеличено.Наша функция сама изменяет только возвращаемое значение, а не сам x.Таким образом, чтобы сохранить его в x, нам нужно сделать:
# let x = inc_nosf x;;
val x : int = 6
# x;;
- : int = 6
Поскольку функция inc_nosf не имеет побочных эффектов (то есть она взаимодействует только с внешним миром, используя свое возвращаемое значение, а не путемлюбые другие изменения).
Но что-то вроде:
let inc_sf r = r := !r+1
имеет побочные эффекты, поскольку изменяет значение, сохраненное в ссылке, представленной как r.Поэтому, если вы запустите аналогичный код на верхнем уровне, вы получите следующее:
# let y = ref 5;;
val y : int ref = {contents = 5}
# inc_sf y;;
- : unit = ()
# y;;
- : int ref = {contents = 6}
Итак, в этом случае, даже если мы все еще не сохраняем возвращаемое значение, оно все равно увеличивается.Это означает, что должны были быть изменения в чем-то, кроме возвращаемого значения.В этом случае этим изменением было назначение с использованием :=
, которое изменило сохраненное значение ссылки.
Как хорошее правило, в Ocaml, если вы избегаете использования ссылок, записей, классов, строк,массивов и хеш-таблиц, тогда вы избежите любого риска побочных эффектов.Хотя вы можете безопасно использовать строковые литералы до тех пор, пока вы не будете изменять строку на месте, используя такие функции, как String.set или String.fill.По сути, любая функция, которая может изменить тип данных на месте, вызовет побочный эффект.