gpt4 book ai didi

Javascript 函数消失

转载 作者:太空宇宙 更新时间:2023-11-03 18:47:59 25 4
gpt4 key购买 nike

我正在尝试使用 JavaScript 作为源语言来实现编程语言 LISP 的一小部分。当这个小 lisp 被喂食一个看起来像这样的字符串时:

(define func (lambda (args)(body)))

然后将其传递给名为 CreateLambda 的函数。例如,正在传递以下字符串:

(define add (lambda(x y)(+ x y)))

然后由该函数创建一个 Javascript 函数;

function createLambda(expr, env) { // lambda args body
expr.shift(); //remove the "lambda".
var lambdaArgs = expr.shift(); //get the arguments
var lambdaBody = expr.shift(); // get the body
var parentEnvironment = env;
return function() {
var lambdaEnvironment = new environment(parentEnvironment, "lambda environment");
for(var i = 0; i < arguments.length; i++) {
var tempVal = evaluate(arguments[i], parentEnvironment);
lambdaEnvironment.add(lambdaArgs[i], tempVal);
}
return evaluate(lambdaBody, lambdaEnvironment);
}
}

稍后,如果在 small lisp 中调用和评估此函数,则如下所示:

(add 2 3)

这个字符串在看起来像这样的情况下被评估循环拾取:

