.. _FP1: .. raw:: html .. |--| unicode:: U+2013 .. en dash .. |---| unicode:: U+2014 .. em dash, trimming surrounding whitespace :trim: .. This file is part of the OpenDSA eTextbook project. See .. http://algoviz.org/OpenDSA for more details. .. Copyright (c) 2012-13 by the OpenDSA Project Contributors, and .. distributed under an MIT open source license. .. avmetadata:: :author: David Furcy and Tom Naps ============================================================================= Introduction to Functional Programming - List Construction and Deconstruction ============================================================================= FP - Constructing Lists with cons --------------------------------- .. .. Just a test to see if we can visualize a beta reduction .. .. Just a test to see if we can visualize a beta reduction -- delete when done testing .. .. .. inlineav:: LC1CON ss .. :long_name: Illustrate Lambda Calculus applicative order .. :links: AV/PL/LC/LCCON.css .. :scripts: AV/PL/interpreters/lambdacalc/version1.4.used.in.book/scripts/init.js AV/PL/interpreters/lambdacalc/version1.4.used.in.book/scripts/grammar.js AV/PL/interpreters/lambdacalc/version1.4.used.in.book/scripts/absyn.js AV/PL/interpreters/lambdacalc/version1.4.used.in.book/scripts/interpreter.js AV/PL/interpreters/lambdacalc/version1.4.used.in.book/scripts/randomExamples.js AV/PL/LC/LC1CON.js .. :output: show **Functional programming** (FP) is a programming paradigm where functions are the main abstraction and in which functions are pure, first-class values and data is immutable. A function is **pure** if it returns a value without having any side effects. A pure function does not affect any data outside of itself (no assignment statements, no I/O) and does not access any global data that could be changed by other functions. A pure function ALWAYS returns the same value given the same input, like in mathematics. In fact, FP started with Alonzo Church’s :math:`\lambda`-calculus, which we will study later in this course. **First-class values**, like integers, booleans, strings, etc., are values that can be assigned to variables, can be stored in arrays and other data structures, can be used as an argument in a function call and can be the return value of a function call. In FP, functions are first-class values. Functions that take one or more functions as parameters and/or return a function are called **higher-order functions** (much, much more on this later). In FP, all data items are **immutable**: once a value is created, it can never be modified. Even in Java, which is an OO language, not a FP language, String objects are immutable. The most basic, built-in data structure in FP languages is the list, whose structure can be described in BNF notation as follows: .. math:: \begin{eqnarray*} & ::= & \epsilon \\ &|& \\ \end{eqnarray*} Note that: #. We are limiting ourselves to lists of integers for now, and #. The grammar above describes the **abstract syntax or structure** of lists, not its **concrete syntax**, that is, how lists actually appear in any particular FP language. For our functional programming module, the concrete syntax of lists will use square brackets around each list and a comma between pairs of consecutive elements in the list. So, the empty list will be represented by:: [ ] and non-empty lists will look like this:: [2,3,5,7,11,13,17,19] Since JavaScript does not come with a built-in immutable list data structure, we provide one as part of a module called ``fp.js``, which is used throughout Chapter 2. You can make this module available in your JS files by including the following line at the top of the file:: var fp = require('./fp'); Then, every time you want to use any of the functions defined in this module (such as the ``hd`` function to be described shortly), you will prepend the prefix ``fp.`` to the function’s name. For example, you would call the ``hd`` function with the argument ``list`` like this:: fp.hd(list) Lists can be constructed using the ``cons`` function, which takes two arguments: a single element and a list of elements. The ``cons`` function returns a new list equal to its second argument but with its first argument inserted in front. So, in a read-eval-print loop such as that provided in *node*:: > fp.cons( 5, [1,2,3] ) [ 5, 1, 2, 3 ] > fp.cons( 1, [ ] ) [ 1 ] The ``fp`` module provides a helper function to create an arbitrarily long list in one call, like this: :: > fp.makeList(1,2,3) [ 1, 2, 3 ] > fp.makeList(1,2,3,4,5,6,7,8,9,10) [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ] > fp.makeList() [] The following problem deals with the syntax and semantics of the ``fp.cons`` function. .. avembed:: Exercises/PL/FPcons.html ka :module: FP1 :points: 1.0 :required: True :threshold: 1 :exer_opts: JXOP-debug=true&JOP-lang=en&JXOP-code=java :long_name: Using cons FP - Deconstructing Lists with fp.hd and fp.tl ---------------------------------------------- So far, we can build lists using the ``fp.cons`` and ``fp.makeList`` constructors. However, we also need to be able to access the elements of a list. The ``fp`` module provides the so-called “head” and “tail” accessors. - ``fp.hd(l)`` returns the first element of its list argument. - ``fp.tl(l)`` returns the list obtained by removing the head from its list argument. :: > fp.hd([1,2,3]) 1 > fp.tl([1,2,3]) // how would you access the second or third element of this list? [ 2, 3 ] > fp.hd([]) Error: hd can only be called with a non-empty list. > fp.tl([]) Error: tl can only be called with a non-empty list. In languages like Lisp and Scheme, these accessors are called “car” and “cdr” respectively. It is important to note the symmetry between the ``cons`` constructor and the list accessors: ``cons`` builds a list using the same building blocks that the accessors return. This problem deals with the semantics of the ``fp.hd``, ``fp.tl``, and ``fp.cons`` functions. Note that this problem is randomized. You must solve it correctly three times in a row to earn the point associated with it. .. avembed:: Exercises/PL/FPHdTlCons1.html ka :module: FP1 :points: 1.0 :required: True :threshold: 3 :exer_opts: JXOP-debug=true&JOP-lang=en&JXOP-code=java :long_name: Head, Tail, and Cons 1 FP - Deconstructing Lists with fp.hd and fp.tl (2) -------------------------------------------------- This problem once more helps you review the semantics of the ``fp.hd``, ``fp.tl``, and ``fp.cons`` functions. .. avembed:: Exercises/PL/FPHdTlCons2.html ka :module: FP1 :points: 1.0 :required: True :threshold: 1 :exer_opts: JXOP-debug=true&JOP-lang=en&JXOP-code=java :long_name: Head, Tail, and Cons 2 FP - fp.isNull, fp.isEq, fp.isZero ---------------------------------- To check whether a list is empty or not, you must use the ’\ ``isNull``\ ’ function: :: > fp.isNull( [ ] ) // we say that a list is null when it is equal to [ ] true > fp.isNull( [1,2,3] ) false The ``isNull`` function is a **predicate**, that is, a function that returns a Boolean value, ``true`` or ``false``. A second predicate that will be useful is ’\ ``isEq``\ ’: :: > fp.isEq(1,1) true > fp.isEq(1,2) false A third useful predicate is ’\ ``isZero``\ ’: :: > fp.isZero(0) true > fp.isZero(1) false The final problem in this section deals with the syntax and semantics of the ``fp.hd``, ``fp.tl``, and ``fp.isEq`` functions. .. avembed:: Exercises/PL/FPisEq.html ka :module: FP1 :points: 1.0 :required: True :threshold: 1 :exer_opts: JXOP-debug=true&JOP-lang=en&JXOP-code=java :long_name: Using isEq test