Skip to content
Dinko Srkoč edited this page Aug 7, 2011 · 4 revisions

Option represents optional values. Instances are either an instance of Some or an instance of None. If None is the result of evaluating takeFrom closure, the entire foreach expression results in None. This allows for chaining of Option values without having to check for the existence of a value.

import static hr.helix.monadologie.MonadComprehension.foreach
import static hr.helix.monadologie.monads.Option.some
import static hr.helix.monadologie.monads.Option.none

def safe(Closure action) {
    try {
        some(action())
    } catch (ignore) {
        none()
    }
}

def check = { name -> name ? some(name) : none() }
def load  = { name -> safe { new File(name).text }},
    parse = { text -> safe { text.tokenize()*.toInteger() }},
    div   = { a, b -> safe { a / b }}
    
def calc = { fileName ->
    foreach {
        file = takeFrom { check fileName }
        text = takeFrom { load  file }
        data = takeFrom { parse text }
        res  = takeFrom { div   data }

        yield { res }
    }
}

assert calc(null) == none() // file name validation failed
assert calc("foo.txt") == none() // file not found

def fileName = "/tmp/data"

new File(fileName).withWriter { w -> w << "aa bb" }
assert calc(fileName) == none()  // number format exception

new File(fileName).withWriter { w -> w << "1 0" }
assert calc(fileName) == none()  // division by zero

new File(fileName).withWriter { w -> w << "10 20" }
assert calc(fileName) == some(0.5)

Clone this wiki locally