From kry|ov@r00t @end|ng |rom gm@||@com  Thu Mar  2 15:47:50 2023
From: kry|ov@r00t @end|ng |rom gm@||@com (Ivan Krylov)
Date: Thu, 2 Mar 2023 17:47:50 +0300
Subject: [Rd] `dendrapply` Enhancements
In-Reply-To: <BL0PR04MB4706B185A345A98AB4AB829AD9AC9@BL0PR04MB4706.namprd04.prod.outlook.com>
References: <BL0PR04MB47068D544F5A49315EF1D042D9AB9@BL0PR04MB4706.namprd04.prod.outlook.com>
 <CALK03d1PWiA4tfbRkxMBU6tckhfB2JRGUmnuqh5ygLcCLHDXNw@mail.gmail.com>
 <BL0PR04MB4706A66884728B9419CEAE00D9A89@BL0PR04MB4706.namprd04.prod.outlook.com>
 <BL0PR04MB4706B185A345A98AB4AB829AD9AC9@BL0PR04MB4706.namprd04.prod.outlook.com>
Message-ID: <20230302174750.19c3b247@arachnoid>

Dear Aidan Lakshman,

To answer your implicit question, VECTOR_ELT() unclasses the nodes
because it doesn't go through the stats:::`[[.dendrogram` method,
instead dereferencing the data pointer directly.

Other *apply functions in base R create a call to the `[[` operator,
letting the language dispatch the generic call, allowing the method to
assign a class to the return value. The following example is taken from
src/main/apply.c:do_lapply():

// prepare a call to FUN(X[[i]], ...)

    SEXP isym = install("i");
    SEXP tmp = PROTECT(lang3(R_Bracket2Symbol, X, isym));
    SEXP R_fcall = PROTECT(lang3(FUN, tmp, R_DotsSymbol));
    MARK_NOT_MUTABLE(R_fcall);

// inside the loop: evaluate the call

        tmp = R_forceAndCall(R_fcall, 1, rho);

Not sure which way is faster, but it may make sense to try, and it's
probably more correct in (contrived) cases where unclass(node)[[i]] is
invalid because it relies on a hypothetical `[[.subclass-of-dendrogram`
to restore some invariants.

Would you mind telling me more about the following case?

> if(!(inherits(res,c('dendrogram', 'list')))){
>  res1 <- lapply(unclass(node), \(x) x)
> }

If you're looking to improve the performance, there might be a way to
avoid the wrapper and this lapply(unclass(node), identity) call in it.

-- 
Best regards,
Ivan



[Rd] `dendrapply` Enhancements
Ivan Krylov