at:tutorial:metaprogramming
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revisionNext revisionBoth sides next revision | ||
at:tutorial:metaprogramming [2007/04/19 21:40] – stimberm | at:tutorial:metaprogramming [2007/07/31 16:46] – jdedecker | ||
---|---|---|---|
Line 1: | Line 1: | ||
- | < | ||
- | |||
===== Metaprogramming ===== | ===== Metaprogramming ===== | ||
Line 14: | Line 12: | ||
>>7 | >>7 | ||
</ | </ | ||
- | However, these constructs are all **syntactic sugar**. Behind the scenes, they all perform message sends. The following code shows the equivalents of the previous code, but with the actual message sends: | + | However, these constructs are all **syntactic sugar** |
< | < | ||
>[5, 6, 7].at(2) | >[5, 6, 7].at(2) | ||
Line 23: | Line 21: | ||
>>7 | >>7 | ||
</ | </ | ||
+ | |||
+ | In the first example above the message //at// is sent to the table **[5, | ||
==== Quasiquoting and splicing ==== | ==== Quasiquoting and splicing ==== | ||
+ | Quasiquoting and splicing are an advanced and powerful metaprogramming techniques that control the evaluation process and allow one to manipulate the evaluation process of the abstract syntax tree. | ||
- | === Qouting | + | === Quoting |
Any valid AmbientTalk expression can be quoted. This prevents the expression from being evaluated. Instead, it is returned literally. | Any valid AmbientTalk expression can be quoted. This prevents the expression from being evaluated. Instead, it is returned literally. | ||
Line 59: | Line 60: | ||
</ | </ | ||
- | Note that in '' | + | Note that in '' |
== Expressions == | == Expressions == | ||
Line 78: | Line 79: | ||
== Statements == | == Statements == | ||
- | Statements (definitions, | + | Statements (definitions, |
< | < | ||
Line 87: | Line 88: | ||
</ | </ | ||
- | If you actually want to quote a literal closure, you should use parantheses, | ||
< | < | ||
- | `{ | foo | foo := 4 } gives a literal closure | + | Quoting a literal closure can be done in two ways: as an expression: < |
+ | To quote a literal closure | ||
</ | </ | ||
Line 127: | Line 128: | ||
>[ 7, 8, 9, @upTo(4) ] | >[ 7, 8, 9, @upTo(4) ] | ||
>>[7, 8, 9, 1, 2, 3, 4] | >>[7, 8, 9, 1, 2, 3, 4] | ||
+ | >[ 7, 8, 9, upTo(4) ] | ||
+ | >>[7, 8, 9, [1, 2, 3, 4]] | ||
</ | </ | ||
+ | In the example above the elements of the table returned by invoking **upTo(4)** are added in place to the table in which the expression was spliced. | ||
Splicing can also be used in combination with quoting and unquoting. AmbientTalk provides the // | Splicing can also be used in combination with quoting and unquoting. AmbientTalk provides the // | ||
Line 154: | Line 158: | ||
> | > | ||
>> | >> | ||
+ | </ | ||
+ | |||
+ | The following example uses meta-programming and reflection to generate a proxy for an object that provides a given interface. The interface' | ||
+ | |||
+ | < | ||
+ | TODO: Update code | ||
+ | </ | ||
+ | |||
+ | < | ||
+ | def isMethodDefinition: | ||
+ | |||
+ | def policyOf: object with: interface { | ||
+ | |||
+ | def policyDefinition := interface.method.bodyExpression.statements; | ||
+ | |||
+ | policyDefinition.each: | ||
+ | if: (isMethodDefinition: | ||
+ | def methodBody := statement.bodyExpression.statements; | ||
+ | if: ((methodBody.length == 1).and: { methodBody[1] == `nil }) then: { | ||
+ | def bodyExpression := `{ #(object) ^ # | ||
+ | statement.bodyExpression := bodyExpression; | ||
+ | } | ||
+ | } | ||
+ | }; | ||
+ | |||
+ | object: interface; | ||
+ | |||
+ | }; | ||
+ | </ | ||
+ | |||
+ | ==== Read / Eval / Print ==== | ||
+ | |||
+ | AmbientTalk reifies the read, eval and print operations. This means that you can read any string and get the responding syntax tree for it, evaluate any syntax tree and get a value for it, and print any value and get a string representation of the value. | ||
+ | |||
+ | < | ||
+ | >read: " | ||
+ | >> | ||
+ | >eval: `(1+2) in: self | ||
+ | >>3 | ||
+ | >print: self | ||
+ | >>"< | ||
+ | </ | ||
+ | |||
+ | Eval is a keyworded message that takes another parameter, namely the object in whose scope the expression must be evaluated. | ||
+ | |||
+ | < | ||
+ | >def o := object: { def x := 4 } | ||
+ | >>< | ||
+ | >eval: `x in: o | ||
+ | >>4 | ||
</ | </ |
at/tutorial/metaprogramming.txt · Last modified: 2009/11/21 07:44 by tvcutsem