从左到右语言语法的优点


18

我一直在Channel9上观看Herb Sutter的一次采访,他在视频的结尾提到,对于将来的C ++标准,从左到右的语言语法将是他的愿望清单上的第一名(尽管他承认以这种方式修改C ++会造出完全不同的野兽)。

除了:

  • 人类更容易理解,肉眼更清晰;例如

    //C syntax
    
    /*pointer to function taking a pointer to function(which takes 2 integers as 
    
    arguments and returns an int), and an int as arguments and returning an int*/
    
    int (*fp)(int (*ff)(int x, int y), int b)
    
    //Go analogous syntax which is left to write
    
    f func(func(int,int) int, int) int
  • 易于解析(如视频中所述,可提供更好的工具支持-例如代码重构)

编程语言中的“从左到右”语法还有什么其他优点。我只知道采用这种语法的Pascal和Go(根据我从这篇博客中获得的例子,Go甚至还没有完全理解),使用这种系统编程语言是否可行?语法?


1
haskell从左到右使用:f :: (Int -> Int -> Int) -> Int -> Int
Karoly Horvath 2011年

1
以及ActionScript :function strlen(s:String):int {...}。此外,键入lambda演算(因此,Haskell)。
2011年

2
谁能解释一下闭幕投票:)?我看不到有任何理由关闭它,但也许我在问一个“错误”的问题。

1
我没有投票关闭,但是@Devjosh的评论很有意义,它对于程序员更合适,希望有人能移植它。...– 2011
Nim,

3
@Frank:并且不要忘记,对于函数指针,语法会很尴尬,因为实际类型是split!这是一个
沉重的

Answers:


12

基本优点是解析更简单,唯一。请注意,在解析该行之后,编译器将知道确切的类型是什么,因此从那以后,如何定义类型是无关紧要的。

当前返回数组类型或函数指针类型参数的任何函数都很难读取:

// common way of obtaining the static size in elements of an array:
template <typename T, int N>
char (&array_size_impl( T (&)[N] ))[N];
// alternative parser:
template <typename T, int N>               // this would probably be changed also
array_simple_impl function( T [N] & ) char [N] &;

而且,误解的可能性将会降低(因为最令人烦恼的分析):

// Current C++
type x( another_type() );      // create an instance x of type passing a
                               // default constructed another_type temporary?
                               // or declare a function x that returns type and takes as argument
                               // a function that has no arguments and returns another_type
// How the compiler reads it:
x function( function() another_type ) type;

// What many people mean:
x type { another_type{} };

使用类似的方法在C ++ 0x中进行统一初始化(即{}识别初始化)。请注意,使用从左到右的方法可以更清楚地定义我们的定义。过去(不止一次),很多人(肯定是我)在任何时候都被这种解析错误所咬,而从左到右的语法却并非如此。


表情怎么样?这种“从左到右的语法”将如何影响运算符的优先级和求值顺序?

1
@celavek:如果您返回面试,您会注意到他不想更改语言的整个语法,只需更改声明 s和定义 s。当然,这可能会渗透到其他表达式中,我不太确定上面示例中的最后一行是正确的从左到右(考虑临时文件的创建方式,可能需要在C#中进行更改...)由给二语义的解决new操作者structclass,这是不适用于C ++如在C ++有上值/参考类型没有区别。
大卫罗德里格斯- dribeas

5

我们如何来到这里

声明功能点的C语法旨在反映用法。考虑如下的常规函数​​声明<math.h>

double round(double number);

要获得一个点变量,您可以使用

fp = round;

您需要以fp这种方式声明该点变量:

double (*fp)(double number);

因此,您所要做的就是查看如何使用该函数,并使用指针引用将该函数的名称替换round*fp。但是,您需要额外的paren集,有人会说这使它更加混乱。

可以说,这在原始C语言中更容易了,它甚至没有函数签名,但是让我们不要回到那里了,好吗?

变得特别讨厌的地方是弄清楚如何声明一个函数,该函数要么作为参数,要么返回指向函数的指针,或两者兼而有之。

如果您具有功能:

void myhandler(int signo);

您可以通过以下方式将其传递给信号函数(3):

signal(SIGHUP, myhandler);

或者如果您想保留旧的处理程序,则

old_handler = signal(SIGHUP, new_handler);

这很容易。使声明正确是一件很容易的事情-也不是很漂亮,也不是很容易。

signal(int signo, ???)

好了,您只需返回函数声明,然后将名称交换为点引用即可:

signal(int sendsig, void (*hisfunc)(int gotsig));

由于您未声明gotsig,如果省略以下内容,可能会更易于阅读:

signal(int sendsig, void (*hisfunc)(int));

或者可能不是。:(

除了那还不够好,因为signal(3)还返回旧的处理程序,如下所示:

old_handler = signal(SIGHUP, new_handler);

因此,现在您必须弄清楚如何声明所有这些内容。

void (*old_handler)(int gotsig);

对于您要分配给的变量就足够了。请注意,您实际上并没有gotsig在这里声明old_handler。这样就足够了:

void (*old_handler)(int);

这使我们对signal(3)有了正确的定义:

void (*signal(int signo, void (*handler)(int)))(int);

救援的Typedef

到这个时候,我想每个人都会同意那是一团糟。有时候,最好为抽象命名。经常,真的。有了权利typedef,这将变得更容易理解:

typedef void (*sig_t) (int);

现在您自己的处理程序变量变为

sig_t old_handler, new_handler;

并且您对signal(3)的声明变为

sig_t signal(int signo, sig_t handler);

突然之间就可以理解了。消除*也消除了一些令人困惑的括号(他们说括号总是使事情更容易理解-哈!)。您的用法仍然相同:

old_handler = signal(SIGHUP, new_handler);

但现在您有机会了解,的声明old_handlernew_handler甚至signal当您初次遇到它们或需要编写它们时也是如此。

结论

少数的C ++程序员,事实证明,能够制定这些东西对自己正确的声明没有咨询的参考材料。

我知道,因为我们曾经在面试问题中遇到这个问题,专门针对从事内核和设备驱动程序工作的人员。:)当然,当他们在白板上崩溃并被烧死时,我们就失去了很多候选人。但是我们也避免雇用那些声称自己在该领域有过经验但实际上无法完成工作的人员。

但是,由于存在这种普遍的困难,有一种方法来处理所有不再需要您成为三位字母的怪胎程序员的方法,而不是明智的做法,而且确实合理,因为要使用此方法,其平均值要高出三个西格码。有点舒服。


1
做作,很难跟随... +1所付出的努力,虽然,因为它说明了一点,它有时很难得到C.该权利
celavek

4

我认为当您专注于从左到右时,您可能会错失一点。

C和C ++的问题是它们所具有的可怕语法,难以同时阅读(人类)和解析(工具)。

具有更一致的(或常规的)语法可以使两者都更容易。更轻松的解析意味着更轻松的工具:大多数当前的工具都无法正确使用C ++,甚至连最新的Eclipse插件也无法正确使用,因为它们试图重塑方向……但失败了,而且他们可能比普通的OS项目拥有更多的人才。

因此,在专注于阅读和解析时,您可能会钉上它……这很重要:)


这让Eclipse仍然无法解析上面的声明之类的东西感到非常惊讶。他们为什么不使用像from这样的真实C解析器gcc
tchrist 2011年

@tchrist:我已经发现了Eclipse的两个问题,而且两个问题似乎都与宏有关。因此,可能比AST一代更多的是预处理器问题。
Matthieu M.
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.