Home‎ > ‎

Unix echo example

The Unix style "echo" program in Zimbu, echo.zu (line numbers added for reference, they are not part of the file):

 1 # Zimbu example program: Unix style "echo"
 2
 3 FUNC Main() int
 4   bool    writeNewline = TRUE
 5   string  sep = ""
 6   bool    didFirst
 7   FOR arg IN ARG.getRawList()
 8     IF !didFirst && arg == "-n"
 9       writeNewline = FALSE
10     ELSE
11       IO.write(sep .. arg)
12       sep = " "
13     }
14     didFirst = TRUE
15   }
16   IF writeNewline
17     IO.write("\n")
18   }
19   RETURN 0
20 }
21 ARG.Status argStatus = ARG.disable()

Let's explain this line by line.

 1 # Zimbu example program: Unix style "echo"
Comments start with the # character and continue until the end of the line.

 3 FUNC Main() int
The entry point to the program.  There are no arguments here.  Command line arguments are handled by the ARG module and are available everywhere.  This avoids having to pass them around and creating dependencies.  Main() always returns an int.

 4   bool    writeNewline = TRUE
This declares the variable writeNewline as a boolean type and initializes it to true.  Zimbu is statically typed, which means the compiler will check that writeNewline will always be used as a Boolean.  One can use the type ANY if type checking is to be done at runtime.

 5   string  sep = ""
This declares the variable sep (short for separator) as a string type and initializes it to an empty string.

 6   bool    didFirst
This declares the variable didFirst as a boolean type.  There is no explicit initialization, the default value FALSE is used.  All variables are initialized to zero, FALSE or NIL by default.

 7   FOR arg IN ARG.getRawList()
Oh my, a lot is going on in this line.  The basis is a FOR arg IN iterable statement.  It iterates over all the elements in the list, assigning the value of each element to arg in turn.  Much like Python.

The list in this case is obtained with ARG.getRawList().  This is the list of all command line arguments.  The ARG module actually has nicer ways to deal with flags, but since the echo command is very specific about how it handles arguments we need to avoid, for example, accepting a --help argument.

The loop variable is arg.  It was not declared yet and therefore it happens here automatically. This is one of the few places where you can use a variable without declaring it. The scope of arg is the FOR loop only. Zimbu also allows using a variable declared elsewhere.

The type of the variable arg is obtained from the iterable list.  Thus it is statically typed, but we don't need to specify the type explicitly.  In this case the type comes from the return value of ARG.getRawList(), a list of Strings.

 8     IF !didFirst && arg == "-n"
A conditional statement.  Parenthesis around the expression are not required.  The expression syntax resembles C and Java.  But string values can be directly compared with ==.  To compare object identity IS can be used, like in Python.

 9       writeNewline = FALSE
The "-n" argument was found, reset writeNewLine so that we omit writing the newline at the end.

10     ELSE
The else part of the IF statement.  It also separates the two blocks of statements, no { or } is required.

11       IO.write(sep .. arg)
The .. operator is used to concatenate strings.

12       sep = " "
Next time we write an argument the prepended separator is one space.

13     }
The end of the IF statement. Yes, Zimbu has unbalanced braces. You can read it as END, like in Pascal. The code is easier to overview with the character } instead of the word END.

14     didFirst = TRUE
Now we are no longer at the first argument.  Next time we will not check for a "-n" argument.  This is consistent with the Unix echo command: "echo -n -n hello" writes "-n hello".

15   }
The end of the FOR loop.

16   IF writeNewline
17     IO.write("\n")
18   }
When writeNewline is true write the final newline.

19   RETURN 0
20 }
Ends the Main() function block.  The exit value of the program is zero.

21 ARG.Status argStatus = ARG.disable()
Tells the ARG module that no command line parsing is to be done.  Be declaring a variable at the module level and initializing it this happens before command line parsing has taken place.

Comments