Re: [MLton] RFC: implement "use" function to support explicit file dependency

Matthew Fluet <[email protected]> Fri, 7 Feb 2014 11:16:21 -0500
Newsgroups gmane.comp.lang.ml.mlton.devel
Message-ID <CAMrhFL6zcaGC10Oj5TFhigX0hb7c4kGt8t=Tmq+UFH-1fzTJWw@mail.gmail.com>
On Tue, Feb 4, 2014 at 8:10 PM, James Deng <[email protected]> wrote:
> I thought this mechanism can be implemented similar to that of the ML Basis
> system. Please point out if I am wrong.
>
> The mlb files are elaborated with the elaborateMLB function in the Elaborate
> phase. I guess this phase is able to combine and substitute all the “use”
> statements with file contents. (I assume the “use” is not a normal function,
> but a compile time meta-programming.)

It is true that you could implement a limited form of file inclusion,
directly within an .sml file, in a manner that is somewhat similar to
the implementation of the ML Basis System.  But, it would need to be
fairly restrictive ("use" is only applied to constant strings, "use"
is only applied at the top-level of the file), and it might be more
confusing to keep the name "use" for the feature.

> For instance, the semantics of this simple file A.sml:
>
> local
>   use “B.sml”;
>   use “C.sml”;
> in
>   (* use B and C here. *)
> end
>
>
> is equivalent to a mlb file A.mlb:
>
> local
>   B.sml
>   C.sml
> in A.sml end
>

Note that one couldn't simply interpret "use" as textual inclusion,
because SML does not allow signature and functor declarations within
local.  But, that's a rather minor point.

The major issue is that "use" is not really compositional in the
manner that one would like to express these sorts of dependencies.
The issue is that if both "B.sml" and "C.sml" rely on "D.sml", the
simplistic interpretation of "use" is that "D.sml" is
included/elaborated/evaluated twice.  Furthermore, because of
generative types, "B.sml" and "C.sml" might end up incompatible in
some manner, because they see different type declarations from their
own inclusions of "D.sml".

That's why the ML Basis System has a semantics where "Each MLB file is
elaborated and evaluated only once, with the result being cached.
Subsequent references use the cached value. Thus, any observable
effects due to evaluation are not duplicated if the MLB file is
referred to multiple times."  In the ML Basis System, if both "B.mlb"
and "C.mlb" both reference "D.mlb", then "D.mlb" is
elaborated/evaluated only once, but the same environment is made
available in both "B.mlb" and "C.mlb".


That said, James's original point is well taken.  One difficulty with
SML programming is that a single SML file is not, in some sense,
self-contained.  It is very true that in most languages, if I see
something in a file that doesn't appear to be defined in the file,
then I jump to the top of the file and look at the "#include" (C/C++),
"import" (Java, Haskell), "open" (OCaml), etc. to see some amount
dependency information.  The ML Basis System was designed to work with
this limitation of SML programming, and so the "implicit dependencies"
is not so much a "feature" in the sense of desirable as a "feature" in
the sense of a simple characteristic of the system.

On the other hand, with the ML Basis System, one could program in a
style that exposes very explicit import and export dependency
information.  One can adopt a style whereby every .sml file is
accompanied by a .mlb file that exactly explains its imports and
exports.  Christopher Cramer mentioned that this is a style that he
has adopted: http://article.gmane.org/gmane.comp.lang.ml.mlton.user/1486.
 With James's example above, we might write "A.mlb" with:

----------
local
  local
    (* IMPORTS *)
    local B.mlb in structure B1 structure B2 end (* "import" B1 and B2
from B.mlb (which corresponds to B.sml) *)
    local C.mlb in structure C end (* "import" C from C.mlb (which
corresponds to C.sml) *)
  in
    (* CODE *)
    A.sml (* may reference B1, B2, and C (but nothing else) *)
  end
in
  (* EXPORTS *)
  structure A1
  structure A2
end
----------

If one were to globally adopt this style, then it would be nice for
some compiler support, in the sense that we would like to push the
IMPORTS and EXPORTS into the A.sml file in some manner --- though it
would necessarily be some kind of extension over Standard ML:

----------
import B.mlb (structure B1, structure B2)
import C.mlb (structure C)
export (structure A1, structure A2)

;;

(* CODE *)
----------


Finally, I think it is a very good thing that SML (and most
programming-in-the-very-large systems layered on top of SML, such as
SML/NJ's Compilation Manager and MLton's ML Basis System) allow
individual .sml files to define multiple module-level constructs
(structures, signatures, functors).  This is in contrast to a number
of other languages that require a one-to-one mapping of module-level
constructs to files.

------------------------------------------------------------------------------
Managing the Performance of Cloud-Based Applications
Take advantage of what the Cloud has to offer - Avoid Common Pitfalls.
Read the Whitepaper.
http://pubads.g.doubleclick.net/gampad/clk?id=121051231&iu=/4140/ostg.clktrk
_______________________________________________
MLton-devel mailing list
[email protected]; [email protected]
https://lists.sourceforge.net/lists/listinfo/mlton-devel