синтаксис sml с трудом просматривает документацию - PullRequest
1 голос
/ 25 октября 2011

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

1 val x = ref 0;
2 fun p(y': int ref)=
3 let
4   val y = !y'
5     in
6         let
7             y = 1
8             in
9                 let x := 0 
10                 in
11                 y' := y
12                 end
13         end  
14 end     
15 p(x)

Ответы [ 2 ]

3 голосов
/ 25 октября 2011

В let <decs> in <exp>, <decs> должно быть одно или несколько объявлений.

В вашем случае в строке 7 вы делаете y = 1 - обратите внимание, это не задание, а сравнение,То есть в C ++ это было бы эквивалентно выполнению y == 1.Вы не можете назначить переменные без ссылки.(И вообще, вы хотите максимально избегать ref-переменных.) Вы можете сделать val y = 1 вместо него, и в этом случае вы создадите новое значение с именем y, которое затеняет старую * 1009.* (но не изменяет его; вы создаете новое значение).

Аналогично, в строке 9 вы делаете x := 0, который является не объявлением, а выражением, которое присваивает значение 0к справочному значению x, а затем возвращает единицу измерения.

Кроме того, вы можете делать несколько объявлений в своих операторах let, поэтому вам не нужно делать вложенность.

НаконецВы пишете p(x) на верхнем уровне.Вы можете писать выражения только на верхнем уровне, если предшествующее объявление заканчивается точкой с запятой;в противном случае он считает, что это является частью декларации.То есть

val a = 5
6

интерпретируется как

val a = 5 6

Короче, вы можете переписать его так:

val x = ref 0;

fun p(y': int ref)=
let
  val y = !y' (* this line might as well be deleted. *)
  val y = 1
in
  x := 0;
  y' := y
end;

p(x)

Или, более короткая версия, так какSML имеет хороший вывод типа:

val x = ref 0;

fun p y' = (x := 0; y' := 1);

p x

Я скажу это, хотя;если вы пришли из языка, подобного C ++ или подобному, может быть соблазнительно использовать 'a ref sa, но вы часто обнаружите, что сведение к минимуму их использования часто приводит к более чистому коду в SML.(И другие функциональные языки.)

2 голосов
/ 25 октября 2011

let y = 1 ... неверно.Так же как и let x := 0.Внутри let ... in вам нужны объявления val или fun.

Кажется, у вас есть некоторые недоразумения в SML.let используется для объявления новых локальных переменных в области видимости.Странно для вас пытаться объявить переменную с именем y во внутренней области видимости, которая затеняет y, который вы объявили в let в непосредственной внешней области видимости.Вы имели в виду одно из двух:

  1. Изменить значение переменной "y", определенной во внешней области видимости.Это невозможно.Вы не можете изменить значение переменной в ML
  2. . Вы хотите объявить новую, не связанную переменную, которая также называется «y», и скрыть предыдущую «y» в этой области;в этом случае вы бы использовали let var y = 1 in ...

Кроме того, странно, что у вас есть let x := 0.x := 0 само по себе является допустимым выражением.Это изменяет значение, содержащееся в ссылке, на которую указывает x.Вам не нужно let.Поскольку x := 0 оценивается только на наличие побочных эффектов и возвращает тип unit (т.е. ничего полезного), вы можете ознакомиться с оператором ;, с помощью которого вы можете связать воедино кучу операторов "побочных эффектов""который оценивает результат последнего: x := 0; y' := y

...