为什么Crystal的宏语法在迭代方面与其他语言不同?

5

作为一个来自Ruby世界的人,我立即理解了为什么Crystal选择不实现for方法。但接着我惊讶地发现,Crystal为宏实现了for方法。更令我惊讶的是,宏不允许使用可枚举(.each等)语法(即{% ["one", "two", "three"].each do |value| %}不是有效的宏语法)。

这种语法差异是否有逻辑上的原因?答案可能只是"因为开发人员决定宏语法看起来像x,而非宏语法看起来像y",但我猜测一定还有其他原因(任意的语法不一致似乎是一个缺陷)。

谢谢!


我猜宏语法的目的是有些类似于像 Liquid 这样的模板引擎。 - Johannes Müller
@JohannesMüller 如果他们只是模仿一个现有的模板语言,难道不应该选择ERB吗?(这对我来说似乎是显而易见的,但也许并不明显?)也许他们试过像Regular Crystal Syntax这样的东西,但很难阅读。我非常好奇是否有任何思考过程的记录。 - John
我不确定它是否在最初的提案中发挥了作用,但是Crystal集成的ECR模板使用类似ERB的语法。如果将相同的语法用于宏,会令人困惑,并且无法在ECR文件中使用宏(虽然这不应该是一个好的实践,但是确实是可能的)。 - Johannes Müller
你应该提出一个关于更改这个的问题。我支持你提出的语法。至于回答你的历史问题,那就是Manas团队的事了。 - Stephie
1个回答

7
主要原因是当解析器解析foo.bar do |arg| ... end时,它期望在|arg|之后有一个表达式,而不是%},这是一个解析错误。因此,为了允许这样做��我们需要增强解析器(已经非常复杂)来考虑这一点。选择for是因为这个原因,还因为它能够清楚地表明这不仅仅是普通的crystal,而是一个不同的东西(它是crystal的解释子集和标准库)。
另一个原因是如果允许 each 和其他迭代方法,为什么不允许 whileuntil?这可能会允许宏中的无限循环,而仅使用 for 是不可能的,因此可以保证宏执行的完成性。但事实并非如此,因为我们在宏中使用了run
因此,我认为改变语言以允许在宏中使用eacheach_with_index等语法,并最终从宏语言中删除for,是可行的。提出请求来实现这一点是一个好的方向。

我已经为此创建了一个问题:https://github.com/crystal-lang/crystal/issues/5506。就个人而言,我不觉得自己有资格强烈推动任何方向,但我很想知道其他人对当前语法的看法。 - John

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接