patternMinor
FizzBuzz in Forth
Viewed 0 times
forthfizzbuzzstackoverflow
Problem
There are quite a large number of existing implementatons of FizzBuzz but I awoke this morning in a cold sweat with the terrible revelation that Code Review had no FizzBuzz implementation in Forth! To redress this terrible oversight, I wrote this while sipping my first cup of coffee.
I'm interested in a general review, including possible alternatives to the use of
For those unfamiliar with Forth, try http://www.forth.org/tutorials.html
: 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 ;I'm interested in a general review, including possible alternatives to the use of
MOD, and whether further factoring should be used. For those unfamiliar with Forth, try http://www.forth.org/tutorials.html
Solution
Are you using two or three spaces of indentation? Yes.
Are you using two and three spaces of indentation? Yes.
Are you using two xor three spaces of indentation? No.
I don't know the coding conventions of Forth, but I'd personally prefer to see using four spaces (one tab) of indentation. Most importantly however, be consistent. As far as I understand the Forth style conventions, three spaces should be used as indentation always.
This line is excessively long and contains a lot of different instructions, in my opinion this is unnecessarily confusing. By splitting it up I consider it easier to read and understand.
It can easily be split up to the following:
I'm not quite sure why you print a new line (CR) at the beginning of your function (sorry, your "word"). IMO it's better to print a new line after each iteration.
It would be easy to extract the 100 to be a parameter to your word instead of hardcoding it into it. That would give some flexibility at least, even though most Fizzbuzz challenges only goes to 100. This can easily be accomplished by removing the
Speaking of 100. Your current implementation actually excludes the number 100. This is easily fixed by adding
Your nested if-else-if-else-if-else-then-then-then is hard to follow when you're not used to how Forth works (yes, I am speaking from experience here). By only changing the indentation of it, it gets easier to follow along with it.
Although it still may look a bit strange that the
With the suggestions above, the code would look like this:
As for alternatives to using mod, even though it is possible to use two separate counters and decrease them and reset them once they hit zero, I don't think that would improve the code much.
Considering that I managed to understand your code and learn a bit of Forth, I'd say that's a compliment to your code. I believe that with some of the changes I've suggested here, it would be much easier for new Forth programmers to understand it.
Are you using two and three spaces of indentation? Yes.
Are you using two xor three spaces of indentation? No.
I don't know the coding conventions of Forth, but I'd personally prefer to see using four spaces (one tab) of indentation. Most importantly however, be consistent. As far as I understand the Forth style conventions, three spaces should be used as indentation always.
I 3 MOD 0= I 5 MOD 0= 2DUP AND IFThis line is excessively long and contains a lot of different instructions, in my opinion this is unnecessarily confusing. By splitting it up I consider it easier to read and understand.
It can easily be split up to the following:
I 3 MOD 0=
I 5 MOD 0=
2DUP AND
IF: FIZZBUZZ ( -- )
CR 100 1 DOI'm not quite sure why you print a new line (CR) at the beginning of your function (sorry, your "word"). IMO it's better to print a new line after each iteration.
It would be easy to extract the 100 to be a parameter to your word instead of hardcoding it into it. That would give some flexibility at least, even though most Fizzbuzz challenges only goes to 100. This can easily be accomplished by removing the
100 at the beginning of your word.Speaking of 100. Your current implementation actually excludes the number 100. This is easily fixed by adding
1 + to the beginning of your word.Your nested if-else-if-else-if-else-then-then-then is hard to follow when you're not used to how Forth works (yes, I am speaking from experience here). By only changing the indentation of it, it gets easier to follow along with it.
Although it still may look a bit strange that the
THEN is at the end, but that's not anything you can do something about :)With the suggestions above, the code would look like this:
: 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
;As for alternatives to using mod, even though it is possible to use two separate counters and decrease them and reset them once they hit zero, I don't think that would improve the code much.
Considering that I managed to understand your code and learn a bit of Forth, I'd say that's a compliment to your code. I believe that with some of the changes I've suggested here, it would be much easier for new Forth programmers to understand it.
Code Snippets
I 3 MOD 0= I 5 MOD 0= 2DUP AND IFI 3 MOD 0=
I 5 MOD 0=
2DUP AND
IF: FIZZBUZZ ( -- )
CR 100 1 DO: 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
;Context
StackExchange Code Review Q#56839, answer score: 7
Revisions (0)
No revisions yet.