FizzBu​​zz的现有实现有很多,但是今天早上我醒来不觉,因为可怕的启示是Code Review在Forth中没有FizzBu​​zz的实现!为了纠正这种可怕的疏忽,我在喝第一杯咖啡的同时写了这篇文章。

: FIZZBUZZ ( -- )
  CR 100 1 DO 
     I 3 MOD 0= I 5 MOD 0= 2DUP AND IF 
        ." fizzbuzz " DROP DROP
     ELSE IF 
        ." buzz " DROP
     ELSE IF 
        ." fizz " 
     ELSE I . THEN THEN THEN
  LOOP ;


我对一般的评论感兴趣,包括使用MOD,以及是否应使用进一步的分解。
对于不熟悉Forth的人,请尝试http://www.forth.org/tutorials.html

评论

这看起来很熟悉。为什么看起来很熟悉?为什么我会识别这种语言?找到了。 Evolve使用过KForth。

#1 楼

您是否使用两个或三个缩进空间?是的。

您是否使用两个和三个缩进空格?是的。

您要使用两个x或三个空格的缩进吗?不。

我不知道Forth的编码约定,但是我个人更希望使用缩进的四个空格(一个制表符)。但是,最重要的是要保持一致。 据我了解Forth样式约定,应始终使用三个空格作为缩进。


I 3 MOD 0= I 5 MOD 0= 2DUP AND IF 


这行过长且包含许多不同的说明,我认为这是不必要的混淆。通过拆分,我认为它更易于阅读和理解。

可以很容易地拆分为以下内容:

I 3 MOD 0=
I 5 MOD 0=
2DUP AND
IF



: FIZZBUZZ ( -- )
  CR 100 1 DO 


我不太确定为什么要在函数的开头(对不起,您的“单词”)打印新行(CR)。 IMO最好在每次迭代后打印新行。


将100提取为单词的参数很容易,而不是对其进行硬编码。即使大多数Fizzbuzz挑战仅达到100,这也至少会带来一定的灵活性。这可以通过在单词开头删除100轻松实现。

说到100。您当前的实现实际上排除数字100。可以通过在单词的开头添加1 +来轻松解决此问题。


您嵌套的if-else-if-else-if-else-then-then-then如果您不习惯Forth的工作原理,那么很难遵循(是的,我是根据经验讲的)。通过仅更改它的缩进,就可以更容易地跟随它。

尽管THEN位于末尾仍然有些奇怪,但是您无能为力。 :)


上面的建议使代码看起来像这样:

: FIZZBUZZ ( u -- )
    1 + 1 DO 
        I 3 MOD 0=
        I 5 MOD 0=
        2DUP AND IF 
            ." fizzbuzz" DROP DROP
        ELSE
            IF 
               ." buzz" DROP
            ELSE
                IF 
                    ." fizz" 
                ELSE
                    I .
                THEN
            THEN
        THEN
        CR
    LOOP
;



至于使用mod的替代方法,即使可以使用两个单独的计数器并减少它们并在它们达到零时重置它们,我认为这不会改善代码。

考虑到这一点我设法理解了您的代码并学到了一点Forth,我想这是对您代码的补充。我相信,通过我在这里提出的一些更改,新的Forth程序员将更容易理解它。

评论


\ $ \ begingroup \ $
感谢您的评论。有关Forth编码约定的示例,请参见seeabout.org/forth_style.html,尽管我实际上使用的是更新的样式。在Forth中,通常以IF作为行尾。另外,您的堆栈注释应修改为(u-)。
\ $ \ endgroup \ $
–爱德华
2014年11月23日15:28

\ $ \ begingroup \ $
“对于以前从未读过或写过Forth的人来说,这句话很混乱”,这是一个公平的标准吗?在我了解它之前,大多数Python在我看来都是胡言乱语。
\ $ \ endgroup \ $
–raptortech97
2014年11月23日在17:41

\ $ \ begingroup \ $
@ raptortech97编辑了该部分。
\ $ \ endgroup \ $
–西蒙·福斯伯格
2014年11月23日20:36

#2 楼

格里(Gerry)的答案来自comp.lang.forth,它避免使用mod,而是使用位向量。

hex
1249 constant 3vec
0421 constant 5vec
4000 constant probe
3vec 5vec or constant 3or5vec
decimal

: bang
   cr 0 101 1
   do
      ?dup 0= if probe then
      3or5vec over and 0= if i . then
      3vec over and if ." fizz" then
      5vec over and if ." buzz" then
      1 rshift cr
   loop
   drop
;