/* * Copyright (c) 2005-2008 The University of Wroclaw. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the University may not be used to endorse or promote * products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN * NO EVENT SHALL THE UNIVERSITY BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ namespace Nemerle { /// class representing a lazy value (delayed computation of some function) /// it is constructed using Nemerle.lazy(complex_code()) macro public class LazyValue ['a] { /// memoized value mutable val : 'a; /// function to obtain the value mutable computation : void -> 'a; /// Create lazy value with given computation function to create the value /// when needed public this (f : void -> 'a) { computation = f; } /// Create already initialized value public static FromValue (val : 'a) : LazyValue ['a] { LazyValue (val, null) } /// Create lazy value with fully specified state private this (val : 'a, fn : void -> 'a) { this.val = val; computation = fn; } public static @: (x : LazyValue ['a]) : 'a { x.Value } public static @: (x : 'a) : LazyValue ['a] { FromValue (x) } public override ToString () : string { Value.ToString () } public override Equals (x : object) : bool { Value.Equals (x) } public override GetHashCode () : int { Value.GetHashCode () } /// Get the underlying value stored in lazy computation. Perform computation /// if it the value was not fethed before /// /// This function is thread safe. Exceptions are rethrowed, but if one occurs during /// computation, then in future it will be always thrown when fetching value. public Value : 'a { get { lock (this) { try { when (computation != null) { val = computation (); computation = null; } val } catch { | e => def e = e; computation = fun () { throw e } throw; } } } } } }