据我所知,有几个人可以,但不是任何一个受欢迎的人。嵌套评论有什么不好的地方吗?
我计划将块注释嵌套在我正在使用的(小)语言中,但是我想知道这是否是个坏主意。
据我所知,有几个人可以,但不是任何一个受欢迎的人。嵌套评论有什么不好的地方吗?
我计划将块注释嵌套在我正在使用的(小)语言中,但是我想知道这是否是个坏主意。
Answers:
还没有人提到一件事,所以我要提及:嵌套注释的愿望通常表明程序员做错了。
首先,让我们同意,程序员只能看到“嵌套”或“非嵌套”的时间是程序员编写如下结构的东西:
do_something();
/* comment /* nested comment */ more comment */
do_something_else();
现在,这种事情什么时候在实践中出现?当然,程序员是不会被写入嵌套评论说,从字面上看起来像上面的代码片段!不,实际上,当我们嵌套注释(或希望我们可以嵌套它们)时,这是因为我们要编写如下内容:
do_something(); /* do a thing */
/* [ajo] 2017-12-03 this turned out to be unnecessary
do_something_else(); /* do another thing */
*/
这是坏的。这不是我们(作为语言设计师)想要鼓励的模式!编写以上代码段的正确方法是:
do_something(); /* do a thing */
该“错误的”代码,该错误的开头或其他内容不属于代码库。它充其量属于源代码管理历史。理想情况下,您甚至永远都不会写错代码,对吗?而且,如果错误的代码在这里达到了目的,则可以通过警告维护人员出于某种原因而不要恢复它,那么,这可能是写得好且有意的代码注释的工作。仅仅留下一些可以做X但被注释掉的旧代码来表达“不要做X”,并不是阻止人们执行X的最易读或有效的方法。
所有这些都归结为您之前可能已经听说过的简单经验法则:不要注释掉代码。(搜索这句话会变成一个很大 的 意见 的 一致。)
在您提出以下要求之前:是的,诸如C,C#和C ++之类的语言已经为程序员提供了另一种 “注释”大型代码块的工具:#if 0
。但这只是C预处理程序的一种特殊应用,它本身就是一个庞大而有用的工具。要使一种语言支持条件编译,#if
而又不支持,实际上将是极其困难和特殊的#if 0
。
因此,我们确定嵌套注释仅在程序员注释掉代码时才相关。并且我们已经建立(通过许多有经验的程序员的共识),注释掉代码是一件坏事。
要完成三段论,我们必须接受语言设计者对推广“好事物”和阻止“坏事物”的兴趣(假设其他所有条件都相同)。
在嵌套注释的情况下,其他所有条件都是相同的-您可以放心地忽略那些低调的答案,这些答案声称解析嵌套/*
对于解析器而言将是“困难的”。(嵌套/*
并不比嵌套难,嵌套(
几乎是世界上每个解析器都需要处理的。)
因此,所有其他条件相同,应该在语言设计使它容易嵌套注释(即注释掉的代码),或难吗? 回想一下,注释掉代码是一件坏事。
优质教育
脚注。请注意,如果您不允许嵌套注释,则
hello /* foo*/bar.txt */ world
是一种误导性的“评论”,等同于
hello bar.txt */ world
(这很可能是语法错误)。但是,如果您确实允许嵌套评论,那么
hello /* foo/*.txt */ world
是一种误导性的“评论”,等同于
hello
但注释始终一直打开到文件末尾(这几乎肯定是语法错误)。因此,这两种方法都不太容易出现无意的语法错误。唯一的区别在于它们如何处理注释掉的代码的有意反模式。
#if DEAD
是规范的和最佳设计的示例。在许多语言中,您只需将无效代码包装为即可if (DEAD)
。在许多IDE中,您实际上可以删除无效的代码,并在需要时依靠Ctrl + Z和/或版本控制将其取回。留下注释,文档字符串,无论其文本是一堆无效代码,还是可读性最差的选择。
因为大多数实现都使用单独的词法分析和解析阶段,并且对于词法分析,它们使用的是普通的旧正则表达式。注释被视为空白-即忽略的标记,因此应完全在词法分析中解决。这种方法的唯一优点是解析速度。许多缺点包括语法上的严格限制(例如,需要维护一组固定的,与上下文无关的关键字)。
制作可以处理嵌套注释的词法分析器是完全有可能的。当它在吃空格时,看到/*
它可以增加一个深度计数器,当看到时可以减少它*/
,当深度为零时停止。也就是说,我已经完成了许多解析器,但从未找到嵌套注释的充分理由。
如果注释可以嵌套,则不利之处是很容易使它们的末端不平衡,并且除非您有高级编辑器,否则它会无形地隐藏您认为存在的代码。
不嵌套的注释的优点如下:
/*
some code
more code
blah blah blah
/**/
您可以在其中删除或添加第一行(一行编辑)来轻松地对代码进行注释或注释。当然,如果该代码本身包含注释,则除非您还允许//
在其中使用C ++样式的注释,否则这将中断。所以这就是我倾向于做的。
//
注释也是C99风格的。
/*$token
,其中identifier
任何字母数字标记为,注释结束为token$*/
。对于令牌生成器而言,包括代码以验证每个结尾注释标记是否包含与其匹配的起始注释块正确的令牌,将相对简单。
一个可能的原因是嵌套注释必须由解析器处理,因为词法分析器中常用的正则表达式不支持递归。lexer可以将简单的空格消除为空白,因此以这种方式实现起来更简单。