为什么CoffeeScript在map之后需要空格?

为什么CoffeeScript在map之后需要空格?,coffeescript,Coffeescript,此代码 nums = [1..10].map (i) -> i*2 运行 鉴于此 nums = [1..10].map(i) -> i*2 已断开第二个中的映射(i)被解释为函数调用。JavaScript如下所示: var nums; nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map(i)(function() { return i * 2; }); var nums; nums = [1, 2, 3, 4, 5, 6, 7, 8,

此代码

nums = [1..10].map (i) -> i*2
运行

鉴于此

nums = [1..10].map(i) -> i*2
已断开

第二个中的
映射(i)
被解释为函数调用。JavaScript如下所示:

var nums;

nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map(i)(function() {
  return i * 2;
});
var nums;

nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map(function(i) {
  return i * 2;
});
这没有任何意义,因为
map
不返回函数,并且没有定义
i

在第一个函数中,空格将其转换为
[1..10].map((i)->i*2)
,因此您最终使用函数作为参数调用
map
;本例中的JavaScript如下所示:

var nums;

nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map(i)(function() {
  return i * 2;
});
var nums;

nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map(function(i) {
  return i * 2;
});

原因是函数调用(调用)的括号是可选的。我发现这在我自己的代码中是一个经常混淆的问题,并且有一个总的策略,总是包括括号来说明这一点

在coffee脚本中,如果省略括号,则假定参数列表位于行的末尾。您的第一个示例咖啡脚本实际上与此相同:

nums = [1..10].map((i) -> i*2)
其中调用map的第一个参数是一个函数
(i)->i*2

如果删除贴图和(i)之间的空格,则coffee脚本将在该行的其余部分包含括号。您的第二个示例咖啡脚本实际上与此相同:

nums = [1..10].map(i)(-> i*2)
在这里,您可以看到map是以
i
作为唯一参数调用的,然后coffee脚本希望
map(i)
调用返回一个函数,该函数随后被调用为传递
->i*2
或更明确的
()->i*2
作为参数


考虑到CoffeeScript是为了消除javascript潜在的编码危害而设计的,我认为如果他们没有包含这个隐含的括号,它会更安全。

我喜欢CoffeeScript。别误会我。。。但这种类型的空白问题让我感到厌烦。从可读性的角度来看,这似乎不重要。。。但确实如此。这就是为什么每当我发现这种模糊性时,我总是把它去掉,然后写:
map((I)->I*2)
,这样它就不会被意外地错误解释。我会比Brian更进一步,为了避免这类事情,我和我的团队决定不利用CoffeeScript的功能,不使用函数调用的paren。我在
if
子句和javascript要求谓词包装在paren中的其他地方省去了paren。但我对所有函数调用都使用它们。我写
()->
,而不仅仅是
->
。例如,我会像Brian一样编写它,
…map((I)->I*2)
;在我看来更具可读性。我不相信括号中的那些内部空格,我个人会这样写:
xs.map((x)->x*2)
。否则,我同意你们两人的看法,在编写DSL风格的代码时,无括号风格看起来很酷,但在编写“普通”代码时,最终会出现问题(例如,在Ruby中也会出现这种情况)。使用parenthenses还有另一个优点:您可以编写外观非常好的可连接Ruby风格的多行块(使用
,就像使用
end
s一样)。@tokland:我也发现缺少显式的close block标记有问题,特别是对于许多人坚持使用的两字符缩进。我倾向于将我的CS分解成微小的方法,以避免嵌套深度超过一个级别,回调也是如此,它们几乎总是被命名为方法,因为CS的块结构很快就会变得混乱。也许我只是个老古董,但我喜欢用牙套固定积木。