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

nerv_ 07.12.2014 21:03

krutoy, не вижу смысла с тобой спорить. Ты уже показал себя на форуме :)

bes, мой полный ответ был здесь. По сути на этом тема должна быть исчерпана.
Даже если в функцию передается объект с параметрами, то:
1. либо он чистый [new Object()]
2. либо, в большинстве случаев его следует интерпретировать как чистый. Например:
foo({bar: 1});
foo({bar: 1}); // какой смысл от того, что это другой объект, если это всего лишь "объект с параметрами"?
т.е. просто глупо тут разницу показывать или нет смысла хранить в массиве ссылки на объекты (если реализация через массивы)

На все негодования кукарекония krutoy, опять-таки, мой ответ был по ссылке выше - смотрите исходники 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];
    };
}

krutoy 07.12.2014 21:28

Цитата:

Сообщение от nerv_
объект с параметрами

Ты, для начала, осиль значение слова параметр. А говорить, действительно, не о чем. Набор базвордов и отборного бреда.

melky 07.12.2014 21:54

Цитата:

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

в ФП во главе угла - функция. ну а иммутабельность и остальные плюхи капают с понятия "функция".

в JS с функциями все в порядке, кроме того, что они медленные.

учитывая моду на ФП (баззворд "функциональщина, йо"), в стандарте ES >= 7 я ожидаю появление плюх для комфортного написания кода в этой парадигме.

кстати, если ты так против ФП и иммутабельности - глянь React, Morearty и ClojureScript. это всё не спроста появилось.

... и не спроста оно всё такое "революционное"

лечись от ООП головного мозга :victory:

(написано как троллинг, но сим не является)

Цитата:

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

ага, именно.
Цитата:

Сообщение от nerv_ (Сообщение 345272)
Ну, и, разумеется, такая функция принимает только примитивы + json like objects. Если очень хочется пихать объекты с циклическими ссылками, то массивы.

Sieg Heil, nerv_

Цитата:

Сообщение от bes
хранение информации в ключах объекта - это из области гениального

обычный хешмап. ты походу пропустил тему марума с задачками по JS - там гениальной жары было навалом :) сейчас эта тема удалена

krutoy 07.12.2014 22:05

Цитата:

Сообщение от melky
это всё не спроста появилось.

Не спроста. Любая функциональщина -- это дрочево под оптимизатор. Когда у тебя есть иммутабельность, ты можешь провернуть такой вот трюк, например
(function f(arg){return foo})(function_with_long_calculation())

Если ты знаешь, что функция function_with_long_calculation чистая, ты можешь редуцировать эту строку до foo в компилтайме.
И при таком раскладе, бредореализация кэширования нерва действительно могла бы работать. В JS это все ни к чему, это экстремально динамичный язык, тут делается упор на выразительность и мозги программиста. А то что ты приводишь, правильно, это мода, когда многие недоумки слышали звон, да не знают где он, но зато знают, что это модно, поэтому пишут ахинею.

В принципе, в JS наверняка код, написанный в ФП-стиле оптимизируется лучше, но это не значит, что надо на это дрочить постоянно.

krutoy 07.12.2014 22:46

Цитата:

Сообщение от nerv_
Ну, и, разумеется, такая функция принимает только примитивы + json like objects. Если очень хочется пихать объекты с циклическими ссылками, то массивы.

Во первых, покажи мне в стандарте, где есть понятие "json-like-objects", товарищ Петросян.
Про примитивы -- это еще вопрос, поскольку в JS любой примитив может быть вызван в объектном контексте.
Насчет массивов -- не п*ди, массивы -- это 100% объекты.

И наконец, 3-й раз спрашиваю, при чем тут циклические ссылки?

bes 07.12.2014 22:49

Цитата:

Сообщение от nerv_
bes, мой полный ответ был здесь. По сути на этом тема должна быть исчерпана.

Цитата:

Сообщение от nerv_
Ну, и, разумеется, такая функция принимает только примитивы + json like objects. Если очень хочется пихать объекты с циклическими ссылками, то массивы.

возможно не заметил/не обратил внимания

Цитата:

Сообщение от nerv_
Для тех, кто кукарекает и не читает ссылки

Цитата:

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

сколько у вас часов в сутках? :)

Цитата:

Сообщение от nerv_
Если очень хочется пихать объекты с циклическими ссылками, то массивы.

пойдёт?

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);

krutoy 07.12.2014 22:53

Цитата:

Сообщение от bes
возможно не заметил/не обратил внимания

bes,
А ты и дальше не обращай, поскольку это тоже полуп*больство, см мой пост выше.
http://javascript.ru/forum/misc/5217...tml#post345384

krutoy 07.12.2014 22:58

Цитата:

Сообщение от 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) ) {
                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 в общем случае, кэширование невозможно.

bes 08.12.2014 00:23

Цитата:

Сообщение от krutoy
И не мучайся. В 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);


есть ещё примеры? :)

krutoy 08.12.2014 00:42

Цитата:

Сообщение от bes
хорошо, но давай двинемся на шаг дальше

Слушай, честно, мне лень разбирать примеры "вечного двигателя":). Понять бессмысленность данной затеи легко. Смотри. В JS объект получается по ссылке. Легко понять, что закэшировать его можно только одним способом -- сохранив ссылку на него в кэше. Естественно, если объект меняется, то из кэша ты получаешь неактуальные значения. Этого понимания достаточно, чтобы прекратить эти нелепые попытки:)
Но это не значит, что мы не можем кэшировать какие то частные случаи. Например, можно часть объектов сделать неизмняемыми. чтоб они работали как простые хэши, можно работать с примитивами, не вызывая их в объектном контексте, и т.п. Это сделать легко.


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