Idioms and Design Patterns

Using Promises as locks

You can use promises to lock references:

val counter = ref 1

fun incr () =
    let val p = Promise.promise ()
        val s = Ref.exchange (counter, Promise.future p)
        Promise.fulfill (p, s + 1)

val t1 = spawn incr ()
val t2 = spawn incr ()
(* wait for both threads to be terminated *)
val _  = Future.await t1 
val _  = Future.await t2
val _  = assert (!counter == 3)

- Bene

Note that this is precisely what Ref.modify does. So incr could also be implemented as

fun incr () = Ref.modify (fn i => i+1) counter

But the idiom is still useful in more complex situations.

- Andreas

Common problems and Workarounds

Cannot save anything

I feel pretty stupid asking this but I cannot save files. The menu-entry for doing so is gray. The shortcuts do not work either. I am running Alice 1.4 on Kubuntu 12.04. What am I doing wrong?

- Julian [01.07.2012] Nevermind, I have been using the interpreter and not the editor. Editor opens when you generate a new file, but not when you open Alice. Maybe worth changing if more people have trouble with that?


spawn swallowed my exception!

You have written something like this:

fun f () = raise Fail "my exception"

fun foo () =
    spawn f ();
    print "thread created"

val _ = foo ()

But mysteriously you never actually see that exception.

What happened? As you probably know spawn creates a future. This future becomes failed as soon as the exception is raised. This STOPS the exception, until someone forces the future evaluate. But in this case the future is tossed away by the ; operator and therefore the exception is gone forever.

So there are two possibilities. You must either use the value returned by the thread, or if you are just interested in the exceptions for debugging purposes (such as the Assert exception) use Ctrl.ispawn from "x-alice:/lib/utility/Ctrl":

import structure Ctrl from "x-alice:/lib/utility/Ctrl"

fun f () = raise Fail "my exception"

fun foo () =
    Ctrl.ispawn (_file_, _line_) f ();
    print "thread created"

val _ = foo ()

Which will terminate your application with a debugging message whenever an uncaught exception occurs.

- Bene

But anyway, since the utility lib is not official and may change any time it is currently preferable to use your own version of ispawn. One possible definition is:

fun ispawn label f x = 
        fun crashWith e =
            (TextIO.output (TextIO.stdErr, label ^ ": uncaught exception " ^ exnName e ^ "\n");
             OS.Process.exit OS.Process.failure)
        ignore (spawn f a handle e => crashWith e)

It is used like:

ispawn "task08_15" f ()

- Andreas

Moving from Oz to Alice


For reference documentation about how the implementation of Resolvers, Component Managers etc. in Alice differs from Mozart, see the [WWW] Alice Manual.


New Developments in ML

(Sorry, don't know if the Wiki is even the right place to put this)

-Jon S.

Thanks for the link. Yes, we are aware of that paper. It surely is interesting, but we did not consider to implement it yet, because for now, we do not want to deviate from SML in (too) incompatible ways.

- Andreas

Assertions Annotations

Is there a way to add some additional information to a failed assertion? somthing like

assert myAssertionExp onFail myAssertionFailedMessage

- Max

No, but the Assert exception carries file name and line number of the respective assertion, which should be enough to identify its origin. If really necessary, you could catch it and use this information to map it to a message, but admittedly, that would be a pretty fragile hack.

- Andreas