Recent Posts
Archives

Posts Tagged ‘FunctionalProgramming’

PostHeaderIcon [DevoxxBE2013] Part 1: Thinking Functional Style

Venkat Subramaniam, an award-winning author and founder of Agile Developer, Inc., guides developers through the paradigm shift of functional programming on the JVM. Renowned for Functional Programming in Java and his global mentorship, Venkat uses Java 8, Groovy, and Scala to illustrate functional tenets. His session contrasts imperative statements with composable expressions, demonstrating how to leverage lambda expressions and higher-order functions for elegant, maintainable code.

Functional programming, Venkat posits, transcends syntax—it’s a mindset fostering immutability and data flow. Through practical examples, he showcases Groovy’s idiomatic functional constructs and Scala’s expression-driven purity, equipping attendees to rethink application design.

Functional Principles and Expressions

Venkat contrasts statements—imperative, mutation-driven blocks—with expressions, which compute and return values. He demos a Java 8 stream pipeline, transforming data without side effects, versus a loop’s mutability.

Expressions, Venkat emphasizes, enable seamless composition, fostering cleaner, more predictable codebases.

Groovy’s Functional Idioms

Groovy, though not purely functional, excels in functional style, Venkat illustrates. He showcases collect and findAll for list transformations, akin to Java 8 streams, with concise closures.

These idioms, he notes, simplify data processing, making functional patterns intuitive for Java developers.

Scala’s Expression-Driven Design

Scala’s expression-centric nature shines in Venkat’s examples: every construct returns a value, enabling chaining. He demos pattern matching and for-comprehensions, streamlining complex workflows.

This purity, Venkat argues, minimizes state bugs, aligning with functional ideals.

Higher-Order Functions and Composition

Venkat explores higher-order functions, passing lambdas as arguments. A Groovy example composes functions to filter and map data, while Scala’s currying simplifies partial application.

Such techniques, he asserts, enhance modularity, enabling parallelization for performance-critical tasks.

Practical Adoption and Parallelization

Venkat advocates starting with small functional refactors, like replacing loops with streams. He demos parallel stream processing in Java 8, leveraging multi-core CPUs.

This pragmatic approach, he concludes, bridges imperative habits with functional elegance, boosting scalability.

Links:

PostHeaderIcon [DevoxxFR2014] Reactive Programming with RxJava: Building Responsive Applications

Lecturer

Ben Christensen works as a software engineer at Netflix. He leads the development of reactive libraries for the JVM. Ben serves as a core contributor to RxJava. He possesses extensive experience in constructing resilient, low-latency systems for streaming platforms. His expertise centers on applying functional reactive programming principles to microservices architectures.

Abstract

This article provides an in-depth exploration of RxJava, Netflix’s implementation of Reactive Extensions for the JVM. It analyzes the Observable pattern as a foundation for composing asynchronous and event-driven programs. The discussion covers essential operators for data transformation and composition, schedulers for concurrency management, and advanced error handling strategies. Through concrete Netflix use cases, the article demonstrates how RxJava enables non-blocking, resilient applications and contrasts this approach with traditional callback-based paradigms.

The Observable Pattern and Push vs. Pull Models

RxJava revolves around the Observable, which functions as a push-based, composable iterator. Unlike the traditional pull-based Iterable, Observables emit items asynchronously to subscribers. This fundamental duality enables uniform treatment of synchronous and asynchronous data sources:

Observable<String> greeting = Observable.just("Hello", "RxJava");
greeting.subscribe(System.out::println);

The Observer interface defines three callbacks: onNext for data emission, onError for exceptions, and onCompleted for stream termination. RxJava enforces strict contracts for backpressure—ensuring producers respect consumer consumption rates—and cancellation through unsubscribe operations.

Operator Composition and Declarative Programming

RxJava provides over 100 operators that transform, filter, and combine Observables in a declarative manner. These operators form a functional composition pipeline:

Observable.range(1, 10)
          .filter(n -> n % 2 == 0)
          .map(n -> n * n)
          .subscribe(square -> System.out.println("Square: " + square));

The flatMap operator proves particularly powerful for concurrent operations, such as parallel API calls:

Observable<User> users = getUserIds();
users.flatMap(userId -> userService.getDetails(userId), 5)
     .subscribe(user -> process(user));

This approach eliminates callback nesting (callback hell) while maintaining readability and composability. Marble diagrams visually represent operator behavior, illustrating timing, concurrency, and error propagation.

Concurrency Control with Schedulers

RxJava decouples computation from threading through Schedulers, which abstract thread pools:

