HomeTable of ContentsPrevious ChapterNext Chapter | ||
NAVIGATIONThe Very BasicsProject FrameworkCreate basics.stanzaCompile and RunIndentationPrinting Simple MessagesStringsPrinting StringsPrint Without a New LineIntsPrinting IntegersPrinting Multiple ThingsFormatted PrintingWhere's the Commas?Lexical StructureLexemesNumbersOperatorsIdentifiersOpening BracketsCommentsOperatorsBasic ArithmeticBitwise ArithmeticOperator PrecedenceUnary OperatorsValuesSyntaxBreaking up Complicated ExpressionsTypesType InferenceVariablesTypesType InferenceUninitialized VariablesFunctionsReturn ValueSide EffectsReturn TypeArgument TypesExample: String ArgumentsLeaving off the Argument TypeThe Unknown TypeComparisonsComparison OperatorsLogical OperatorsIf ExpressionsResult of an If ExpressionDefault Else BranchNested If ExpressionsTrue and FalseExpression SequencesStructure Through IndentationWhile LoopsFor "Loops"Counting LoopsRange ExpressionsLabeled ScopesFor Returning EarlyFor Breaking From LoopsGeneral FormWell-Typed Labeled ScopesScopes and the Let ExpressionArraysPutting Things InGetting Things OutAsking For Its LengthArrays and LoopsTuplesReturning Multiple ValuesBasic TypesStructsGetter FunctionsStruct TypeExercises |
The Very BasicsThis chapter introduces the basic programming constructs in Stanza. After this chapter, you'll be able to write basic programs that do simple things. Project FrameworkFollow these steps to set up a project framework. Create basics.stanzaIn your
Again, make sure you do not forget the space between the Compile and RunCompile and run the basic framework by typing the following in the terminal
The basic framework should print out
Follow the chapter and try out the examples by replacing the IndentationTry changing the basic framework to
and try to compile it. It won't work. My Stanza installation says
Indentation is important in Stanza programs. Be careful when trying out the examples. And don't use tabs. Stanza won't let you. We don't like tabs. Printing Simple MessagesPrinting is important. It's the only way to observe what your program is doing. StringsThis is a string.
It's a bunch of characters surrounded in double quotes. Printing StringsUse the
prints out
Print Without a New LineUse the
prints out
IntsThis is an integer.
It's a bunch of digits, and represents the integers that you were taught in school. Printing IntegersThe
prints out
Actually Printing Multiple ThingsCalling
prints out
If you don't want to start a new line at the end, use
prints out
Don't fret about the Formatted PrintingSometimes it's tedious to print multiple things even with
prints out
Notice that you're calling the same Where's the Commas?Some of you may have noticed the lack of commas in the examples. Try adding them back in.
still prints out
Commas are treated identically to spaces in Stanza. (Unless they are part of a string.) Try going crazy!
The above still prints out what it used to. But don't do that. That was just an example. Lexical StructureBefore compilation, a Stanza program is lexed into individual identifiers, numbers, and lists. Here are the rules that you'll need to know. LexemesThe first thing that Stanza does is break down a program into a sequence of lexemes, where each lexeme is separated by either whitespace or one of the following characters.
NumbersA number is a lexeme that begins with a digit, or a hyphen followed by a digit. Here are some examples.
OperatorsAn operator is any lexeme that is made up of the following characters.
Here are some example operators.
IdentifiersAn identifier is any lexeme that is not a number or operator. Here are some examples.
Opening BracketsSyntactically, an identifier followed immediately by a opening bracket character is treated differently than if the two were separated by spaces. For example
is syntactically different than
The former calls the function This is similar to how
is syntactically different than
The two mean different things. Please keep this in mind when following the examples in this book. For example, this is why it was stressed to you to remember the space after
Additionally,
is syntactically different than
and
is syntactically different than
and
is syntactically different than
CommentsComments begin with the
Code without comments is very difficult to understand. Use comments often. OperatorsBasic ArithmeticTo add two numbers together, use the
prints out
That means the result of adding Here are examples of using the other arithmetic operators.
Bitwise ArithmeticHere are examples of using the bitwise operators.
Operator PrecedenceAll the operators are left associative. This means that in the following expression
the operators are applied left to right. The above is equivalent to
In expressions containing a mix of operators, the operators with highest precedence are grouped together first, followed by the operators with second highest precedence, until you reach the operators with lowest precedence. The shift operators ( The following expression
first groups the precedence 3 operators
followed by the precedence 2 operators
followed by the precedence 1 operators
Unary OperatorsHere's how to negate a number.
The parentheses are not optional! Here's how to flip all the bits in a number.
Again, the parentheses are not optional! This is different than most other languages. There's a good reason for this. But don't forget them! ValuesSyntaxThe statement
calculates the result of After the storing the result in
You cannot change what is stored in a value once it is initialized. Breaking up Complicated ExpressionsYou can use values to break up complicated expressions into smaller ones.
can be rewritten as
TypesThe Stanza won't let you store anything else into
but attempting to compile it gives us this error.
If you want to store a string into
Later, we will learn more about types and about types other than Type InferenceIf you leave off the type annotation
then Stanza figures out the type based on the expression it's initialized with. Most Stanza programmers leave off type declarations for values. VariablesA variable is declared like a value, but using
Just like a value, the result of calculating And just like a value, you can refer to it by name afterwards.
The difference is that, even after it is initialized, you can still store something else into a variable.
prints out
After we print out TypesJust like values, a variable's type annotation restricts what you can store inside it. Here's what happens when we attempt to store a string into
Compiling the above gives us
Type InferenceJust like values, you can leave off the type annotation for a variable.
However, the inferred type for a variable depends upon all the values assigned to it, not just the initial one. For various reasons, Stanza cannot always infer the type of a variable, as in this example. (Don't mind the functions you don't know. We'll learn them later.)
Attempting to compile the above gives us this error.
In these cases, you'll have to provide an explicit type annotation for the variable. Uninitialized VariablesVariables don't have to be declared with an initial value. Here's a variable, declared to only hold integers, but with no initial value.
Attempting to read from an uninitialized variable will crash the program. The following program
when compiled and ran crashes with this error.
FunctionsHere's a function that subtracts forty two from its argument.
And here's how you call the function.
Here's the complete program.
It prints out:
This means that the result of calling Return ValueHere's a silly change we can make to
Side EffectsHere's another change we can make to
Now the following code
prints
The expressions in a function body are evaluated one at a time, but only the result of the last one is returned. Return TypeThe Stanza won't let you return anything else. If we try to return a string
then the Stanza compiler gives us this error.
You can leave off the return type annotation
in which case, Stanza will figure out the return type automatically based on the last expression in the function body. In certain cases, Stanza will not be able to figure it out and you'll have to provide it explicitly. Argument TypesThe
gives the error
The second is that it restricts what you are allowed to do with
Compiling it gives us this error.
Roughly, that error message tells us that there are four different functions called modulo, and none of them can called with Example: String ArgumentsHere is an example of a function that accepts a string as an argument.
Compiling and running the above prints
We did not provide an explicit return type for
Leaving off the Argument TypeBeware. Argument types are not inferred automatically. You can leave off the argument types
but this is not equivalent to declaring If you leave off the type annotation for an argument, it means that the argument can be anything. You can call the function with whatever you want, and within the body of the function Stanza will let you do whatever you wish with the argument. If you do something wrong then the program will crash when ran. Here is an incorrect program that compiles correctly.
But when the program is ran, it crashes with this error.
The error message is saying that in the expression The Unknown TypeMore precisely, leaving off the type annotation for an argument is equivalent to declaring the argument with the
The You can use the
It prints out
Notice that we're using ComparisonsComparison OperatorsTo test whether one integer is smaller than another number, you can use the
It prints out
This means that
prints out
This means that Here's all the other comparison operators you can use.
Logical OperatorsYou can use the
Here is how to test whether
Here is how to test whether
If ExpressionsIf expressions let you test whether a value is
prints out
The result of Change the Result of an If ExpressionIf expressions evaluate to a result. The result of an if expression is the result of the last expression in the consequent branch if the predicate is Here's an example of using the result of an if expression.
It prints out the same message as the last example. Default Else BranchIf you leave off the
nothing is ever printed. Nested If ExpressionsYou can nest if expressions inside other if expressions. The following code prints different messages when x falls in different ranges.
It uses nested if expressions to test a series of conditions. Because nested if expressions are so common, you are allowed to omit the colon after the
Here's another example.
True and FalseThe The following
prints out
To print The value Expression SequencesMultiple expressions can be grouped together as an expression sequence by surrounding them with parentheses.
prints out
The expressions in an expression sequence are evaluated one at a a time, and the result of the last expression is the result of the expression sequence. In the above example, the first expression in the sequence, Structure Through IndentationSome of you may be concerned about Stanza's use of structure through indentation due to how this system has been implemented in the past. Don't worry. Stanza's indentation structuring mechanism is very simple and predictable. The indentation structuring mechanism is governed by a single rule: a line ending colon automatically inserts parentheses around the following indented block. Thus, after the implicit parentheses have been added, the previous
A program with no line ending colons can even be written on a single line if desired.
Here is one more example.
becomes the following after implicit parentheses are added.
Here is
As you may have noticed, the indentation mechanism is simply used as a shorthand for creating expression sequences out of indented blocks. While LoopsThe following
prints out
Here is the general form.
A while loop repeatedly evaluates a block of code so long as the predicate expression evaluates to Here is the order in which the while loop does things.
For "Loops"Stanza's for construct is extremely powerful. "Loops" is in double quotes because, strictly speaking, the for construct is not a looping mechanism. But it is often used as one, so we'll explain it here as if it were. Later, we'll learn the general form of the for construct. Counting LoopsThe following
prints out The following
prints out
A counting loop has this general form.
For each integer between Range ExpressionsIn the previous example, the expression Here's how to create a
It represents the numbers The following
prints out
To make the ending index inclusive rather than exclusive, use the
represents the numbers If you use
represents the numbers Labeled ScopesFor Returning EarlyAs you've learned so far, functions return the result of the last expression in its body. But what if you want to return earlier? As an example, here's a function that computes the n'th fibonacci number.
Let's use a labeled scope to change
The first line within the labeled scope
checks to see whether For Breaking From LoopsLabeled scopes are also useful for breaking early out of loops. Here's how the while loop in
The code above starts an infinite loop, but breaks out of it when General FormThe general form of a labeled scope is
You can name the exit function whatever you like. When used to return early from a function, The label construct simply executes the given body. If the exit function is never called then the result of the body expression is the result of the label construct. If the exit function is called, then we immediately stop evaluation of the body, and the argument to the exit function is the result of the label construct. Well-Typed Labeled ScopesThe type annotation on the label construct enforces two properties.
The first restriction is fairly obvious. If you pass an argument of the wrong type to the exit function
then Stanza will issue an error.
The second restriction sometimes arises in more subtle situations. The following function computes the first integer whose square is greater than 1000.
But compiling it gives us this error.
This message says that the body of the labeled scope returns Since we know that the
Scopes and the Let ExpressionWe have now seen a number of expressions that introduce a new scope: functions, while loops, for loops, if expressions, and labeled scopes. Values and variables defined within a scope are only visible within that scope. For example, in the following code
is illegal and would not pass the Stanza compiler. Scopes may themselves contain other nested scopes. In the above example,
If there are multiple values with the same name that are visible, you automatically refer to the one in the nearest scope. Thus the following code prints
This feature is called shadowing. Sometimes it is useful to artificially introduce a new scope, simply because you will define a number of values that you only want visible within the scope. You can do this using the let expression.
In the above code, the let expression introduces a new scope where ArraysArrays are one of Stanza's most fundamental datastructures. The following
creates an array of length 10 and gives it the name Putting Things InYou can put things into the boxes like this.
The first box is numbered box 0. The next box is numbered box 1. The last box in Getting Things OutYou can retrieve the contents of boxes like this.
prints out
Asking For Its LengthYou can call the
prints out
The type of Arrays and LoopsArrays are most powerful when combined with loops. This function
computes the sum of every integer in an array. Let's use it to compute the sum of 10, 11, 7, and 8.
prints out
TuplesTuples represent an immutable collection of items. The following creates a two-element type.
It contains an
The above code checks that Notice that the type of the expression Returning Multiple ValuesTuples are often used to return multiple values from a function. The following function takes an argument,
We can call and receive both return values from
Basic TypesAt this point, we have seen a couple of different types now. Here is a listing of the other basic types in Stanza.
As we've said already, the All of the types listed in the previous table are examples of ground types. It means that you refer to them simply by their name and they don't take any parameters. With the introduction of arrays, you have now also been introduced to your first parametric type.
Unlike ground types, parametric types take additional type parameters. An array needs to know what type of objects it holds, so it has one type parameter for specifying that. Note that for parametric types, if you leave off its parameters, then it is equivalent to specifying
is equivalent to
And
is equivalent to
Tuple types have their own syntax, and consists of surrounding the types of all of its elements with the
Here is a tuple containing an integer, a string, and a tuple of a single integer.
StructsFor convenience, Stanza provides a simple way to create compound types out of existing types using structs. Here is how to define a new
Once
Getter FunctionsTo retrieve the values of the fields it was constructed from, you may call the
prints out
Struct TypeAdditionally, once a struct is defined, you may now also use it as the name of a type. Here is a function that prints out the contents of an array of
Let's try calling
prints out
Structs are just a convenient form for quickly declaring a new type, constructor function, and getter functions. Later we'll learn the general method for creating new types. Exercises
|
|
Site design by Luca Li. Copyright 2015. |