Formative Idea: Exit Guards

The | in PARSE has an interesting property, in that if a match fails, the BLOCK! combinator will scan forward looking for it before exiting the block.

>> parse [d d d] ['a 'b 'c | some 'd]
== d

So a FAIL happens right at the 'a, but instead of considering that an overall failure it spooled the rules ahead looking for a | and picks up there.

There's another tool in UPARSE of || called the "Inline Sequencing Operator":

>> parse "ac" ["a" | "b" || "c"]
== "c"

>> parse "bc" ["a" | "b" || "c"]
== "c"

What About More "Spool Ahead Before Exiting" Tools?

I don't have the ideas fully formed, but here's a sample "weird thing" that seems useful:

func: extras.guardfunc/

foo: func [file data] {
   port: open file
   write port data.1
   if not text? data.2 [return fail "data.2 wasn't text"]
   write port data.3
   return okay
   ---
   close port
}

What if no matter how you exited the routine, it would somehow always run the close port?

It would be a bad idea to tax the evaluator to require such things foundationally. But maybe it could give tools that could help. Perhaps there's a GUARD! datatype, and --- looks up to it, and there's EVAL-GUARD which would help you out here, so that you didn't have to slice and dice that function body to get the benefits.

Just a little weird idea that I was reminded of today, when thinking "what should --- mean?"

1 Like