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 | 
