The default value of the parameter is undefined; is this a javascript error?

The following is a syntactically active javascript program - only it does not behave as we expect. The title of the question should help your eyes zoom in. Problem area

const recur = (...args) =>
  ({ type: recur, args })

const loop = f =>
  {
    let acc = f ()
    while (acc.type === recur)
      acc = f (...acc.args)
    return acc
  }

const repeat = n => f => x =>
  loop ((n = n, f = f, x = x) => // The Problem Area
    n === 0
      ? x
      : recur (n - 1, f, f (x)))

console.time ('loop/recur')
console.log (repeat (1e6) (x => x + 1) (0))
console.timeEnd ('loop/recur')
// Error: Uncaught ReferenceError: n is not defined
Run codeHide result

If instead I use unique identifiers, the program works fine

const recur = (...args) =>
  ({ type: recur, args })

const loop = f =>
  {
    let acc = f ()
    while (acc.type === recur)
      acc = f (...acc.args)
    return acc
  }

const repeat = $n => $f => $x =>
  loop ((n = $n, f = $f, x = $x) =>
    n === 0
      ? x
      : recur (n - 1, f, f (x)))

console.time ('loop/recur')
console.log (repeat (1e6) (x => x + 1) (0)) // 1000000
console.timeEnd ('loop/recur')              // 24 ms
Run codeHide result

Only this does not make sense. Let's talk about source code that no longer uses $-prefixes.

loop, n, repeat, . n n shadow n. JavaScript , n undefined.

, , .

?

+4
1

, , . let. , n = n, ( undefined) n . , .

, Racket , Racket let letrec. . let . , . letrec . , .

letrec , let, let . Haskell, ( , let letrec). , , Haskell, let. , :

-- Inserts value into slot1 or slot2
insert :: (Bool, Bool, Bool) -> (Bool, Bool, Bool)
insert (slot1, slot2, value) =
    let (slot1', value')  = (slot1 || value,  slot1 && value)
        (slot2', value'') = (slot2 || value', slot2 && value')
    in  (slot1', slot2', value'')

let Haskell , :

-- Inserts value into slot1 or slot2
insert :: (Bool, Bool, Bool) -> (Bool, Bool, Bool)
insert (slot1, slot2, value) =
    let (slot1, value) = (slot1 || value, slot1 && value)
        (slot2, value) = (slot2 || value, slot2 && value)
    in  (slot1, slot2, value)

, Haskell ? , . , , , . , .

, . , , . , , . , , , , - , . , ( JavaScript) , .


, . , , . - , . - let. , Racket let - , - -. , :

(let ([x 5])
  (* x x))

let --:

((lambda (x) (* x x)) 5)

Haskell, (&):

import Data.Function ((&))

-- Inserts value into slot1 or slot2
insert :: (Bool, Bool, Bool) -> (Bool, Bool, Bool)
insert (slot1, slot2, value) =
    (slot1 || value, slot1 && value) & \(slot1, value) ->
    (slot2 || value, slot2 && value) & \(slot2, value) ->
    (slot1, slot2, value)

, "" let:

const recur = (...args) => ({ type: recur, args });

const loop = (args, f) => {
    let acc = f(...args);
    while (acc.type === recur)
        acc = f(...acc.args);
    return acc;
};

const repeat = n => f => x =>
    loop([n, f, x], (n, f, x) =>
        n === 0 ? x : recur (n - 1, f, f(x)));

console.time('loop/recur');
console.log(repeat(1e6)(x => x + 1)(0)); // 1000000
console.timeEnd('loop/recur');
Hide result

loop. loop (&) Haskell, . , Haskell:

import Prelude hiding (repeat)

data Recur r a = Recur r | Return a

loop :: r -> (r -> Recur r a) -> a
loop r f = case f r of
    Recur r  -> loop r f
    Return a -> a

repeat :: Int -> (a -> a) -> a -> a
repeat n f x = loop (n, f, x) (\(n, f, x) ->
    if n == 0 then Return x else Recur (n - 1, f, f x))

main :: IO ()
main = print $ repeat 1000000 (+1) 0

, let . , let, letrec, , . Haskell , .

+1

Source: https://habr.com/ru/post/1685377/


All Articles