wtd
|
Posted: Thu May 26, 2005 5:54 pm Post subject: Critical Concepts |
|
|
Critical concepts to learn as you evolve as a programmer.
Sections
- How to communicate
- Command-line knowledge
- Expressions and Statements
- Understand where the syntax begins and ends
- Understand compound data structures, and especially how they relate to arrays, lists and other collections
- Understand "for" vs. "for each"
How to communicate
We live in a world where english is the language of choice for communication. It is the standard. We must know how to wield it effectively in order to communicate.
Write and speak clearly and say what you mean. Use no excessive wording. Avoid idioms. You know what they mean, and a lot of other people probably do too, but not everyone does. A thesaurus isn't just for showing off. All of those words that basically mean the same thing do have different meanings. Being precise means having a large vocabulary at your disposal.
When you write, use proper spelling, capitalization and punctuation. Do this even when it doesn't seem important.
Now, with that out of the way, onto computers.
Command-line knowledge
Whether you use Windows, Linux, Mac OS X, FreeBSD, Solaris, or another operating system, get comfortable with the command-line. Understand how to move back and forth between directories, and on Windows, how to move between drives. Understand how to examine the contents of a directory.
Understand how to run a program via the command-line. Understand what environment variables are, how to modify them, and how they impact how you run programs.
Knowing your way around a command-line way seem a foolish thing to waste your time on in this age of graphical interfaces, but the truth remains that command-line programs provide the simplest and least distracting way to learn how to program.
Onto programming stuff.
Expressions and Statements
This is a critical concept to understand, and an enormous source of confusion. An expression takes one or more values and produces something new without altering what has gone in. Let's consider addition.
The above expression adds 42 to "some_var" and produces a new value.
This statement takes "some_var", adds 42 to it, and stores that value in "some_var". The variable is altered and no new value is introduced into the program.
This is often a confusing topic because many languages do very little to differentiate expressions and statements. For instance, in C++, the "+=" operator returns a reference to the variable. It looks like "some_var += 42" returns a new value, but it doesn't.
Understand where the syntax begins and ends
I often hear people talk about "commands" and refer to functions as though they were part of the language's basic syntax. Let's consider a line of Java code.
code: | System.out.println("Hello world!"); |
This kind of thing is excruciatingly common in Java code. "Hello world!" is what we're printing, but how does it get printed?
Is "System.out.println();" some magical "command" for printing a string? Well, no, it's not. "System" simply refers to a class in Java's standard library. A library is just another piece of code. It uses the language, but does not define the language. Think of it as the difference between words and grammar in spoken language. I can make up new words, but I still need a subject, object and verb to make a sentence.
But I digress. "out" is just an object within the System class, which happens to have a method called "println" which we can call like any other method.
But let's look at a language where this isn't the case.
Similar code in Python would look like:
code: | print "Hello world!" |
This is built right into Python, and it doesn't behave like a function. It is an integral part of the Python syntax.
In the case of Python's "print", and in many other languages, parts of the syntax are conveniently differentiated by how they look. A function call in Python has to have parentheses around its arguments.
Of course, all of this is complicated by the fact that many languages allow for elements of syntax to have their behavior "overloaded". Let's consider Ada.
code: | procedure Test is
A, B : Integer := 1;
C : Integer := 0;
begin
C := A + B;
end Test; |
It's pretty clear what we're doing here, right? The "+" is a syntactic keyword that adds two numbers, right?
Well, yes, but that behavior is defined by Ada code, so we can add our own rules.
code: | procedure Test2 is
type New_Type is record
A : Integer;
end record;
A, B : New_Type := (1);
C : Integer := 0;
begin
C := A + B;
end Test2; |
This won't work. There's no way to add two New_Type pieces of data together and get an integer.
code: | procedure Test2 is
type New_Type is record
A : Integer;
end record;
function "+"(F, G : in New_Type) return Integer is
begin
return F.A + G.A;
end "+";
A, B : New_Type := (1);
C : Integer := 0;
begin
C := A + B;
end Test2; |
Now it does work.
So, is "+" a piece of syntax, or a user-defined function? The line is often blurred. Understanding how to cope with this is vital.
Understand compound data structures, and especially how they relate to arrays, lists and other collections
This is a topic often saved for "advanced" programming classes and tutorials. It shouldn't be. Compound data structures offer too many benefits, especially when paired with arrays.
Let's say we have a store. We have a number of items on the shelves. Each item has a name and a price. How do we organize this. The classic strategy is to have two arrays. One will store the name of the item, and the corresponding item in the other arrays will store the price.
Let's look at this in O'Caml, and we'll assume we have only 4 items.
code: | names = ["Potatoes"; "Carrots"; "Celery"; "Onions"] |
Then, we need an array/list with 4 prices (in cents).
code: | prices = [39; 59; 79; 129] |
But, what if I make a mistake, and switch two of the prices?
code: | prices = [129; 59; 79; 39] |
Now potatoes are ridiculously expensive, and onions are far too cheap.
Instead, since the price and name of a product are intimately linked, let's actually place them in one place together.
code: | type product = { name : string; price : int };; |
Now we need only have one array/list.
code: | items = [{name="Potatoes"; price=39}; {name="Carrots"; price=59}; {name="Celery"; price=79}; {name="Onions"; price=129}] |
Comparing this situation back to a real store, the first scenario has each item on the shelf having a unique number on it. You can write this number down and refer back to a book at the checkout line that tells you the price. Or you can just print the price on the item. In this case, finding the item you're looking for means finding the price with no extra effort.
Understand "for" vs. "for each"
There are two different types of "for" loop. There are clear "for" loops which go from a starting state to an end state, with some update code. These are essentially syntactic sugar for "while" loops.
Then there are languages which provide "for each" loops which iterate over the elements in an array/list/collection.
Consider Ruby.
code: | for x in some_arr
puts x
end |
And then a for loop in C#.
code: | for (int i = 0; i < someArr.Length; i++)
{
Console.WriteLine(someArr[i]);
} |
Some languages, such as C# and Java possess both.
code: | for (int x in someArr)
{
Console.WriteLine(x);
} |
And the situation is further complicated by languages which have neither of these looping structures. Haskell has no syntax for looping at all. Eiffel has only one form of loop which is most analogous to the common "while" loop.
code: | class TEST
creation make
feature
make is
local
some_arr : ARRAY[INTEGER]
i : INTEGER
do
-- setup some_arr
from i := 0
until i > some_arr.size
loop
std_output.put_integer(some_arr @ i)
std_output.put_new_line
i := i + 1
end
end
end |
Understand the difference between "for" and for each" and also what to do if neither is present. |
|
|