Re: Interactive SML use from Emacs, a question of approach

Christopher Cramer <[email protected]>
Newsgroups gmane.comp.lang.ml.mlton.user
Message-ID <[email protected]>
On Fri, Oct 11, 2013 at 12:45:04PM -0500, Grant Rettke wrote:
> 1. Interactively send code to a REPL. Let the environment grow and
> evolve. Restart the interpreter as needed.
> 
> 2. Start a fresh REPL every time code is evaluated so that the
> entirety of the system state is known and predictable.
> 
> When I set up OCaml mode (tuareg), I did it like #2 and it worked
> fine. Now I'm setting up SML mode, and I'm curious how other people do
> their real development workflow in regards to REPL and development
> management.

MLton doesn't have an interactive REPL, so one could say #2 is the only
way. But in practice most people seem to use SML/NJ or Poly/ML for
development and then use MLton for the final build. MLton has very
few deviations from the Definition, so you just need to make sure you
don't use any SML/NJ or Poly/ML extensions.

Personally, I use Vim and just use MLton to compile and nothing else. For
large programs it can take a long time to compile everything, so what
I do is type-check small, single files at a time (with -stop tc). There
are two things that are necessary to make this work:

1. Split up the code into small (1000 lines or less ideally) files, with
a simple external interface for each file, using opaque types. Otherwise
the type errors will drive you crazy.

2. Create one MLB file (or more, see below) per SML source file. This
encapsulates the dependencies and annotations for a given source file
in one discrete place.

Example MLB, which I name foo.mlb:

	local
		$(SML_LIB)/basis/basis.mlb
		bar.mlb
		baz.mlb
	in
		foo.sml
	end

And you can then just run "mlton -stop tc foo.mlb" to test that everything
is OK with foo.sml. It will take a couple seconds or less, if you kept
foo.sml small.

This has the bonus that you don't need to decide which order everything
should go in, in one big confusing MLB. Note that even if a source
file doesn't depend on anything else other than the Basis Library, you
still make an MLB for it, because the semantics of referencing a source
file directly are different. If a source file is referenced multiple
times, it's loaded multiple times and creates distinct, incompatible
signatures/structures/, whereas if an MLB file is referenced multiple
times, it's only loaded once.

Most of the time, with defensive use of the type system (types can be
used to enforce invariants at compile-time, much like "assert" is used in
certain other languages) this is actually sufficient, and I don't write
tests for the code. But when I want to write tests (and I think that
basically any time you have the desire to try something out in a REPL,
you should probably just create some test code, so you can reuse it),
I follow these steps:

1. put the test code into a functor named Test ().

foo.sml:

	signature FOO = sig
		(* ... *)
	end

	structure Foo = struct
		(* ... *)
	end

	functor TestInternal () = struct
		(* ... *)
	end

	structure Foo :> FOO = Foo

	functor TestExternal () = struct
		(* ... *)
	end

	functor Test () = struct
		structure Z = TestInternal ()
		structure Z = TestExternal ()
	end

2. create an MLB, foo-all.mlb, which contains the dependencies and the
source file:

	local
		$(SML_LIB)/basis/basis.mlb
		bar.mlb
	in
		foo.sml
	end

3. create an MLB, foo.mlb, which elides the test functors and can be
referenced by other MLBs:

	local
		foo-all.mlb
	in
		signature FOO
		structure Foo
	end

4. create a test source program, test.sml:

	structure Z = Test ()

5. create an MLB, foo-test.mlb, for testing:

	local
		foo-all.mlb
	in
		test.sml
	end

Then I can make changes to the code (including the test code) in foo.sml,
and test it in isolation from the rest of the code by running "mlton
foo-test.mlb" and running the resulting program.

So I guess you could say I'm in camp #2.

To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].

------------------------------------------------------------------------------
October Webinars: Code for Performance
Free Intel webinars can help you accelerate application performance.
Explore tips for MPI, OpenMP, advanced profiling, and more. Get the most from 
the latest Intel processors and coprocessors. See abstracts and register >
http://pubads.g.doubleclick.net/gampad/clk?id=60134071&iu=/4140/ostg.clktrk
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.