Compile-time calculation: Difference between revisions
Content added Content deleted
(Added Prolog) |
Thundergnat (talk | contribs) (Rename Perl 6 -> Raku, alphabetize, minor clean-up) |
||
Line 122: | Line 122: | ||
In both cases, the identifier <code>factorial10</code> is given the value 3628800 without any runtime calculations, although in many (or perhaps most) BASICs the first one is handled similarly to C's <code>#define</code>: if it isn't used elsewhere in the code, it doesn't appear at all in the final executable. |
In both cases, the identifier <code>factorial10</code> is given the value 3628800 without any runtime calculations, although in many (or perhaps most) BASICs the first one is handled similarly to C's <code>#define</code>: if it isn't used elsewhere in the code, it doesn't appear at all in the final executable. |
||
=={{header|C}}== |
=={{header|C}}== |
||
Line 196: | Line 195: | ||
.def printf; .scl 2; .type 32; .endef |
.def printf; .scl 2; .type 32; .endef |
||
</pre> |
</pre> |
||
=={{header|C++}}== |
|||
This is called [[wp:Template metaprogramming|Template metaprogramming]]. In fact, templates in C++ are Turing-complete, making deciding whether a program will compile undecidable. |
|||
<lang cpp>#include <iostream> |
|||
template<int i> struct Fac |
|||
{ |
|||
static const int result = i * Fac<i-1>::result; |
|||
}; |
|||
template<> struct Fac<1> |
|||
{ |
|||
static const int result = 1; |
|||
}; |
|||
int main() |
|||
{ |
|||
std::cout << "10! = " << Fac<10>::result << "\n"; |
|||
return 0; |
|||
}</lang> |
|||
Compile-time calculations in C++ look quite different from normal code. We can only use templates, type definitions and a subset of integer arithmetic. It is not possible to use iteration. C++ compile-time programs are similar to programs in pure functional programming languages, albeit with a peculiar syntax. |
|||
{{works with|C++11}} |
|||
Alternative version, using constexpr in C++11: |
|||
<lang cpp>#include <stdio.h> |
|||
constexpr int factorial(int n) { |
|||
return n ? (n * factorial(n - 1)) : 1; |
|||
} |
|||
constexpr int f10 = factorial(10); |
|||
int main() { |
|||
printf("%d\n", f10); |
|||
return 0; |
|||
}</lang> |
|||
Output: |
|||
<pre>3628800</pre> |
|||
The asm produced by G++ 4.6.0 32 bit (-std=c++0x -S), shows the computation is done at compile-time: |
|||
<lang asm>_main: |
|||
pushl %ebp |
|||
movl %esp, %ebp |
|||
andl $-16, %esp |
|||
subl $16, %esp |
|||
call ___main |
|||
movl $3628800, 4(%esp) |
|||
movl $LC0, (%esp) |
|||
call _printf |
|||
movl $0, %eax |
|||
leave |
|||
ret</lang> |
|||
=={{header|C sharp}}== |
=={{header|C sharp}}== |
||
Line 345: | Line 290: | ||
{{out}} |
{{out}} |
||
<pre>3628800</pre> |
<pre>3628800</pre> |
||
=={{header|C++}}== |
|||
This is called [[wp:Template metaprogramming|Template metaprogramming]]. In fact, templates in C++ are Turing-complete, making deciding whether a program will compile undecidable. |
|||
<lang cpp>#include <iostream> |
|||
template<int i> struct Fac |
|||
{ |
|||
static const int result = i * Fac<i-1>::result; |
|||
}; |
|||
template<> struct Fac<1> |
|||
{ |
|||
static const int result = 1; |
|||
}; |
|||
int main() |
|||
{ |
|||
std::cout << "10! = " << Fac<10>::result << "\n"; |
|||
return 0; |
|||
}</lang> |
|||
Compile-time calculations in C++ look quite different from normal code. We can only use templates, type definitions and a subset of integer arithmetic. It is not possible to use iteration. C++ compile-time programs are similar to programs in pure functional programming languages, albeit with a peculiar syntax. |
|||
{{works with|C++11}} |
|||
Alternative version, using constexpr in C++11: |
|||
<lang cpp>#include <stdio.h> |
|||
constexpr int factorial(int n) { |
|||
return n ? (n * factorial(n - 1)) : 1; |
|||
} |
|||
constexpr int f10 = factorial(10); |
|||
int main() { |
|||
printf("%d\n", f10); |
|||
return 0; |
|||
}</lang> |
|||
Output: |
|||
<pre>3628800</pre> |
|||
The asm produced by G++ 4.6.0 32 bit (-std=c++0x -S), shows the computation is done at compile-time: |
|||
<lang asm>_main: |
|||
pushl %ebp |
|||
movl %esp, %ebp |
|||
andl $-16, %esp |
|||
subl $16, %esp |
|||
call ___main |
|||
movl $3628800, 4(%esp) |
|||
movl $LC0, (%esp) |
|||
call _printf |
|||
movl $0, %eax |
|||
leave |
|||
ret</lang> |
|||
=={{header|Clojure}}== |
=={{header|Clojure}}== |
||
Line 742: | Line 741: | ||
grep 172801 sec.s |
grep 172801 sec.s |
||
movl $<span style="color:red">172801</span>, camlSec |
movl $<span style="color:red">172801</span>, camlSec |
||
=={{header|Oforth}}== |
=={{header|Oforth}}== |
||
Line 876: | Line 874: | ||
<lang perl>my $tenfactorial = 10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2;</lang> |
<lang perl>my $tenfactorial = 10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2;</lang> |
||
=={{header|Perl 6}}== |
|||
<lang perl6>constant $tenfact = [*] 2..10; |
|||
say $tenfact;</lang> |
|||
Like Perl 5, we also have a BEGIN block, but it also works to introduce a blockless statement, |
|||
the value of which will be stored up to be used in the surrounding expression at run time: |
|||
<lang perl6> say(BEGIN [*] 2..10);</lang> |
|||
=={{header|Phix}}== |
=={{header|Phix}}== |
||
Line 1,061: | Line 1,048: | ||
(fact10) |
(fact10) |
||
</lang> |
</lang> |
||
=={{header|Raku}}== |
|||
(formerly Perl 6) |
|||
<lang perl6>constant $tenfact = [*] 2..10; |
|||
say $tenfact;</lang> |
|||
Like Perl 5, we also have a BEGIN block, but it also works to introduce a blockless statement, |
|||
the value of which will be stored up to be used in the surrounding expression at run time: |
|||
<lang perl6> say(BEGIN [*] 2..10);</lang> |
|||
=={{header|REXX}}== |
=={{header|REXX}}== |
||
Line 1,105: | Line 1,103: | ||
func factorial nr if nr = 1 return 1 else return nr * factorial(nr-1) ok |
func factorial nr if nr = 1 return 1 else return nr * factorial(nr-1) ok |
||
</lang> |
</lang> |
||
=={{header|Rust}}== |
=={{header|Rust}}== |
||
The Rust compiler can automatically do optimizations in the code to calculate the factorial. |
The Rust compiler can automatically do optimizations in the code to calculate the factorial. |
||
Line 1,161: | Line 1,160: | ||
20: dup |
20: dup |
||
21: new #40 // class java/lang/StringBuilder</pre> |
21: new #40 // class java/lang/StringBuilder</pre> |
||
=={{header|Seed7}}== |
=={{header|Seed7}}== |
||