王垠的几道思考题,你的回答是? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
darasion
V2EX    程序员

王垠的几道思考题,你的回答是?

  •  
  •   darasion 2013-03-15 23:25:55 +08:00 7277 次点击
    这是一个创建于 4590 天前的主题,其中的信息可能已经有所发展或是发生改变。
    http://blog.sina.com.cn/s/blog_5d90e82f0101j529.html

    先说我自己,
    两道思考题中提到的风格,是我比较喜欢的。

    第三道题,
    暂时不太懂,半路出家没学过理论。
    31 条回复    1970-01-01 08:00:00 +08:00
    tioover
        1
    tioover  
       2013-03-16 15:39:22 +08:00 via Android
    最后一题大概是:=
    Xrong
        2
    Xrong  
       2013-03-16 15:52:35 +08:00
    希望有人解释下第二题,语义上感觉一样啊
    Alex_L
        3
    Alex_L  
       2013-03-16 16:55:25 +08:00 via iPad
    @tioover := 有什么问题?
    volCANo
        4
    volCANo  
       2013-03-17 11:56:54 +08:00
    @Xrong 我觉得第二道题这么改的意义在于:
    不管这个方法的逻辑是怎样,是必须保证要有return的。
    所以在你程序逻辑之外(if else),你需要有return。
    y
        5
    y  
       2013-03-17 12:31:57 +08:00
    @tioover += 也是一个吧。
    alexrezit
        6
    alexrezit  
       2013-03-17 12:37:47 +08:00   1
    1. 加上花括号是个好习惯;

    2. 在某些编译器的默认设置里, 这样的结构是要给出一个 warning 的:
    myFreakyFunction {
    if (what) { return oo; }
    else { return xx; }
    }
    必须要写成这样来消除这个 warning:
    myFreakyFunction {
    if (what) { return oo; }
    else { return xx; }
    return xx;
    }
    例如旧版本 Xcode 默认的编译器, 但现在最新版本已经不会给出 warning 了, 貌似是从 Apple LLVM 4.x 开始.

    其实为了逻辑更清晰, 我自己现在已经尽量在每个 function / method 里只 return 一次了. 例如当 type 为 BOOL 时:
    BOOL myFreakyFunction {
    BOOL isXXX = NO;
    if (what) { isXXX = YES; }
    else { isXXX = NO; }
    return isXXX;
    }
    而不是:
    BOOL myFreakyFunction {
    if (what) { return NO; }
    else { return YES; }
    }
    或:
    BOOL myFreakyFunction {
    if (what) { return NO; }
    return YES;
    }
    cassyfar
        7
    cassyfar  
       2013-03-17 12:54:37 +08:00
    @alexrezit 什么version的编译器报warning啊?我用Gcc-redhat-4.1.2这种老编译器都没给出warning...
    我觉得改了之后至少逻辑不清晰了,不能一眼看去就知道是个if else逻辑,我不会写被改成的第二个,也不知道第一个有什么错...
    我赞成你的写法,保留一个return。

    @volCANo 为什么return不能放if语句里? 只要if语句执行了,肯定就会有一个return被执行。
    volCANo
        8
    volCANo  
       2013-03-17 13:57:00 +08:00
    @cassyfar 肯定有吗?又不是说if else 里面一定要有return,如果里面不写呢?
    代码逻辑是没什么问题的,只是编码规范。你想想,如果if else里面的东西非常多,你去读甚至都找不到return在哪儿,那么你会觉得这代码不爽吗?应该会的,甚至你会说,这个函数没有返回,是错的。
    所以在if else外面写return,别人读起来会容易些。这只是个编码规范问题。
    还有第一个if后面只有一句代码也要加大括号,我一直有这个习惯,我的理由是:虽然你现在是只要一行,但以后非常有可能要添加逻辑,就不只是一行了,到时候也要加括号;况且,都加括号不是更一致吗?而且,很多编译器都帮你加好了,你写个if 后面的大括号都自动给你不气了。
    for4
        9
    for4  
       2013-03-17 14:09:54 +08:00
    @Xrong
    @cassyfar

    赞同@volCANo 的说法

    if {
    return 1
    } else {
    return 2
    }
    这种在后面不再加个return x的话, golang就不会让编译通过
    laskuma
        10
    laskuma  
       2013-03-17 15:21:45 +08:00
    不觉得他说的有道理 这只是纯粹的taste上的问题 你偏好哪一种 风格不差 看着不乱 易于理解就好了 他对++的分析我倒是很赞成 这种带side effect太多的语句写多了连debug的时候都会造成困难 但是关于if(){return}else{return}却是我不能接受的 个人还是觉得if(){return}return;的写法没有什么难理解的 代码一行行看下来也都明白 多写一个return反而会让人摸不着头脑
    best1a
        11
    best1a  
       2013-03-17 15:33:22 +08:00
    第二种写法还有一些别的好处,比如有时可以减少一下if的嵌套
    qiukun
        12
    qiukun  
       2013-03-17 15:50:31 +08:00
    @for4 golang 毕竟是 google's lang
    cassyfar
        13
    cassyfar  
       2013-03-17 17:02:09 +08:00
    @volCANo 你理解错我最后一句了。

    @for4 你这...例子举得
    perrywky
        14
    perrywky  
       2013-03-18 13:57:11 +08:00
    其实他说的道理《代码大全》里都已经提到了,就是“代码是写给人看的”

    1. 加上花括弧,块的边界更清晰,别人读起来更轻松
    2. 去掉花括弧,语义发生了变化,第二个return从“其它情况”变成了“默认情况”,本来是很简单的互斥关系,现在第一个return成了特殊情况,读代码的人就会想,还有没有其他特殊情况呢?
    yemoluo
        15
    yemoluo  
       2013-03-18 17:40:58 +08:00
    1. 防止手贱在 if 后加了 分号(";");另外一个就是某些代码编辑器tab和space不分的情况下,某些人就会进入思维误区,为是并行还是串行想破脑袋;其它风格问题

    2.语义上来说是不一样的,同样可以防止某些人手贱 把 else 写成 else if

    3. 不要只研究i = i+1 和 i++两个表达式,而是要研究上下文!何况 i++ 与 ++i本身就是两种语境;举个例子:a = ++i; 和 a=i=i+1;哪种更好? a=i++;用一条语句怎么写加法的方式 ?

    这三个问题,一般都是语义上的问题,计算机是死的,人是活的,但更悲剧的是计算机遵守交通规则,但人却不一定遵守交通规则;计算机的智力几乎都是一样的,但人的呢?千奇百怪,很多人就是转不过那个弯弯
    yemoluo
        16
    yemoluo  
       2013-03-18 17:45:04 +08:00
    针对第三个问题,有很多牛角尖可以钻的,仔细研究下去,可能永远出不了那个坑
    guotie
        17
    guotie  
       2013-03-18 17:49:00 +08:00
    i++ ++i单独写没有任何问题;

    如果单独写i++ 也要改成i = i + 1就有点装逼了
    iEverX
        18
    iEverX  
       2013-03-18 23:47:21 +08:00
    @guotie
    同意

    @perrywky
    对于第二个,虽然是这样说,但是默认不就是意味着以上都不满足的情况吗?
    if (...) { return ... }
    return
    还是感觉这样比较清爽、舒服、习惯
    leafduo
        19
    leafduo  
       2013-03-19 01:04:15 +08:00
    第一个加括号是有必要的,改代码的时候不会忘记加,switch 里面的 break 语句同理。

    第二个更多是 personal taste 的问题吧,另外就是有的版本的编译器对第一种写法会给 warning,最新版本的 clang 已经能识别两种了。

    对于自增操作符这种,我都是觉得实践中哪个清楚、方便就用哪个,没歧义的时候就用自增,难理解了就拆开。
    skydark
        20
    skydark  
       2013-03-19 08:48:22 +08:00
    @tioover 同希望解释一下最后一题,thx~
    zhujinliang
        21
    zhujinliang  
       2013-03-19 09:00:12 +08:00
    @GTim C语言里一边移动指针一边取出数据或写入数据是多么的惬意。 while(count--) *pBuf++ = 0x00;
    fancl20
        22
    fancl20  
       2013-03-19 10:39:47 +08:00   1
    @cassyfar warn 报的是一个有返回值的函数可能不返回值。
    @skydark 估计是说 go 把定义变量和对变量赋值混淆了
    yemoluo
        23
    yemoluo  
       2013-03-19 17:57:38 +08:00
    @zhujinliang 我也是
    tioover
        24
    tioover  
       2013-03-20 08:14:17 +08:00 via Android   1
    @skydark
    @Alex_L
    大半…是猜的…惭愧
    作者给了入门连接,说明可能不是什么深的特性,比如gontinue ,而比较简单的特性,看起来又是:=最可疑。感觉上是省略了对类型的声明交给编译器,和++对赋值的省略很像。
    zztom
        25
    zztom  
       2013-03-20 08:24:19 +08:00
    花括号应该是个还习惯,不过我起初加他的理由竟然是为了好看
    skydark
        26
    skydark  
       2013-03-20 08:35:35 +08:00
    @fancl20 @tioover 个人倒是觉得这种编译器自己能推断的事情交给它们做很对啦……
    不过又仔细看了下,是因为`:=`允许 redeclaration 吗?不过它的 redeclaration 很受限一般倒是不会出什么问题,但的确会产生看起来是声明+初始化的地方进行了重新赋值的行为……
    http://golang.org/ref/spec#Short_variable_declarations
    palxex
        27
    palxex  
       2013-03-20 09:36:29 +08:00
    ++这个例子,拿任意高级语言举例都不错。就放在C里不合适……因为它就是高级语法的汇编。强调的是语句可以几乎直接对应到不长的汇编段落。
    i++这种情况下,i强调的是一个内存地址,用图灵机的语言,就是一个具体可以打孔的位置。你对这一个位置强调i2=i1+1,i2跟i1是两个不同的变量……完全没有意义。
    在SSA的情况下强调其是两个变量,正是因为"变量"与"地址"的解耦,让更高级的优化成为可能。但这本来就不是C,甚至C++这类语言的设计目的。如果要批判这里,C的指针设计才是更应该批判的,但这就是它的设计和精髓:可移植汇编语言。unix hater's handbook分析的不错,这个特性让unix和C得以病毒式传播,而且方兴未艾。
    关于王垠的第三题,如果要改造图灵机,维持相同的计算能力并规避地址的存在……我简单的大脑当机了若干次也没什么结果。莫非要改造成lambda演算?
    alexrezit
        28
    alexrezit  
       2013-03-20 09:46:34 +08:00
    @cassyfar
    以前用 Xcode 默认的 Apple LLVM 就会报 warning. 因为它需要返回值, 又没有给一个返回值. (其实是编译器没有对 if else 做静态分析以为它没有给一个返回值)

    @iEverX
    但如果后来又需要加一些其他的判断呢?
    iEverX
        29
    iEverX  
       2013-03-20 12:37:36 +08:00
    @alexrezit
    如果原来的写法,需要加一些判断你要怎么写,不也是加一个 else if 吗?有什么区别吗
    alexrezit
        30
    alexrezit  
       2013-03-20 12:49:45 +08:00
    @iEverX
    就是说值不能直接返回的情况, 而要二次判断后再返回. 如果按那种写法就需要三处以上的 return 了, 而且每处 return 所在的层级还不同.
    iEverX
        31
    iEverX  
       2013-03-21 21:34:50 +08:00
    @alexrezit
    不明白你的意思。我认为,这两种写法是完全等价的。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2764 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 26ms UTC 14:08 PVG 22:08 LAX 07:08 JFK 10:08
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86