'Yes you can shoot yourself in the foot, hang the compiler, and launch missiles at the same time. You're a good programmer or you wouldn't be using this language. So don't do that. If you do, don't do it again.'
That's not always a good attitude to have in software development, but a modern language that backs away from the "wrap us all in bubble wrap" philosophy is refreshing.
#include <stdio.h>
#include <stdlib.h>
#COMPILETIME
int fib(int n) {
if(n < 2) return n;
return fib(n-1) + fib(n-2);
}
int main() {
printf("int fib(int n) {\n");
printf(" switch(n) {\n");
for(int i=0; i < 30; i++) {
printf("case %d: return %d\n", i, fib(i));
}
printf("default: return fib(n-1) + fib(n-2);\n");
printf("}\n}");
}
#ENDCOMPILETIME
and then at compile time that would get run and the source could generated would be: int fib(int n) {
switch(n) {
case 0: return 0;
case 1: return 1;
case 2: return 1;
case 3: return 2;
case 4: return 3;
case 5: return 5;
case 6: return 8;
... etc up to i=29...
default: return fib(n-1) + fib(n-2);
}
}In particular string mixins will do what you want; they will also do much more, like for instance include external files written in domain specific languages and compile them in native D code; all this is done by the compiler, using language facilities, without external tools.
(These is not some theoretically cool feature; it's used in real world code, like dproto, which compiles protobuf definitions into native code, or HTML templating engines which compile templates to the equivalent of Java servlets)
That feature is called compile-time function evaluation, and there are a bunch of languages that support CTFE[1]. Blow's language has, from what I've seen, the cleanest CTFE syntax and most straightforward usage approach. In terms of what you can use today, check out D[2] (which has multiple competing ways to do CTFE).
[1]: http://en.wikipedia.org/wiki/Compile_time_function_execution [2]: http://dlang.org/
It's macro facilities are actually fairly amazing, and allow for a lot of boilerplate code to be generated at compile time (think: the kind of things reflection is used for in other languages).
Sadly, it's a GCed language, so while it's very popular for game development, it's use is mainly in the indie scene, and so it's probably never something I'll use for anything other than a toy.
[0]: http://haxe.org/
Your example could look like this in Common Lisp:
(defun fib (n)
(if (< n 2)
n
(+ (fib (- n 1)) (fib (- n 2)))))
(defmacro spliced-fibs (x n)
`(case ,x
,(map-iota (lambda (v) (list v (fib v))) n)))
(defun hardcoded-fib (num)
(spliced-fibs num 29))
spliced-fibs macro will generate you a full case block at compile time, so the hardcoded-fib will be basically one big switch/case block. map-iota call maps a function over a list of numbers from 0 to n. Note that a macro can call ordinary functions at compile time, which themselves can use other macros, etc. So a lot of code can be used both at compile and run time.I'm not sure what you mean by 'in the language itself', since isn't all compile-time metaprogramming in the language itself? But this question has an example of computing Fibonacci sequences in C++ templates:
http://stackoverflow.com/questions/908256/getting-template-m...
The second part of the question is about how to turn that into a table which can be referenced at runtime, which would seem to be the same as your question.
I occasionally write C# which writes C# (using .NET APIs to compile it at runtime, typically) and C# in T4 Text Templates which write C# (they integrate nicely into Visual Studio's build process right out of the box.)
Improvements can always be made on man-made things like C++, even if improvements aren't always obvious at first.
You miss 100% of the shots you don't take!
Tangentially, I hate this phrase. It ignores the fact that there's an opportunity cost to missed shots. If you're imagining the metaphor of a ball game, it's possession (and thus time and position). If you imagine the metaphor of a gun, it's your limited supply of bullets. This exhortation has an implicit assumption of endless resources, which are typically not available in the real world. Of course there are times you should risk things on an uncertain outcome, and be willing to move on to the next opportunity - trying to hold on to a declining situation is often motivated by a sunk-costs fallacy.
But I've heard the 'miss shots you don't take' thing proffered too many times as an excuse for ego-driven, risk-indifferent, and resource-wasting decisions and I'm pretty tired of it. There is a certain sort of person (but I don't men you, parent poster) who comes into a situation, fucks everything up, and then sails off with the excuse of what a bold, visionary risk-taker they are, blaming any obvious failures on the timidity of the team/colleagues. An excess reliance on sports metaphors has become a huge red flag for me in picking the people I work with.
For the record, Blow has said that he's making the language primarily for his own use. I expect that most of the games he makes in the future will be written in this language.
Now if you'll excuse me, I have some kids that I need to eject from my lawn :-)
Until very recently C++ has been the best tool for the job (or more usually C++ and Lua or other scripting language).
- Proprer games are written in Assembly, while AMOS, Turbo Pascal, C, GFA Basic, Turbo BASIC are for wannabe game developers
- Proper games are written in C, Turbo Pascal, AMOS with some Assembly while C++ is too bloated.
- C++ with some Assembly is the proper way, while Java, C#, Go, ... are too bloated.
So it is always kind of interesting to see what the current generation says.
Just an example.
Then there is Unity, and plethora of frameworks where you write in some language and then it gets translated into another and there are just too many variations.
There are still games shipped done in Borland Pascal for that matter :)