Here's is R3-Alpha's PARSE-WRITE-DIALECT from %prot-http.r
parse-write-dialect: func [port block /local spec] [
spec: port/spec
parse block [
[set block word! (spec/method: block) | (spec/method: 'post)]
opt [set block [file! | url!] (spec/path: block)]
[set block block! (spec/headers: block) | (spec/headers: [])]
[set block [any-string! | binary!] (spec/content: block) | (spec/content: none)]
]
]
You couldn't set paths in R3-Alpha parse, which is weird. So things had to be captured into a temporary variable (it reused the input block for some reason).
Let's imagine that setting paths were legal:
parse-write-dialect: func [port block /local spec] [
spec: port/spec
parse block [
[set spec/method word! | (spec/method: 'post)]
opt [set spec/path [file! | url!]]
[set spec/headers block! | (spec/headers: [])]
[set spec/content [any-string! | binary!] | (spec/content: none)]
]
]
Let's do a quick transformation of this to PARSE3 in Ren-C, where the keyword TRY now replaces OPT:
parse-write-dialect: func [port block <local> spec] [
spec: port.spec
parse3 block [ ; PARSE3 is R3-Alpha-compatible parse
[set spec.method word! | (spec.method: 'post)]
try [set spec.path [file! | url!]]
[set spec.headers block! | (spec.headers: [])]
[set spec.content [any-string! | binary!] | (spec.content: null)]
]
]
-
The TUPLE!s help us see we're not making function calls, which is nice
-
/LOCAL is a legitimate normal refinement, and
<local>
variables are truly local--you can't slip them in from the caller. Because they are invisible, you can build function compositions that don't have to worry about colliding with their names.- It also frees up /LOCAL to just be a typical refinement, like TIME/LOCAL
Now let's throw in some UPARSE, with the SET-WORD!s for assignment...
parse-write-dialect: func [port block <local> spec] [
spec: port.spec
parse block [ ; PARSE is now UPARSE
[spec.method: word! | (spec.method: 'post)]
try [spec.path: [file! | url!]]
[spec.headers: block! | (spec.headers: [])]
[spec.content: [any-string! | binary!] | (spec.content: null)]
]
]
It looks a little tighter...but then we also have the ability to factor the assignments out. And as it happens, that last line could just be try [any-string! | binary!], because TRY would assign the result to NULL if it can't match:
parse-write-dialect: func [port block <local> spec] [
spec: port.spec
parse block [
spec.method: [word! | ('post)]
spec.path: try [file! | url!]
spec.headers: [block! | ([])]
spec.content: try [any-string! | binary!]
]
]
Improved!