Observable.just(1, 2, 3)
          .subscribeOn(Schedulers.io())
          .observeOn(Schedulers.computation())
          .map(this::cpuIntensiveTask)
          .subscribe(result -> display(result));

Common schedulers include:
Schedulers.io() for I/O-bound operations (network, disk).
Schedulers.computation() for CPU-bound tasks.
Schedulers.newThread() for fire-and-forget operations.

This abstraction enables non-blocking I/O without manual thread management or blocking queues.

Error Handling and Resilience Patterns

RxJava treats errors as first-class citizens in the data stream:

Observable risky = Observable.create(subscriber -> {
    subscriber.onNext(computeRiskyValue());
    subscriber.onError(new RuntimeException("Failed"));
});
risky.onErrorResumeNext(throwable -> Observable.just("Default"))
     .subscribe(value -> System.out.println(value));

Operators like retry, retryWhen, and onErrorReturn implement resilience patterns such as exponential backoff and circuit breakers—critical for microservices in failure-prone networks.

Netflix Production Use Cases

Netflix employs RxJava across its entire stack. The UI layer composes multiple backend API calls for personalized homepages:

Observable<Recommendation> recs = userIdObservable
    .flatMap(this::fetchUserProfile)
    .flatMap(profile -> Observable.zip(
        fetchTopMovies(profile),
        fetchSimilarUsers(profile),
        this::combineRecommendations));

The API gateway uses RxJava for timeout handling, fallbacks, and request collapsing. Backend services leverage it for event processing and data aggregation.

Broader Impact on Software Architecture

RxJava embodies the Reactive Manifesto principles: responsive, resilient, elastic, and message-driven. It eliminates common concurrency bugs like race conditions and deadlocks. For JVM developers, RxJava offers a functional, declarative alternative to imperative threading models, enabling cleaner, more maintainable asynchronous code.

Links:

PostHeaderIcon [DevoxxBE2013] Lambda: A Peek Under the Hood

Brian Goetz, Java Language Architect at Oracle, offers an illuminating dissection of lambda expressions in Java SE 8, transcending syntactic sugar to reveal the sophisticated machinery powering this evolution. Renowned for Java Concurrency in Practice and leadership in JSR 335, Brian demystifies lambdas’ implementation atop invokedynamic from Java SE 7. His session, eschewing introductory fare, probes the VM’s strategies for efficiency, contrasting naive inner-class approaches with optimized bootstrapping and serialization.

Lambdas, Brian asserts, unlock expressive potential for applications and libraries, but their true prowess lies in performance rivaling or surpassing inner classes—without the bloat. Through benchmarks and code dives, he showcases flexibility and future-proofing, underscoring the iterative path to a robust design.

From Syntax to Bytecode: The Bootstrap Process

Brian traces lambdas’ lifecycle: source code desugars to invokedynamic callsites, embedding a “recipe” for instantiation. The bootstrap method, invoked once per callsite, crafts a classfile dynamically, caching for reuse.

This declarative embedding, Brian illustrates, avoids inner classes’ per-instance overhead, yielding leaner bytecode and faster captures—non-capturing lambdas hit 1.5x inner-class speeds in early benchmarks.

Optimization Strategies and Capture Semantics

Capturing lambdas, Brian explains, leverage local variable slots via synthetic fields, minimizing allocations. He contrasts “eager” (immediate class creation) with “lazy” (deferred) strategies, favoring the latter for reduced startup.

Invokedynamic’s dynamic binding enables profile-guided refinements, promising ongoing gains. Brian’s throughput metrics affirm lambdas’ edge, even in capturing scenarios.

Serialization and Bridge Methods

Serializing lambdas invokes writeReplace to a serialized form, preserving semantics without runtime overhead. Brian demos bridge methods for functional interfaces, ensuring compatibility.

Default methods, he notes, extend interfaces safely, avoiding binary breakage—crucial for library evolution.

Lessons from Language Evolution

Brian reflects on Lambda’s odyssey: discarded ideas like inner-class syntactic variants paved the way for invokedynamic’s elegance. This resilience, he posits, exemplifies evolving languages amid obvious-but-flawed intuitions.

Project Lambda’s resources—OpenJDK docs, JCP reviews—invite deeper exploration, with binary builds for experimentation.

Links:

PostHeaderIcon [DevoxxFR2013] WTF – What’s The Fold?

Lecturer

Olivier Croisier operates as a freelance Java expert, trainer, and speaker through Moka Technologies. With over twelve years in the field, he assists clients in Java 8 migrations, advanced stack development, and revitalizing team enthusiasm for coding.

Abstract

Olivier Croisier elucidates the fold concept from functional programming, demonstrating its abstraction of iteration for enhanced code expressiveness. Using Java 8 streams and Haskell parallels, he dissects implementations, applications in mapping/filtering/reducing, and performance implications. The analysis positions fold as a versatile pattern surpassing traditional loops, integrable even in pre-Java 8 environments.

Origins and Essence: Fold as Iterative Abstraction

Croisier traces fold to functional languages like Haskell, where it generalizes accumulation over collections. Left fold (foldl) processes sequentially; right fold (foldr) enables laziness.

In essence, fold applies a binary operation cumulatively: start with accumulator, combine with each element.

Java analogy: external iterators (for-loops) versus internal (streams). Fold internalizes control, yielding concise, composable code.

Implementing Fold in Java: From Basics to Streams

Pre-Java 8, Croisier crafts a utility:

public static <T, R> R fold(Collection<T> coll, R init, BiFunction<R, T, R> f) {
    R acc = init;
    for (T e : coll) acc = f.apply(acc, e);
    return acc;
}

Usage: sum integers—fold(list, 0, (a, b) -> a + b).

Java 8 streams natively provide reduce (fold alias):

int sum = list.stream().reduce(0, Integer::sum);

Parallel streams distribute: .parallelStream().reduce().

Croisier notes identity requirement for parallelism; non-associative operations risk inconsistencies.

Beyond Reduction: Mapping, Filtering, and Collection Building

Fold transcends summing; rebuild collections:

List<String> mapped = fold(list, new ArrayList<>(), (acc, e) -> { acc.add(transform(e)); return acc; });

Filter via conditional accumulation. This unifies operations—map/filter as specialized folds.

Haskell’s foldr constructs lists lazily, enabling infinite structures. Java’s eager evaluation limits but streams offer similar chaining.

Expressive Power and Performance Trade-offs

Croisier contrasts verbose loops with declarative folds, enhancing readability/maintainability. Encapsulate patterns in methods for reuse/optimization.

Performance: sequential folds match loops; parallel leverages multicore but incurs overhead (threading, combining).

JVM optimizations (invokedynamic for lambdas) potentially outperform anonymous classes. Croisier advocates testing under load.

Versus map-reduce: fold suits in-memory; Hadoop for distributed big data.

Integration Strategies and Broader Implications

Adopt incrementally: utility class for legacy code. Java 8+ embraces streams.

Croisier views fold as expressivity tool—not replacing conditionals but abstracting mechanics.

Implications: functional paradigms ease concurrency, prepare for multicore era. Fold’s versatility—from reductions to transformations—elevates code abstraction.

Links:

PostHeaderIcon [DevoxxFR2013] FLATMAP ZAT SHIT: Monads Explained to Geeks

Lecturer

François Sarradin is a Java and lambda developer, serving as a technical capitalization manager. He contributes to the Brown Bag Lunch initiative, sharing expertise through presentations.

Abstract

François Sarradin’s session introduces monads in functional programming, using Scala and Java 8 examples to demystify their utility. He addresses handling errors, asynchrony, and technical concerns without cluttering business logic, employing monadic structures like Try and Future. The talk analyzes code transformations for cleaner, composable designs, highlighting monads’ role in aspect-oriented programming and drawing parallels to AOP frameworks.

The Problem: Technical Debt Obscuring Business Logic

Sarradin illustrates a common plight: initial clean code accumulates technical safeguards—null checks, try-catch blocks, synchronization—eroding readability and productivity. He proposes separating concerns: keep business logic pure, inject technical aspects via mechanisms akin to aspect-oriented programming (AOP).

Using AOP tools like AspectJ or Spring AOP declares cross-cutting concerns (e.g., logging, error handling) separately, leveraging compilers for coherence. This maintains original code structure while addressing realities like exceptions or async calls.

An example application in Scala computes total balance across bank accounts, initially straightforward but vulnerable. Technical intrusions (e.g., if-null, try-catch) bloat it, prompting a search for elegant solutions.

Introducing Monads: Error Handling with Try

To manage errors without pervasive checks, Sarradin introduces the Try monad in Scala: a container wrapping success (Success(value)) or failure (Failure(exception)). This allows chaining operations via flatMap and map, propagating errors implicitly.

Transforming the balance app: wrap account retrieval in Try, use for-comprehensions (sugaring flatMap/map) for composition. If any step fails, the whole computation fails gracefully, without explicit exception handling.

Code evolves from imperative checks to declarative chains:

val total = for {
  account1 <- Try(getAccount(bank1))
  account2 <- Try(getAccount(bank2))
  balance1 <- Try(getBalance(account1))
  balance2 <- Try(getBalance(account2))
} yield balance1 + balance2

This yields Try[Double], inspectable via isSuccess, get, or getOrElse. Monads here abstract error propagation, enhancing modularity.

Java 8’s Optional partially mirrors this but lacks full monadic power; Sarradin implements a custom Try for illustration, using abstract classes with Success/Failure subclasses.

Extending to Asynchrony: Futures for Non-Blocking Computations

Asynchrony poses similar issues: callbacks or blocking awaits disrupt flow. Scala’s Future monad encapsulates eventual values, enabling composition without blocking.

In the app, wrap async calls in Future: use flatMap to chain, ensuring non-blocking execution. For-comprehensions again simplify:

val totalFuture = for {
  account1 <- Future(getAccountAsync(bank1))
  account2 <- Future(getAccountAsync(bank2))
  balance1 <- Future(getBalanceAsync(account1))
  balance2 <- Future(getBalanceAsync(account2))
} yield balance1 + balance2

totalFuture completes asynchronously; callbacks via onComplete handle results. This maintains sequential appearance while parallelizing under the hood.

Sarradin contrasts with Java 8’s CompletableFuture, which offers thenApply/thenCompose for similar chaining, though less idiomatic without for-comprehensions.

Monads as a Unifying Abstraction: Synthesis and Implications

Monads generalize: a type M[A] with map (transform value) and flatMap (chain computations). They inject contexts (error, future) into pure functions, separating concerns.

In the app, combining Try and Future (via Scalaz’s EitherT or custom) handles both errors and asynchrony. This AOP-like injection leverages type systems for safety, contrasting annotation-based AOP.

Java 8 approximates with lambdas and CompletableFuture/Optional, but lacks Scala’s expressiveness. Custom implementations reveal monads’ essence: abstract class with map/flatMap, subclasses for Success/Failure.

Sarradin concludes monads enhance composability, reducing boilerplate for robust, maintainable code in functional paradigms.

Relevant Links and Hashtags

Links:

PostHeaderIcon [DevoxxFR2013] Objects and Functions: Conflict Without a Cause?

Lecturer

Martin Odersky is a professor at EPFL in Lausanne, Switzerland, specializing in programming languages that blend object-oriented and functional paradigms. His research unifies these approaches, evidenced by designs like Pizza, GJ, and Functional Nets. He co-designed Java generics and authored the original javac compiler. Currently, he focuses on Scala, fusing functional and object-oriented programming while ensuring interoperability with Java and .NET.

Abstract

Martin Odersky’s lecture traces object-oriented programming’s (OOP) rise, parallels it with functional programming’s (FP) resurgence, and argues for their synthesis. Analyzing historical catalysts, methodological benefits, and modern hardware demands, he demonstrates how FP addresses parallelism and reactivity challenges. Through Scala examples, Odersky shows OOP and FP as complementary, enhancing modularity and abstraction without mutual exclusion.

Historical Roots and Catalysts for OOP Adoption

Odersky recounts his journey from Pascal compilers to modular languages, Java involvement, and Scala creation. OOP’s mainstreaming, he argues, stemmed not from encapsulation or reuse but practical necessities. Simula (1967) for simulations and Smalltalk (late 1970s) for GUI widgets inverted traditional data structures: fixed operations, unbounded implementations.

In procedural languages like C, this was cumbersome via function pointers; OOP simplified dynamic binding for unknown implementations. Odersky notes early confusion with Smalltalk, mirroring current FP bewilderment. OOP’s advantages – modeling, dependency inversion – emerged post-adoption, sparked by widget programming appeal.

Functional Programming’s Resurgence and Methodological Strengths

FP offers fewer errors, superior modularity, and productivity via higher abstractions and shorter code. Yet, despite 50-year existence, mainstream adoption lagged. Odersky identifies multicore and cloud computing as catalysts: parallelism for hardware utilization, reactivity for asynchronous events, distribution for delays/failures.

Mutable state exacerbates issues like cache coherence and non-determinism in concurrent environments. Immutable data mitigates races, enabling safe caching. Locks/threads scale poorly; even transactions retain problems. FP’s immutability fosters determinism, crucial for scalable systems.

Addressing Modern Computing Challenges with FP

Odersky outlines a triple challenge: parallel, reactive, distributed programming. Mutable state hinders each; FP excels by avoiding it.

For parallelism, he exemplifies mapping developer names: sequential in Scala, parallel via .par, yielding a parallel collection. Side effects risk chaos due to reordered executions, necessitating functional purity for correctness.

