Отслеживание реализации функции для нахождения значения sine

#javascript

#javascript

Вопрос:

Я читаю SICP в javascript и упражнение для нахождения приближения синуса:

 function abs(x) {
    return x >= 0 ? x : -x;
}

function cube(x) {
    return x * x * x;
}
function p(x) {
    return 3 * x - 4 * cube(x);
}
function sine(angle) {
    return !(abs(angle) > 0.1)
           ? angle
           : p(sine(angle / 3));//p for procedure
}
 

запустите его и получите:

 > sine(1.57)
0.9999999959705563
> sine(3.14/6)
0.5000259145195963
 

Как я мог бы отследить выполнение sine(1.57), как это делается в scheme?

 > (trace sine)
> (sine 1.57)
|(sine 1.57)
| (sine 0.5233333333333333)
| |(sine 0.17444444444444443)
| | (sine 0.05814814814814814)
| | 0.05814814814814814
| |0.17365800071127369
| 0.5000259145195963
|0.9999999959705563
0.9999999959705563
 

Комментарии:

1. Где вы запускаете этот код? Я почти уверен, что существует множество отладчиков Javascript, и в этом случае вы можете просто установить точку останова и выполнить пошаговое выполнение.

Ответ №1:

Получите возвращаемое значение в переменной и распечатайте его. Вы можете использовать необязательные параметры для определения уровня намерения

 function abs(x) {
    return x >= 0 ? x : -x;
}

function cube(x) {
    return x * x * x;
}
function p(x) {
    return 3 * x - 4 * cube(x);
}
function sine(angle, showTrace = false, indentationLevel = 1) {
  const indentString = Array(indentationLevel).fill('|').join(' ');
    console.log(indentString, `sine(${angle})`);
  const returnValue = !(abs(angle) > 0.1)
           ? angle
           : p(sine(angle / 3, showTrace, indentationLevel   1));//p for procedure
    console.log(indentString, returnValue);
    return returnValue;
}

console.log(sine(1.57, true)); 

Ответ №2:

Встроенной trace функции нет, но ее можно реализовать с помощью механизма исправления ошибок (который, вероятно, похож на то, как это обычно делается в Lisp).

 const traced_functions = {};

function trace(funcname) {
  if (funcname in traced_functions) {
    console.log(`${functioname} is already being traced.`);
    return;
  }
  traced_functions[funcname] = {
    orig: window[funcname],
    depth: 0
  };

  window[funcname] = function(...args) {
    traced_functions[funcname].depth  ;
    let prefix = Array(traced_functions[funcname].depth).fill('|').join('');
    console.log(`${prefix}${funcname}(${args.join(', ')})`);
    let result = traced_functions[funcname].orig(...args);
    console.log(`${prefix}= ${result}`);
    traced_functions[funcname].depth--;
    return resu<
  }
}

function untrace(funcname) {
  if (funcname in traced_functions) {
    window[funcname] = traced_functions[funcname].orig;
  } else {
    console.log(`${funcname} is not traced`);
  }
}

function abs(x) {
  return x >= 0 ? x : -x;
}

function cube(x) {
  return x * x * x;
}

function p(x) {
  return 3 * x - 4 * cube(x);
}

function sine(angle) {
  return !(abs(angle) > 0.1) ?
    angle :
    p(sine(angle / 3)); //p for procedure
}

trace('sine');
sine(1.57); 

Это работает только для глобальных функций, поскольку для этого требуется, чтобы имя функции было эквивалентно window[funcname] .

Комментарии:

1. Это здорово, вы динамически переписываете функцию и копируете исходную?

2. Это довольно умно, я не знал этого шаблона, спасибо