18 karma · joined January 12, 2008
I don't really have as deep an understanding of this subject as I'd like, so my explanation might seem rough, but here's my two cents.
You can say a language is a set of rules. Syntactic rules describe what proper sentences in that language look like, while semantic rules describe actions associated with syntactic constructs. The most basic of languages have simple semantic rules. For each language, you can have a program, which accepts as it's input a sentence, checks if it respects the syntactic rules of that language, and then performs the actions dictated by the semantic rules. This bit is clear, I think. Starting from the other direction, if you have a program, you can invent a language, which describes what the program does (semantic) and what are proper inputs (syntactic).
Some examples are in order.
* Suppose you have a program that finds out the maximum element in a sequence of comma separated numbers. What would the language associated with this program be? Well, it's syntactic rules are simple : a proper input sentence of this program's language is a list of comma separated numbers. The semantic action associated with such a sentence would be to find the maximum of the sentence.
* For your Fibonacci example. Even a simple function/program such as this defines it's own language. What would the syntactic rules be? A proper sentence for the Fibonacci function would be a single number (let's call it n). The semantic rule associated is calculating the nth number in the series.
* Of course, no list of examples would be complete without the poster children on language - program equivalence : regular expressions and compilers. Regular expressions are written in a small language that describes a program which, when given a certain input, says weather the input matches or doesn't. The syntactic and semantic rules are more complex than in our previous examples, but are well known. As for compilers, if we bend our minds and language a little bit, we can say that GCC is a program which receives a sentence written in the C programming language (so GCC's syntactic rules are C's syntactic rules), and produces an equivalent program in machine language (so GCC's semantic rules are to produce a machine language translation of a C program).
Anyway, I hope these few examples help.
As I've said - code is all you've got in the end, and if it's good, the shipped product will reflect that.
There's a small thinking shift between writing a game in an imperative style and writing it in a functional style. In particular, it's smaller, I think, for games than for other kinds of applications.
In a typical game, you have a global state - a series of objects describing the properties of the game world at a certain time. You continuously update these objects, based on what input you receive from the user, and then present those changes to him, by way of video and audio rendering.
In pseudoC it would look like this :
gameState s; int time = 0;
int main() { load_resources();
while(!game_exit()) {
get_input();
update_state();
render_video();
render_audio();
time = time + 1;
}
return 0;
}Switching to a functional language, a way of thinking about the game flow I've found useful is this :
The main loop becomes a function of two parameters : the current game state and the current inputs. From these it computes the next state. After the current simulation tick has passed, the next game state become the current one, whatever video and audio you have is updated and new inputs are gathered. It would look like this :
int main() { game_loop(load_resources(),init_inputs(),0); }
gameState game_loop(gameState currentState, gameInput inputs, int game_time) { render_video(currentState); render_audio(currentState);
game_loop(next_state(currentState,inputs),new_inputs(),game_time + 1);
}Yeah, in C it will blow your stack, but functional languages have to deal with recursion much more often, and what you see there will be optimised away to a loop and be executed in constant space.
Other things to note are that you see the state passed explicitly between functions (no relying on it inherently existing as a global) and that the shift is from modifing an object as the game progresses, to creating a new object to represent the new state of the world, and discarding the old one.
Languages, be it lisp, haskell, calm, scala, f# or python, java, c, c# (used as functional languages) are relatively easy to learn. What's hard is adapting your thinking to the strengths and limitations imposed by them.
Hope this helped.
if(t > 3)
return t;
else
return 2 + rand15();
}I dunno? will that work?
There is only a small step from writing stuff like this :
FILE* ofile = fopen("test.txt","w"); fprintf(ofile,"%s %s %s",1,2,3); fclose(ofile)
to writing code like this :
FILE ofile("test.txt","w"); ofile.printf("%s %s %s",1,2,3); ofile.close();
So. you've grouped some data and some code together so it's easier to work with it. This is just the first step though, but the small objects you make will be very useful. You can make a small library of useful objects that way : file, string, date, time, point, rectangle, socket, regexp etc.
Also, you don't have to make the whole program OO. You can keep it procedural (and for most scripts that's the case), but you can use the above objects just like you'd use their procedural counterparts before. Slowly, and with experience both with OOP and larger programs, you'll see other parts of your work that would make sense as an object. On the other hand, some of them won't. And it's perfectly ok - not all problems can be naturally modeled as a system of objects.
It's important to start with a real task, and not only do the simple training programs you'll find in every manual/tutorial. I can't stress enough the difference between grasping a concept and actually being able to apply it in the field.
Second, after you learn your first language, don't ever think of sticking only to it. Learn your second, learn your third and your Nth language and never stop learning them. Sure, most of them are similar (python is like ruby, perl, lisp, c is like c++,c#,java) but there are some oddballs like prolog and haskell which will make you a better programmer just by knowing that they exist and what they're about). Thus you'll have a tool for every job.
Also, after a while, learn assembler (x86) and some hardware theory (how a computer works, what's in a CPU or a GPU etc.).
Finnaly, have fun! Don't feel pressured to know anything you don't need or don't think will make you a better programmer. Don't learn Java and it's assorted libraries because every job wants you to know it. Don't learn LISP because the cool kids are doing it, and don't write programs you won't use.
I have a feeling that if you learned Assembler and then a language without pointers and then came to C, you'd still be confused.