dtonhofer
Functional Programming in Java, Second Edition: Functional Programming in Java, Second Edition: JUnit code improvements for Chapter 11, pages 185 ff “Refactoring Unbounded Loops”
The same remarks apply as for “Refactoring the Traditional for Loop”
- No init()
- Negative tests which apply for input less than 1900, resulting in exceptions.
but we cannot implement a common interface as the method parameters change. So we wrap the new class into a class that obeys the old interface, which agains llaows us to use the same test code to test both odl and new classes.
There is also a little tweak to the semantics of the case where 1900 is already rejected - instead of returning 0, we throw. Because there basically is no result in that case.
package chapter11;
import org.junit.jupiter.api.Test;
import java.time.Year;
import java.util.function.Predicate;
import java.util.stream.IntStream;
import static org.junit.jupiter.api.Assertions.*;
public class UnboundedLoopTest {
interface Continue {
boolean check(int year);
}
interface WithContinue {
int countFrom1900(final Continue shouldContinue);
}
static class LeapYearsUnboundedBefore implements WithContinue {
public int countFrom1900(final Continue shouldContinue) {
if (!shouldContinue.check(1900)) {
throw new IllegalArgumentException("Cannot 'continue' right at the start!'");
}
int count = 0;
for (int year = 1900; ; year += 4) {
if (!shouldContinue.check(year)) {
break;
}
if (Year.isLeap(year)) {
count++;
}
}
return count;
}
}
// Does NOT implement WithContinue!!
static class LeapYearsUnboundedAfter {
public int countFrom1900(final Predicate<Integer> shouldContinue) {
if (!shouldContinue.test(1900)) {
throw new IllegalArgumentException("Cannot 'continue' right at the start!'");
}
return (int) IntStream.iterate(1900, year -> year + 4)
.takeWhile(shouldContinue::test)
.filter(Year::isLeap)
.count();
}
}
static class LeapYearsUnboundedAfterWrapped implements WithContinue {
private final LeapYearsUnboundedAfter ly;
public LeapYearsUnboundedAfterWrapped(LeapYearsUnboundedAfter ly) {
this.ly = ly;
}
public int countFrom1900(final Continue shouldContinue) {
return ly.countFrom1900(year -> shouldContinue.check(year));
}
}
// One should maybe have a separate method to test the throws
private static void commonLeapYearsTests(final WithContinue withContinue) {
assertAll(
() -> assertEquals(0, withContinue.countFrom1900(year -> year <= 1900)),
() -> assertEquals(25, withContinue.countFrom1900(year -> year <= 2000)),
() -> assertEquals(27, withContinue.countFrom1900(year -> year <= 2010)),
() -> assertEquals(31, withContinue.countFrom1900(year -> year <= 2025)),
() -> assertEquals(49, withContinue.countFrom1900(year -> year <= 2100)),
() -> assertEquals(267, withContinue.countFrom1900(year -> year <= 3000)),
() -> assertThrows(IllegalArgumentException.class, () ->
withContinue.countFrom1900(year -> year < 1800)
),
() -> assertThrows(IllegalArgumentException.class, () ->
withContinue.countFrom1900(year -> year < 1900)
)
);
}
@Test
void leapYearCountBefore() {
commonLeapYearsTests(new LeapYearsUnboundedBefore());
}
@Test
void leapYearCountAfter() {
commonLeapYearsTests(new LeapYearsUnboundedAfterWrapped(new LeapYearsUnboundedAfter()));
}
}
Popular Pragmatic Bookshelf topics
The following is cross-posted from the original Ray Tracer Challenge forum, from a post by garfieldnate. I’m cross-posting it so that the...
New
Hi @Margaret ,
On page VII the book tells us the example and snippets will be all using Elixir version 1.11
But on page 3 almost the en...
New
Hi,
build fails on:
bracket-lib = “~0.8.1”
when running on Mac Mini M1 Rust version 1.5.0:
Compiling winit v0.22.2
error[E0308]: mi...
New
In case this helps anyone, I’ve had issues setting up the rails source code. Here were the solutions:
In Gemfile, change
gem 'rails'
t...
New
“The ProductLive.Index template calls a helper function, live_component/3, that in turn calls on the modal component. ”
Excerpt From: Br...
New
I found an issue in Chapter 7 regarding android:backgroundTint vs app:backgroundTint.
How to replicate:
load chapter-7 from zipfile i...
New
Hey there,
I’m enjoying this book and have learned a few things alredayd. However, in Chapter 4 I believe we are meant to see the “>...
New
AWDWR 7, page 152, page 153:
Hello everyone,
I’m a little bit lost on the hotwire part. I didn’t fully understand it.
On page 152 @rub...
New
Modern Front-End Development for Rails - application does not start after run bin/setup (page xviii)
After some hassle, I was able to finally run bin/setup, now I have started the rails server but I get this error message right when I vis...
New
I’ve got to the end of Ch. 11, and the app runs, with all tabs displaying what they should – at first. After switching around between St...
New
Other popular topics
Ruby, Io, Prolog, Scala, Erlang, Clojure, Haskell. With Seven Languages in Seven Weeks, by Bruce A. Tate, you’ll go beyond the syntax—and...
New
My first contact with Erlang was about 2 years ago when I used RabbitMQ, which is written in Erlang, for my job. This made me curious and...
New
Small essay with thoughts on macOS vs. Linux:
I know @Exadra37 is just waiting around the corner to scream at me “I TOLD YOU SO!!!” but I...
New
Build efficient applications that exploit the unique benefits of a pure functional language, learning from an engineer who uses Haskell t...
New
I am trying to crate a game for the Nintendo switch, I wanted to use Java as I am comfortable with that programming language. Can you use...
New
If you want a quick and easy way to block any website on your Mac using Little Snitch simply…
File > New Rule:
And select Deny, O...
New
Author Spotlight:
Bruce Tate
@redrapids
Programming languages always emerge out of need, and if that’s not always true, they’re defin...
New
Hair Salon Games for Girls Fun
Girls Hair Saloon game is mainly developed for kids. This game allows users to select virtual avatars to ...
New
A concise guide to MySQL 9 database administration, covering fundamental concepts, techniques, and best practices.
Neil Smyth
MySQL...
New
Open-source implementation of the classic GTA engine now running directly in your browser. Experience the reVC technology demo on DOS.Zon...
New
Categories:
Sub Categories:
Popular Portals
- /elixir
- /rust
- /wasm
- /ruby
- /erlang
- /phoenix
- /keyboards
- /python
- /js
- /rails
- /security
- /go
- /swift
- /vim
- /clojure
- /java
- /emacs
- /haskell
- /typescript
- /svelte
- /onivim
- /kotlin
- /c-plus-plus
- /crystal
- /tailwind
- /react
- /gleam
- /ocaml
- /flutter
- /elm
- /vscode
- /ash
- /html
- /deepseek
- /opensuse
- /zig
- /centos
- /php
- /scala
- /react-native
- /lisp
- /textmate
- /sublime-text
- /nixos
- /debian
- /agda
- /deno
- /django
- /kubuntu
- /arch-linux
- /nodejs
- /ubuntu
- /spring
- /revery
- /manjaro
- /lua
- /diversity
- /julia
- /markdown
- /quarkus









