105 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			105 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
pub int Display
 | 
						|
    fn toString() -> String
 | 
						|
end
 | 
						|
 | 
						|
pub int LazyDisplay
 | 
						|
    fn toLazyString() -> DString
 | 
						|
end
 | 
						|
 | 
						|
pub int DString : Display
 | 
						|
    parts: Array<DStringPart>
 | 
						|
end
 | 
						|
 | 
						|
pub enum DStringPart
 | 
						|
    Constant(String),
 | 
						|
    Display(Display),
 | 
						|
    Lazy(Fn<Display>)
 | 
						|
end
 | 
						|
 | 
						|
#internal
 | 
						|
class DStringImpl(parts) : DString
 | 
						|
    cachedEval: Option<String>
 | 
						|
    canCache: Option<Boolean>
 | 
						|
 | 
						|
    fn getCanCache() -> Boolean
 | 
						|
        for part in parts do
 | 
						|
            if part is Lazy then return false end
 | 
						|
        end
 | 
						|
        true
 | 
						|
    end
 | 
						|
 | 
						|
    impl Display
 | 
						|
        pub fn toString() -> String
 | 
						|
            if cachedEval is Some(s) then
 | 
						|
                return s
 | 
						|
            end
 | 
						|
            if canCache is None then
 | 
						|
                canCache = Some(getCanCache())
 | 
						|
            end
 | 
						|
            // Note the groovy-like property getter
 | 
						|
            if canCache.truthy then
 | 
						|
                cachedEval = Some(
 | 
						|
                    parts.reduce('') { acc, part ->
 | 
						|
                        let partAsString = match part as
 | 
						|
                            Constant(s) => s,
 | 
						|
                            Display(d) => d.toString(),
 | 
						|
                            Lazy(f) => throw DumbProgrammerException(
 | 
						|
                                'Cannot cache when parts contains a Lazy.'
 | 
						|
                            )
 | 
						|
                        end
 | 
						|
                        acc + partAsString
 | 
						|
                    }
 | 
						|
                )
 | 
						|
                cachedEval.unwrap()
 | 
						|
            else
 | 
						|
                parts.reduce('') { acc, part ->
 | 
						|
                    let partAsString = match part as
 | 
						|
                        Constant(s) => s,
 | 
						|
                        Display(d) => d.toString(),
 | 
						|
                        Lazy(f) => f().toString()
 | 
						|
                    end
 | 
						|
                    acc + partAsString
 | 
						|
                }
 | 
						|
            end
 | 
						|
        end
 | 
						|
    end
 | 
						|
end
 | 
						|
 | 
						|
// Special "extension" implementation of Option for all T where T : Boolean
 | 
						|
pub int HasTruth
 | 
						|
    fn isTruthy() -> Boolean
 | 
						|
end
 | 
						|
 | 
						|
impl HasTruth for Option<T> where T is Boolean
 | 
						|
    pub fn isTruthy() -> Boolean
 | 
						|
        self is Some(b) ? b : false
 | 
						|
    end
 | 
						|
end
 | 
						|
 | 
						|
// some other file
 | 
						|
use std::extensions::HasTruth[Option<Boolean>]
 | 
						|
 | 
						|
fn maybeSomeOrNone -> Option<Boolean>
 | 
						|
    Some(true)
 | 
						|
end
 | 
						|
 | 
						|
fn main()
 | 
						|
    let o = maybeSomeOrNone()
 | 
						|
    if o.truthy then
 | 
						|
        println "It's truthy!"
 | 
						|
    else
 | 
						|
        println "It's falsy..."
 | 
						|
    end
 | 
						|
end
 | 
						|
 | 
						|
fn stringDemo() -> Void
 | 
						|
    let plain = 'Hello, World!'
 | 
						|
    let x = 42
 | 
						|
    let withDisplay = "Hello! x is $x"
 | 
						|
    let withLazy = "Hello! x is ${ x + 42 }"
 | 
						|
    println plain // Hello, World!
 | 
						|
    println withDisplay // Hello! x is 42
 | 
						|
    println withLazy // Hello! x is 84
 | 
						|
    x += 42
 | 
						|
    println withLazy // Hello! x is 126
 | 
						|
end |