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)