Просмотр полной версии : Function Cache
Всем привет!
Задача в том, что:
0) Создается некоторая функция, принимающая N аргументов;
1) Создается кэширующая функция, которая принимает вышеуказанную в качестве фунарга и дальше с возвращенным ей значением мы можем работать следующим образом:
- если такая функция-обертка вызывается с новым набором аргументов, то выполняется оригинальная функция;
- в противном случае, если вызов с такими аргументами уже был, то возвращается закэшированный результат, без вызова.
Вот оригинальное описание: "If you are calculating complex things or execute time-consuming API calls, you sometimes want to cache the results. In this case we want you to create a function wrapper, which takes a function and caches its results depending on the arguments, that were applied to the function."
Мой код:
function cache(func) {
var cached_func = func,
cached_func_data = [];
return function() {
var args_len = arguments.length,
i,
j;
if (!cached_func_data.length) {
return callCachedFunc(arguments);
}
for (i = 0; i < args_len; i++) {
for (j = 0; j < cached_func_data[i].args.length; j++) {
if (cached_func_data[i].args[i] === arguments[i]) {
continue;
}
return cached_func_data[i].res;
}
return callCachedFunc(arguments);
}
function callCachedFunc(arguments) {
var cache_obj = {};
cache_obj.args = Array.prototype.slice.call(arguments);
cache_obj.res = cached_func.apply(null, arguments);
cached_func_data.push(cache_obj);
return cache_obj.res;
}
}
}
Прошу провести ревью кода. Решение не полностью корректно, но я не могу пока что, к большому своему огорчению, найти ошибку.
Спасибо.
Вот пример использования:
var complexFunction = function(arg1, arg2) { /* complex calculation in here */ };
var cachedFunction = cache(complexFunction);
cachedFunction('foo', 'bar'); // complex function should be executed
cachedFunction('foo', 'bar'); // complex function should not be invoked again, instead the cached result should be returned
cachedFunction('foo', 'baz'); // should be executed, because the method wasn't invoked before with these arguments
Заранее благодарен за любые комментарии по делу.
https://yadi.sk/i/er6gs7TEdCUGg
nerv_,
чушь собачья
a=Object.create({a: 1})
b=Object.create({a: 2})
fu=function(){
var f=function(arg){return arg.a}
return function(){alert(JSON.stringify(arguments)); return f(arguments[0])}
}()
alert(fu(a))
alert(fu(b))
// {"0":{}}
// 1
// {"0":{}}
// 2
Закешировали, ага.
я вчера было уже хотел выложить вариант с двумя массивами, но вариант nerv_ c cache[stamp] дал понять, где настоящий скил :)
в качестве отработки при помощи FineReader-a извлёк код nerv_ (шутка :D )
function f(a, b, c) {
return a * b + c;
};
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);
cacheF(2, 2, "asdf");
cacheF(2, 2, "asdf");
cacheF(2, 3, "asdf");
cacheF(2, 3, "asdf");
Vlasenko Fedor
07.12.2014, 12:35
if (!cache.hasOwnProperty(stamp)) {/*... */}
а так не лучше будет?
if (!cache.hasOwnProperty(stamp)) {/*... */}
а так не лучше будет?
лучше, потому что немного быстрее, но это из области незначительной оптимизации, а вот хранение информации в ключах объекта - это из области гениального :)
а вот хранение информации в ключах объекта - это из области гениального
стандартный прием)
Общепринятое название функции memorize (у меня на скрине опечатка, скопипастил название у lowdash), от memorization
https://lodash.com/docs#memoize
Читайте Стоян Стефанов - JavaScript. Шаблоны (http://www.books.ru/books/javascript-shablony-827259/), там все есть
Ну, и, разумеется, такая функция принимает только примитивы + json like objects. Если очень хочется пихать объекты с циклическими ссылками, то массивы.
danik.js
07.12.2014, 13:59
Общепринятое название функции memorize
:no: http://en.wikipedia.org/wiki/Memoization
danik.js, значит в книжке опечатка)
https://yadi.sk/i/IlMM8krQdCoLf
https://ru.wikipedia.org/wiki/%D0%9C%D0%B5%D0%BC%D0%BE%D0%B8%D0%B7%D0%B0%D1%86%D 0%B8%D1%8F
или в википедии опечатка, т.к. запоминание согласно переводчику гугла это memorization от слова memory (насколько я понимаю)
https://translate.google.ru/#en/ru/memorization
Если очень хочется пихать объекты с циклическими ссылками, то массивы.
С какими чиклическими ссылками? Я выше показал, что с объектами ф-ция вообще работает некорректно, с любыми объектами. А учитывая то, что в js все есть объект, ф-ция не работает в общем случае. Не понимаю, откуда в треде столько поросячего восторга. Ставлю палец вниз:)
krutoy, я рад, что ты открыл для себя функцию Object.create(). Жаль, что только ее :)
Я выше показал, что с объектами ф-ция вообще работает некорректно
а я показал, куда тебе идти :D Шутка) Не показывал еще, но если будешь настаивать, то покажу)))
иди почитай что такое JSON (https://ru.wikipedia.org/wiki/JSON)
nerv_,
Я ничего не понял. Что не так в моем коде? JSON.stringify берет только верхнюю (ближний хеш) часть объекта, которая объектом, безусловно не является. И ты так и не ответил, причем тут циклические ссылки.
А Object.create тут не при чем, он взят в качестве примера. с юбым прототипом и их цепочкой, будет то же самое.
стандартный прием)
ну мы-то люди простые, институтов не кончали :D
идём от очевидного, где-то надо хранить - в переменной, массиве, объекте, до ключа объекта не догадались :no:
до ключа объекта не догадались
Ключ объекта в этом смысле является эквивалентом переменной. Все переменные в JS фактически также являются св-ми объекта, на считая некоторых деталей. Поэтому, мне тоже не понятно, чему ты удивляешься. Есть всего лишь строка, которая сслыается на объект.
Ключ объекта в этом смысле является эквивалентом переменной. Все переменные в JS фактически также являются св-ми объекта, на считая некоторых деталей. Поэтому, мне тоже не понятно, чему ты удивляешься. Есть всего лишь строка, которая сслыается на объект.
ладно, будем считать, что тогда уже поздно было, мозг плохо работал :yes:
bes,
Это идет, видимо, от общего, превратного понимания JS, в массе. JS является чистейшим ООП языком, в стиле смолтока или селфа, то есть, ООП в хорошем смысле этого слова. В подобных семантиках, надо рассматривать ключ объекта, как предикат, определяющий, может ли объект принять данное сообщение, "знает" ли он данное определение.
bes,
Но, в целом, ф-ция -- говно, см мои комменты выше. Ее написал не "гений", как ты выразился, а, мягко говоря, чел далекий от понимания JS.
bes,
Но, в целом, ф-ция -- говно, см мои комменты выше. Ее написал не "гений", как ты выразился, а, мягко говоря, чел далекий от понимания JS.
JSON.stringify
так лучше?
Array.prototype.slice.call(arguments).toString()
так лучше?
не думаю
f=function(arg){
return [].slice.call(arguments).toString()
}
o1=Object.create({a: 1})
o2=Object.create({a: 2})
alert(f(o1))
alert(f(o2))
// [object Object]
// [object Object]
что мы будем сравнивать?
А если так
f=function(arg){
return [].slice.call(arguments[0]).toString()
}
o1=Object.create({a: 1})
o2=Object.create({a: 2})
alert(f(o1))
alert(f(o2))
вернем 2 пустые строки, в даном случае, то есть, те же яйца сбоку.
krutoy, возьми мой пример и покажи, что не так
возьми мой пример и покажи, что не так
вот в этой строке
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
У тебя из кеша будет извлечено не то, что ты ожидаешь.
https://yadi.sk/i/er6gs7TEdCUGg
хакер :)
bes,
Это идет, видимо, от общего, превратного понимания JS, в массе. JS является чистейшим ООП языком, в стиле смолтока или селфа, то есть, ООП в хорошем смысле этого слова. В подобных семантиках, надо рассматривать ключ объекта, как предикат, определяющий, может ли объект принять данное сообщение, "знает" ли он данное определение.
JS - мультипарадигменный язык.
бахать "сикретные свойства" примитивам для того , чтобы их "опознать" - это уже не мемоизация, а геморизация.
ты взял этот способ из книги Фленегана?. (да, мы все его читали)
мультипарадигменный
Этот базворд я слышал раз тысячу, но до сих пор не понял, что в него вкладывается. В частности, многие кукарекают о якобы, поддержке JS ФП, чего и близко нет в реальности (и не нужно), если следовать современной трактовке, где во главе угла иммутабельность.
примитивам
А, если речь только лишь о примитивах, тогда ок, только тогда надо отдельно указывать, что массивы, регекпы, функции, объекты, объекты строк, объекты чисел и прочая и прочая, то есть, пости все, иными словами, запрешены в качестве аргументов.
способ из книги Фленегана
Я ни о каком способе не писал, я лишь сказал, что ф-ция говно. А Фленагана я толком не читал, не люблю тягомотину.
бахать "сикретные свойства" примитивам для того , чтобы их "опознать" - это уже не мемоизация, а геморизация.
Кстати, никакого геммороя тут нет, достаточно расширить бызовые типы, это буквально несколько строк кода, и никакой сложности. Только я об этом не говорил ничего в данном треде.
и я не совсем понял, что ты имеешь в виду. Если ты расшитяешь именно примитив, то ты делаешь это так
String.prototype.foo=1
и, в этом случае, у тебя все строки будут иметь св-во foo. Если же ты делаешь
foo=new String("foo")
foo.foo=1
alert(foo.foo)
// 1
Ты расширяешь не примитив, а конкретный строковый объект.
вот в этой строке
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
У тебя из кеша будет извлечено не то, что ты ожидаешь.
всё хорошо, но речь шла о том, что
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);
с новым набором аргументов
bes,
только тогда надо отдельно указывать, что массивы, регекпы, функции, объекты, объекты строк, объекты чисел и прочая и прочая, то есть, почти все, иными словами, запрешены в качестве аргументов.
Сообщение от krutoy
только тогда надо отдельно указывать, что массивы, регекпы, функции, объекты, объекты строк, объекты чисел и прочая и прочая, то есть, почти все, иными словами, запрешены в качестве аргументов.
нет, не запрещены, речь шла только о работе с возвращённым значением, то, о чём говоришь ты, другая задача
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,
Нет, ты опять не понял. Задача твоей кэширующей ф-ции в том, чтобы "понять", была ли данная функция (которая в замыкании), уже вызвана с данными аргументами. Именно этого она не делает, точней делает, но только с примитивами. Она не может по этой "псевдосигнатуре" объекта определить, был ли данный объект уже в качестве аргумента, или нет, потому что разные объекты могут давать одинаковый отпечаток.
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
//
ок, показательный пример
krutoy, не вижу смысла с тобой спорить. Ты уже показал себя на форуме :)
bes, мой полный ответ был здесь (http://javascript.ru/forum/misc/52176-function-cache.html#post345272). По сути на этом тема должна быть исчерпана.
Даже если в функцию передается объект с параметрами (http://learn.javascript.ru/arguments-named), то:
1. либо он чистый [new Object()]
2. либо, в большинстве случаев его следует интерпретировать как чистый. Например:
foo({bar: 1});
foo({bar: 1}); // какой смысл от того, что это другой объект, если это всего лишь "объект с параметрами"? т.е. просто глупо тут разницу показывать или нет смысла хранить в массиве ссылки на объекты (если реализация через массивы)
На все негодования кукарекония krutoy, опять-таки, мой ответ был по ссылке выше (http://javascript.ru/forum/misc/52176-function-cache.html#post345272) - смотрите исходники lowdash, там все есть. Для тех, кто кукарекает и не читает ссылки, а в частности krutoy, напишу примерный код того, как эта функция выглядит в lowdash:
var fn = function() {
console.log(1);
};
var foo = memoize(fn);
foo({a:1}); // 1
foo({a:1}); //
var bar = memoize(fn, function() {
return Date.now();
});
bar({a:1}); // 1
bar({a:1}); // 1
/**
* @param {Function} fn
* @param {Function} [identify]
*/
function memoize(fn, identify) {
var cache = {};
var getKey = identify || JSON.stringify;
return function() {
var key = getKey(arguments);
if (!cache.hasOwnProperty(key)) {
cache[key] = fn.apply(this, arguments);
}
return cache[key];
};
}
объект с параметрами
Ты, для начала, осиль значение слова параметр. А говорить, действительно, не о чем. Набор базвордов и отборного бреда.
В частности, многие кукарекают о якобы, поддержке JS ФП, чего и близко нет в реальности (и не нужно), если следовать современной трактовке, где во главе угла иммутабельность.
в ФП во главе угла - функция. ну а иммутабельность и остальные плюхи капают с понятия "функция".
в JS с функциями все в порядке, кроме того, что они медленные.
учитывая моду на ФП (баззворд "функциональщина, йо"), в стандарте ES >= 7 я ожидаю появление плюх для комфортного написания кода в этой парадигме.
кстати, если ты так против ФП и иммутабельности - глянь React, Morearty и ClojureScript. это всё не спроста появилось.
... и не спроста оно всё такое "революционное"
лечись от ООП головного мозга :victory:
(написано как троллинг, но сим не является)
А, если речь только лишь о примитивах, тогда ок, только тогда надо отдельно указывать, что массивы, регекпы, функции, объекты, объекты строк, объекты чисел и прочая и прочая, то есть, пости все, иными словами, запрешены в качестве аргументов.
ага, именно.
Ну, и, разумеется, такая функция принимает только примитивы + json like objects. Если очень хочется пихать объекты с циклическими ссылками, то массивы.
Sieg Heil, nerv_
хранение информации в ключах объекта - это из области гениального
обычный хешмап. ты походу пропустил тему марума с задачками по JS - там гениальной жары было навалом :) сейчас эта тема удалена
это всё не спроста появилось.
Не спроста. Любая функциональщина -- это дрочево под оптимизатор. Когда у тебя есть иммутабельность, ты можешь провернуть такой вот трюк, например
(function f(arg){return foo})(function_with_long_calculation())
Если ты знаешь, что функция function_with_long_calculation чистая, ты можешь редуцировать эту строку до foo в компилтайме.
И при таком раскладе, бредореализация кэширования нерва действительно могла бы работать. В JS это все ни к чему, это экстремально динамичный язык, тут делается упор на выразительность и мозги программиста. А то что ты приводишь, правильно, это мода, когда многие недоумки слышали звон, да не знают где он, но зато знают, что это модно, поэтому пишут ахинею.
В принципе, в JS наверняка код, написанный в ФП-стиле оптимизируется лучше, но это не значит, что надо на это дрочить постоянно.
Ну, и, разумеется, такая функция принимает только примитивы + json like objects. Если очень хочется пихать объекты с циклическими ссылками, то массивы.
Во первых, покажи мне в стандарте, где есть понятие "json-like-objects", товарищ Петросян.
Про примитивы -- это еще вопрос, поскольку в JS любой примитив может быть вызван в объектном контексте.
Насчет массивов -- не п*ди, массивы -- это 100% объекты.
И наконец, 3-й раз спрашиваю, при чем тут циклические ссылки?
bes, мой полный ответ был здесь. По сути на этом тема должна быть исчерпана.
Ну, и, разумеется, такая функция принимает только примитивы + json like objects. Если очень хочется пихать объекты с циклическими ссылками, то массивы.
возможно не заметил/не обратил внимания
Для тех, кто кукарекает и не читает ссылки
обычный хешмап. ты походу пропустил тему марума с задачками по JS - там гениальной жары было навалом сейчас эта тема удалена
сколько у вас часов в сутках? :)
Если очень хочется пихать объекты с циклическими ссылками, то массивы.
пойдёт?
function f(obj) {
return obj.a + obj.b;
}
function isSame(args1, args2) {
var len1 = args1.length;
var len2 = args2.length;
if ( len1 != len2 ) return false;
for (var i = 0; i < len1; i++) {
if ( args1[i] === args2[i] ) continue;
return false;
}
return true;
}
function cacheFn(fn) {
var cache = [];
return function () {
var len = cache.length;
for (var i = 0; i < len; i++) {
if ( isSame(cache[i].args, arguments) ) {
console.log("cache: " + cache[i].res + "\n\n");
return cache[i].res;
}
}
cache.push( {args: arguments, res: fn.apply(this, arguments)} );
console.log("call: " + cache[len].res + "\n\n")
return cache[len].res;
}
}
var cacheF = cacheFn(f);
var o1 = Object.create({b: 2})
var o2 = Object.create({b: 3})
o1.a = 1
o2.a = 1
cacheF(o1);
cacheF(o1);
cacheF(o2);
cacheF(o2);
возможно не заметил/не обратил внимания
bes,
А ты и дальше не обращай, поскольку это тоже полуп*больство, см мой пост выше.
http://javascript.ru/forum/misc/52176-function-cache-4.html#post345384
пойдёт?
Нет
function f(obj) {
return obj.a + obj.b;
}
function isSame(args1, args2) {
var len1 = args1.length;
var len2 = args2.length;
if ( len1 != len2 ) return false;
for (var i = 0; i < len1; i++) {
if ( args1[i] === args2[i] ) continue;
return false;
}
return true;
}
function cacheFn(fn) {
var cache = [];
return function () {
var len = cache.length;
for (var i = 0; i < len; i++) {
if ( isSame(cache[i].args, arguments) ) {
console.log("cache: " + cache[i].res + "\n\n");
return cache[i].res;
}
}
cache.push( {args: arguments, res: fn.apply(this, arguments)} );
console.log("call: " + cache[len].res + "\n\n")
return cache[len].res;
}
}
var cacheF = cacheFn(f);
var o1 = Object.create({b: 2})
var o2 = Object.create({b: 3})
o1.a = 1
o2.a = 1
cacheF(o1);
cacheF(o1);
cacheF(o2);
cacheF(o2);
o2.a = 10
cacheF(o2);
// call: 3
//
//
// cache: 3
//
//
// call: 4
//
//
// cache: 4
//
//
// cache: 4
И не мучайся. В JS в общем случае, кэширование невозможно.
И не мучайся. В JS в общем случае, кэширование невозможно.
хорошо, но давай двинемся на шаг дальше
function f(obj) {
return obj.a + obj.b;
}
function isSame(args1, args2) {
var len1 = args1.length;
var len2 = args2.length;
if ( len1 != len2 ) return false;
for (var i = 0; i < len1; i++) {
if ( args1[i] === args2[i] ) continue;
return false;
}
return true;
}
function cacheFn(fn) {
var cache = [];
return function () {
var len = cache.length;
for (var i = 0; i < len; i++) {
if ( isSame(cache[i].args, arguments) && JSON.stringify(arguments) == cache[i].strArg) {
console.log("cache: " + cache[i].res + "\n\n");
return cache[i].res;
}
}
cache.push( {args: arguments, strArg: JSON.stringify(arguments), res: fn.apply(this, arguments)} );
console.log("call: " + cache[len].res + "\n\n")
return cache[len].res;
}
}
var cacheF = cacheFn(f);
var o1 = Object.create({b: 2})
var o2 = Object.create({b: 3})
o1.a = 1
o2.a = 1
//cacheF(o1);
//cacheF(o1);
cacheF(o2);
cacheF(o2);
console.log("----");
o2.a = 10
cacheF(o2);
cacheF(o2);
console.log("****");
o2.b = 10;
cacheF(o2);
cacheF(o2);
есть ещё примеры? :)
хорошо, но давай двинемся на шаг дальше
Слушай, честно, мне лень разбирать примеры "вечного двигателя":). Понять бессмысленность данной затеи легко. Смотри. В JS объект получается по ссылке. Легко понять, что закэшировать его можно только одним способом -- сохранив ссылку на него в кэше. Естественно, если объект меняется, то из кэша ты получаешь неактуальные значения. Этого понимания достаточно, чтобы прекратить эти нелепые попытки:)
Но это не значит, что мы не можем кэшировать какие то частные случаи. Например, можно часть объектов сделать неизмняемыми. чтоб они работали как простые хэши, можно работать с примитивами, не вызывая их в объектном контексте, и т.п. Это сделать легко.
Любая функциональщина -- это дрочево под оптимизатор
похоже , что у нас тут типичное неприятие нового
сколько у вас часов в сутках?
раньше было около тысячи , сейчас - такое чувство, что в сутках 6 часов, не больше
но раньше сутки были длиннее, да
мой полный ответ был здесь.
И заметь, что так называемый "твой ответ" появился уже после того, как я тебя ткнул лицом в это говно. А ты должен был не отвечать бесу, а в первом же посте указать на эти ограничения ТСу. Но ты этого не сделал по той причине, что пока я тебя не ткнул в твое говно, ты об этом и не думал и не знал. А вместо спасибо, ты начал борзеть, и именно по этой причине окончательно был слит в гавно.
krutoy, припекло тебя :D
А ты должен был
я никому ничего не должен :)
Я показал свою реализацию, которой мне хватает более чем. Да, у нее есть ограничения. Если тот, кто ее использует не способен их увидеть - это его проблемы)
как я тебя ткнул лицом в это говно
Пожалуйста, не тяни меня в свое говно, в кот. ты плаваешь постоянно. Ты сделан из него, им пропитан, плохо воспитан и, вообще, говорить с тобой мне не о чем. Не сейчас, не в будущем.
Не сейчас, не в будущем.
Ни.
вот оно че, Михалыч (http://javascript.ru/forum/misc/51748-pishut-li-v-takom-stile-4.html#post341658)
комментарии излишни)
Слушай, честно, мне лень разбирать примеры "вечного двигателя". Понять бессмысленность данной затеи легко. Смотри. В JS объект получается по ссылке. Легко понять, что закэшировать его можно только одним способом -- сохранив ссылку на него в кэше. Естественно, если объект меняется, то из кэша ты получаешь неактуальные значения. Этого понимания достаточно, чтобы прекратить эти нелепые попытки
Но это не значит, что мы не можем кэшировать какие то частные случаи. Например, можно часть объектов сделать неизмняемыми. чтоб они работали как простые хэши, можно работать с примитивами, не вызывая их в объектном контексте, и т.п. Это сделать легко.
смотри: есть объект, есть его состояние, кешируем ссылку на объект и его состояние, если ни ссылка, ни состояние не изменилось, можно обращаться к кешу
в моём последнем примере как раз так и делается, с учётом того, что ссылку сохранить не проблема, а сохранение состояния можно реализовывать с различной степенью сложности
bes,
Не взрывай мне мозг :)
function f(obj) {
return obj.a + obj.b;
}
function isSame(args1, args2) {
var len1 = args1.length;
var len2 = args2.length;
if ( len1 != len2 ) return false;
for (var i = 0; i < len1; i++) {
if ( args1[i] === args2[i] ) continue;
return false;
}
return true;
}
function cacheFn(fn) {
var cache = [];
return function () {
var len = cache.length;
for (var i = 0; i < len; i++) {
if ( isSame(cache[i].args, arguments) && JSON.stringify(arguments) == cache[i].strArg) {
console.log("cache: " + cache[i].res + "\n\n");
return cache[i].res;
}
}
cache.push( {args: arguments, strArg: JSON.stringify(arguments), res: fn.apply(this, arguments)} );
console.log("call: " + cache[len].res + "\n\n")
return cache[len].res;
}
}
var cacheF = cacheFn(f);
o={b: 2}
var o1 = Object.create(o)
o1.a = 1
cacheF(o1);
o.b=10
console.log("----");
cacheF(o1);
console.log("****");
cacheF(o1);
// call: 3
//
//
// ----
// cache: 3
//
//
// ****
// cache: 3
bes,
Не взрывай мне мозг :)
лови fuel injection, possibly with slices of shit :D
ещё куча непокрытого, но твой случай покрывает :)
function type(el) {
var type = typeof el;
if ( type != "object" ) return type;
if ( el == null ) return "null";
if ( el.length || el.length >= 0 ) return "array";
return "object";
}
function len(obj) {
var n = 0;
for (var key in obj) {
n++;
}
return n;
}
function isEqual(obj1, obj2) {
if ( type(obj1) != "object" && type(obj2) != "object" ) return obj1 == obj2;
if ( len(obj1) != len(obj2) ) return false;
for (var key in obj1) {
if (obj1[key] === obj2[key]) {
continue;
}
return false;
}
return true;
}
function cloneObject(obj) {
var clone = {};
for (var key in obj) {
clone[key] = obj[key];
}
return clone;
}
function isSame(args1, args2) {
var len1 = args1.length;
var len2 = args2.length;
if ( len1 != len2 ) return false;
for (var i = 0; i < len1; i++) {
if ( isEqual(args1[i], args2[i]) ) continue;
return false;
}
return true;
}
function giblets(args) {
var giblet = [];
var length = args.length;
for ( var i = 0; i < length; i++ ) {
if ( type(args[i]) != "object" ) {
giblet.push(args[i]);
} else {
giblet.push( cloneObject(args[i]) );
}
}
return giblet;
}
function cacheFn(fn) {
var cache = [];
return function () {
var len = cache.length;
for (var i = 0; i < len; i++) {
if ( isSame(cache[i].args, giblets(arguments)) ) {
console.log("cache: " + cache[i].res + "\n\n");
return cache[i].res;
}
}
cache.push( {args: giblets(arguments), res: fn.apply(this, arguments)} );
console.log("call: " + cache[len].res + "\n\n")
return cache[len].res;
}
}
function f(obj) {
return obj.a + obj.b;
}
var cacheF = cacheFn(f);
o={b: 2}
var o1 = Object.create(o)
o1.a = 1
cacheF(o1);
cacheF(o1);
o.b=10
console.log("----");
cacheF(o1);
cacheF(o1);
Vlasenko Fedor
09.12.2014, 00:03
krutoy,
function isSame(args1, args2) {
var len1 = args1.length;
var len2 = args2.length;
if ( len1 != len2 ) return false;
for (var i = 0; i < len1; i++) {
if ( args1[i] === args2[i] ) continue;
return false;
}
return true;
}
и
function isSame(args1, args2) {
return args1 === args2;
}
Это напомнило мне прошлую неделю. Задание было переписать самописный ACl в самописном движке.
Час я смотрел на этот код и не мог понять, что здесь было написано. Я хотел понять мысль того разработчика который это написал. Это был запрос на пол-страницы , пришлось и по гуглить так как некоторые операторы я встретил впервые, а также много рекурсивных функций. Копаться в этом дерьме не было особого интереса. Решение было интересное. Пару проведенных тестов подача одних параметров на вход привело к очевидности к замене 300 строк кода 3 строками. Тестировщик позже подтвердил правильность решения.
В общем к чему я. Приведенный в начале топика код напоминает напоминает шаблон Реестр (Registry)
Poznakomlus,
Да, но ваша ассоциация, кстати, не совсем к месту:). Все таки "выяснить, указывают ли 2 ссылки на один и тот же объект(массив)" и "имеют ли 2 объекта (массива) идентичную структуру" это далеко не одно и то же.
есть объект, есть его состояние, кешируем ссылку на объект и его состояние, если ни ссылка, ни состояние не изменилось, можно обращаться к кешу
Зачем так сложно? Либо ты идешь по одному пути
выяснить, указывают ли 2 ссылки на один и тот же объект
либо по другомуимеют ли 2 объекта (массива) идентичную структуру
не вижу смысла совмещать
Зачем так сложно? Либо ты идешь по одному пути
Сообщение от krutoy
>>выяснить, указывают ли 2 ссылки на один и тот же объект
либо по другому
Сообщение от krutoy
>>имеют ли 2 объекта (массива) идентичную структуру
не вижу смысла совмещать
в первом случае пути нет, так как это уже реализовано
во втором случае, если полностью сохранять состояние объекта со всеми тянущимися оттуда потрохами зависимостями, то дополнительно сохранять ссылку смысла нет,
если же сохранять состояние не полностью, то сохранение ссылки дополнительно отсекает случаи локальной "идентичности" совершенно разных объектов с их индивидуальными зависимостями
vBulletin® v3.6.7, Copyright ©2000-2025, Jelsoft Enterprises Ltd. Перевод: zCarot