else if(typeof expr[0] === 'string') {
var lispFunc = env.get(expr[0]); //find the function in the environment.
expr.shift();
var lispFuncArgs = [];
var tempArg = expr.shift();
while(tempArg != null) { //apply the variables
lispFuncArgs.push(evaluate(tempArg, env));
tempArg = expr.shift();
}
return lispFunc.apply(this, lispFuncArgs);

第一次将它传递给评估函数时,它按预期工作并返回数字 5。

但是,如果再次调用同一个函数。它仅作为“未定义”进入评估循环。

完整的 HTML;

<html>
<head>
<meta content="text/html; charset=UTF-8" http-equiv="Content-Script-
Type" content="text/javascript">
<title>LISP in JavaScript</title>
<script type="text/javascript" src="lisp.js"></script>
</head>
<body>
<form id="repl" name="repl" action="parse(prompt.value)">
lisp==&gt;
<input id="prompt" size="200" value="" name="prompt"
maxlength="512">
<br>
<input type=button style="width:60px;height:30px" name="btnEval"
value="eval" onclick="output(prompt.value)">
<br>
</form>
<div id="debugdiv" style="background-
color:orange;width=100px;height=20px">
</div>

</body>
</html>

完整的 JavaScript;

//functions for parsing input String

function parse(exp) {
return readFromTokes(tokenize(exp)); //code
}

function isNumeric(arg) {
return !isNaN(arg);
}

function readFromTokes(exp) {
//Create abstract syntax tree
if(exp.length == 0) {
}
var token = exp.shift();
if(token == '(') {
var L = [];
while(exp[0] != ')') {
L.push(readFromTokes(exp));
}
exp.shift(); //remove end paranthesis
return L;
} else {
if(token == ')') {
console.log("Unexpected )");
} else {
return atom(token);
}
}
}

function tokenize(exp) {
//Convert a program in form of a string into an array (list)
var re = /\(/g;
var re2 = /\)/g;
exp = exp.replace(re, " ( ");
exp = exp.replace(re2, " ) ");
exp = exp.replace(/\s+/g, ' ');
exp = exp.trim().split(" ");
return exp;
}

function atom(exp){
if(isNumeric(exp)) {
return parseInt(exp); //A number is a number
} else {
return exp; //Everything else is a symbol
}
}

function environment(parentEnvironment, name) {
var bindings = [];
var parent = parentEnvironment;
var name = name;

function add(variable, value) {
console.log("variable: " + variable + " value: " + value);
bindings.push([variable, value]);
}

function printName() {
console.log(name);
}

function print() {
console.log("printing environment: ")
for(var i = 0; i < bindings.length; i++) {
console.log(bindings[i][0] + " " + bindings[i][1]);
}
}

function get(variable) {
for(var i = 0; i < bindings.length; i++) {
if(variable == bindings[i][0]) {
return bindings[i][1];
}
}
if(parent != null) {
return parent.get(variable);
} else {
console.log("No such variable");
}
}

function getParent(){
return parent;
}

this.add = add;
this.get = get;
this.getParent = getParent;
this.print = print;
this.printName = printName;
return this;
}

function addPrimitives(env) {
env.add("+", function() {
var s = 0;
for(var i = 0; i < arguments.length; i++) {
s += arguments[i];
}
return s
});
env.add("-", function() {
var s = arguments[0];
for(var i = 1; i < arguments.length; i++) {
s -= arguments[i];
}
return s
});
env.add("*", function() {
var s = 1;
for(var i = 0; i < arguments.length; i++){
s *= arguments[i];
}
return s
});
env.add("/", function(x, y) { return x / y });
}


function createLambda(expr, env) { // lambda args body
expr.shift(); //remove the "lambda".
var lambdaArgs = expr.shift(); //get the arguments
var lambdaBody = expr.shift(); // get the body
var parentEnvironment = env;
return function() {
var lambdaEnvironment = new environment(parentEnvironment, "lambda
environment");
for(var i = 0; i < arguments.length; i++) {
var tempVal = evaluate(arguments[i], parentEnvironment);
lambdaEnvironment.add(lambdaArgs[i], tempVal);
}
return evaluate(lambdaBody, lambdaEnvironment);
}
}

function evaluate(expr, env) {
console.log(expr + " has entered evaluate loop");
env.printName();
env.print();
if(typeof expr === 'string') {
console.log(expr + " is a symbol");
return env.get(expr);
} else if(typeof expr === 'number') {
console.log(expr + " is a number");
return expr;
} else if(expr[0] === 'define') { // (define var value)
console.log(expr + " is a define statement");
expr.shift();
var newVar = expr.shift();
var newVal = evaluate(expr.shift(), env);
env.add(newVar, newVal);
return env;
} else if (expr[0] === 'lambda') { // (lambda args body)
console.log(expr + " is a lambda statement");
return createLambda(expr, env);
} else if (typeof expr[0] === 'string'){
var lispFunc = env.get(expr[0]);
expr.shift();
var lispFuncArgs = [];
var tempArg = expr.shift();
while(tempArg != null) {
lispFuncArgs.push(evaluate(tempArg, env));
tempArg = expr.shift();
}
console.log("Function: " + lispFunc);
console.log("Arguments: " + lispFuncArgs);
return lispFunc.apply(this, lispFuncArgs);
} else {
console.log(expr + " cannot be interpreted");
}
}


var globalEnvironment = new environment(null, "Global");

addPrimitives(globalEnvironment);

function start(string) {
return evaluate(parse(string), globalEnvironment);
}

var output = function (string) {
try {
document.getElementById('debugdiv').innerHTML = start(string);
} catch(e) {
document.getElementById('debugdiv').innerHTML = e.name + ': ' + e.message;
}
};

最佳答案

这是因为您的代码中存在一个小错误。当您在第 134 行调用 evaluate(lambdaBody, lambdaEnvironment) 时,您提供 lambdaBody 作为第一个参数,即 expr 参数'function evaluate(expr, env)' 函数(第 138 行)。在评估期间,您使用 tempArg = expr.shift(); 函数使用它,并在它为空时退出循环。不幸的是,您的 lambdaBody 第二次是一个空数组。

要修复它,您应该更改求值函数而不是修改它的参数(例如,创建一个副本并使用该副本)


我建议您修复评估函数中的错误,但真正有效的示例是将第 134 行更改为深度复制 lambdaBody,如下所示:

  evaluate(lambdaBody.slice(0), lambdaEnvironment);

无论调用多少次,您都会发现它现在可以正常工作。但该错误实际上在评估函数内部,因此请在那里修复它。

关于Javascript 函数消失,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47778271/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com