2016-12-23 6 views
0

Предположим, мне нужно обновить список при каждом вызове функции, чтобы сохранился предыдущий элемент списка.Как сохранить элементы в списке через программу в SML?

Вот моя попытка:

local 
    val all_list = []; 
in 
    fun insert (x:int) : string = int2string (list_len((([email protected][x])))) 
end; 

Проблема в том, что каждый раз, когда я звоню, чтобы вставить, я получаю выход «1», что указывает, что список начинается с [] снова.

Однако я ожидал вывода "1" для первого вызова для вставки и "2" для второго вызова, ... и т. Д.

Я не могу найти обходной путь. Как это сделать?

+0

В функциональном программировании, вызывая функцию несколько раз с тем же входом будет повторно дать такие же результаты. Почему вы ожидаете иначе? – Bergi

+0

Вы никогда не обновляете переменную (а вы не можете!).Вы просто создаете новый список, длина которого вы затем определяете. – Bergi

+0

Я могу порекомендовать прочитать [Программирование в стандартном ML] (http://www.cs.cmu.edu/~rwh/isml/book.pdf) Р. Харпера. Действительно хорошая книга! –

ответ

2

Вам необходимо использовать side-effects. Большую часть времени функциональные программисты предпочитают использовать pure functions, которые не имеют побочных эффектов. Ваша реализация является чистой функцией, поэтому она всегда будет возвращать одно и то же значение для одного и того же ввода (и в вашем случае оно возвращает то же значение для любого ввода).

Вы можете иметь дело с этим с помощью ссылки .

Ускоренный курс на ссылки в Standard ML:

  • использования ref создать новую ссылку, ref имеет тип 'a -> 'a ref, поэтому упаковывает произвольное значение в эталонную ячейку, которую можно изменить позже;
  • ! предназначен для распаковки ссылки: (!) : 'a ref -> 'a, на самых императивных языках эта операция неявная, но не в SML или OCaml;
  • (:=) : 'a ref * 'a -> unit - это инфиксный оператор, используемый для изменения ссылок, вот как вы увеличиваете содержание целочисленной ссылки: r := !r + 1.

выше дает нам следующий код (я предварять x S на список, вместо добавления их):

local 
    val rxs = ref [] 
in 
    fun insert (x:int) : string = 
     (rxs := x :: !rxs; 
     Int.toString (length (!rxs))) 
end 
1

Значения неизменяемы в SML. insert определяется в контексте, в котором значение all_list равно [], и ничего о вашем коде не меняет это значение.

[email protected][x] 

не мутировать значение all_list - она ​​возвращает новый список, один из которых ваш код быстро сбрасывает (после взятия его длины).

Использование ссылочных типов (одна из нечистых функций SML) позволяет делать то, что вы пытаетесь сделать, но полученный код не будет идиоматическим SML. Он нарушит ссылочную прозрачность (желательная особенность языков функционального программирования, где функция с одинаковыми входами дает идентичные выходы).

 Смежные вопросы

  • Нет связанных вопросов^_^