Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 06.12.2014, 22:41
Интересующийся
Отправить личное сообщение для y0uix Посмотреть профиль Найти все сообщения от y0uix
 
Регистрация: 22.10.2013
Сообщений: 11

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


Прошу провести ревью кода. Решение не полностью корректно, но я не могу пока что, к большому своему огорчению, найти ошибку.

Спасибо.
Ответить с цитированием
  #2 (permalink)  
Старый 06.12.2014, 23:18
Интересующийся
Отправить личное сообщение для y0uix Посмотреть профиль Найти все сообщения от y0uix
 
Регистрация: 22.10.2013
Сообщений: 11

Вот пример использования:
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


Заранее благодарен за любые комментарии по делу.
Ответить с цитированием
  #3 (permalink)  
Старый 07.12.2014, 00:48
Аватар для nerv_
junior
Отправить личное сообщение для nerv_ Посмотреть профиль Найти все сообщения от nerv_
 
Регистрация: 29.11.2011
Сообщений: 3,924

https://yadi.sk/i/er6gs7TEdCUGg
__________________
Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина - самый громкий звук
Ответить с цитированием
  #4 (permalink)  
Старый 07.12.2014, 02:37
Профессор
Посмотреть профиль Найти все сообщения от krutoy
 
Регистрация: 09.11.2014
Сообщений: 610

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

Закешировали, ага.
Ответить с цитированием
  #5 (permalink)  
Старый 07.12.2014, 10:37
Аватар для bes
bes bes вне форума
Профессор
Отправить личное сообщение для bes Посмотреть профиль Найти все сообщения от bes
 
Регистрация: 22.03.2012
Сообщений: 3,744

я вчера было уже хотел выложить вариант с двумя массивами, но вариант nerv_ c cache[stamp] дал понять, где настоящий скил

в качестве отработки при помощи FineReader-a извлёк код nerv_ (шутка )
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");
Ответить с цитированием
  #6 (permalink)  
Старый 07.12.2014, 12:35
Аватар для Vlasenko Fedor
Профессор
Отправить личное сообщение для Vlasenko Fedor Посмотреть профиль Найти все сообщения от Vlasenko Fedor
 
Регистрация: 13.03.2013
Сообщений: 1,572

if (!cache.hasOwnProperty(stamp)) {/*... */}

а так не лучше будет?
Ответить с цитированием
  #7 (permalink)  
Старый 07.12.2014, 12:51
Аватар для bes
bes bes вне форума
Профессор
Отправить личное сообщение для bes Посмотреть профиль Найти все сообщения от bes
 
Регистрация: 22.03.2012
Сообщений: 3,744

Сообщение от Poznakomlus Посмотреть сообщение
if (!cache.hasOwnProperty(stamp)) {/*... */}

а так не лучше будет?
лучше, потому что немного быстрее, но это из области незначительной оптимизации, а вот хранение информации в ключах объекта - это из области гениального
Ответить с цитированием
  #8 (permalink)  
Старый 07.12.2014, 13:49
Аватар для nerv_
junior
Отправить личное сообщение для nerv_ Посмотреть профиль Найти все сообщения от nerv_
 
Регистрация: 29.11.2011
Сообщений: 3,924

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

Общепринятое название функции memorize (у меня на скрине опечатка, скопипастил название у lowdash), от memorization
https://lodash.com/docs#memoize

Читайте Стоян Стефанов - JavaScript. Шаблоны, там все есть

Ну, и, разумеется, такая функция принимает только примитивы + json like objects. Если очень хочется пихать объекты с циклическими ссылками, то массивы.
__________________
Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина - самый громкий звук

Последний раз редактировалось nerv_, 07.12.2014 в 13:53.
Ответить с цитированием
  #9 (permalink)  
Старый 07.12.2014, 13:59
Аватар для danik.js
Профессор
Отправить личное сообщение для danik.js Посмотреть профиль Найти все сообщения от danik.js
 
Регистрация: 11.09.2010
Сообщений: 8,804

Сообщение от nerv_
Общепринятое название функции memorize
http://en.wikipedia.org/wiki/Memoization
__________________
В личку только с интересными предложениями
Ответить с цитированием
  #10 (permalink)  
Старый 07.12.2014, 14:12
Аватар для nerv_
junior
Отправить личное сообщение для nerv_ Посмотреть профиль Найти все сообщения от nerv_
 
Регистрация: 29.11.2011
Сообщений: 3,924

danik.js, значит в книжке опечатка)

https://yadi.sk/i/IlMM8krQdCoLf

https://ru.wikipedia.org/wiki/%D0%9C...%D 0%B8%D1%8F

или в википедии опечатка, т.к. запоминание согласно переводчику гугла это memorization от слова memory (насколько я понимаю)
https://translate.google.ru/#en/ru/memorization
__________________
Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина - самый громкий звук

Последний раз редактировалось nerv_, 07.12.2014 в 14:15.
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
сабытие Onchange serrrgggeee Javascript под браузер 1 25.09.2014 10:11
jQuery научите пользоваться. Станислав89 Общие вопросы Javascript 10 19.12.2013 23:01
вопрос про кнопку javascript Ruxx Общие вопросы Javascript 9 22.01.2013 21:01
Свойства посредством полиморфных функций tenshi Ваши сайты и скрипты 0 18.03.2010 17:12
Модуль для работы с геометрией окна JSprog Библиотеки/Тулкиты/Фреймворки 25 31.08.2009 12:54