Prior to this, words such as
run-process
would take either a string, an array of strings, or an assoc. The latter was used to specify more advanced launch parameters, such as I/O redirection. Here is a typical example of the old way:{
{ +command+ "make clean install" }
{ +stdout+ "../build-log" }
{ +stderr+ +stdout+ }
} run-process
This looks nice and neat, however, if some of the values are computed, then you cannot use a literal assoc, you have to construct one. Suppose we want to add a 5 minute timeout. Here is one way:
[
"make clean install" +command+ set
"../build-log" +stdout+ set
+stdout+ +stderr+ set
5 minutes +timeout+ set
] { } make run-process
Having to change all of the code just because one parameter becomes computed is not so nice. The other alternative is to use something like bake:
{
{ +command+ "make clean install" }
{ +stdout+ "../build-log" }
{ +stderr+ +stdout+ }
{ +timeout+ %[ 5 minutes ] }
} bake run-process
This is better but now you have
bake
, %[
which don't pertain to your problem domain, plus some unnecessary Lisp-style nesting. And what if you wanted to build up a descriptor in one word, but then have another word which amended it further? You'd have to bake two assocs and use an assoc word such as 'union'. Bake is nice in other contexts but it is the wrong solution here.Now suppose we used a tuple of process launch parameters:
<process>
"make clean install" over set-process-command
"../build-log" over set-process-stdout
+stdout+ over set-process-stderr
5 minutes over set-process-timeout
run-process
This is more composable; you can write a word which takes a descriptor, and sets some slots in it. It is also relatively easy to have both literal launch parameters and computed ones, and adding a computed parameter to an all-literal descriptor doesn't require introducing
make-assoc
or bake
. However, now we've introduced some stack shuffles and the accessor names are kind of long.Enter new-slots:
<process>
"make clean install" >>command
"../build-log" >>stdout
+stdout+ >>stderr
5 minutes >>timeout
run-process
This is about as ideal as it gets. No unnecessary nesting, no stack shuffling, and the only words that appear directly pertain to your problem domain.
What about the case where a launch parameter comes off the stack? Suppose the command name is an input and everything else is computed on the spot. Here is the old way:
[
+command+ set
"../build-log" +stdout+ set
+stdout+ +stderr+ set
5 minutes +timeout+ set
] { } make run-process
The new way introduces a swap, but there is still a net reduction in complexity:
<process>
swap >>command
"../build-log" >>stdout
+stdout+ >>stderr
5 minutes >>timeout
Now suppose we have a make target name on the stack and we want to run make with that target. Here is the old way:
[
"make" swap 2array +command+ set
"../build-log" +stdout+ set
+stdout+ +stderr+ set
5 minutes +timeout+ set
] { } make run-process
With new-slots:
<process>
"make" rot 2array >>command
"../build-log" >>stdout
+stdout+ >>stderr
5 minutes >>timeout
With bake and new-slots:
<process>
swap { "make" , } bake >>command
"../build-log" >>stdout
+stdout+ >>stderr
5 minutes >>timeout
I find the latter preferrable to the first two.
The situation with smtp is a little different. Previously, I had a
send-simple-message
word which took a body, subject, from and to on the stack:"Blahblah" "Hi" { "alice@aol.com" "joe@aol.com" } "bob@aol.com" send-simple-message
Clearly, this doesn't scale as additional parameters are added; header lines, attachments, etc. The new code uses new-slots and it is a lot more aesthetically pleasing:
<email>
"Blahblah" >>body
"Hi" >>subject
{ "alice@aol.com" "joe@aol.com" } >>to
"bob@aol.com" >>from
send
Not only does it read better but also it is easy to add additional fields such as CC, BCC, attachments, S/MIME support, etc. (Well, easy enough to add the fields; actually implementing some of these is another matter altogether...)
New-slots is going into the core very soon now. Bake will need to be worked on some more; then it will go in the core and replace usages of make there. Make will go into a library in extra and be phased out along with old slots.
3 comments:
What other libraries are planed for a move into core?
nice. one question .. is the <email> tuple predefined somewhere (in the same vocab as "send" probably) or it is defined (what slots it contains) and created right there?
middayc: the email tuple is defined in the smtp vocab.
Post a Comment