There are some routines in Maple's library which, when called the first time, redefine themselves.
One plausible explanation for this is that the new versions are session dependent (external calls, say) while also more efficient to call (repeatedly).
For example, consider StringTools:-Join which seems typical of that package. First, consider it before it's been called at all.
> restart: > showstat(StringTools:-Join); StringTools:-Join := proc() 1 passign(procname,defun(convert(join,'string'))); 2 procname(args) end proc
Now call it a first time. And examine it again.
> StringTools:-Join(["hi","bye"]): > showstat(StringTools:-Join); StringTools:-Join := proc() 1 call_external(0,182946067904,true,args) end proc
So the magic was in those calls to `passign` and `defun`, which can also be examined.
> kernelopts(opaquemodules=false):
StringTools:-defun := proc(nom)
local extsym, solib;
1 solib := ExternalCalling:-ExternalLibraryName("mstring",'HWFloat');
2 extsym := nprintf("mstring_%s",nom);
3 userinfo(5,StringTools,nprintf("Defining %a",extsym));
4 define_external(extsym,'MAPLE',('LIB') = solib)
end proc
> showstat(StringTools:-passign);
StringTools:-passign := proc(n::name, v)
1 unprotect(n);
2 assign(n,v);
3 protect(n);
4 NULL
end proc
A neat little technique.
Comments
A better method
This 'trick' is very old, and used to be pervasive back in the days where readlib was necessary. Luckily, readlib was made obsolete, and yet now this trick pops up again!
I thought that that was exactly why
ModuleLoadwas created for. This kind of initialization really ought to be done at load-time of the StringTools module, rather than through evil side-effects. There is a downside toModuleLoad: all routines, whether they are used or not, would get loaded if any are. But that should be fixeable too. The 'persistent store' mechanism should be able to deal with that too! Creating a thunk that is only resolved upon first read (for the 2nd parameter to thecall_external) should be relatively simple.small modules
The one-time cost of defining all the StringTools exports as their session-dependent call_externals may be negligible compared to the cost of the initial dlopen of the mstring dynamic library.
Here is a crude illustration, done in order in a fresh TTY session.
> st:=time(): > try StringTools:-Join(): catch: end try: > time()-st; 0.002 > st:=time(): > try > for j in exports(StringTools) do > StringTools[j](): > end do: > catch: end try: > time()-st; 0.001 > st:=time(): > try > for j in exports(StringTools) do > StringTools[j](): > end do: > catch: end try: > time()-st; 0.Ignoring effects due to try..catch overhead and the cost of raising errors, and assuming that the timer is accurate at such small granularity, it looks like the initial dlopen costs 2/3's as much as initializing/redefining all of the (approximately 200) StringTools exports.
It may only be for packages with many exports (which each need redefining) that having ModuleLoad deal with them all at once on the first access might be undesirable. So it may be reasonable to have StringTools:-ModuleLoad initialize them all, without any change to the persistent store mechanism.
acer