-
Notifications
You must be signed in to change notification settings - Fork 21
两种函数语法(fn)和(箭头=>)同时存在。有不同吗?你选哪一个? #13
Comments
两种函数语法应该说没有太大区别。在 使用 let x = (a, b) => a + b
printf("x(1,2)=%d\n", x(1,2)) //Output: x(1,2)=3 let x = fn(a, b) { a + b }
printf("x(1,2)=%d\n", x(1,2)) //Output: x(1,2)=3 但是使用 let complex = {
"add" :(x, y) => (z) => x + y + z, // function returns a closure
"sub" : (x, y) => x - y ,
}
println(complex["add"](1,2)(3)) // Output: 6
println(complex["sub"](10, 2)) // Output: 8 let complex = {
"add" : fn(x, y) { return fn(z) { x + y + z } }, // function returns a closure
"sub" : fn(x, y) { x - y },
}
println(complex["add"](1,2)(3)) // Output: 6
println(complex["sub"](10, 2)) // Output: 8
如果一定要说用哪一个好的话,我想每个人都有自己的想法。但是总体的原则大致如下:
|
感谢分享。 我认为你的原则很有参考价值,但是我认为例子中影响可读性的是运算优先级,如果加上花括号看起来也会很好。
我认为这个例子中内在的问题是:自由度大就会有人写出更晦涩的代码。 其实原题想问的是,有没有类似javascript上的两种函数的问题。
|
这里出错的原因是,我将所有let声明的变量作为一个类的Member变量,而非Method了。更改的话,只需要将 具体更改如下: // parser.go的parseClassLiteral函数的部分实现:
cls.Block = p.parseClassBody(false)
for _, statement := range cls.Block.Statements {
switch s := statement.(type) {
case *ast.LetStatement: //class fields
// For simplicity, we need 'let' statement's Names and Values are the same length.
if len(s.Names) != len(s.Values) {
msg := fmt.Sprintf("Syntax Error:%v- In class, Let-Statement's Names and Values must have the same length.", s.Pos())
p.errors = append(p.errors, msg)
return nil
}
//The 'let' statment might define a FunctionLiteral, like below:
// let add = (x, y) => x + y
//so we need to treat it as a method
for idx, name := range s.Names {
value := s.Values[idx]
switch v := value.(type) {
case *ast.FunctionLiteral:
//If it's a FunctionLiteral, we need to treat it as a method.
FnStmt := &ast.FunctionStatement{Name: name, FunctionLiteral: v}
cls.Methods[name.Value] = FnStmt
default:
cls.Members = append(cls.Members, s)
}
} //end for
case *ast.FunctionStatement: //class methods
cls.Methods[s.Name.Value] = s
case *ast.PropertyDeclStmt: //properties
cls.Properties[s.Name.Value] = s
default:
msg := fmt.Sprintf("Syntax Error:%v- Only 'let' statement, 'function' statement and 'property' statement is allow in class definition.", s.Pos())
p.errors = append(p.errors, msg)
return nil
}
} 修改已经反映在最新上传的代码中。你可以下载最新的代码确认一下。 |
从新获取了一下,可以正常运行了。
还想讨论一下不带参数的成员方法调用问题。
这里想传递add函数本身作参数,代码是上符合直觉的。 我个人建议定义方法需要更特殊的语法,提示定义的是方法而不是普通字段,类似这样:
普通字段不要特殊处理更符合直觉。 这只是我的个人意见,你考虑一下。 |
如果我的理解没有错误的话,对于普通字段: class Calc {
let add = (x,y) => x + y ;
} 直接解析报告类似如下的错误:
关于定义方法需要特殊的语法,我认为这个建议也可以接受。不过这样的话,需要加入不少的代码。这个我会考虑。如果时间允许的话,考虑会加入此功能。 不过如果你能够贡献代码的话,非常欢迎您的 |
关于你说的“定义方法需要更特殊的语法”这一点,我有一个自认为更好的方法,就是在方法后面加'&'。像下面这样: class Calc {
let add = (x,y) => x + y ;
}
let c = new Calc();
let exec = (op,x,y) => op(x,y);
w = exec(c.add&,1,2); //注意add后面的'&'符号
printf("w=%d\n", w) 这样可能更易于理解(自我认为),而且代码改动量也比较小。代码我已经实现了,达到了预期的效果。 不过我需要再仔细考虑考虑是否有更好的解决办法。 但是代码暂时还没有上传,希望听听你的意见! |
对于你提到的在使用字段的时候用特殊语法,我的观点是:
看起来这个懒加载器是通用的,但是遇上函数就出问题了。
设计者不容易想到要写特殊语法 return this.value&,字段语法在使用时需要考虑是否可能存放函数。 我又回忆了其他语言在这方面,有参考的价值的的处理方式。 ruby中,访问对象成员只有一种形式,就是方法调用,
这种方式对于monkey已有的语法不兼容,monkey字段语法在外部是可以访问的。 javascript中,方法调用强制要加括号。 scala中,区分了方法和成员变量的定义语法。 希望你能选择一种合理的设计, 我乐意贡献代码,我也能借此学习你的经验。 |
谢谢你的思路,你说的很有道理。至于代码,你有任何不懂的地方,请随时联系我, 我也很乐意提供帮助。下面是我的邮箱地址:
|
No description provided.
The text was updated successfully, but these errors were encountered: