Pull to refresh

Comments 14

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

val valid_a = ['object', 'string', 'number']
val valid_b = valid_a
val valid_c = ['string', 'undefined']

//список всех возможных валидных троек для параметров
val tuples = decartMultiplication(valid_a, valid_b, valid_c, (a, b, c) -> Tuple3(a, b, c))

val dispatchMap = Map<Tuple3, Closure>
tuples.forEach(tuple -> dispatchMap.put(tuple, (a, b, c) -> call_function(a, b, c))

//usage
val dispatcher = dispatchMap.get(Tuple3(a.type, b.type, c.type))

if (dispatcher != null) dispatcher(a, b, c) else call_badargs(a, b, c)

Вкратце, делаем ассоциативный массив [множество типов аргументов] -> лямбда
Плюсы — мало букв. Минусы — кол-во элементов в мапе растет весьма быстро.
тут была одна особенность, если аргумент не определен, то это вызывает синтаксическую ошибку при попытке передать его в функцию, но typeof определяет его тип:
//x не существует
test_func(x) //ReferenceError: x is not defined
typeof x //'undefined'
не синтаксическую, описался
UFO just landed and posted this here
Про память — сейчас добавлю.
Взятие по индексу — точно быстрее, чем последовательный перебор 'else if'-ами. Cомнение вызывает indexOf, но можно обойтись без него и, он как минимум пропорционален числу условий, а может и быстрее. Поиск в хеш-мапе приблизительно O(1), за исключением коллизий, — тут зависит от реализации. Хотя, была ситуация: поиск по длинным строкам в качестве ключа жутко тормозил, пришлось сначала искать по числовому хешу от строки(вычисление которого, впрочем, также вписывается в этот подход). Что касается вычислений, то возведение в целую степень также может быть линейным, но такие алгоритмы врядли еще где остались. Однако, завершения вычисления 50-го число фибоначчи рекурсивным алгоритмом не дождался(отчасти поэтому не включил код в статью), а для индексного результат был без задержки. По-хорошему, конечно, надо бы сделать замеры скорости, но для простых формул — это не актуально. Итого, ответ — возможно, но только для неоптимизированных вариантов: как вы правильно заметили, расходуется дополнительная память, — мы преобразуем временную сложность в пространственную.
UFO just landed and posted this here
Время от времени применяю на практике уже лет 25 (правда, не знал как это называется), но обычно только в случаях хорошо ложащихся на классические массивы, когда разворачивание в условные операторы реально является тупой копипастой, когда условия N-го уровня повторяются каждом N-1 уровне, да ещё являются четко дискретными.
Называется это «табличный метод». Code Complete, второе издание, 18 глава.
спасибо, добавлю упоминание в конец статьи
var type = typeof a + typeof b + typeof c,
    callback = {
       "objectobjectstring": process,
       "objectobjectundefined": process,
       "objectstringstring": process,
       "objectstringundefined": process,
       "objectnumberstring": process,
       "objectnumberundefined": process,
       "stringobjectstring": process,
       "stringobjectundefined": process,
       "stringstringstring": process,
       "stringstringundefined": process,
       "stringnumberstring": process,
       "stringnumberundefined": process,
       "numberobjectstring": process,
       "numberobjectundefined": process,
       "numberstringstring": process,
       "numberstringundefined": process,
       "numbernumberstring": process,
       "numbernumberundefined": process
    }[type] || process;

callback && callback(a, b, c);
var type = typeof a + typeof b + typeof c;

({
   "objectobjectstring": process,
   "objectobjectundefined": process,
   "objectstringstring": process,
   "objectstringundefined": process,
   "objectnumberstring": process,
   "objectnumberundefined": process,
   "stringobjectstring": process,
   "stringobjectundefined": process,
   "stringstringstring": process,
   "stringstringundefined": process,
   "stringnumberstring": process,
   "stringnumberundefined": process,
   "numberobjectstring": process,
   "numberobjectundefined": process,
   "numberstringstring": process,
   "numberstringundefined": process,
   "numbernumberstring": process,
   "numbernumberundefined": process
}[type] || process)(a, b, c);
var type = (typeof a)[0] + (typeof b)[0] + (typeof c)[0];

({
   "oos": process,
   "oou": process,
   "oss": process,
   "osu": process,
   "ons": process,
   "onu": process,
   "sos": process,
   "sou": process,
   "sss": process,
   "ssu": process,
   "sns": process,
   "snu": process,
   "nos": process,
   "nou": process,
   "nss": process,
   "nsu": process,
   "nns": process,
   "nnu": process
}[type] || process)(a, b, c);
Обычно составные ключи разделяю подчеркиванием:
var type = typeof a + '_' + typeof b + '_' + typeof c,
    callback = {
       "object_object_string": process,
       "object_object_undefined": process,
       ...
Sign up to leave a comment.

Articles