The help for custom-set-variables says:
The arguments should each be a list of the form:
(SYMBOL EXP [NOW [REQUEST [COMMENT]]])
This stores EXP (without evaluating it) as the saved value for SYMBOL.
If NOW is present and non-nil, then also evaluate EXP and set
the default value for the SYMBOL to the value of EXP.
REQUEST is a list of features we must require in order to
handle SYMBOL properly.
So if NOW is nil then EXP won't be evaluated immediately, which suggests to me that it should be possible for EXP to refer to variables or functions provided by features in the REQUEST list which are not yet loaded.
Even if my interpretation is wrong, it should be possible to safely use custom-set-variables to customize variables in features which are not yet loaded. For example, if I have something like:
(custom-set-variables
'(yas-snippet-dirs
('("~/.config/yasnippets/rails")) nil (yasnippet)))
Then I would expect this variable only to be set once yasnippet is loaded.
It turns out that custom-set-variables tries to load yasnippet immediately. This means that the custom-file containing this directive has to be loaded after all other user init code which takes care of ensuring that yasnippet is available (e.g. loading it from MELPA or el-get or via req-package). That's all well and good if yasnippet is available, but what if it isn't available, or at least not yet available, due to some deferred or lazy-loading?
Currently this will result in a backtrace ending in something like this:
Debugger entered--Lisp error: (file-error "Cannot open load file" "no such file or directory" "yasnippet")
require(yasnippet)
mapc(require (yasnippet))
custom-theme-set-variables(user (yas-snippet-dirs (quote ("~/.config/yasnippets/rails")) nil (yasnippet)))
which will then break the rest of the user's initialisation, which is really bad. OTOH, if I just remove the REQUEST argument in order to allow deferred loading, then presumably the value of specifying that argument is lost.
So what's the correct way to safely customize variables for packages which are lazy-loaded or loaded on demand?
(BTW in case it's not obvious, I'm looking for a solution which doesn't bypass custom.el, because then I lose the ability to customize via custom.el's nice UI. Otherwise I would simply do setq inside the :config section of my use-package declaration ... Doing custom-set-variables in the same place doesn't work either, because updating the value via the custom.el UI would still update the file pointed to by custom-file rather than this correct location.)