Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #31 (permalink)  
Старый 08.07.2014, 00:41
foo foo вне форума
Профессор
Отправить личное сообщение для foo Посмотреть профиль Найти все сообщения от foo
 
Регистрация: 17.05.2014
Сообщений: 197

Сообщение от melky
единственный кейс для кодогенерации и eval в JavaScript
Я не совсем понял. Вы о чем? зачем там эвал?
Сообщение от melky
я бы так не говорил
Ну а как? Я говорю конкретно про оптимизацию хвостовой рекурсии, а не оптимизацию в вакууме, а Вы о чем?
Ответить с цитированием
  #32 (permalink)  
Старый 08.07.2014, 01:23
sinistral
Посмотреть профиль Найти все сообщения от melky
 
Регистрация: 28.03.2011
Сообщений: 5,418

можно попробовать перевести код функции к циклу через конструкцию с throw и try-catch

try будет ловить исключение, выбрасываемое, когда стек переполнен, а catch будет менять значение аргументов, ибо они передаются в объекте исключения. и так бесконечно, пока не выйдем из функции

бредовый пример правда чутка мимо кассы

функция
function foo (from) {
  return from ? foo ( document.body.innerHTML = --from ) : from;
}


вызываем
foo(1e6);


JSBIN ---> http://jsbin.com/rojeguze/1

и её взломанный вариант
function foo (from) {

  function foo () {
    throw arguments;
  }
  
  while (true) {
    
    try {
    
      // START
      return from ? foo ( document.body.innerHTML = --from ) : from;
      // END
    
    } catch (e) {
      from = e[0];
    }
    
  }
  
}


Осторожно! Firefox замерзает на несколько секунд.
JSBIN ---> http://jsbin.com/ridibaye/1

Последний раз редактировалось melky, 08.07.2014 в 01:30.
Ответить с цитированием
  #33 (permalink)  
Старый 08.07.2014, 08:58
Аватар для kobezzza
Быдлокодер;)
Отправить личное сообщение для kobezzza Посмотреть профиль Найти все сообщения от kobezzza
 
Регистрация: 19.11.2010
Сообщений: 4,338

Цитата:
Эта функция 100% содержит хвосторекурсивный вызов. Если бы оптимизация была, этот код выполнялся бы бесконечно. Как видишь, никаких эвалов и прочих Function тут нет. Выполнение остановились на 25104
Попробуй на своей модной новейшей ноде, потом расскажешь. А пока я засчитываю тебе слив. В JS нет оптимизации хвостовой рекурсии.
Да, нет, но нет в том виде, как например в Lisp, т.е. полная замена хвостового вызова на цикл и поэтому у нас всегда есть ограничение в виде максимальной глубина стека вызова. Т.е. на уровне языка никаких стандартов про оптимизацию хвостовой рекурсии нет, НО

В современных VM JIT компиляторы неплохо оптимизируют такие виды рекурсий (уж не знаю что они там делают) и часто получается, что рекурсивная форма работает также быстро как и pure цикл, но ограничение стека по прежнему есть.

Пожалуй я не правильно выразил свою мысль, когда говорил про оптимизацию.

(Однако следует заметить, что настоящая оптимизация хвостовой рекурсии добавлена в стандарт ES6 и будет работать с флагом 'use strict')

***

Я всё жду когда ты мне дашь код паттерна "примесь" на циклах и докажешь, что та простыня кода очевиднее и лучше рекурсии Только не надо рассказывать, что "раз мы юзаем рекурсии, то не юзаем циклы". Для любой задачи поиска в глубину рекурсия самое простое, короткое и очевидное решение.

И вообще я спорю не про то, что рекурсия лучше или быстрее цикла (очевидно, что цикл потенциально позволит написать более оптимальный код), а про то, что есть пласт задач, которые рекурсивно решаются очень просто, а при решении одними циклами, то нам придётся городить лес дополнительных инструкций и в большинстве случаев это лишнее. Но при этом я не отказываюсь от циклов, а юзаю всё вместе, когда это удобно и делает код нагляднее, а язык позволяет так делать.

Пример я уже приводил:

removeFolder(cat) {
    var dir = readdir(cat);

    for (var i = 0; i < dir.length; i++) {
        if (isFile(dir[i])) {
            unlink(dir[i]);
        } else {
            removeFolder(dir[i]);
        }
    }

    rmdir(cat);
}


Мне трудно представить ситуацию, когда количество вложенных папок приведёт к переполнению стека и придётся этот код переписывать
__________________
kobezzza
code monkey

Последний раз редактировалось kobezzza, 08.07.2014 в 20:57.
Ответить с цитированием
  #34 (permalink)  
Старый 08.07.2014, 18:33
foo foo вне форума
Профессор
Отправить личное сообщение для foo Посмотреть профиль Найти все сообщения от foo
 
Регистрация: 17.05.2014
Сообщений: 197

Сообщение от kobezzza
дашь код паттерна "примесь" на циклах и докажешь, что та простыня кода очевиднее
Я, честно говоря, плохо язык знаю, я еще даже толком не въехал до конца в примеси, но я постараюсь, как время будет.
Я начал читать твой код, и, попутно вопрос возник. Ты там клонируешь объект
Код:
Collection.clone = function (obj) {
return JSON.parse(JSON.stringify(obj));
};
Но ведь он так не клонируется с прототипами? Нахрена так делать? Ведь это же "ненастоящее" клонирование, ты так объект не получишь. А в прототипах может быть 99% объекта, ты их выкидываешь. Это противоречит идеологии языка, имхо.
Ответить с цитированием
  #35 (permalink)  
Старый 08.07.2014, 19:21
Аватар для kobezzza
Быдлокодер;)
Отправить личное сообщение для kobezzza Посмотреть профиль Найти все сообщения от kobezzza
 
Регистрация: 19.11.2010
Сообщений: 4,338

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

Настоящие клонирования может сделать extend (тут уже я переписал на рекурсию с циклов, т.к. в последних VM профита уже не стало, а код стал реально понятнее и проще).

// Полное клонирование объекта a
var b = Collection.extend({deep: true, withProto: true, withAccessors: true}, {}, a)


Тут тебе и клонирование прототипов, аксессоров, штрихи, примеси и т.д.
__________________
kobezzza
code monkey

Последний раз редактировалось kobezzza, 08.07.2014 в 19:29.
Ответить с цитированием
  #36 (permalink)  
Старый 08.07.2014, 19:54
foo foo вне форума
Профессор
Отправить личное сообщение для foo Посмотреть профиль Найти все сообщения от foo
 
Регистрация: 17.05.2014
Сообщений: 197

kobezzza,
А там у тебя let используется. Это же не часть стандарта насколько я понял? Зачем ты используешь let? чем тебя не устраивают var? Это же тоже самое, насколько я понимаю? Или есть разница?
Ответить с цитированием
  #37 (permalink)  
Старый 08.07.2014, 20:00
Аватар для Erolast
Профессор
Отправить личное сообщение для Erolast Посмотреть профиль Найти все сообщения от Erolast
 
Регистрация: 24.09.2013
Сообщений: 1,436

let - это часть ES6. И отличается он от var тем, что объявляет переменные с блочной областью видимости.
Ответить с цитированием
  #38 (permalink)  
Старый 08.07.2014, 20:04
Аватар для kobezzza
Быдлокодер;)
Отправить личное сообщение для kobezzza Посмотреть профиль Найти все сообщения от kobezzza
 
Регистрация: 19.11.2010
Сообщений: 4,338

Вот для сравнения сейчас накалякал на коленке: функция удаления непустой папки (которая может содержать вложенные папки и т.д.)

С рекурсией: - 13 строк

function removeFolder(cat) {
    var dir = readdir(cat);

    for (var i = 0; i < dir.length; i++) {
        if (isFile(dir[i])) {
            unlink(dir[i]);
        } else {
            removeFolder(dir[i]);
        }
    }

    rmdir(cat);
}


Без рекурсии: - 35 строк

function removeFolder(cat) {
    var dir = readdir(cat),
        stack = [];

    for (var i = 0; i < dir.length; i++) {
        if (isFile(dir[i])) {
            unlink(dir[i]);
        
        } else {
            stack.push({
                i: i,
                dir: dir,
                cat: cat
            });
            
            cat = dir[i];
            dir = readdir(cat);
            i = -1;
            
            continue;
        }
        
        if (i === dir.length - 1 && stack.length) {
            rmdir(cat);
            var last = stack.pop();
            
            cat = last.cat;
            dir = last.dir;
            
            i = last.i;
        }
    }

    rmdir(cat);
}


Вариант на одних циклах в 2.5 раза больше, понять его сложнее и сложнее модифицировать.
Мне кажется это самоочевидно, я даже не понимаю о чём тут можно спорить.

Конечно, когда у нас хвостовая рекурсия, то её с оптимизировать можно проще, т.к. не нужно создавать стек, но это уже частный случай.
__________________
kobezzza
code monkey

Последний раз редактировалось kobezzza, 08.07.2014 в 20:12.
Ответить с цитированием
  #39 (permalink)  
Старый 08.07.2014, 20:06
Аватар для kobezzza
Быдлокодер;)
Отправить личное сообщение для kobezzza Посмотреть профиль Найти все сообщения от kobezzza
 
Регистрация: 19.11.2010
Сообщений: 4,338

Сообщение от foo Посмотреть сообщение
kobezzza,
А там у тебя let используется. Это же не часть стандарта насколько я понял? Зачем ты используешь let? чем тебя не устраивают var? Это же тоже самое, насколько я понимаю? Или есть разница?
Я пишу на новом стандарте ES6 и использую транслятор в ES5.
let - это переменная с блочной видимостью, а var с функциональной.

if (1) {
    let a = 1;
}
a // a is not defined
__________________
kobezzza
code monkey
Ответить с цитированием
  #40 (permalink)  
Старый 08.07.2014, 20:16
foo foo вне форума
Профессор
Отправить личное сообщение для foo Посмотреть профиль Найти все сообщения от foo
 
Регистрация: 17.05.2014
Сообщений: 197

Сообщение от kobezzza
et - это переменная с блочной видимостью, а var с функциональной.
Нахрен надо язык усложнять. что трудно в функцию обернуть чтоли? И так язык в посмешище превратили. А тут и еще одна неоднозначность появляется. В большинстве языков, насколько я помню, лет -- это как раз таки лексическое замыкание. По идее, лет с вар логично было бы поменять. Цирк да и только
Ответить с цитированием
Ответ



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

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


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Javascript чат-бот FanAizu Общие вопросы Javascript 5 30.01.2014 03:00
Цикл завешивает страницу, помогите Romingood jQuery 5 19.10.2013 14:30
подключать jquery-ui.custom.js или jquery-ui.custom.min.js? Faab jQuery 4 11.10.2013 20:53
Кастомный селект, чекбокс, радио vostok Ваши сайты и скрипты 0 12.08.2013 00:33
В зависимости от referrer выводить рекламу adsene или зорьки wlad2 Общие вопросы Javascript 12 19.12.2010 01:02