blob: eab8aaf42745a122d31eddd02389cbd1b5a742bb [file] [log] [blame]
// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
/// [Try] is similar to Haskell monad, where
/// a computation may throw an exception.
/// There is no checking of passing null into
/// the value, so be mindful.
class Try<T> {
final T _val;
final StackTrace _stackTrace;
final dynamic _err;
Try.from(this._val)
: _err = null,
_stackTrace = null;
Try.fail(this._err, this._stackTrace) : _val = null;
Try<S> bind<S>(S f(T x)) {
if (_err != null) {
return new Try.fail(_err, _stackTrace);
}
try {
return new Try<S>.from(f(_val));
} catch (ex, stackTrace) {
return new Try<S>.fail(ex, stackTrace);
}
}
Future<Try<S>> bindAsync<S>(Future<S> f(T x)) async {
if (_err != null) {
return new Try.fail(_err, _stackTrace);
}
try {
return new Try.from(await f(_val));
} catch (ex, stackTrace) {
return new Try.fail(ex, stackTrace);
}
}
void fold(void caseErr(dynamic ex, StackTrace st), void caseVal(T x)) {
if (_err != null) {
caseErr(_err, _stackTrace);
} else {
caseVal(_val);
}
}
Future foldAsync(
Future caseErr(dynamic ex, StackTrace st), Future caseVal(T x)) async {
if (_err != null) {
await caseErr(_err, _stackTrace);
} else {
await caseVal(_val);
}
}
bool get isError => _err != null;
Exception get error => _err;
StackTrace get stackTrace => _stackTrace;
T get value => _val;
T getOrDefault(T defval) => _err != null ? defval : _val;
}
Try<T> tryStart<T>(T action()) {
return new Try<int>.from(0).bind<T>((dummy) => action());
}
Future<Try<T>> tryStartAsync<T>(Future<T> action()) {
return new Try<int>.from(0).bindAsync<T>((dummy) => action());
}