Last active
March 17, 2018 04:13
-
-
Save slwu89/fd20b07cb6e18877dfc66c1fc9c742c0 to your computer and use it in GitHub Desktop.
rewrite of eapply without memory allocation for return values (for calling functions just for side effects)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* ################################################################################ | |
* BEGIN UTILITY FUNCTIONS | |
################################################################################ */ | |
#define NONEMPTY_(_FRAME_) \ | |
CHAR(PRINTNAME(TAG(_FRAME_)))[0] != '.' && CAR(_FRAME_) != R_UnboundValue | |
static int FrameSize(SEXP frame, int all) | |
{ | |
int count = 0; | |
if (all) { | |
while (frame != R_NilValue) { | |
count += 1; | |
frame = CDR(frame); | |
} | |
} else { | |
while (frame != R_NilValue) { | |
if (NONEMPTY_(frame)) | |
count += 1; | |
frame = CDR(frame); | |
} | |
} | |
return count; | |
} | |
#define CHECK_HASH_TABLE(table) do { \ | |
if (TYPEOF(table) != VECSXP) \ | |
error("bad hash table contents"); \ | |
} while (0) | |
static int HashTableSize(SEXP table, int all) | |
{ | |
CHECK_HASH_TABLE(table); | |
int count = 0; | |
int n = length(table); | |
int i; | |
for (i = 0; i < n; i++) | |
count += FrameSize(VECTOR_ELT(table, i), all); | |
return count; | |
} | |
static void FrameValues(SEXP frame, int all, SEXP values, int *indx) | |
{ | |
if (all) { | |
while (frame != R_NilValue) { | |
# define DO_FrameValues \ | |
SEXP value = CAR(frame); \ | |
if (TYPEOF(value) == PROMSXP) { \ | |
PROTECT(value); \ | |
value = eval(value, R_GlobalEnv); \ | |
UNPROTECT(1); \ | |
} \ | |
SET_VECTOR_ELT(values, *indx, lazy_duplicate(value)); \ | |
(*indx)++ | |
DO_FrameValues; | |
frame = CDR(frame); | |
} | |
} else { | |
while (frame != R_NilValue) { | |
if (NONEMPTY_(frame)) { | |
DO_FrameValues; | |
} | |
frame = CDR(frame); | |
} | |
} | |
} | |
#undef DO_FrameValues | |
static void HashTableValues(SEXP table, int all, SEXP values, int *indx) | |
{ | |
CHECK_HASH_TABLE(table); | |
int n = length(table); | |
int i; | |
for (i = 0; i < n; i++) | |
FrameValues(VECTOR_ELT(table, i), all, values, indx); | |
} | |
/* ################################################################################ | |
* END UTILITY FUNCTIONS | |
################################################################################ */ | |
/* ################################################################################ | |
* call: a language object generated by match.call(expand.dots = FALSE) | |
* rho: the environment in which the call was executed | |
################################################################################ */ | |
SEXP hash_apply(SEXP call, SEXP rho){ | |
/* advance to 2nd element (CAR) of call pairlist; 1st element is just the eapply3 function */ | |
SEXP args = CDR(call); | |
/* get environment (2nd element) and advance to 3rd element */ | |
SEXP envSymbol = install("X"); | |
args = CDR(args); | |
/* get function (3rd element) and advance to 4th element */ | |
SEXP funSymbol = install("FUN"); | |
args = CDR(args); | |
/* env is the hash table */ | |
SEXP env = PROTECT(eval(envSymbol,rho)); | |
int n = HashTableSize(HASHTAB(env), 0); | |
/* get the values out of the hash table as vector/list: vals */ | |
SEXP vals; | |
PROTECT(vals = allocVector(VECSXP,n)); | |
int ix = 0; | |
HashTableValues(HASHTAB(env), 0, vals, &ix); | |
/* make the bit of the function call that indexes over the values in the hash table */ | |
SEXP tmp; | |
PROTECT(tmp = LCONS(R_Bracket2Symbol, LCONS(envSymbol, R_NilValue))); | |
/* make the f(X[[i]],...) bit of the function call (tmp is the indexing) */ | |
SEXP R_fcall; | |
PROTECT(R_fcall = LCONS(funSymbol, LCONS(tmp , LCONS(R_DotsSymbol,R_NilValue)))); | |
/* map the function(...) over the hash table */ | |
for(int j=0; j<n; j++){ | |
printf("j: %i\n",j); | |
SETCADR(R_fcall, VECTOR_ELT(vals, j)); | |
R_forceAndCall(R_fcall, 1, rho); | |
}; | |
UNPROTECT(4); | |
return R_NilValue; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment