См. Мой ответ в списке камер
Зачем задавать один и тот же вопрос дважды в разных местах?Это только приводит к дублированию усилий, а знающие люди тратят свое время, чтобы ответить вам.Если вы хотите сделать это, пожалуйста, по крайней мере, опубликуйте перекрестные ссылки (от вашего сообщения stackoverflow в архив списка и наоборот [1]), чтобы люди могли проверить, что он еще не ответил в другом месте.
[1] да, вы можете иметь циклические перекрестные ссылки, так как сообщение stackoverflow изменчиво!
Семантика изменяемых полей и ссылок сильно изменилась (навсегда)между Caml Light и объективом Caml.Помните, что этот код является специфичным для Caml Light - и если вы хотите изучать Caml, вам лучше использовать Objective Caml, реализация которого все еще поддерживается.В Objective Caml изменяются только поля записей.Ссылки являются производным понятием, тип 'a ref определяется следующим образом:
type 'a ref = { mutable contents : 'a }
Вы изменяете изменяемое поле с помощью синтаксиса foo.bar <- baz (где "bar" - это поле записи, а fooи baz - любое выражение, foo типа записи) </p>
В Caml Light поля записи являются изменяемыми, но поля типа суммы (варианты) также изменяемы;изменяемые варианты полей, однако, здесь не используются.См. http://caml.inria.fr/pub/docs/manual-caml-light/node4.6.html для документации.
В Caml Light запись может возвращать изменяемое местоположение, похожее на lvalue в C-подобных языках.Например, с изменяемым вариантом
type foo = Foo of mutable int
вы можете написать:
let set_foo (f : foo) (n : int) =
match f with
| Foo loc ->
loc <- n
"foo <- bar" используется здесь, чтобы присвоить значение "bar" lvalue "foo"связан в изменчивом образце.В вашем примере используются два изменяемых шаблона: </p>
| { tail = Cons(_, ref newtail) as oldtail } ->
- oldtail - изменяемый шаблон, обозначающий изменяемое поле "tail" записи
(ref newtail)это определенный синтаксис, образец ссылок.Он связывает изменяемый шаблон «newtail», соответствующий местоположению ссылки. Другими словами, в Caml Light вы можете написать оператор «: =» следующим образом:
let prefix: = rv = match r с |ref loc -> loc <- v </p>
Надеюсь, это поможет.
.
Редактировать:
О странном сообщении об ошибке: я думаю, что внутренне Caml Light поддерживает список «идентификаторов значений» в области видимости, которые происходят из шаблона, соответствующего изменяемому полю (запись или вариант).Когда они видят выражение foo <- bar
, они ищут в этой среде соответствующее местоположение.Такая среда является локальной для выражения, она никогда не ускользает.В частности, на верхнем уровне он пуст, и ошибки говорят о том, что в области действия не существует «идентификатора значения» (изменяемого шаблона).
Существует еще одна вещь: пространство имен идентификаторов значений и обычные идентификаторы не различаются,Когда вы сопоставляете идентификатор значения, Caml Light добавляет в область действия идентификатор значения (изменяемый), а также соответствующий идентификатор с соответствующим значением r.Это может сбивать с толку, поскольку вы можете изменить местоположение, но значение не изменится:
#match ref 1 with (ref x) -> (x <- 2; x);;
- : int = 1
#match ref 1 with (ref x) as a -> (x <- 2; !a);;
- : int = 2
Идентификатор (значение) будет затенять любой более старый идентификатор (идентификатор значения или нет)
#let x = 1 in let (ref x) = ref 2 in x;;
- : int = 2
(Если вы не знали, let pattern = e1 in e2
эквивалентно match e1 with pattern -> e2
(за исключением системы типов))
Поскольку синтаксические классы для идентификаторов и идентификаторов значений одинаковы,Переменный идентификатор также будет скрывать идентификатор значения, порождая другую ошибку:
#let (ref x) = ref 2 in let x = 1 in x <- 3;;
Toplevel input:
>let (ref x) = ref 2 in let x = 1 in x <- 3;;
> ^^^^^^
The identifier x is not mutable.