#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. Это довольно умно, я не знал этого шаблона, спасибо