1Promises::Cookbook::ScaUlsaeFrutCuornetsrCiobPmurptoaemrdiissPeoesnr:(l:3C)Dooockubmoeonkt:a:tSicoanlaFuturesComparison(3)
2
3
4
6 Promises::Cookbook::ScalaFuturesComparison - A comparison of Scala
7 Futures with Promises
8
10 version 1.04
11
13 Here is the example Scala code, it assumes a function called "fetch"
14 which when given a URL will return a Future.
15
16 def getThumbnail(url: String): Future[Webpage] = {
17 val promise = new Promise[Webpage]
18 fetch(url) onSuccess { page =>
19 fetch(page.imageLinks(0)) onSuccess { p =>
20 promise.setValue(p)
21 } onFailure { exc =>
22 promise.setException(exc)
23 }
24 } onFailure { exc =>
25 promise.setException(exc)
26 }
27 promise
28 }
29
30 If we take this and translate this into Perl code using the
31 Mojo::UserAgent library, the "fetch" function would look like this:
32
33 sub fetch {
34 state $ua = Mojo::UserAgent->new;
35 my $url = shift;
36 my $d = deferred;
37 $ua->get($url => sub {
38 my ($ua, $tx) = @_;
39 $d->resolve( $tx );
40 });
41 $d->promise;
42 }
43
44 And if we were to take the "get_thumbnail" function and translate it
45 exactly, we would end up with this:
46
47 sub get_thumbnail {
48 my $url = shift;
49 my $d = deferred;
50 fetch( $url )->then(
51 sub {
52 my $tx = shift;
53 fetch( $tx->res->dom->find('img')->[0]->{'src'} )->then(
54 sub { $d->resolve( $_[0] ) },
55 sub { $d->reject( $_[0] ) },
56 )
57 },
58 sub { $d->reject( $_[0] ) }
59 );
60 $d->promise;
61 }
62
63 Scala Futures have a method called "flatMap", which takes a function
64 that given value will return another Future. Here is an example of how
65 the "getThumbnail" method can be simplified by using it.
66
67 def getThumbnail(url: String): Future[Webpage] =
68 fetch(url) flatMap { page =>
69 fetch(page.imageLinks(0))
70 }
71
72 But since our "then" method actually creates a new promise and wraps
73 the callbacks to chain to that promise, we don't need this "flatMap"
74 combinator and so this, Just Works.
75
76 sub get_thumbnail {
77 my $url = shift;
78 fetch( $url )->then(
79 sub {
80 my $tx = shift;
81 fetch( $tx->res->dom->find('img')->[0]->{'src'} );
82 }
83 );
84 }
85
86 Scala Futures also have a "rescue" method which can serve as a kind of
87 catch block that potentially will return another Future.
88
89 val f = fetch(url) rescue {
90 case ConnectionFailed =>
91 fetch(url)
92 }
93
94 Just as with "flatMap", since our callbacks are wrapped and chained
95 with a new Promise, we can do a rescue just by using the error callback
96 The Promise returned by "fetch" will get chained and so this will
97 depend on it.
98
99 sub get_thumbnail {
100 my $url = shift;
101 fetch( $url )->then(
102 sub {
103 my $page = shift;
104 fetch( $page->image_links->[0] );
105 },
106 sub {
107 given ( $_[0] ) {
108 when ('connection_failed') {
109 return fetch( $url );
110 }
111 default {
112 return "failed";
113 }
114 }
115 }
116 );
117 }
118
119 TODO ... figure out how retry can be generic ...
120
122 Systems Programming at Twitter -
123 <http://monkey.org/~marius/talks/twittersystems/>
124
126 Stevan Little <stevan.little@iinteractive.com>
127
129 This software is copyright (c) 2020, 2019, 2017, 2014, 2012 by Infinity
130 Interactive, Inc.
131
132 This is free software; you can redistribute it and/or modify it under
133 the same terms as the Perl 5 programming language system itself.
134
135
136
137perl v5.32.0 P2r0o2m0i-s0e7s-:2:8Cookbook::ScalaFuturesComparison(3)