Hi Hans-Peter,
thanks, see below.
On 3/2/26 17:02, Hans-Peter Sorge wrote:
Re: Two questions about native/template.hh Hi Jürgen,
thank you for the details.
for -1- : I thought so. Just making sure.
for -2-: Digging deeper into F12 :
/2 2 ⍴'abcd'
SYNTAX ERROR+
/2 2⍴'abcd'
^
⍝ Should the SYNTAX ERROR not being reported before calling F12?
??? There is no F12 above. The syntax error comes because there is no
phrase that matches END OPER VALUE.
F12 /0 0 ⍴'abcd'
eval_ident_Bx() called
Looks OK.
F12 /1 1 ⍴'abcd'
a
Looks OK.
F12 /2 2 ⍴'abcd'
eval_AB() called eval_AB() called
Looks OK except that F12 should be called only once. I would need your
F12 to
troubleshoot this.
Regarding an e.g. more elaborate F12 function, ****
*eval_ident_Bx() *and *eval_fill_B()* are functions that the
interpreter does not have to (or should not) call.
No. It is actually the reduce operator (and not F12) that decides if F12
should be called
normally or if the identity function of F12 should be called instead.
This decision is based on the
shape of B before F12 is even considered. Otherwise different functions
could decide
differently how empty arguments shall be handled.
If F12 gets invoked, the contents of* Value_P A, B, X * is telling F12
how/what to process.
Any kind of side effect (dimentioness, emptiness..) " coming from *A,
B *or*X* has to be handled by F12 internally.
No. It is (in your example) the reduce operator that prepares the
arguments for F12. F12 can not see the
original arguments of the reduce operator; it only sees the argument
that the reduce operator passes to
it in each iteration (if any). The IBM APL2 reference manual clearly
states that F12 is not called if B of
*F12 / B i*s empty and, as a consequence, F12 cannot handle that.
Is this correct?
Best Regards
Hans Peter ****
On 01/03/2026 18:35, Dr. Jürgen Sauermann wrote:
Hi Hans-Peter,
see below.
On 3/1/26 17:49, Hans-Peter Sorge wrote:
Hi Jürgen,
-for 1- In file native/template.hhthe comment states:
// mandatory functions
....
static Token *eval_fill_B*(Value_P B, const NativeFunction * caller);
However there is a fill function for argument B in template_f0:
#if defined TEMPLATE_F0
...
get_function_mux(const char * function_name)
{
....
if (!strcmp(function_name, "*eval_fill_B*"))
return reinterpret_cast<void *>(&*eval_fill_B*);
....
Compile without * if ... eval_fill_B .. * is OK
-for 2- in src/ScalarFunction.cc
it says
/* *eval_fill_B()* is called for:
1. a monadic scalar function with empty B, or ...
...
The Qs:
-1- F0 is niladic. What are the circumstances that *eval_fill_B()*
could get called?
Supposedly never. The *function_mux()* of the native function maps a
function
name string like *"eval_fill_B"*) to a function pointer like
*eval_fill_B()* that can
be called.
To keep things simple, the *function_mux()* is independent of the
arity of the function.
fill functions are either monadic or dyadic, therefore niladic
functions don't have one.
One could remove the calls to *eval_fill_B()* and *eval_fill_AB()* in
the *get_function_mux()
*in *template.hh* but then you have different function_muxed for
different arities which
is merely complicating matters without an obvious advantage.
-2- A monadic call to F12('lib_template_F12.so' ⎕FX 'F12')
with an empty B does not call *eval_fill_B(). *Why not?
F12 'b'
eval_B() called
⍝ as expected
F12 ⍬
eval_B() called
⍝ *eval_fill_B() called* expected too
No The eval_Fill_B function is not called for any empty B but only for
empty arguments of particular functions (most prominently for
reduction or
scan of functions with empty arguments). The IBM APL2 reference manual
contains a list of functions and operators for which the fill
functions are
being called.
I suppose that *F12 / ⍬* will say that the fill function was called.
What am I missing?
Best Regards
Hans-Peter