NivaarExam PrepOfficial exam papers ↗

19-Soft-B17 Data Visualization · December 2014

Question 7 of 10

Nivaar worked solution (AI-drafted; not reviewed by a licensed engineer)

Notes on this paper

04-Soft-B17, Programming Language Paradigm — National Exams, December 2014 (3 hours, open book, 10 questions of equal value, essay-format answers).

Reference texts: Sebesta, Concepts of Programming Languages, 12th ed. (object-oriented language design, subtyping, functional programming, exception handling, lambda expressions); Sommerville, Software Engineering, 10th ed. (object-oriented design, modularity); Gamma et al. (GoF), Design Patterns, 1st ed. (composition-over-inheritance, Liskov Substitution Principle in practice).

Check: this paper's printed course title and all ten questions are exclusively about object-oriented and functional programming-language concepts (classes, subtyping, overriding/overloading, exceptions, functional vs. procedural style, actor model, lambda expressions, immutability) — there is no data-visualization content anywhere in the paper. This solution follows the exam as printed ("04-SOFT-B17: Programming Language Paradigm").

Question 7 (10%)

Question text not reproduced: the examination questions are © Engineers and Geoscientists BC. Open the official past paper (linked at the top of this page) to read the question, then follow the worked solution below.

The most significant difference is in how each paradigm treats state and mutation. A procedural language expresses a computation as an ordered sequence of statements that repeatedly read and mutate shared program state (variables) — assignment, loops that update a running total or index, and subroutines that may modify data structures passed to them by reference. Correctness in this style depends on the exact order statements execute in, because a later statement's meaning depends on state changes made by earlier ones. A functional language, by contrast, expresses a computation as the evaluation of pure functions applied to (typically immutable) data: a pure function's output depends only on its inputs, has no observable side effects, and never mutates shared state. Instead of loops with mutable counters, functional style favours recursion and higher-order functions such as map, filter, and reduce that transform whole collections at once. Because a pure function has no side effects and no dependence on external mutable state, the order in which independent function applications occur (or whether they occur concurrently) cannot change the result — a property procedural code, with its shared mutable state, does not have in general.

This absence of shared mutable state is exactly what makes the functional paradigm significant for big-data frameworks such as Hadoop (and its MapReduce programming model). MapReduce asks the programmer to supply two functions: a map function applied independently to each record of a (potentially enormous, distributed) dataset, and a reduce function that combines the mapped results grouped by key. This is a direct application of the functional map/reduce higher-order functions to a cluster-scale dataset. Because a well-written map function is pure — it reads one input record and produces output based only on that record, touching no shared state — the framework is free to run thousands of map invocations in parallel, across many machines, in any order, with no risk of one invocation corrupting another's result through a shared variable, and no need for locks or other concurrency-control mechanisms that a procedural, mutable-state implementation of the same logic would require. Purity also makes fault tolerance straightforward: if a worker node fails partway through, Hadoop can simply re-run the same map task on another node, because a pure function produces the identical result given the identical input — there is no mutable state left in an inconsistent, half-updated condition to worry about, unlike a re-run of a procedural task that had already mutated shared state before failing. In short, the procedural paradigm's reliance on ordered mutation of shared state is precisely the property that makes naive parallelization dangerous (race conditions, non-reproducible results), while the functional paradigm's avoidance of that same property is precisely what lets a framework like Hadoop safely and automatically distribute, reorder, retry, and parallelize computation across a cluster without the programmer having to reason about concurrency at all.