-
Notifications
You must be signed in to change notification settings - Fork 135
Description
It would be possible to extend the ideas from #207 to references. For example, we could have:
structure Unsafe.Ref:
sig
val alloc: unit -> 'a ref
val uninit: 'a ref -> unit
structure Raw:
sig
type 'a rawref
val alloc: unit -> 'a rawref
val toRef: 'a rawref -> 'a ref
val uninit: 'a rawref -> unit
end
endOne potential motivation is to eliminate the (admittedly small) dispatch overhead in a ('a -> 'b) ref that is only ever meant to hold one function. For example, recall the classic "back-patching" technique for recursion with first-class functions and references:
val fact_ref = ref (fn _ => raise Fail "fact")
val fact = fn n => if n <= 1 then 1 else n * (!fact_ref) (n - 1)
val () = fact_ref := factControl-flow analysis will determine that the contents of fact_ref is either fn _ => raise Fail "fact" or fn n => ..., and the application (!fact_ref) (n - 1) will have a case-analysis to select between these functions. [Note that the overhead is essentially the same, but more obvious to the programmer, when using an ('a -> 'b) option ref.]
With a Ref_alloc primitive, one could write:
val fact_ref = Unsafe.Ref.alloc ()
val fact = fn n => if n <= 1 then 1 else n * (!fact_ref) (n - 1)
val () = fact_ref := factControl-flow analysis will determine that the contents of fact_ref is only fn n => ... and the application will have a single (exhaustive) case-match. Subsequent ConstantPropagation and/or Useless optimizations would probably eliminate the reference entirely.