I've also investigated the issue a little bit further and wrote and email with my conclusions about the same time Max wrote his. I comment inline about a few of your thoughts:
> For `defcustom' autoload generates no more than > > (defvar org-capture-templates nil "...") > > It seems, behavior depends on whether `org-capture-templates' has the :set > attribute. Not really, all defcustoms have a :set attribute, be it passed explicitly as a parameter or the default value, set-default. This issue happens with all autoload functions that use a custom variable: if they are called inside a let form binding that variable and the feature was not loaded yet, the let-binding will have no effect. > The setter receives nil instead of the let-bound value. I can not say > I understand the tricks with bypassing lexical binding in `defcustom' and some > checks in `custom-declare-variable'. Since emacs-26 something has changed: > I am unsure that the setter of `defcustom' should get let-bound value in the > case of autoloading since it might lead to fragile behavior. See my other email where I explain what I think that defcustom of a variable is doing when called inside a let-binding of that variable. >> https://git.savannah.gnu.org/cgit/emacs.git/commit/?id=6309131349 >>> - ;; Use defvar to set the docstring as well as the special-variable-p >>> flag. >>> - ;; FIXME: We should reproduce more of `defvar's behavior, such as the >>> warning >>> - ;; when the var is currently let-bound. >>> - (if (not (default-boundp symbol)) But the conclusion is that right now it does not work, so I think that warning is needed. > It looks like the setter on org-capture-template is used to do some > form of conversion on the template specification to force a new > format. Not sure how long that has been there or whether it is > actually still required. Could be that this setter was added to aid in > transition to a new template format which could/should be removed at > some point. That is right, it seems it was added for backwards compatibility when a new template format was added. However, it's not actually needed, since org-capture-select-template also calls that function to ensure they are in the new format. It needs to do so in order to allow setting org-capture-templates also with setq, or let-binding org-capture-templates as I do. That's not the problem anyway, as I explained above. > However, this behaviour seems like it may be the tip of a much bigger > issue outside of org-mode and potential source of bugs for Emacs. > Bottom line is I don't think any function should behave differently > depending on when autoload runs > Regardless, I don't think having the situation where the programmer must > know (guess) whether autoload will/could execute during the evaluation > of code they write is tenable and am beginning to suspect it may be an > Emacs bug OR a subtle bug in org-mode as a result to the transition to > lexical binding as the default. My recommendation would be to come up > with a non-org specific example which reproduces the behaviour and then > ask on emacs-devel, using the example to demonstrate the issue. I agree. I'm on it. >> Reading the code I noticed `org-capture-templates-contexts' so I wonder if it >> might help for the original use case. > > I thought about that as well. However, from re-reading the OP's posts, I > suspect not. org-capture-templates-contexts seems to be useful when you > want to restrict access to some templates based on context. However, > from reading the OP's posts, I get the impression that what they want is > for templates to be different based on context i.e. they still want the > template associated with 'd', but want its definition to be different. > > It is possible org-capture-template-contexts might provide an > alternative solution where you don't need to dynamically modify/add > templates in this manner. For example, you could have all your templates > defined, but only offer those relevant based on context. However, I > guess this would mean having to have different template keys, which > might be an issue. If I recall correctly template contexts allow to redefine the template key, so that would not be an issue. And yes, using template contexts could probably be a solution to my use case, as it would be having an org-capture version with template parameter. But don't worry too much about my use case, since a simple (require 'org-capture) is enough to keep doing what I was doing.