В Haskell у меня есть контейнер вроде:
data Container a = Container { length :: Int, buffer :: Unboxed.Vector (Int,a) }
Этот контейнер представляет собой сплющенное дерево. Его метод доступа (!)
выполняет двоичный (log(N)
) поиск по вектору, чтобы найти нужное ведро, в котором хранится index
.
(!) :: Container a -> Int -> a
container ! index = ... binary search ...
Поскольку последовательные обращения, скорее всего, будут в одном и том же сегменте, это можно оптимизировать следующим образом:
if `index` is on the the last accessed bucket, skip the search
Сложный момент - часть last accessed bucket
. В JavaScript я бы просто нечисто изменил скрытую переменную в объекте-контейнере.
function read(index,object){
var lastBucket = object.__lastBucket;
// if the last bucket contains index, no need to search
if (contains(object, lastBucket, index))
var bucket = lastBucket;
// if it doesn't
else {
// then we search the bucket
var bucket = searchBucket(index,object);
// And impurely annotate it on the container, so the
// next time we access it we could skip the search.
container.__lastBucket = bucket;
}
return object.buffer[bucket].value;
}
Поскольку это просто оптимизация, и результат один и тот же, независимо от выбранной ветки, я считаю, что это не нарушает ссылочную прозрачность. Как возможно в Haskell нечисто изменить состояние, связанное со значением времени выполнения?
~
Я подумал о двух возможных решениях.
Глобальная изменяемая хэш-карта, связывающая указатели со значением
lastBucket
, и используйте unsafePerformIO для записи в нее. Но мне нужен способ получить указатель времени выполнения объекта или, по крайней мере, какой-то уникальный идентификатор (как?).Добавьте дополнительное поле в
Container
,lastBucket :: Int
и каким-то образом нечисто измените его в(!)
и считайте это поле внутренним (потому что оно явно нарушает ссылочную прозрачность).
lastBucket :: IORef Int
и использоватьunsafePerformIO
для «нечистой модификации». Ваш код JS не обрабатывает тот факт, что__lastBucket
может быть изменен другим вызовомread()
из другого потока, следовательно, имеет разные значения вif
и=
. - person Émilien Tlapale   schedule 26.08.2015__lastBucket
в переменной в начале. (JS не имеет потоков...). Изменить: обновил OP. - person MaiaVictor   schedule 26.08.2015ST
... - person Daniel Wagner   schedule 26.08.2015