[erlang-questions] Updates, lenses, and why cross-module inlining would be nice

Michael Truog mjtruog@REDACTED
Thu Dec 3 08:11:36 CET 2015

On 12/02/2015 06:25 PM, Richard A. O'Keefe wrote:
> On 2/12/2015, at 7:19 pm, Michael Truog <mjtruog@REDACTED> wrote:
>> On 12/01/2015 08:06 PM, Richard A. O'Keefe wrote:
>>> On 1/12/2015, at 8:42 am, Michael Truog <mjtruog@REDACTED> wrote:
>>>> The header approach is preferable to make the dependency problems
>>>> a compile-time concern, rather than creating a runtime failure when
>>>> attempting a module update.  It is important to not crash running source
>>>> code due to errors.
>>> It *would* be "preferable to make the dependency problems
>>> a compile-time concern".  But using headers DOES NOT DO THAT.
>> The lens.hrl created from your lens.erl file does due to containing only
>> functions, that get dropped into the module that includes the header file,
>> making them look like local functions within the module.
> No, that does NOT "make the dependency problems a compile-time
> concern".  It really doesn't.  Your lens.hrl defines functions,
> and mine defines macros.  That doesn't make any difference.
> Either way, this is what CREATES untracked dependencies!
> T1. Module A includes header H.
>      Module A is compiled.
> T2. Module B includes header H.
>      Module B is compiled.
> (:-) Modules A and B are compatible.
> T3. Header H is changed.
> (:-( Modules A and B are still compatible but out of date.
> T4. Module B is recompiled.
> !$#@ Modules A and B are now incompatible
> Now *if* you are diligent in using erlc's -M* options
> to create/update your Makefiles, you can ensure that
> both A and B will be automatically updated (when you get
> around to asking for updates).
> But there is no reason why erlc -M... couldn't track
> -import_static just as well as -include, and ensuring that
> it does would be an important part of implementing -import_static.
>>> Nor does the import_static approach "crash running source code
>>> due to errors."  import_static has two purposes:
>>> (1) to permit cross-module inlining and type inference safely;
>>> (2) to detect a clashing update *before* changing the state of
>>> the system in order to *avoid* crashing running source code.
>> The two (high-level) approaches I see for implementing import_static is
>> where either:
>> 1) modules are made permanent to make sure the modules do not change,
>> so functions may be inlined between modules safely
>> 2) modules are updated in groups and the groups are created by the
>> inlining between modules
> And in this respect there is no difference between
> cross-module inlining and headers.
> Except that (2) is a slightly weird way to put it.
> Updates should be based on the *dependency graph* just
> as updates triggered by changes to headers or to yecc
> and/or leex or to parse transforms should be based on
> the dependency graph.  Put thus, (2) is what I had in
> mind.
>>> If the modules in question are tested *separately*,
>>> the tests don't help.  If you test the modules *together*,
>>> you might as well *reload* them together.
>> Then that seems to favor the approach #2 mentioned above.
> Yes.
> Oh, I should point out that -include files defining a bunch
> of functions *do* address many of my reasons for disliking
> preprocessor use.  But not the untracked dependencies problem.
If we had header files that were only allowed to contain functions and
types that we called "template files" for lack of a better name
(ideally, they would have their own export statements to help
distinguish between private functions/types and the interface for modules
to use)
we had the include files (and template files) versioned within the beam
output (to address the untracked dependency problem).

Wouldn't that approach be preferable when compared
to trying to manage the module dependency graph during a
runtime code upgrades?  Why would the "template files" approach
not be sufficient?

More information about the erlang-questions mailing list