Как смоделировать выражения let в JavaScript?

1

Рассмотрим следующую реализацию take:

const take = (n, [x, ...xs]) =>
    n === 0 || x === undefined ?
    [] : [x, ...take(n - 1, xs)];

console.log(take(7, [1, 2, 3, 4, 5])); // [1, 2, 3, 4, 5]
console.log(take(3, [1, 2, 3, 4, 5])); // [1, 2, 3]
console.log(take(1, [undefined, 1]));  // []

Как вы можете видеть, он не работает для массивов с undefined потому что x === undefined не лучший способ проверить, пуст ли массив. Следующий код исправляет эту проблему:

const take = (n, xs) =>
    n === 0 || xs.length === 0 ?
    [] : [xs[0], ...take(n - 1, xs.slice(1))];

console.log(take(7, [1, 2, 3, 4, 5])); // [1, 2, 3, 4, 5]
console.log(take(3, [1, 2, 3, 4, 5])); // [1, 2, 3]
console.log(take(1, [undefined, 1]));  // [undefined]

Однако запись xs[0] и xs.slice(1) не такая элегантная. Кроме того, это проблематично, если вам нужно использовать их несколько раз. Либо вам придется дублировать код и выполнять лишнюю дополнительную работу, либо вам придется создавать область блока, определять константы и использовать ключевое слово return.

Лучшим решением было бы использовать выражение let. К сожалению, JavaScript их не имеет. Итак, как имитировать let выражения в JavaScript?

  • 2
    undefined - это реальное значение, но не часть разреженного массива с его использованием. реальный разреженный массив выглядит как [, 1] .
  • 0
    @NinaScholz NinaScholz А, понятно. У меня сложилось впечатление, что [, 1] и [undefined, 1] были эквивалентны, но, видимо, это не так. Спасибо, что дал мне знать.
Показать ещё 3 комментария
Теги:
ecmascript-6
functional-programming
let

1 ответ

3
Лучший ответ

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

(let ([x 1]
      [y 2])
  (+ x y))

; This is syntactic sugar for:

((lambda (x y)
    (+ x y))
  1 2)

В ES6 мы можем использовать функции стрелок и параметры по умолчанию для создания IIFE, который выглядит как выражение let следующим образом:

const z = ((x = 1, y = 2) => x + y)();

console.log(z);

С помощью этого хака, мы можем определить take следующим образом:

const take = (n, xxs) =>
    n === 0 || xxs.length === 0 ?
    [] : (([x, ...xs] = xxs) => [x, ...take(n - 1, xs)])();

console.log(take(7, [1, 2, 3, 4, 5])); // [1, 2, 3, 4, 5]
console.log(take(3, [1, 2, 3, 4, 5])); // [1, 2, 3]
console.log(take(1, [undefined, 1]));  // [undefined]

Надеюсь, это поможет.

  • 0
    Использование значений параметров по умолчанию - это то, что я считаю хаком :-)
  • 0
    Можно ли передать значения в качестве аргументов вместо использования параметров по умолчанию, нет?
Показать ещё 5 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню