=======
Problem
=======

Here is an interesting experiment I performed do to determine how tactics are evaluated, and subsequent side-effects carried out.

Consider the following functions defining tactics:

fun store_asms_tac loc =
	GET_ASMS_T (fn asms => (loc := (map concl asms); id_tac));

fun retain_asm_tac terms =
	GET_ASMS_T (fn asms => (
		LIST_DROP_ASM_T ((map concl asms) term_diff terms) discard_tac));

fun apply_spec_auto_tac def =
	let val orig_asms = ref []; in
		(store_asms_tac orig_asms)
		THEN (strip_asm_tac def)
		THEN (all_asm_fc_tac [])
		THEN (asm_rewrite_tac [])
		THEN (retain_asm_tac (!orig_asms))
	end;

The above doesn't work as intended, i.e. !orig_asms will always yield the initial value [] rather than the one assigned by (store_asms_tac orig_asms). The debugging output we get clarify evaluation order is

xxxyyyaaabbb

which reveals that retain_asm_tac is evaluated BEFORE the tactic is applied, and hence orig_asms is appropriately initialised to the assumptions of the current goal.

Question: How can we communicate values between tactics connected via THEN?

========
Solution
========

I solved the problem by providing an alternative function:

fun ref_retain_asm_tac terms =
	GET_ASMS_T (fn asms =>
		LIST_DROP_ASM_T ((map concl asms) term_diff !terms) discard_tac);

which acts on references rather than values. If we replace

    (retain_asm_tac (!orig_asms))
by
    (ref_retain_asm_tac orig_asms)

in the apply_spec_auto_tac function, evaluation of orig_terms would be deferred until GET_ASMS_T is evaluated. This is what we want ;-).
