Hi Elias,
that construct is already in place, called an EOC (end-of-context)
handler .
However, using EOC handlers appears to be easy, but using them properly
is
extremely difficult, because they require very
detailed knowledge of the internals
of GNU APL.
For example, if your native function is used together with an
operator (typically the
EACH or the POWER operator) then every iteration of the operator
may construct
a new )SI frame (and call its EOC handlers when finished, except
for the last iteration).
And you there could be have multiple EOC handlers in the same )SI
frame.
There is a fairly large number of previous trouble reports that
were caused by improper
use of EOC handlers (by myself). EOC handlers are one of the two
most difficult (read:
error-prone) areas in GNU APL (the other one being output
formatting).
Besides the trouble that EOC handlers cause, it is not really
clear to me under which
circumstances it would make sense to defer the handling of an
error until the )SI stack
is popped (as opposed to handling it right away).
If all you need is a APL function cleanup that is called
after some other function foo
has finished (with an error or not) then you could do something
like:
cleanup ⊢ ''
⎕EA 'foo'
This is somewhat ugly because you do it above foo rather
than inside foo, but it is beautiful
when compared to an EOC solution
/// Jürgen
On 04/20/2016 08:31 AM, Elias Mårtenson
wrote:
Do you think it would be possible to implement a
"finally" construct for native libraries? Basically, what I'm
asking for is the ability to register a callback with a specific
stack frame that is called when that frame is unrolled.
Regards,
Elias
On 14 Apr 2016 01:51, "Juergen Sauermann"
< address@hidden>
wrote:
Hi Kacper et al,
I understand. But I would say that using ⎕EA as
you describe is exactly how
cleanup should be done. I see ⎕EA not like (as
the name may suggest) a means of
trying different paths until one succeeds like in:
'try_A'
⎕EA 'try_B' ⎕EA 'try_C' ...
but rather as:
'cleanup_failed_B'
⎕EA 'try_B'
I also don;t see a good way of introducing a defer
function without introducing
a dubious APL syntax extension that would be difficult to
read for people not
knowing the extended syntax. For the sake of
compatibility, such things should,
IMHO, be avoided.
/// Jürgen
On 04/12/2016 02:10 AM, Kacper Gutowski wrote:
If I understand correctly, Elias wants to have something that would
ensure that every file opened is eventually closed (only more general so
it can be applied to any external resources not only files). That is in
a code similar to the following, to ensure the line 3 is always run even
if there's an error in FUN.
[1] FD←⎕FIO[3]STH
[2] FUN FD
[3] ⎕FIO[4]FD
This can be ensured by wrapping FUN call with ⎕EA or ⎕EC. They return
to the caller instead of suspending execution if error happens and this
is correct and expected behaviour. But the intention is to have the
file closed, not making the function unsuspendable, so this would be
a side effect of the solution of using ⎕EA rather than the intended
behaviour. But this doesn't mean there's anything wrong with ⎕EA or
⎕EC, of course.
My understanding is that requested is some way to associate some kind of
clean up code with )SI entry that would be run upon that entry being
cleared from )SI regardless of how that happens.
The way I imagine it, it could look like this (using an imaginary
function ‘defer’ with a name borrowed from Golang; not an actual
transcript):
∇ FOO
[1] FD←⎕FIO[3]STH
[2] defer '⎕FIO[4]FD'
[3] FUN FD
[4] other stuff ∇
STH←'filename'
⎕FX 'FUN F' '1+'
FOO
SYNTAX ERROR
FUN[1] 1+
^^
⍝ here situation can be examined
)VARS
F FD
)SIS
FUN[1] 1+
^^
FOO[3] FUN FD
^
⋆ FOO
^
→
⍝ here ⎕FIO[4]FD is executed
-k
|