Modules: formal specification of word attributes
Similar to script files and ordinary functions, REBOL modules provide a formal specification. It takes the form of a block at the head of the module body. Both these forms are allowed:
REBOL [spec]
body
Note that this is an extension of the script header. That is intentional. Modules can be scripts.
The dynamic make method is:
mod: make module! [
[spec]
body
]
The formal spec provides a lot of information and control over the module (title, name, version, author, needs, etc.) similar to script headers. This is too large of a topic to cover here, nor do I want to make this article that complex. (I will provide details soon enough.)
Instead, I want to focus on specific issues related to module context word (variable) attributes.
First, you should know that a module word can be:
- Commented (like functions)
- Restricted to a specific datatype. E.g. integer only.
- Local or exported. E.g. local words cannot be accessed externally.
- Set, get, and do protected. E.g. you can protect words in various ways.
- Set by an accessor function (possibly).
Each of these is a separate dimension of specification.
The obvious form for word specification is to duplicate that of function specification. That makes it easy to remember. For example:
words: [
user "Name of user" [string!]
pass "User password hash" [binary!]
]
That satisfies #1 and #2 dimensions above.
The question is how to specify LOCAL, EXPORT, and protections. On possibility is to integrate that into the above block:
words: [
user "Name of user" [export string!]
pass "User password hash" [local binary!]
]
Another approach is to split the locals from the exports:
export: [
user "Name of user" [string!]
]
local: [
pass "User password hash" [binary!]
]
This has the advantage of making it clear what is exported and what is not. (And, I prefer this form.)
Also note, that default rules can apply. For instance, if an export block is provided, it can be assumed that all module words not found in the export block are local only. The inverse is also possible.
And finally, there is the get, set, and do protection attributes.
A possibility is to use this approach:
export: [
user "Name of user" [get string!]
key "Encryption key" [set string!]
]
This allows external code to get, but not set the user field, and set but not get the key field (e.g. it is an encryption key that you want to protect).
Then, there is the issue of the DO attribute. It only makes sense for computational datatypes, e.g. functions. So, is DO really necessary? Or, should it be possible to allow DO, but not allow GET (source for the function)?
So, there are some things to think about.
For now, I'm going to ignore the word protection attributes. We can return to those later once we have a running alpha for us all to "play with".
17 Comments
|