Reactivity example: an online store querying users, orders, products, stock. Synchronous calls block threads on slow services, degrading performance. Asynchronous futures prevent blocking; Scala’s for-comprehensions compose them elegantly, hiding complexity. Refactoring for parallelism pairs futures, executing concurrently.

For-comprehensions translate universally to map, flatMap, filter, allowing library-defined interpretations – sequential or async – without polluting domain logic.

Synthesizing OOP and FP: Beyond False Dichotomies

Communities often view OOP and FP oppositely, but Odersky argues orthogonality. Objects modularize (“what goes where”), providing containers with dynamic binding and inheritance. Essential for large codebases (e.g., million-line Scala systems), they prevent global namespace chaos – a Haskell limitation.

Redefine objects: eliminate mutable state dogma (e.g., immutable java.lang.String), structural equality over identity, focus on behavior. Scala embodies this fusion, modeling algebraic types with objects while importing FP capabilities.

Scala unifies scripting (winning JavaOne Script Bowl) and safe, performant systems (core for Twitter, LinkedIn). Odersky concludes OOP/FP synergy enhances development, urging exploration via Scala Days, courses, and talks.

Relevant Links and Hashtags

Links:

PostHeaderIcon [DevoxxBE2012] First Steps with Scala (Part 1/2)

In an engaging session, Dick Wall and Bill Venners, co-founders of Escalate Software and prominent figures in the Scala community, introduced newcomers to the Scala programming language. Dick, known for his JavaPosse involvement, and Bill, president of Artima and author of key Java texts, adapted their training curriculum to cover foundational elements. Their approach fused object-oriented and functional paradigms, emphasizing Scala’s blend of familiarity and innovation.

They commenced with the Scala REPL, a tool they use daily for experimentation. This interactive shell allows immediate code execution, inferring types and storing results for reuse, making it invaluable even for Java developers exploring libraries.

Dick and Holly—wait, Dick and Bill—highlighted Scala’s strong typing with inference, reducing boilerplate while maintaining safety. They demonstrated basic operations, showing how everything integrates into a unified hierarchy, unlike Java’s primitives and references.

Defining Variables and Immutability

Transitioning to variables, Dick and Bill distinguished between vals (immutable) and vars (mutable), promoting vals for reliability. This design choice encourages constant use without extra syntax, contrasting Java’s final keyword. They illustrated reassignment errors, noting REPL’s scoping allows redefinitions, mimicking nested blocks.

Type specifications, optional due to inference, follow names with colons, inverting Java’s order for natural flow. Examples showed string inferences and explicit declarations, underscoring flexibility.

They addressed mutability choices, advising private volatile vars for necessary changes, or mutable objects within immutable structures, depending on context.

Control Structures and Expressions

Dick and Bill explored control structures, revealing Scala’s expression-oriented nature. If statements return values, enabling concise assignments without ternaries. While loops, though imperative, yield Unit, encouraging functional alternatives.

For comprehensions, powerful for iteration, support guards and yields, transforming collections declaratively. They demonstrated filtering even numbers or yielding transformed lists, highlighting pattern matching integration.

Try-catch blocks, also expressions, handle exceptions functionally, with finally clauses for cleanup. This uniformity simplifies code, treating controls as value producers.

Functions and Closures

Delving into functions, they defined them as objects, enabling higher-order usage. Simple defs showed parameter typing and inference, with return types often omitted.

Function literals, akin to lambdas, capture environments as closures, allowing deferred execution. Examples illustrated anonymous functions for mapping or filtering, emphasizing Scala’s functional leanings.

They introduced by-name parameters for lazy evaluation, useful in custom controls like loops, mimicking built-in syntax without special privileges.

Collections and Functional Programming

Scala collections, immutable by default, support transformations via methods like map and filter. Dick and Bill showcased creating lists, accessing elements, and applying operations, yielding new collections without mutation.

They contrasted mutable variants, advising caution for concurrency. For comprehensions over collections generate new ones, combining iteration with functional purity.

Approaching functional style, they encouraged avoiding side effects, using recursion or folds for aggregations, fostering predictable code.

Advanced Basics and Q&A Insights

In Q&A, they addressed optimizations: Scala uses primitives internally, with @specialized for generics avoiding boxing. Profiling mirrors Java tools, with quirks in coverage.

Dick and Bill wrapped by previewing afternoon labs on Scala Koans, urging practice. Their session laid a solid groundwork, blending theory with practical demos, preparing attendees for Scala’s expressive power.

Links: