Difference between revisions of "Guide:Introspection and Reflection"
(New page: === Introspection and reflection === Ioke supports quite fancy introspection and reflection capabilities. In Ioke, reflection includes the ability to change data dynamically, as well as i...) |
(→Introspection and reflection) |
||
Line 1: | Line 1: | ||
− | + | = Introspection and reflection = | |
Ioke supports quite fancy introspection and reflection capabilities. In Ioke, reflection includes the ability to change data dynamically, as well as introspect on it. Since the message based structure of a program is available at runtime, most things can be changed dynamically. The internal structure of a program is also very easy to inspect. | Ioke supports quite fancy introspection and reflection capabilities. In Ioke, reflection includes the ability to change data dynamically, as well as introspect on it. Since the message based structure of a program is available at runtime, most things can be changed dynamically. The internal structure of a program is also very easy to inspect. | ||
Line 5: | Line 5: | ||
All objects in Ioke have some core methods that are used to look at them. Some come from Base, and some come from DefaultBehavior. The rest of the reflection and metaprogramming capabilities belong to the Message kind. | All objects in Ioke have some core methods that are used to look at them. Some come from Base, and some come from DefaultBehavior. The rest of the reflection and metaprogramming capabilities belong to the Message kind. | ||
− | + | === kind === | |
Should be a text that gives the full name of the kind this object is closest mimic to. Except for nil, true and false, this will return a text that starts with a capital letter. | Should be a text that gives the full name of the kind this object is closest mimic to. Except for nil, true and false, this will return a text that starts with a capital letter. | ||
Line 16: | Line 16: | ||
This code will first print "Foo", and then print "Foo Bar", since an object assigned to a cell with a capital initial letter will get a new kind value. | This code will first print "Foo", and then print "Foo Bar", since an object assigned to a cell with a capital initial letter will get a new kind value. | ||
− | + | === kind? === | |
Takes one text argument and returns true if the object has that kind anywhere in its mimic chain. | Takes one text argument and returns true if the object has that kind anywhere in its mimic chain. | ||
Line 31: | Line 31: | ||
As you can see in this example, "kind?" can return true for several different texts. | As you can see in this example, "kind?" can return true for several different texts. | ||
− | + | === notice === | |
When looking at objects, there are two ways to get information about them, notice and inspect. If you want a brief description of an object where it's important that the description doesn't take up much space, notice should be used. If an exhaustive description is needed, inspect should be used instead. For some objects these both return the same thing, but for Origin mimics, the difference is large. | When looking at objects, there are two ways to get information about them, notice and inspect. If you want a brief description of an object where it's important that the description doesn't take up much space, notice should be used. If an exhaustive description is needed, inspect should be used instead. For some objects these both return the same thing, but for Origin mimics, the difference is large. | ||
Line 41: | Line 41: | ||
The default notice for Origin mimics will combine the kind and the unique hex id for the object, and create a text of that. The "notice" method should be overridden to provide better information in most cases. | The default notice for Origin mimics will combine the kind and the unique hex id for the object, and create a text of that. The "notice" method should be overridden to provide better information in most cases. | ||
− | + | === inspect === | |
In contrast to notice, inspect is used to get exhaustive information. If a composite object is asked for its inspect, a quite large dump of information will often be shown. For a new object the output will be smaller, but usually still larger than the notice for it. | In contrast to notice, inspect is used to get exhaustive information. If a composite object is asked for its inspect, a quite large dump of information will often be shown. For a new object the output will be smaller, but usually still larger than the notice for it. | ||
Line 57: | Line 57: | ||
If another representation makes more sense for inspection, "inspect" should definitely be overridden by custom objects. | If another representation makes more sense for inspection, "inspect" should definitely be overridden by custom objects. | ||
− | + | === uniqueHexId === | |
This method is used to return a text that contains a unique hex identity for an object. This text is guaranteed to be unique within a virtual machine for any object, and is the mechanism that "inspect" and "notice" uses. | This method is used to return a text that contains a unique hex identity for an object. This text is guaranteed to be unique within a virtual machine for any object, and is the mechanism that "inspect" and "notice" uses. | ||
− | + | === cellSummary === | |
Calling "inspect" on any Origin mimic will dispatch to "cellSummary", which displays all the cell information about a specific object. | Calling "inspect" on any Origin mimic will dispatch to "cellSummary", which displays all the cell information about a specific object. | ||
− | + | === cell === | |
The "cell" method can be used for two different things. The first one is to get access to a value without activating it, and the second is to get access to a cell based on a name that you don't know at the time you're writing the program. The "cell" method takes one argument that is the name of the cell to fetch. The fetching works the same as regular cell lookup, except that activation doesn't happen. This means that a condition will still be signalled if you try to get something that doesn't exist. | The "cell" method can be used for two different things. The first one is to get access to a value without activating it, and the second is to get access to a cell based on a name that you don't know at the time you're writing the program. The "cell" method takes one argument that is the name of the cell to fetch. The fetching works the same as regular cell lookup, except that activation doesn't happen. This means that a condition will still be signalled if you try to get something that doesn't exist. | ||
Line 77: | Line 77: | ||
name = :foo | name = :foo | ||
cell(name) ;; the value of foo</pre> | cell(name) ;; the value of foo</pre> | ||
− | + | ||
+ | === cell= === | ||
Just as with "cell", "cell=" can be used to set cells that you don't know the name of at the time of writing the program. As discussed in the chapter on assignment, cell= can also be used to set cells that can't be set in the regular way due to naming strangeness. | Just as with "cell", "cell=" can be used to set cells that you don't know the name of at the time of writing the program. As discussed in the chapter on assignment, cell= can also be used to set cells that can't be set in the regular way due to naming strangeness. | ||
− | + | === cell? === | |
If you're not sure if a cell exists, using "cell?" is the way to find out. Give it a name and it returns true or false depending on if that cell exists. | If you're not sure if a cell exists, using "cell?" is the way to find out. Give it a name and it returns true or false depending on if that cell exists. | ||
− | + | === cellNames === | |
If you want to get the names of all the cells an object contains, you can get that with cellNames. By default, cellNames will only return the names of cells that belong to the receiver, but if an argument of true is sent to the call, the resulting list will contain the names of all cells of all mimics too. | If you want to get the names of all the cells an object contains, you can get that with cellNames. By default, cellNames will only return the names of cells that belong to the receiver, but if an argument of true is sent to the call, the resulting list will contain the names of all cells of all mimics too. | ||
Line 94: | Line 95: | ||
x cellNames(true) ;; return a long list, including :f</pre> | x cellNames(true) ;; return a long list, including :f</pre> | ||
− | + | ||
+ | === cells === | ||
Just like cellNames return the names of all the cells, the "cells" method will return a Dict of all the cells with their values. And just like cellNames, cells take an optional boolean argument on whether to include the cells of mimics too. | Just like cellNames return the names of all the cells, the "cells" method will return a Dict of all the cells with their values. And just like cellNames, cells take an optional boolean argument on whether to include the cells of mimics too. | ||
Line 103: | Line 105: | ||
x cells(true) ;; return a large dict, including f: 42</pre> | x cells(true) ;; return a large dict, including f: 42</pre> | ||
− | + | ||
+ | === mimics === | ||
Returns a list of all direct mimics of the receiver. | Returns a list of all direct mimics of the receiver. | ||
− | + | === mimics? === | |
Takes one object as argument and returns true or false depending on if the argument is anywhere in the receiving objects mimic chain. | Takes one object as argument and returns true or false depending on if the argument is anywhere in the receiving objects mimic chain. | ||
− | + | === message === | |
Takes one symbol argument and creates a new Message mimic with that argument as its name. | Takes one symbol argument and creates a new Message mimic with that argument as its name. | ||
− | + | === Message code === | |
Returns a text that describes the code this message chain represents. It will hide some of the internal shuffling, but operators will be displayed using canonical form. | Returns a text that describes the code this message chain represents. It will hide some of the internal shuffling, but operators will be displayed using canonical form. | ||
− | + | === Message formattedCode === | |
Returns a text that is formatted and indented in a canonical way. This method is used to generate the documentation code for DokGen, among other things. | Returns a text that is formatted and indented in a canonical way. This method is used to generate the documentation code for DokGen, among other things. | ||
− | + | === Message evalArgAt === | |
Takes the index of the argument to evaluate, and the ground to evaluate it on - returns the result of evaluating the argument. | Takes the index of the argument to evaluate, and the ground to evaluate it on - returns the result of evaluating the argument. | ||
− | + | === Message fromText === | |
Takes one text argument that should contain Ioke code, and returns the parsed message chain from that code, without evaluating it. | Takes one text argument that should contain Ioke code, and returns the parsed message chain from that code, without evaluating it. | ||
− | + | === Message doText === | |
Takes one text argument that should contain Ioke code, and returns the result of evaluating that code in the current context. | Takes one text argument that should contain Ioke code, and returns the result of evaluating that code in the current context. | ||
− | + | === Message filename === | |
Returns the filename where the receiving message was defined. | Returns the filename where the receiving message was defined. | ||
− | + | === Message line === | |
Returns the line number where the receiving message was defined. | Returns the line number where the receiving message was defined. | ||
− | + | === Message position === | |
Returns the position in the line where the receiving message was defined. | Returns the position in the line where the receiving message was defined. | ||
− | + | === Message name === | |
Returns the name of the message. The name of the message is what you generally talk about when saying you send a message. It can also be called the selector in other languages. | Returns the name of the message. The name of the message is what you generally talk about when saying you send a message. It can also be called the selector in other languages. | ||
− | + | === Message name= === | |
Update the message with a new name. From this point on the message will only have that name, so doing this on a message that is part of an existing message chain will change the behavior of that code: | Update the message with a new name. From this point on the message will only have that name, so doing this on a message that is part of an existing message chain will change the behavior of that code: | ||
Line 158: | Line 161: | ||
msg next name = "-" | msg next name = "-" | ||
msg code ;; "2 -(1)"</pre> | msg code ;; "2 -(1)"</pre> | ||
− | + | ||
+ | === Message prev === | ||
Returns the prev pointer of this message, or nil if no prev pointer exists. | Returns the prev pointer of this message, or nil if no prev pointer exists. | ||
− | + | === Message prev= === | |
Sets the prev pointer of a message. The new value should be either nil or another message. | Sets the prev pointer of a message. The new value should be either nil or another message. | ||
− | + | === Message next === | |
Returns the next pointer of this message, or nil if no next pointer exists. | Returns the next pointer of this message, or nil if no next pointer exists. | ||
− | + | === Message next= === | |
Sets the next pointer of a message. The new value should be either nil or another message. | Sets the next pointer of a message. The new value should be either nil or another message. | ||
− | + | === Message sendTo === | |
Sends a message to an object. It's important to realize that sendTo will not evaluate the whole message chain -- it will only send one message with arguments to an object. | Sends a message to an object. It's important to realize that sendTo will not evaluate the whole message chain -- it will only send one message with arguments to an object. | ||
− | + | === Message keyword? === | |
Returns true if this message is a keyword message, and false otherwise. | Returns true if this message is a keyword message, and false otherwise. | ||
Line 184: | Line 188: | ||
There are many more methods that can be used to do interesting introspection and reflection in Ioke. The reference documentation includes them all. Most of the interesting stuff can be found on the Message kind. | There are many more methods that can be used to do interesting introspection and reflection in Ioke. The reference documentation includes them all. Most of the interesting stuff can be found on the Message kind. | ||
− | + | === send === | |
In many cases you want to activate something activatable in a cell, with a specific receiver. You can do this using send. You can send messages to most objects. Send takes one argument that should evaluate to the name of the message to send, and then sends along all other arguments given to send to the new message. These arguments will remain unevaluated, and will be evaluated at the leisure of the final method activated. | In many cases you want to activate something activatable in a cell, with a specific receiver. You can do this using send. You can send messages to most objects. Send takes one argument that should evaluate to the name of the message to send, and then sends along all other arguments given to send to the new message. These arguments will remain unevaluated, and will be evaluated at the leisure of the final method activated. |
Revision as of 00:27, 26 January 2009
Contents
- 1 Introspection and reflection
- 1.1 kind
- 1.2 kind?
- 1.3 notice
- 1.4 inspect
- 1.5 uniqueHexId
- 1.6 cellSummary
- 1.7 cell
- 1.8 cell=
- 1.9 cell?
- 1.10 cellNames
- 1.11 cells
- 1.12 mimics
- 1.13 mimics?
- 1.14 message
- 1.15 Message code
- 1.16 Message formattedCode
- 1.17 Message evalArgAt
- 1.18 Message fromText
- 1.19 Message doText
- 1.20 Message filename
- 1.21 Message line
- 1.22 Message position
- 1.23 Message name
- 1.24 Message name=
- 1.25 Message prev
- 1.26 Message prev=
- 1.27 Message next
- 1.28 Message next=
- 1.29 Message sendTo
- 1.30 Message keyword?
- 1.31 send
Introspection and reflection
Ioke supports quite fancy introspection and reflection capabilities. In Ioke, reflection includes the ability to change data dynamically, as well as introspect on it. Since the message based structure of a program is available at runtime, most things can be changed dynamically. The internal structure of a program is also very easy to inspect.
All objects in Ioke have some core methods that are used to look at them. Some come from Base, and some come from DefaultBehavior. The rest of the reflection and metaprogramming capabilities belong to the Message kind.
kind
Should be a text that gives the full name of the kind this object is closest mimic to. Except for nil, true and false, this will return a text that starts with a capital letter.
Foo = Origin mimic Foo mimic kind println Foo Bar = Origin mimic Foo Bar mimic kind println
This code will first print "Foo", and then print "Foo Bar", since an object assigned to a cell with a capital initial letter will get a new kind value.
kind?
Takes one text argument and returns true if the object has that kind anywhere in its mimic chain.
Foo = Origin mimic foo = Foo mimic foo kind?("foo") ;; false foo kind?("Foo") ;; true foo kind?("Text") ;; false foo kind?("Origin") ;; true foo kind?("Ground") ;; true foo kind?("DefaultBehavior") ;; true foo kind?("Base") ;; true
As you can see in this example, "kind?" can return true for several different texts.
notice
When looking at objects, there are two ways to get information about them, notice and inspect. If you want a brief description of an object where it's important that the description doesn't take up much space, notice should be used. If an exhaustive description is needed, inspect should be used instead. For some objects these both return the same thing, but for Origin mimics, the difference is large.
Foo = Origin mimic Foo x = "blarg" Foo y = 42 Foo notice ;; Foo_0x7CBDE6
The default notice for Origin mimics will combine the kind and the unique hex id for the object, and create a text of that. The "notice" method should be overridden to provide better information in most cases.
inspect
In contrast to notice, inspect is used to get exhaustive information. If a composite object is asked for its inspect, a quite large dump of information will often be shown. For a new object the output will be smaller, but usually still larger than the notice for it.
Foo = Origin mimic Foo x = "blarg" Foo y = 42 Foo inspect println
This will print:
Foo_0x7CBDE6: kind = "Foo" x = "blarg" y = 42
If another representation makes more sense for inspection, "inspect" should definitely be overridden by custom objects.
uniqueHexId
This method is used to return a text that contains a unique hex identity for an object. This text is guaranteed to be unique within a virtual machine for any object, and is the mechanism that "inspect" and "notice" uses.
cellSummary
Calling "inspect" on any Origin mimic will dispatch to "cellSummary", which displays all the cell information about a specific object.
cell
The "cell" method can be used for two different things. The first one is to get access to a value without activating it, and the second is to get access to a cell based on a name that you don't know at the time you're writing the program. The "cell" method takes one argument that is the name of the cell to fetch. The fetching works the same as regular cell lookup, except that activation doesn't happen. This means that a condition will still be signalled if you try to get something that doesn't exist.
x = 42 cell(:x) ;; 42 x = method() cell(:x) ;; the method object name = :foo cell(name) ;; the value of foo
cell=
Just as with "cell", "cell=" can be used to set cells that you don't know the name of at the time of writing the program. As discussed in the chapter on assignment, cell= can also be used to set cells that can't be set in the regular way due to naming strangeness.
cell?
If you're not sure if a cell exists, using "cell?" is the way to find out. Give it a name and it returns true or false depending on if that cell exists.
cellNames
If you want to get the names of all the cells an object contains, you can get that with cellNames. By default, cellNames will only return the names of cells that belong to the receiver, but if an argument of true is sent to the call, the resulting list will contain the names of all cells of all mimics too.
x = Origin mimic x f = 42 x cellNames ;; return [:f] x cellNames(true) ;; return a long list, including :f
cells
Just like cellNames return the names of all the cells, the "cells" method will return a Dict of all the cells with their values. And just like cellNames, cells take an optional boolean argument on whether to include the cells of mimics too.
x = Origin mimic x f = 42 x cells ;; return {f: 42} x cells(true) ;; return a large dict, including f: 42
mimics
Returns a list of all direct mimics of the receiver.
mimics?
Takes one object as argument and returns true or false depending on if the argument is anywhere in the receiving objects mimic chain.
message
Takes one symbol argument and creates a new Message mimic with that argument as its name.
Message code
Returns a text that describes the code this message chain represents. It will hide some of the internal shuffling, but operators will be displayed using canonical form.
Message formattedCode
Returns a text that is formatted and indented in a canonical way. This method is used to generate the documentation code for DokGen, among other things.
Message evalArgAt
Takes the index of the argument to evaluate, and the ground to evaluate it on - returns the result of evaluating the argument.
Message fromText
Takes one text argument that should contain Ioke code, and returns the parsed message chain from that code, without evaluating it.
Message doText
Takes one text argument that should contain Ioke code, and returns the result of evaluating that code in the current context.
Message filename
Returns the filename where the receiving message was defined.
Message line
Returns the line number where the receiving message was defined.
Message position
Returns the position in the line where the receiving message was defined.
Message name
Returns the name of the message. The name of the message is what you generally talk about when saying you send a message. It can also be called the selector in other languages.
Message name=
Update the message with a new name. From this point on the message will only have that name, so doing this on a message that is part of an existing message chain will change the behavior of that code:
msg = Message fromText("2 + 1") msg next name = "-" msg code ;; "2 -(1)"
Message prev
Returns the prev pointer of this message, or nil if no prev pointer exists.
Message prev=
Sets the prev pointer of a message. The new value should be either nil or another message.
Message next
Returns the next pointer of this message, or nil if no next pointer exists.
Message next=
Sets the next pointer of a message. The new value should be either nil or another message.
Message sendTo
Sends a message to an object. It's important to realize that sendTo will not evaluate the whole message chain -- it will only send one message with arguments to an object.
Message keyword?
Returns true if this message is a keyword message, and false otherwise.
There are many more methods that can be used to do interesting introspection and reflection in Ioke. The reference documentation includes them all. Most of the interesting stuff can be found on the Message kind.
send
In many cases you want to activate something activatable in a cell, with a specific receiver. You can do this using send. You can send messages to most objects. Send takes one argument that should evaluate to the name of the message to send, and then sends along all other arguments given to send to the new message. These arguments will remain unevaluated, and will be evaluated at the leisure of the final method activated.