danieldietrich on v1.0.0
Fixes malformed .travis.yml (#2… (compare)
danieldietrich on v1.0.0
Simplification (#2367) (compare)
danieldietrich on travis-yml-fix
Fixes malformed .travis.yml (compare)
Good day experts.
I would like to know what the best way to do this is - I have a list of customers and within that list is a list of countries they have been to. If a customer has been to a tropical country then he needs to be added to the list. I have it this way in traditional java. Could you tell me the best way to achieve this in vavr?
List<Customer> customersInTropicalCountries = new ArrayList<>();
for (val customer : people.getCustomers()) {
for (val countryVisited : customer.getCountriesVisited()) {
if (countryVisited.isTropical()) {
customersInTropicalCountries.add(customer);
}
}
}
Good day, Sir!
I translated your statement based code to something more functional. I think you could also achieve the same with plain Java Streams, but it is a bit more verbose if you use the collect
calls. Here is a Vavr version, a direct translation of your requirements:
// use io.vavr.collection.List instead of java.util.List
var customersInTropicalCountries = people.getCustomers().map(customer -> // I have a list of customers
customer.getCountriesVisited() // and within that list is a list of countries they have been to
.filter(countryVisited -> countryVisited.isTropical()) // If a customer has been to a tropical country
.map(countryVisited -> customer) // then he needs to be added to the list
);
.distinct()
in order to get sure that each customer appears only once in the list. Your original code could be modified by using a Set instead of a List.
.distinct()
work correctly, Customer needs to have a proper implementation of equals and hashCode.
I have a question, can I work with the vavr library and vert.x at the same time? Additionally applying the CQRS pattern with this two technologies, how productive or feasible can it be? About two years ago I worked with Java 8 + vavr and CQRS, I found it very good.
Thanks.
Hi all and thanks for the great library! I am trying to write a Stream.unfoldRight
but I am getting some compiler errors I cannot seem to understand. Here is the code:
Stream<Tuple2<Point, BigDecimal>> points = Stream.<StreamState, Tuple2<Point, BigDecimal>>unfoldRight(startState, ss -> {
Option<Tuple2<Tuple2<Point, BigDecimal>, StreamState>> next = ss.next();
return next;
});
And this is the error I get:
Type mismatch: cannot convert from Option<Tuple2<Tuple2<Point,BigDecimal>,StreamState>> to Option<Tuple2<? extends Tuple2<Point,BigDecimal>,? extends StreamState>>Java(16777235)
The following however compiles:
Stream<Tuple2<Point, BigDecimal>> points = Stream.<StreamState, Tuple2<Point, BigDecimal>>unfoldLeft(startState, ss -> {
return Option.some(Tuple.of(ss, Tuple.of(Point.of(1d, 1d), BigDecimal.ONE)));
});
while if I explicitly assign it to a variable it doesn't:
Stream<Tuple2<Point, BigDecimal>> points = Stream.<StreamState, Tuple2<Point, BigDecimal>>unfoldLeft(startState, ss -> {
Option<Tuple2<StreamState, Tuple2<Point, BigDecimal>>> some = Option.some(Tuple.of(ss, Tuple.of(Point.of(1d, 1d), BigDecimal.ONE)));
return some;
});
I understand this is primarily a Java issue, but any ideas are welcome.
I'm running into an issue between {io.grpc.Context
, java.util.concurrent.CompletableFuture
, io.vavr.Future
}.
It seems that doing a Future.fromCompletableFuture(someCompletableFuture)
loses the gRPC Context.
I'm not sure if this is an implementation detail (and shouldn't be relied on), but it seems that someCompletableFuture.thenApply(func1).thenApply(func2)
don't suffer from the problem of switching threads (and thus losing context).
I don't know if I can rely on someVavrFuture.map(func1).map(func2)
to also happen in the same thread?
i.e. i'm not sure if my problem is just building my initial io.vavr.Future
(and then through any downstream maps, the thread (and thus thread context) will be the same), or if i basically can't use vavr Futures because any thread context will go missing.
lastly, i know that my code's public API needs to provide CompletableFuture
s, so I'll need to call future.toCompletableFuture()
. is this another point where my thread context will go missing?
i did find this issue (vavr-io/vavr#1530) that seems to suggest that the same thread will be re-used, but i'm not sure if this is something to be relied on.
hope this channel is still active. thank you!
30 tests later, and i've narrowed it down to introducing a flatMap(v -> Future.fromCompletableFuture(CompletableFuture.completedFuture(v)))
(with any variation of executor supplied, including guava's MoreExecutors.directExecutor
and swapping completedFuture
for supplyAsync
).
what's strange is that it doesn't seem to happen when i just do flatMap(v -> Future.of(directExecutor(), () -> v))
.
executor
provided to Future.fromCompletableFuture
as shown here @Test
void testFuture_FromCompletableFuture_ContextExecutor__failure() {
assertHandler(
(contextValue) ->
Future.fromCompletableFuture(
Context.currentContextExecutor(EXECUTOR),
CompletableFuture.completedFuture(getContextValue()))
.map(assertReturnValueEquals(contextValue))
// we should be executing on *our* context executor, but apparently we're not
.map(assertContextValueIsNull())
.toCompletableFuture()
.thenApply(assertContextValueIsNull()));
}
to contribute to a system I'm building for, i need to ensure that a CompletableFuture
has access to the "context value on the thread", and that the CompletableFuture
returned also has access to the "context value on the thread".
if i don't use vavr's Future
at all (effectively sticking with CompletableFuture.thenApply().thenApply()
, then i don't have this issue, though i'm also not able to take advantage of the future monad.
Hi @dfee,
Hi,
by looking at the implementation I don't see a problem with the internal use of the Exector
at the moment (which does not necessarily mean there is none ;):
// Future.java
@Override
default <U> Future<U> map(Function<? super T, ? extends U> mapper) {
Objects.requireNonNull(mapper, "mapper is null");
return transformValue(t -> t.map(mapper));
}
default <U> Future<U> transformValue(Function<? super Try<T>, ? extends Try<? extends U>> f) {
Objects.requireNonNull(f, "f is null");
return run(executor(), complete ->
onComplete(t -> Try.run(() -> complete.with(f.apply(t)))
.onFailure(x -> complete.with(Try.failure(x)))
)
);
}
static <T> Future<T> run(Executor executor, Task<? extends T> task) {
return FutureImpl.sync(executor, task);
}
// FutureImpl.java
static <T> FutureImpl<T> sync(Executor executor, Task<? extends T> task) {
return new FutureImpl<>(executor, Option.none(), Queue.empty(), Queue.empty(), (complete, updateThread) ->
task.run(complete::with)
);
}
// constructor
private FutureImpl(Executor executor, Option<Try<T>> value, Queue<Consumer<Try<T>>> actions, Queue<Thread> waiters, Computation<T> computation) {
this.executor = executor;
synchronized (lock) {
this.cancelled = false;
this.value = value;
this.actions = actions;
this.waiters = waiters;
try {
computation.execute(this::tryComplete, this::updateThread);
} catch (Throwable x) {
tryComplete(Try.failure(x));
}
}
}
However, the Executor
isn't respected when creating the CompletableFuture
:
@Override
default CompletableFuture<T> toCompletableFuture() {
final CompletableFuture<T> future = new CompletableFuture<>();
onSuccess(future::complete);
onFailure(future::completeExceptionally);
return future;
}
That might be one problem. However, you also see problems during mapping a Future
, right? Could you provide a minimal working example that does not use any 3rd library code?
Please create an issue if you think it is a bug. I could translate your example to Scala (which we align to) and see, how it behaves.
Context
create a ThreadLocal
? It would be nice to have a bare example that removes all involved library code.
1.0.0-alpha-4
) branch. i am still using Java 8.@danieldietrich more than happy to provide an even more minimal impl. however, i'll need to figure out how to identify /which/ executor i'm using.
unfortunately, i've not identified a great way to do this. perhaps creating executors with a single thread, using a threadlocal variable to "put" markers, and then sweep for those markers at the end of the test?
as to your other question; unfortunately at $job, we're still using 8
thank you!
perhaps creating executors with a single thread, using a threadlocal variable to "put" markers, and then sweep for those markers at the end of the test?
yes, it seems that you want to ensure that you use exactly the same same thread from a pool of threads when doing subsequent computations. it would be good to add a unit test to Vavr, in order to ensure we do not have regressions in the future. Of course, I need to check first, if that fits into the computational model of Vavr, also by verifying how Scala's Future behaves. Having a minimal working example will help to verify that in Scala.
@danieldietrich Thanks for the quick answer.
Just to clarify, some sort of sync is still needed. Because if the memoized function is shared between threads the cache has to be sync.
I tried using a ConcurrentHashMap to avoid full sync, my changes broke a test about recursion, after 3am, I went to sleep and this morning I found this:
https://blog.jooq.org/avoid-recursion-in-concurrenthashmap-computeifabsent/
Apparently we do not have a solution except from the old sync block.