You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@mesos.apache.org by "Benjamin Mahler (JIRA)" <ji...@apache.org> on 2016/10/19 23:44:58 UTC
[jira] [Commented] (MESOS-785) Extend stout/try to support
functional composition
[ https://issues.apache.org/jira/browse/MESOS-785?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15590263#comment-15590263 ]
Benjamin Mahler commented on MESOS-785:
---------------------------------------
(Some additional context from a discussion awhile back with [~benjaminhindman])
In order to preserve our error composition technique [~benjaminhindman] had shown me an approach like this:
{code}
Try<T> t;
Try<X> = t.bind(
[=](const T& t) { return t.toX(); }
[=](const Error& error) { return Error("Additional context: " + error.message); }
);
{code}
We were trying to avoid the issues around error message composition that currently exist with Future chaining (where the design of .then prevents the caller from adding additional error message context).
> Extend stout/try to support functional composition
> --------------------------------------------------
>
> Key: MESOS-785
> URL: https://issues.apache.org/jira/browse/MESOS-785
> Project: Mesos
> Issue Type: Improvement
> Components: stout
> Reporter: Ian Downes
> Priority: Minor
> Labels: c++11
>
> Motivating example was fetching a list of URIs where each 'fetch' is actually a sequence of operations: fetch the uri to a local file, pass the local file on to chmod or extract, and pass on to chown it or the directory. Individual operations needn't be asynchronous.
> This can be written using Futures but is potentially confusing when the code is actually synchronous.
> {code}
> Future<Nothing> fetch(
> const CommandInfo& commandInfo,
> const string& directory,
> const HDFS& hdfs,
> const Option<string>& frameworks_home,
> const Option<string>& user)
> {
> foreach (const CommandInfo::URI& uri, commandInfo.uris()) {
> bool executable = uri.has_executable() && uri.executable();
> // This code is synchronous!
> Future<string> result =
> _fetch(uri, directory, hdfs, frameworks_home)
> .then(lambda::bind(_chmod, lambda::_1, directory, executable))
> .then(lambda::bind(_extract, lambda::_1, directory, !executable))
> .then(lambda::bind(_chown, lambda::_1, directory, user));
> if (result.isFailed()) {
> LOG(ERROR) << "Fetch of uri '" << uri.value() << "' failed: " << result.failure();
> return Future<Nothing>::failed(result.failure());
> }
> }
> return Nothing();
> }
> {code}
> [~bmahler] and I had these thoughts:
> * .ifSome() and .ifError() to express control flow.
> * .and() for chaining to make it clear the code is synchronous and also that it will short-circuit error.
> e.g.
> {code}
> Try<string> result =
> _fetch(...)
> .and(chmod...)
> .and(extract...)
> .and(chown...);
> {code}
> Thoughts? How do other languages express this?
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)