Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Function Cache (https://javascript.ru/forum/misc/52176-function-cache.html)

bes 07.12.2014 17:06

krutoy, возьми мой пример и покажи, что не так

krutoy 07.12.2014 17:19

Цитата:

Сообщение от bes
возьми мой пример и покажи, что не так

вот в этой строке
cache[stamp] = fn.apply(this, arguments);

в ключ записывается не объект, а лишь текстовое представление его "верхушки", первого хеша. В дальнейшем, когда ты делаешь проверку, у тебя следующий "отпечаток", при сравнении строк даст true, хотя объекты, записанные туда, могут быть другими.
o1={a: 1}
o2={a: 1}

textRepresent1=JSON.stringify(o1)
textRepresent2=JSON.stringify(o2)
console.log(
o1===o2,
textRepresent1===textRepresent2
)
//  false true

У тебя из кеша будет извлечено не то, что ты ожидаешь.

melky 07.12.2014 17:27

Цитата:

Сообщение от nerv_ (Сообщение 345144)

хакер :)

Цитата:

Сообщение от krutoy (Сообщение 345324)
bes,
Это идет, видимо, от общего, превратного понимания JS, в массе. JS является чистейшим ООП языком, в стиле смолтока или селфа, то есть, ООП в хорошем смысле этого слова. В подобных семантиках, надо рассматривать ключ объекта, как предикат, определяющий, может ли объект принять данное сообщение, "знает" ли он данное определение.

JS - мультипарадигменный язык.

бахать "сикретные свойства" примитивам для того , чтобы их "опознать" - это уже не мемоизация, а геморизация.

ты взял этот способ из книги Фленегана?. (да, мы все его читали)

krutoy 07.12.2014 17:43

Цитата:

Сообщение от melky
мультипарадигменный

Этот базворд я слышал раз тысячу, но до сих пор не понял, что в него вкладывается. В частности, многие кукарекают о якобы, поддержке JS ФП, чего и близко нет в реальности (и не нужно), если следовать современной трактовке, где во главе угла иммутабельность.
Цитата:

Сообщение от melky
примитивам

А, если речь только лишь о примитивах, тогда ок, только тогда надо отдельно указывать, что массивы, регекпы, функции, объекты, объекты строк, объекты чисел и прочая и прочая, то есть, пости все, иными словами, запрешены в качестве аргументов.
Цитата:

Сообщение от melky
способ из книги Фленегана

Я ни о каком способе не писал, я лишь сказал, что ф-ция говно. А Фленагана я толком не читал, не люблю тягомотину.

krutoy 07.12.2014 17:49

Цитата:

Сообщение от melky
бахать "сикретные свойства" примитивам для того , чтобы их "опознать" - это уже не мемоизация, а геморизация.

Кстати, никакого геммороя тут нет, достаточно расширить бызовые типы, это буквально несколько строк кода, и никакой сложности. Только я об этом не говорил ничего в данном треде.

и я не совсем понял, что ты имеешь в виду. Если ты расшитяешь именно примитив, то ты делаешь это так
String.prototype.foo=1

и, в этом случае, у тебя все строки будут иметь св-во foo. Если же ты делаешь
foo=new String("foo")
foo.foo=1
alert(foo.foo)
// 1

Ты расширяешь не примитив, а конкретный строковый объект.

bes 07.12.2014 18:07

Цитата:

Сообщение от krutoy (Сообщение 345330)
вот в этой строке
cache[stamp] = fn.apply(this, arguments);

в ключ записывается не объект, а лишь текстовое представление его "верхушки", первого хеша. В дальнейшем, когда ты делаешь проверку, у тебя следующий "отпечаток", при сравнении строк даст true, хотя объекты, записанные туда, могут быть другими.
o1={a: 1}
o2={a: 1}

textRepresent1=JSON.stringify(o1)
textRepresent2=JSON.stringify(o2)
console.log(
o1===o2,
textRepresent1===textRepresent2
)
//  false true

У тебя из кеша будет извлечено не то, что ты ожидаешь.

всё хорошо, но речь шла о том, что
Цитата:

Сообщение от y0uix
0) Создается некоторая функция, принимающая N аргументов;
1) Создается кэширующая функция, которая принимает вышеуказанную в качестве фунарга и дальше с возвращенным ей значением мы можем работать следующим образом:
- если такая функция-обертка вызывается с новым набором аргументов, то выполняется оригинальная функция;
- в противном случае, если вызов с такими аргументами уже был, то возвращается закэшированный результат, без вызова.

поэтому и пример ниже не рассчитан на решение тех задач, о которых ты говоришь
function f(obj) {
	return obj.a = 2;
};
function cacheFn(fn) {
	var cache = {};
	return function () {
		var stamp = JSON.stringify(arguments); 
		console.log(cache);
		if (!(stamp in cache)) {
			cache[stamp] = fn.apply(this, arguments);
			console.log("call: " + cache[stamp]);
		}
		console.log("cache: " + cache[stamp] + "\n\n");
		return cache[stamp];
	
	}
}
var cacheF = cacheFn(f);
var o1 = {a: 1}; 
var o2 = {a: 1}; 
cacheF(o1);
cacheF(o2);
console.log("o1:");
console.log(o1);
console.log("o2:");
console.log(o2);

krutoy 07.12.2014 18:09

Цитата:

Сообщение от bes
с новым набором аргументов

bes,
Цитата:

Сообщение от krutoy
только тогда надо отдельно указывать, что массивы, регекпы, функции, объекты, объекты строк, объекты чисел и прочая и прочая, то есть, почти все, иными словами, запрешены в качестве аргументов.


bes 07.12.2014 18:14

Цитата:

Сообщение от krutoy
Сообщение от krutoy
только тогда надо отдельно указывать, что массивы, регекпы, функции, объекты, объекты строк, объекты чисел и прочая и прочая, то есть, почти все, иными словами, запрешены в качестве аргументов.

нет, не запрещены, речь шла только о работе с возвращённым значением, то, о чём говоришь ты, другая задача

krutoy 07.12.2014 18:18

bes,
Нет, ты опять не понял. Задача твоей кэширующей ф-ции в том, чтобы "понять", была ли данная функция (которая в замыкании), уже вызвана с данными аргументами. Именно этого она не делает, точней делает, но только с примитивами. Она не может по этой "псевдосигнатуре" объекта определить, был ли данный объект уже в качестве аргумента, или нет, потому что разные объекты могут давать одинаковый отпечаток.

o1=Object.create({b: 2})
o2=Object.create({b: 3})

o1.a=1
o2.a=1

f=function(o){return o.a+o.b}

function cacheFn(fn) {
    var cache = {};
    return function () {
        var stamp = JSON.stringify(arguments);
        console.log(cache);
        if (!(stamp in cache)) {
            cache[stamp] = fn.apply(this, arguments);
            console.log("call: " + cache[stamp]);
        }
        console.log("cache: " + cache[stamp] + "\n\n");
        return cache[stamp];
     
    }
}

theCache=cacheFn(f)
alert(theCache(o1))
alert(theCache(o2))
//  {}
//  call: 3
//  cache: 3
//  
//  
//  3
//  { '{"0":{"a":1}}': 3 }
//  cache: 3
//  
//  
//  3
//

bes 07.12.2014 20:12

Цитата:

Сообщение от krutoy (Сообщение 345344)
bes,
Нет, ты опять не понял. Задача твоей кэширующей ф-ции в том, чтобы "понять", была ли данная функция (которая в замыкании), уже вызвана с данными аргументами. Именно этого она не делает, точней делает, но только с примитивами. Она не может по этой "псевдосигнатуре" объекта определить, был ли данный объект уже в качестве аргумента, или нет, потому что разные объекты могут давать одинаковый отпечаток.

o1=Object.create({b: 2})
o2=Object.create({b: 3})

o1.a=1
o2.a=1

f=function(o){return o.a+o.b}

function cacheFn(fn) {
    var cache = {};
    return function () {
        var stamp = JSON.stringify(arguments);
        console.log(cache);
        if (!(stamp in cache)) {
            cache[stamp] = fn.apply(this, arguments);
            console.log("call: " + cache[stamp]);
        }
        console.log("cache: " + cache[stamp] + "\n\n");
        return cache[stamp];
     
    }
}

theCache=cacheFn(f)
alert(theCache(o1))
alert(theCache(o2))
//  {}
//  call: 3
//  cache: 3
//  
//  
//  3
//  { '{"0":{"a":1}}': 3 }
//  cache: 3
//  
//  
//  3
//

ок, показательный пример


Часовой пояс GMT +3, время: 08:51.