COP 4020 Lecture -*- Outline -*- * Declarative Programming Techniques (Ch 3) Based on Peter van Roy and Seif Haridi's book, "Concepts, Techniques, and Models of Computer Programming" (MIT Press, 2004), where all references that are not otherwise attributed are found. Now we concentrate on programming techniques using the declarative model. ** Why declarative programming? Q: When is declarative programming useful? Why is it useful? ------------------------------------------ WHEN IS DECLARATIVE PROGRAMMING USEFUL? WHY IS IT USEFUL? ------------------------------------------ ... It's easy to compose (combine) declarative programs. Functional abstraction allows abstraction to avoid duplication. E.g., Jane Street Capital Reasoning is simple (often equational) Most important: it describes all techniques for programming with expressions. Q: Why is declarative programming deterministic? Because no source of nondeterminism in the declarative model. Q: What do we mean by an expression being deterministic? It has the same value in a given environment and store. Q: What is referential transparency? ------------------------------------------ REFERENTIAL TRANSPARENCY def: A model is referentially transparent ------------------------------------------ Expression evaluation doesn't affect the store, no race conditions, so it has a simple semantics that allows simple reasoning. ... An expression in a given environment has only one value (i.e., evaluation is deterministic): for all F, X: {F X} == {F X} One definition is the following (W. v O. Quine, "Word and Object", MIT Press, 1960, as quoted in, A. J. T. Davie, "An Introduction to Functional Programming Systems Using Haskell", Cambridge, 1992, p. 5): "A language in which the value of expressions only depends on the values of their well-formed sub expressions is called referentially transparent." Davie continues, "another equivalent way of thinking about this is to say that any well formed sub-expression must be able to be replaced by another with the same value without affecting the value of the whole." So, for example, in an expression such as {F {G {Get A I}} - {G {Get A J}}} for the case when I == J, a compiler might choose to compute {G {Get A I}}, to verify it has a value and then compute {F 0}. However, in a language that does not have referential transparency, this may change the meaning of the overall expression. Similarly, if we have (in C): (a[i]*h(x) == 0 ? q(x) : r(x)) doesn't need to evaluate h(x) if we know from the value of i that a[i] is zero, and if we know h(x) will have a value. This is important for optimization. ** How A declarative program looks like a bunch of recursive function definitions Q: What technique can be used to simplify declarative program structures? higher-order abstractions, modules Q: How can we tell if a program is declarative? ------------------------------------------ WHEN IS A PROGRAM DECLARATIVE? ------------------------------------------ ... 1. if it uses the declarative model of chapter 2 2. or if it acts declaratively: stateless, and deterministic. If for the same bindings of inputs and free variables to values, we get the same outputs (deterministic) each time (stateless) Also: independent, i.e., not affected by changes in its environment? Q: Why does the declarative model lead to declarative programs? Composition doesn't introduce nondeterminism or state.