Declarative Programming Techniques Accumulators (CTM 3. 4

Slides:



Advertisements
Similar presentations
Modern Programming Languages, 2nd ed.
Advertisements

C. Varela; Adapted w/permission from S. Haridi and P. Van Roy1 Declarative Programming Techniques Accumulators, Difference Lists (VRH ) Carlos Varela.
Declarative Programming Lists in PROLOG Autumn 2014.
© Patrick Blackburn, Johan Bos & Kristina Striegnitz Lecture 6: More Lists Theory –Define append/3, a predicate for concatenating two lists, and illustrate.
Prolog Programming (Volume 5) Dr W.F. Clocksin. List cells + Unification = Great Idea Normally we use ‘proper lists’, which are defined according to the.
© Patrick Blackburn, Johan Bos & Kristina Striegnitz Lecture 6: More Lists Theory –Define append/3, a predicate for concatenating two lists, and illustrate.
Prolog: List © Patrick Blackburn, Johan Bos & Kristina Striegnitz.
C. Varela; Adapted from S. Haridi and P. Van Roy1 Declarative Programming Techniques Lazy Execution (VRH 4.5) Carlos Varela RPI Adapted with permission.
Functional Programming. Pure Functional Programming Computation is largely performed by applying functions to values. The value of an expression depends.
Lambda Calculus and Lisp PZ03J. Lambda Calculus The lambda calculus is a model for functional programming like Turing machines are models for imperative.
C. Varela; Adapted w/permission from S. Haridi and P. Van Roy1 Declarative Computation Model From kernel to practical language (CTM 2.6) Exceptions (CTM.
S. Haridi and P. Van Roy1 Declarative Programming Techniques Seif Haridi KTH Peter Van Roy UCL.
C. Varela; Adapted w/permission from S. Haridi and P. Van Roy1 Declarative Computation Model Defining practical programming languages Carlos Varela RPI.
C. Varela; Adapted w/permission from S. Haridi and P. Van Roy1 Declarative Computation Model Memory management, Exceptions, From kernel to practical language.
MINI ERLANG ID1218 Lecture Christian Schulte Software and Computer Systems School of Information and Communication Technology.
C. Varela; Adapted w/permission from S. Haridi and P. Van Roy1 Declarative Computation Model Single assignment store Kernel language syntax Carlos Varela.
C. Varela; Adapted w/permission from S. Haridi and P. Van Roy1 Data Abstraction and State Abstract Data Types (3.7) State/Data Abstraction(6.1, 6.3, 6.4.1,
C. Varela; Adapted w. permission from S. Haridi and P. Van Roy1 Introduction to Programming Concepts Carlos Varela RPI Adapted with permission from: Seif.
C. Varela; Adapted w/permission from S. Haridi and P. Van Roy1 Declarative Computation Model Kernel language semantics Carlos Varela RPI Adapted with permission.
C. Varela; Adapted w/permission from S. Haridi and P. Van Roy1 Declarative Computation Model Memory management, Exceptions, From kernel to practical language.
C. Varela; Adapted w/permission from S. Haridi and P. Van Roy1 Declarative Programming Techniques Non-declarative needs (VRH 3.8) Program design in the.
FUNCTIONAL PROGRAMMING IN ERLANG ID1218 Lecture Christian Schulte Software and Computer Systems School of Information and.
C. Varela; Adapted w/permission from S. Haridi and P. Van Roy1 Declarative Programming Techniques Declarativeness, iterative computation (VRH 3.1-2) Higher-order.
C. Varela; Adapted w/permission from S. Haridi and P. Van Roy1 Declarative Computation Model Memory management (CTM 2.5) Carlos Varela RPI April 6, 2015.
S. Haridi and P. Van Roy1 Lazy Execution Seif Haridi KTH Peter Van Roy UCL.
S. Haridi and P. Van Roy1 Declarative Programming Techniques Seif Haridi KTH Peter Van Roy UCL.
Chapter 9: Functional Programming in a Typed Language.
A Second Look At ML 1. Outline Patterns Local variable definitions A sorting example 2.
C. Varela; Adapted w. permission from S. Haridi and P. Van Roy1 Functional Programming: Lists, Pattern Matching, Recursive Programming (CTM Sections ,
S. Haridi and P. Van Roy1 Introduction to Programming Seif Haridi KTH Peter Van Roy UCL.
Chapter SevenModern Programming Languages1 A Second Look At ML.
07/10/04 AIPP Lecture 5: List Processing1 List Processing Artificial Intelligence Programming in Prolog Lecturer: Tim Smith Lecture 5 07/10/04.
C. Varela1 Logic Programming (CTM ) Constraint Programming: Constraints and Computation Spaces Carlos Varela Rennselaer Polytechnic Institute.
C. Varela1 Logic Programming (PLP 11, CTM 9.3) Prolog Imperative Control Flow: Backtracking, Cut, Fail, Not Lists, Append Carlos Varela Rennselaer Polytechnic.
Higher-Order Programming: Iterative computation (CTM Section 3
Functional Programming: Lists, Pattern Matching, Recursive Programming (CTM Sections , 3.2, , 4.7.2) Carlos Varela RPI September 12,
GC211Data Structure Lecture2 Sara Alhajjam.
CSE341: Programming Languages Lecture 6 Nested Patterns Exceptions Tail Recursion Dan Grossman Spring 2017.
ML Again ( Chapter 7) Patterns Local variable definitions
Higher-Order Programming: Iterative computation (CTM Section 3
Carlos Varela RPI September 22, 2017 Adapted with permission from:
PROGRAMMING IN HASKELL
PROGRAMMING IN HASKELL
Carlos Varela Rensselaer Polytechnic Institute November 17, 2017
COP4020 Programming Languages
Carlos Varela Rensselaer Polytechnic Institute December 5, 2017
Carlos Varela Rennselaer Polytechnic Institute December 6, 2016
Carlos Varela Rensselaer Polytechnic Institute December 8, 2017
Declarative Computation Model Kernel language semantics (Non-)Suspendable statements (VRH ) Carlos Varela RPI October 11, 2007 Adapted with.
Declarative Programming Techniques
PROGRAMMING IN HASKELL
CSE341: Programming Languages Lecture 6 Nested Patterns Exceptions Tail Recursion Dan Grossman Spring 2013.
Higher-Order Programming: Closures, procedural abstraction, genericity, instantiation, embedding. Control abstractions: iterate, map, reduce, fold, filter.
CSE341: Programming Languages Lecture 6 Nested Patterns Exceptions Tail Recursion Dan Grossman Autumn 2018.
CSCE 314: Programming Languages Dr. Dylan Shell
PROGRAMMING IN HASKELL
Declarative Programming Techniques Accumulators (CTM 3. 4
CSE341: Programming Languages Lecture 6 Nested Patterns Exceptions Tail Recursion Zach Tatlock Winter 2018.
Introduction to Programming Concepts (VRH )
Declarative Computation Model Single assignment store (VRH 2
CSCE 314: Programming Languages Dr. Dylan Shell
Introduction to Programming Concepts
CSE341: Programming Languages Lecture 6 Nested Patterns Exceptions Tail Recursion Dan Grossman Spring 2016.
State, Object-Oriented Programming Explicit State, Polymorphism (CTM 6
Declarative Programming Techniques Accumulators (CTM 3. 4
CSE341: Programming Languages Lecture 6 Nested Patterns Exceptions Tail Recursion Dan Grossman Spring 2019.
Carlos Varela Rennselaer Polytechnic Institute November 15, 2016
Brett Wortzman Summer 2019 Slides originally created by Dan Grossman
CSE341: Programming Languages Lecture 6 Nested Patterns Exceptions Tail Recursion Dan Grossman Autumn 2017.
Presentation transcript:

Declarative Programming Techniques Accumulators (CTM 3. 4 Declarative Programming Techniques Accumulators (CTM 3.4.3) Difference Lists (CTM 3.4.4) Carlos Varela Rensselaer Polytechnic Institute Adapted with permission from: Seif Haridi KTH Peter Van Roy UCL December 1, 2017 C. Varela; Adapted w/permission from S. Haridi and P. Van Roy

C. Varela; Adapted w/permission from S. Haridi and P. Van Roy Accumulators Accumulator programming is a way to handle state in declarative programs. It is a programming technique that uses arguments to carry state, transform the state, and pass it to the next procedure. Assume that the state S consists of a number of components to be transformed individually: S = (X,Y,Z,...) For each predicate P, each state component is made into a pair, the first component is the input state and the second component is the output state after P has terminated S is represented as (Xin, Xout, Yin, Yout, Zin, Zout,...) C. Varela; Adapted w/permission from S. Haridi and P. Van Roy

A Trivial Example in Prolog increment takes N0 as the input and produces N as the output by adding 1 to N0. square takes N0 as the input and produces N as the output by multiplying N0 to itself. inc_square takes N0 as the input and produces N as the output by using an intermediate variable N1 to carry N0+1 (the output of increment) and passing it as input to square. The pairs N0-N1 and N1-N are called accumulators. increment(N0,N) :- N is N0 + 1. square(N0,N) :- N is N0 * N0. inc_square(N0,N) :- increment(N0,N1), square(N1,N). C. Varela; Adapted w/permission from S. Haridi and P. Van Roy

C. Varela; Adapted w/permission from S. Haridi and P. Van Roy A Trivial Example in Oz Increment takes N0 as the input and produces N as the output by adding 1 to N0. Square takes N0 as the input and produces N as the output by multiplying N0 to itself. IncSquare takes N0 as the input and produces N as the output by using an intermediate variable N1 to carry N0+1 (the output of Increment) and passing it as input to Square. The pairs N0-N1 and N1-N are called accumulators. proc {Increment N0 N} N = N0 + 1 end proc {Square N0 N} N = N0 * N0 proc {IncSquare N0 N} N1 in {Increment N0 N1} {Square N1 N} C. Varela; Adapted w/permission from S. Haridi and P. Van Roy

The same concept applies to predicates in Prolog Accumulators Assume that the state S consists of a number of components to be transformed individually: S = (X,Y,Z) Assume P1 to Pn are procedures in Oz accumulator proc {P X0 X Y0 Y Z0 Z} : {P1 X0 X1 Y0 Y1 Z0 Z1} {P2 X1 X2 Y1 Y2 Z1 Z2} : {Pn Xn-1 X Yn-1 Y Zn-1 Z} end The procedural syntax is easier to use if there is more than one accumulator The same concept applies to predicates in Prolog C. Varela; Adapted w/permission from S. Haridi and P. Van Roy

C. Varela; Adapted w/permission from S. Haridi and P. Van Roy MergeSort Example Consider a variant of MergeSort with accumulator proc {MergeSort1 N S0 S Xs} N is an integer, S0 is an input list to be sorted S is the remainder of S0 after the first N elements are sorted Xs is the sorted first N elements of S0 The pair (S0, S) is an accumulator The definition is in a procedural syntax in Oz because it has two outputs S and Xs C. Varela; Adapted w/permission from S. Haridi and P. Van Roy

C. Varela; Adapted w/permission from S. Haridi and P. Van Roy Example (2) fun {MergeSort Xs} Ys in {MergeSort1 {Length Xs} Xs _ Ys} Ys end proc {MergeSort1 N S0 S Xs} if N==0 then S = S0 Xs = nil elseif N ==1 then X in X|S = S0 Xs=[X] else %% N > 1 local S1 Xs1 Xs2 NL NR in NL = N div 2 NR = N - NL {MergeSort1 NL S0 S1 Xs1} {MergeSort1 NR S1 S Xs2} Xs = {Merge Xs1 Xs2} end C. Varela; Adapted w/permission from S. Haridi and P. Van Roy

MergeSort Example in Prolog mergesort(Xs,Ys) :- length(Xs,N), mergesort1(N,Xs,_,Ys). mergesort1(0,S,S,[]) :- !. mergesort1(1,[X|S],S,[X]) :- !. mergesort1(N,S0,S,Xs) :- NL is N // 2, NR is N - NL, mergesort1(NL,S0,S1,Xs1), mergesort1(NR,S1,S,Xs2), merge(Xs1,Xs2,Xs). C. Varela; Adapted w/permission from S. Haridi and P. Van Roy

Multiple accumulators Consider a stack machine for evaluating arithmetic expressions Example: (1+4)-3 The machine executes the following instructions push(1) push(4) plus push(3) minus 4 5 3 2 1 5 C. Varela; Adapted w/permission from S. Haridi and P. Van Roy

Multiple accumulators (2) Example: (1+4)-3 The arithmetic expressions are represented as trees: minus(plus(1 4) 3) Write a procedure that takes arithmetic expressions represented as trees and output a list of stack machine instructions and counts the number of instructions proc {ExprCode Expr Cin Cout Nin Nout} Cin: initial list of instructions Cout: final list of instructions Nin: initial count Nout: final count C. Varela; Adapted w/permission from S. Haridi and P. Van Roy

Multiple accumulators (3) proc {ExprCode Expr C0 C N0 N} case Expr of plus(Expr1 Expr2) then C1 N1 in C1 = plus|C0 N1 = N0 + 1 {SeqCode [Expr2 Expr1] C1 C N1 N} [] minus(Expr1 Expr2) then C1 N1 in C1 = minus|C0 [] I andthen {IsInt I} then C = push(I)|C0 N = N0 + 1 end C. Varela; Adapted w/permission from S. Haridi and P. Van Roy

Multiple accumulators (4) proc {ExprCode Expr C0 C N0 N} case Expr of plus(Expr1 Expr2) then C1 N1 in C1 = plus|C0 N1 = N0 + 1 {SeqCode [Expr2 Expr1] C1 C N1 N} [] minus(Expr1 Expr2) then C1 N1 in C1 = minus|C0 [] I andthen {IsInt I} then C = push(I)|C0 N = N0 + 1 end proc {SeqCode Es C0 C N0 N} case Es of nil then C = C0 N = N0 [] E|Er then N1 C1 in {ExprCode E C0 C1 N0 N1} {SeqCode Er C1 C N1 N} end C. Varela; Adapted w/permission from S. Haridi and P. Van Roy

C. Varela; Adapted w/permission from S. Haridi and P. Van Roy Shorter version (4) proc {ExprCode Expr C0 C N0 N} case Expr of plus(Expr1 Expr2) then {SeqCode [Expr2 Expr1] plus|C0 C N0 + 1 N} [] minus(Expr1 Expr2) then {SeqCode [Expr2 Expr1] minus|C0 C N0 + 1 N} [] I andthen {IsInt I} then C = push(I)|C0 N = N0 + 1 end proc {SeqCode Es C0 C N0 N} case Es of nil then C = C0 N = N0 [] E|Er then N1 C1 in {ExprCode E C0 C1 N0 N1} {SeqCode Er C1 C N1 N} end C. Varela; Adapted w/permission from S. Haridi and P. Van Roy

C. Varela; Adapted w/permission from S. Haridi and P. Van Roy Functional style (4) fun {ExprCode Expr t(C0 N0) } case Expr of plus(Expr1 Expr2) then {SeqCode [Expr2 Expr1] t(plus|C0 N0 + 1)} [] minus(Expr1 Expr2) then {SeqCode [Expr2 Expr1] t(minus|C0 N0 + 1)} [] I andthen {IsInt I} then t(push(I)|C0 N0 + 1) end fun {SeqCode Es T} case Es of nil then T [] E|Er then T1 = {ExprCode E T} in {SeqCode Er T1} end C. Varela; Adapted w/permission from S. Haridi and P. Van Roy

C. Varela; Adapted w/permission from S. Haridi and P. Van Roy Difference lists in Oz A difference list is a pair of lists, each might have an unbound tail, with the invariant that one can get the second list by removing zero or more elements from the first list X # X % Represent the empty list nil # nil % idem [a] # [a] % idem (a|b|c|X) # X % Represents [a b c] [a b c d] # [d] % idem [a b c d|Y] # [d|Y] % idem [a b c d|Y] # Y % Represents [a b c d] C. Varela; Adapted w/permission from S. Haridi and P. Van Roy

Difference lists in Prolog A difference list is a pair of lists, each might have an unbound tail, with the invariant that one can get the second list by removing zero or more elements from the first list X , X % Represent the empty list [] , [] % idem [a] , [a] % idem [a,b,c|X] , X % Represents [a,b,c] [a,b,c,d] , [d] % idem [a,b,c,d|Y] , [d|Y] % idem [a,b,c,d|Y] , Y % Represents [a,b,c,d] C. Varela; Adapted w/permission from S. Haridi and P. Van Roy

Difference lists in Oz (2) When the second list is unbound, an append operation with another difference list takes constant time fun {AppendD D1 D2} S1 # E1 = D1 S2 # E2 = D2 in E1 = S2 S1 # E2 end local X Y in {Browse {AppendD (1|2|3|X)#X (4|5|Y)#Y}} end Displays (1|2|3|4|5|Y)#Y C. Varela; Adapted w/permission from S. Haridi and P. Van Roy

Difference lists in Prolog (2) When the second list is unbound, an append operation with another difference list takes constant time append_dl(S1,E1, S2,E2, S1,E2) :- E1 = S2. ?- append_dl([1,2,3|X],X, [4,5|Y],Y, S,E). Displays X = [4, 5|_G193] Y = _G193 S = [1, 2, 3, 4, 5|_G193] E = _G193 ; C. Varela; Adapted w/permission from S. Haridi and P. Van Roy

A FIFO queue with difference lists (1) A FIFO queue is a sequence of elements with an insert and a delete operation. Insert adds an element to the end and delete removes it from the beginning Queues can be implemented with lists. If L represents the queue content, then deleting X can remove the head of the list matching X|T but inserting X requires traversing the list {Append L [X]} (insert element at the end). Insert is inefficient: it takes time proportional to the number of queue elements With difference lists we can implement a queue with constant-time insert and delete operations The queue content is represented as q(N S E), where N is the number of elements and S#E is a difference list representing the elements C. Varela; Adapted w/permission from S. Haridi and P. Van Roy

A FIFO queue with difference lists (2) fun {NewQueue} X in q(0 X X) end fun {Insert Q X} case Q of q(N S E) then E1 in E=X|E1 q(N+1 S E1) end end fun {Delete Q X} case Q of q(N S E) then S1 in X|S1=S q(N-1 S1 E) end fun {EmptyQueue Q} case Q of q(N S E) then N==0 end end Inserting ‘b’: In: q(1 a|T T) Out: q(2 a|b|U U) Deleting X: In: q(2 a|b|U U) Out: q(1 b|U U) and X=a Difference list allows operations at both ends N is needed to keep track of the number of queue elements C. Varela; Adapted w/permission from S. Haridi and P. Van Roy

C. Varela; Adapted w/permission from S. Haridi and P. Van Roy Flatten fun {Flatten Xs} case Xs of nil then nil [] X|Xr andthen {IsLeaf X} then X|{Flatten Xr} [] X|Xr andthen {Not {IsLeaf X}} then {Append {Flatten X} {Flatten Xr}} end Flatten takes a list of elements and sub-lists and returns a list with only the elements, e.g.: {Flatten [1 [2] [[3]]]} = [1 2 3] Let us replace lists by difference lists and see what happens. C. Varela; Adapted w/permission from S. Haridi and P. Van Roy

Flatten with difference lists (1) Flatten of nil is X#X Flatten of a leaf X|Xr is (X|Y1)#Y flatten of Xr is Y1#Y Flatten of X|Xr is Y1#Y where flatten of X is Y1#Y2 flatten of Xr is Y3#Y equate Y2 and Y3 Here is what it looks like as text C. Varela; Adapted w/permission from S. Haridi and P. Van Roy

Flatten with difference lists (2) proc {FlattenD Xs Ds} case Xs of nil then Y in Ds = Y#Y [] X|Xr andthen {IsLeaf X} then Y1 Y in {FlattenD Xr Y1#Y2} Ds = (X|Y1)#Y [] X|Xr andthen {IsList X} then Y0 Y1 Y2 in Ds = Y0#Y2 {FlattenD X Y0#Y1} {FlattenD Xr Y1#Y2} end fun {Flatten Xs} Y in {FlattenD Xs Y#nil} Y end Here is the new program. It is much more efficient than the first version. C. Varela; Adapted w/permission from S. Haridi and P. Van Roy

C. Varela; Adapted w/permission from S. Haridi and P. Van Roy Reverse Here is our recursive reverse: Rewrite this with difference lists: Reverse of nil is X#X Reverse of X|Xs is Y1#Y, where reverse of Xs is Y1#Y2, and equate Y2 and X|Y fun {Reverse Xs} case Xs of nil then nil [] X|Xr then {Append {Reverse Xr} [X]} end C. Varela; Adapted w/permission from S. Haridi and P. Van Roy

Reverse with difference lists (1) The naive version takes time proportional to the square of the input length Using difference lists in the naive version makes it linear time We use two arguments Y1 and Y instead of Y1#Y With a minor change we can make it iterative as well fun {ReverseD Xs} proc {ReverseD Xs Y1 Y} case Xs of nil then Y1=Y [] X|Xr then Y2 in {ReverseD Xr Y1 Y2} Y2 = X|Y end end R in {ReverseD Xs R nil} R end C. Varela; Adapted w/permission from S. Haridi and P. Van Roy

Reverse with difference lists (2) fun {ReverseD Xs} proc {ReverseD Xs Y1 Y} case Xs of nil then Y1=Y [] X|Xr then {ReverseD Xr Y1 X|Y} end end R in {ReverseD Xs R nil} R end C. Varela; Adapted w/permission from S. Haridi and P. Van Roy

Difference lists: Summary Difference lists are a way to represent lists in the declarative model such that one append operation can be done in constant time A function that builds a big list by concatenating together lots of little lists can usually be written efficiently with difference lists The function can be written naively, using difference lists and append, and will be efficient when the append is expanded out Difference lists are declarative, yet have some of the power of destructive assignment Because of the single-assignment property of dataflow variables Difference lists originated from Prolog and are used to implement, e.g., definite clause grammar rules for natural language parsing. C. Varela; Adapted w/permission from S. Haridi and P. Van Roy

C. Varela; Adapted w/permission from S. Haridi and P. Van Roy Exercises Rewrite the Oz multiple accumulators example in Prolog. Rewrite the Oz FIFO queue with difference lists in Prolog. Draw the search trees for Prolog queries: append([1,2],[3],L). append(X,Y,[1,2,3]). append_dl([1,2|X],X,[3|Y],Y,S,E). CTM Exercise 3.10.11 (page 232) CTM Exercise 3.10.14 (page 232) CTM Exercise 3.10.15 (page 232) C. Varela; Adapted w/permission from S. Haridi and P. Van Roy