What Is Metaprogramming?
Metaprogramming refers to the writing of certain types of computer programs. These types of computer programs write or manipulate other programs (or themselves) as their data, or complete some of the work that should be done at compile time at runtime. In many cases it is more efficient than writing all the code by hand. The language in which the metaprogram is written is called the metalanguage, and the language being operated on is called the target language. The ability of a language to be its own meta-language is called reflection.
Metaprogramming
- Reflection is a valuable language feature that promotes metaprogramming. Treat programming languages themselves as first-class objects (such as
- The LISP language is typical of metaprogramming and was very popular from the 1970s to the 1980s, especially in the field of artificial intelligence. C ++ 's metaprogramming (or generic programming, to be precise) came to light in early 1994 and was first discovered by a man named Erwin Unruh. During a meeting of the C ++ Standards Committee in San Diego in 1994, Erwin Unruh presented a special piece of code. What makes this code special is that the functionality of the program is implemented at compile time, not at run time.
- A simple metaprogramming example is a production programming example using a bash script:
- #! / bin / bash
- # metaprogram
- echo '#! / bin / bash'> program
- for ((I = 1; I <= 992; I ++)) do
- echo "echo $ I" >> program
- done
- chmod + x program
- This script (or program) generates a new 993-line program to print 1 to 992. This is just a demonstration that writing more code with code is not the most efficient way to print numbers. However, a programmer can write and execute metaprograms in minutes, but generates nearly 1,000 lines of code.
- ===========
- Templates can also be used for metaprogramming in C ++ (the following code is compiled and passed in VC2008):
- #include <iostream>
- using namespace std;
- int Result;
- // Main template
- template <int N> // template
- class Fibonacci
- {
- public:
- enum {Result = Fibonacci <N-1> :: Result + Fibonacci <N-2> :: Result};
- // enum with implicit calculations
- };
- // Fully specialized template
- template <>
- class Fibonacci <1> // Constructor with constant parameter 1
- {
- public:
- enum {Result = 1};
- // Assign an initial value of 1 to the enumeration
- };
- // Fully specialized template
- template <>
- class Fibonacci <0> // Template with parameter 0
- {
- public:
- enum {Result = 0};
- // Assign an initial value of 0 to the enumeration
- };
- int main ()
- {
- std :: cout << "The Fibonacci number of item 20 is:" << Fibonacci <20> :: Result << std :: endl;
- // Hidden calculation
- system ("pause");
- return 1;
- }
- This example defines a class template, an enum type is declared in the class, and the secret of the program lies in the construction of the enum type. From the construction of the enumeration type, it can be seen that he has a kind of implicit iterative calculation. Two constructors initialize the initial value of the sequence for the enumeration type. When "Fibonacci <20> :: Reasult" is called, iterate based on these two initial values. Therefore, the program does not display calculations at run time, but is calculated by the compiler at compile time.
- When the compiler instantiates Fibonacci <20>, in order to assign values to its enum Result, the compiler needs to instantiate Fibonacci <19> and Fibonacci <18>, and then do the same ... when instantiating to Fibonacci At <1> and Fibonacci <0>, the fully specialized template is instantiated, and the iteration ends.
- Therefore, the compiled result of this program contains only one constant value, and the output is as follows:
- The Fibonacci number of the 20th term is: 6765
- ===========
- Not all metaprogramming uses production programming. If programs can change at runtime (such as Lisp, Ruby, Python, Smalltalk, Lua, Groovy, and JavaScript), this technique can use metaprogramming without actually generating source code.
- In Ruby, the most commonly used methods are the attr series, such as attr, attr_reader, attr_writer, and attr_accessor. The attr_reader method generates a method for reading an instance variable for an instance variable, the attr_writer generates a method for writing a value for it, and the attr_accessor has both of these functions.
- class Foo
- attr_reader: just_read
- attr_writer: just_write
- attr_accessor: both_read_and_write
- def initialize
- @just_read = 0
- @just_write = 0
- @both_read_and_write = 0
- end
- end
- # Output attr method generation method
- puts Foo.instance_methods-Foo.superclass.instance_methods
- The most commonly used metaprogramming tool is a compiler, which translates a high-level language into assembly or machine language. A more flexible method is to embed an interpreter in the program to directly process the program data. There are implementations such as RemObject's Pascal Script written for Object Pascal.
- Another very common example of metaprogramming is lex and yacc, which are used to generate lexers and parsers. Yacc is often used as a compiler compiler, generating a tool for converting high-level languages to machine languages.
- Quine is a special metaprogram whose source code is equal to the output.
- Language-oriented programming is a programming style with a strong focus on metaprogramming, implemented through domain-specific languages.