<<

TYPES OF PROGRAMMING LANGUAGES PRINCIPLES OF PROGRAMMING LANGUAGES

Norbert Zeh Winter 2019

Dalhousie University

1/30 • Easy to express complex ideas • Easy to control exactly how the computation is carried out • Rich set of data types • Extensive (standard) library • Active, friendly community • Was used for this project before I joined • Good support • Open-source

REASONS TO CHOOSE A PARTICULAR

2/30 REASONS TO CHOOSE A PARTICULAR PROGRAMMING LANGUAGE

• Easy to express complex ideas • Easy to control exactly how the computation is carried out • Rich set of data types • Extensive (standard) library • Active, friendly community • Was used for this project before I joined • Good compiler support • Open-source

2/30 • Trade-off between features • Speed vs expressiveness/elegance • Speed, vs rapid development • … • Tinkering with programming languages is fun … and then they sometimes get adopted.

• Corporate pressure

WHY ARE THERE SO MANY PROGRAMMING LANGUAGES?

3/30 • Tinkering with programming languages is fun … and then they sometimes get adopted.

• Corporate pressure

WHY ARE THERE SO MANY PROGRAMMING LANGUAGES?

• Trade-off between features • Speed vs expressiveness/elegance • Speed, type safety vs rapid development • …

3/30 • Corporate pressure

WHY ARE THERE SO MANY PROGRAMMING LANGUAGES?

• Trade-off between features • Speed vs expressiveness/elegance • Speed, type safety vs rapid development • … • Tinkering with programming languages is fun … and then they sometimes get adopted.

3/30 WHY ARE THERE SO MANY PROGRAMMING LANGUAGES?

• Trade-off between features • Speed vs expressiveness/elegance • Speed, type safety vs rapid development • … • Tinkering with programming languages is fun … and then they sometimes get adopted.

• Corporate pressure

3/30 Examples: • , C++, , Python, Ruby • Haskell, Scheme, • Lua, /Tk • …

• (La)TeX, HTML/XML, XSLT • , Matlab • sed, awk • …

• Designed to express arbitrary computations • Turing-complete

Examples: • Designed to make it easy to express certain types of programs • May not be Turing-complete

GENERAL PURPOSE VS SPECIAL PURPOSE

General-purpose programming language:

Special-purpose programming language:

4/30 • (La)TeX, HTML/XML, XSLT • R, Matlab • sed, awk • …

Examples: • C, C++, Java, Python, Ruby • Haskell, Scheme, Prolog • Lua, Tcl/Tk • …

Examples: • Designed to make it easy to express certain types of programs • May not be Turing-complete

GENERAL PURPOSE VS SPECIAL PURPOSE

General-purpose programming language: • Designed to express arbitrary computations • Turing-complete

Special-purpose programming language:

4/30 • (La)TeX, HTML/XML, XSLT • R, Matlab • sed, awk • …

Examples: • C, C++, Java, Python, Ruby • Haskell, Scheme, Prolog • Lua, Tcl/Tk • …

Examples:

GENERAL PURPOSE VS SPECIAL PURPOSE

General-purpose programming language: • Designed to express arbitrary computations • Turing-complete

Special-purpose programming language: • Designed to make it easy to express certain types of programs • May not be Turing-complete

4/30 • (La)TeX, HTML/XML, XSLT • R, Matlab • sed, awk • …

• C, C++, Java, Python, Ruby • Haskell, Scheme, Prolog • Lua, Tcl/Tk • …

Examples:

GENERAL PURPOSE VS SPECIAL PURPOSE

General-purpose programming language: Examples: • Designed to express arbitrary computations • Turing-complete

Special-purpose programming language: • Designed to make it easy to express certain types of programs • May not be Turing-complete

4/30 • (La)TeX, HTML/XML, XSLT • R, Matlab • sed, awk • …

• Haskell, Scheme, Prolog • Lua, Tcl/Tk • …

Examples:

GENERAL PURPOSE VS SPECIAL PURPOSE

General-purpose programming language: Examples: • Designed to express arbitrary computations • C, C++, Java, Python, Ruby • Turing-complete

Special-purpose programming language: • Designed to make it easy to express certain types of programs • May not be Turing-complete

4/30 • (La)TeX, HTML/XML, XSLT • R, Matlab • sed, awk • …

• Lua, Tcl/Tk • …

Examples:

GENERAL PURPOSE VS SPECIAL PURPOSE

General-purpose programming language: Examples: • Designed to express arbitrary computations • C, C++, Java, Python, Ruby • Turing-complete • Haskell, Scheme, Prolog

Special-purpose programming language: • Designed to make it easy to express certain types of programs • May not be Turing-complete

4/30 • (La)TeX, HTML/XML, XSLT • R, Matlab • sed, awk • …

• …

Examples:

GENERAL PURPOSE VS SPECIAL PURPOSE

General-purpose programming language: Examples: • Designed to express arbitrary computations • C, C++, Java, Python, Ruby • Turing-complete • Haskell, Scheme, Prolog • Lua, Tcl/Tk

Special-purpose programming language: • Designed to make it easy to express certain types of programs • May not be Turing-complete

4/30 • (La)TeX, HTML/XML, XSLT • R, Matlab • sed, awk • …

Examples:

GENERAL PURPOSE VS SPECIAL PURPOSE

General-purpose programming language: Examples: • Designed to express arbitrary computations • C, C++, Java, Python, Ruby • Turing-complete • Haskell, Scheme, Prolog • Lua, Tcl/Tk • …

Special-purpose programming language: • Designed to make it easy to express certain types of programs • May not be Turing-complete

4/30 • (La)TeX, HTML/XML, XSLT • R, Matlab • sed, awk • …

GENERAL PURPOSE VS SPECIAL PURPOSE

General-purpose programming language: Examples: • Designed to express arbitrary computations • C, C++, Java, Python, Ruby • Turing-complete • Haskell, Scheme, Prolog • Lua, Tcl/Tk • …

Special-purpose programming language: Examples: • Designed to make it easy to express certain types of programs • May not be Turing-complete

4/30 • R, Matlab • sed, awk • …

GENERAL PURPOSE VS SPECIAL PURPOSE

General-purpose programming language: Examples: • Designed to express arbitrary computations • C, C++, Java, Python, Ruby • Turing-complete • Haskell, Scheme, Prolog • Lua, Tcl/Tk • …

Special-purpose programming language: Examples: • Designed to make it easy to express certain • (La)TeX, HTML/XML, XSLT types of programs • May not be Turing-complete

4/30 • sed, awk • …

GENERAL PURPOSE VS SPECIAL PURPOSE

General-purpose programming language: Examples: • Designed to express arbitrary computations • C, C++, Java, Python, Ruby • Turing-complete • Haskell, Scheme, Prolog • Lua, Tcl/Tk • …

Special-purpose programming language: Examples: • Designed to make it easy to express certain • (La)TeX, HTML/XML, XSLT types of programs • R, Matlab • May not be Turing-complete

4/30 • …

GENERAL PURPOSE VS SPECIAL PURPOSE

General-purpose programming language: Examples: • Designed to express arbitrary computations • C, C++, Java, Python, Ruby • Turing-complete • Haskell, Scheme, Prolog • Lua, Tcl/Tk • …

Special-purpose programming language: Examples: • Designed to make it easy to express certain • (La)TeX, HTML/XML, XSLT types of programs • R, Matlab • May not be Turing-complete • sed, awk

4/30 GENERAL PURPOSE VS SPECIAL PURPOSE

General-purpose programming language: Examples: • Designed to express arbitrary computations • C, C++, Java, Python, Ruby • Turing-complete • Haskell, Scheme, Prolog • Lua, Tcl/Tk • …

Special-purpose programming language: Examples: • Designed to make it easy to express certain • (La)TeX, HTML/XML, XSLT types of programs • R, Matlab • May not be Turing-complete • sed, awk • …

4/30 GENERAL PURPOSE VS SPECIAL PURPOSE

General-purpose programming language: Examples: • Designed to express arbitrary computations • C, C++, Java, Python, Ruby • Turing-complete • Haskell, Scheme, Prolog • Lua, Tcl/Tk • …

Special-purpose programming language: Examples: • Designed to make it easy to express certain • (La)TeX, HTML/XML, XSLT types of programs • R, Matlab • May not be Turing-complete • sed, awk • …

4/30 Declarative

Concatenative Imperative Object-oriented Functional

Postscript C C++ Lisp Scala Scheme Haskell Prolog

Forth Pascal Python ML Hilog

Factor Modula Ruby

Ada Java

Fortran Objective C

Swift

TYPES OF PROGRAMMING LANGUAGES

5/30 Declarative

Concatenative Imperative Object-oriented Functional Logic

Postscript C Lisp Scala Scheme Haskell Prolog

Forth Pascal ML Hilog

Factor Modula

Ada

Fortran

TYPES OF PROGRAMMING LANGUAGES

C++

Python

Ruby

Java

Objective C

Swift 5/30 Declarative

Concatenative Functional Logic

Postscript C Lisp Scala Scheme Haskell Prolog

Forth Pascal ML Hilog

Factor Modula

Ada

Fortran

TYPES OF PROGRAMMING LANGUAGES

Imperative Object-oriented

C++

Python

Ruby

Java

Objective C

Swift 5/30 Declarative

Concatenative Functional Logic

Postscript Lisp Scala Scheme Haskell Prolog

Forth ML Hilog

Factor

TYPES OF PROGRAMMING LANGUAGES

Imperative Object-oriented

C C++

Pascal Python

Modula Ruby

Ada Java

Fortran Objective C

Swift 5/30 Declarative

Functional Logic

Lisp Scala Scheme Haskell Prolog

ML Hilog

TYPES OF PROGRAMMING LANGUAGES

Concatenative Imperative Object-oriented

Postscript C C++

Forth Pascal Python

Factor Modula Ruby

Ada Java

Fortran Objective C

Swift 5/30 Lisp Scala Scheme Haskell Prolog

ML Hilog

TYPES OF PROGRAMMING LANGUAGES

Declarative

Concatenative Imperative Object-oriented Functional Logic

Postscript C C++

Forth Pascal Python

Factor Modula Ruby

Ada Java

Fortran Objective C

Swift 5/30 Lisp Scala Scheme Prolog

ML Hilog

TYPES OF PROGRAMMING LANGUAGES

Declarative

Concatenative Imperative Object-oriented Functional Logic

Postscript C C++ Haskell

Forth Pascal Python

Factor Modula Ruby

Ada Java

Fortran Objective C

Swift 5/30 Scala Prolog

Hilog

TYPES OF PROGRAMMING LANGUAGES

Declarative

Concatenative Imperative Object-oriented Functional Logic

Postscript C C++ Lisp Scheme Haskell

Forth Pascal Python ML

Factor Modula Ruby

Ada Java

Fortran Objective C

Swift 5/30 Prolog

Hilog

TYPES OF PROGRAMMING LANGUAGES

Declarative

Concatenative Imperative Object-oriented Functional Logic

Postscript C C++ Lisp Scala Scheme Haskell

Forth Pascal Python ML

Factor Modula Ruby

Ada Java

Fortran Objective C

Swift 5/30 TYPES OF PROGRAMMING LANGUAGES

Declarative

Concatenative Imperative Object-oriented Functional Logic

Postscript C C++ Lisp Scala Scheme Haskell Prolog

Forth Pascal Python ML Hilog

Factor Modula Ruby

Ada Java

Fortran Objective C

Swift 5/30 TYPES OF PROGRAMMING LANGUAGES

Declarative

Concatenative Imperative Object-oriented Functional Logic

Postscript C C++ Lisp Scala Scheme Haskell Prolog

Forth Pascal Python ML Hilog

Factor Modula Ruby

Ada Java

Fortran Objective C

Swift 5/30 TYPES OF PROGRAMMING LANGUAGES

Declarative

Concatenative Imperative Object-oriented Functional Logic

Postscript C C++ Lisp Scala Scheme Haskell Prolog

Forth Pascal Python ML Hilog

Factor Modula Ruby

Ada Java

Fortran Objective C

Swift 5/30 THE LANGUAGES I USE

Rust or C++ Python • When I need performance • When I need to write a prototype quickly C • When I feel nostalgic Scala • When I’m told to use Java Haskell • When I want to have fun and Java write elegant code that I trust • Never

Prolog Scheme • When I want to solve puzzles • When I’d rather teach you Haskell

6/30 • Focus on telling the • Focus on telling the computer what computer exactly which to do, not how to do it steps to execute • More high-level, elegant, expressive • Close to the machine • Need to include evaluation engine • Difficult to analyze/ in run-time system automatically optimize • Can come with performance • Functions called for penalties • Return values • Easier to analyze/automatically • Side effects optimize/parallelize

IMPERATIVE VS

Imperative programming: Declarative programming:

7/30 • Focus on telling the computer what to do, not how to do it • More high-level, elegant, expressive • Close to the machine • Need to include evaluation engine • Difficult to analyze/ in run-time system automatically optimize • Can come with performance • Functions called for penalties • Return values • Easier to analyze/automatically • Side effects optimize/parallelize

IMPERATIVE VS DECLARATIVE PROGRAMMING

Imperative programming: Declarative programming: • Focus on telling the computer exactly which steps to execute

7/30 • More high-level, elegant, expressive • Close to the machine • Need to include evaluation engine • Difficult to analyze/ in run-time system automatically optimize • Can come with performance • Functions called for penalties • Return values • Easier to analyze/automatically • Side effects optimize/parallelize

IMPERATIVE VS DECLARATIVE PROGRAMMING

Imperative programming: Declarative programming: • Focus on telling the • Focus on telling the computer what computer exactly which to do, not how to do it steps to execute

7/30 • More high-level, elegant, expressive • Need to include evaluation engine • Difficult to analyze/ in run-time system automatically optimize • Can come with performance • Functions called for penalties • Return values • Easier to analyze/automatically • Side effects optimize/parallelize

IMPERATIVE VS DECLARATIVE PROGRAMMING

Imperative programming: Declarative programming: • Focus on telling the • Focus on telling the computer what computer exactly which to do, not how to do it steps to execute • Close to the machine

7/30 • Need to include evaluation engine • Difficult to analyze/ in run-time system automatically optimize • Can come with performance • Functions called for penalties • Return values • Easier to analyze/automatically • Side effects optimize/parallelize

IMPERATIVE VS DECLARATIVE PROGRAMMING

Imperative programming: Declarative programming: • Focus on telling the • Focus on telling the computer what computer exactly which to do, not how to do it steps to execute • More high-level, elegant, expressive • Close to the machine

7/30 • Difficult to analyze/ automatically optimize • Can come with performance • Functions called for penalties • Return values • Easier to analyze/automatically • Side effects optimize/parallelize

IMPERATIVE VS DECLARATIVE PROGRAMMING

Imperative programming: Declarative programming: • Focus on telling the • Focus on telling the computer what computer exactly which to do, not how to do it steps to execute • More high-level, elegant, expressive • Close to the machine • Need to include evaluation engine in run-time system

7/30 • Difficult to analyze/ automatically optimize • Functions called for • Return values • Easier to analyze/automatically • Side effects optimize/parallelize

IMPERATIVE VS DECLARATIVE PROGRAMMING

Imperative programming: Declarative programming: • Focus on telling the • Focus on telling the computer what computer exactly which to do, not how to do it steps to execute • More high-level, elegant, expressive • Close to the machine • Need to include evaluation engine in run-time system • Can come with performance penalties

7/30 • Functions called for • Return values • Easier to analyze/automatically • Side effects optimize/parallelize

IMPERATIVE VS DECLARATIVE PROGRAMMING

Imperative programming: Declarative programming: • Focus on telling the • Focus on telling the computer what computer exactly which to do, not how to do it steps to execute • More high-level, elegant, expressive • Close to the machine • Need to include evaluation engine • Difficult to analyze/ in run-time system automatically optimize • Can come with performance penalties

7/30 • Functions called for • Return values • Side effects

IMPERATIVE VS DECLARATIVE PROGRAMMING

Imperative programming: Declarative programming: • Focus on telling the • Focus on telling the computer what computer exactly which to do, not how to do it steps to execute • More high-level, elegant, expressive • Close to the machine • Need to include evaluation engine • Difficult to analyze/ in run-time system automatically optimize • Can come with performance penalties • Easier to analyze/automatically optimize/parallelize

7/30 IMPERATIVE VS DECLARATIVE PROGRAMMING

Imperative programming: Declarative programming: • Focus on telling the • Focus on telling the computer what computer exactly which to do, not how to do it steps to execute • More high-level, elegant, expressive • Close to the machine • Need to include evaluation engine • Difficult to analyze/ in run-time system automatically optimize • Can come with performance • Functions called for penalties • Return values • Easier to analyze/automatically • Side effects optimize/parallelize

7/30 … are evil:

• Source of 90% of all software bugs

… are the only reason we compute at all:

• Taking input and communicating results requires side effects.

SIDE EFFECTS

• Variable updates, I/O (disk, screen, keyboard, network, …)

8/30 … are the only reason we compute at all:

• Taking input and communicating results requires side effects.

SIDE EFFECTS

• Variable updates, I/O (disk, screen, keyboard, network, …)

… are evil:

• Source of 90% of all software bugs

8/30 SIDE EFFECTS

• Variable updates, I/O (disk, screen, keyboard, network, …)

… are evil:

• Source of 90% of all software bugs

… are the only reason we compute at all:

• Taking input and communicating results requires side effects.

8/30 • Easier to analyze/optimize • Can be less efficient than • No specified execution order well-designed imperative code → easy to parallelize • Some imperative data structures are inherently more efficient than their purely functional counterparts

• Functions have no side effects • Variables are immutable once defined • Functions are first-class objects • Can express imperative computations elegantly!

Pros: Cons:

FUNCTIONAL PROGRAMMING

9/30 • Easier to analyze/optimize • Can be less efficient than • No specified execution order well-designed imperative code → easy to parallelize • Some imperative data structures are inherently more efficient than their purely functional counterparts

• Variables are immutable once defined • Functions are first-class objects • Can express imperative computations elegantly!

Pros: Cons:

FUNCTIONAL PROGRAMMING

• Functions have no side effects

9/30 • Easier to analyze/optimize • Can be less efficient than • No specified execution order well-designed imperative code → easy to parallelize • Some imperative data structures are inherently more efficient than their purely functional counterparts

• Functions are first-class objects • Can express imperative computations elegantly!

Pros: Cons:

FUNCTIONAL PROGRAMMING

• Functions have no side effects • Variables are immutable once defined

9/30 • Easier to analyze/optimize • Can be less efficient than • No specified execution order well-designed imperative code → easy to parallelize • Some imperative data structures are inherently more efficient than their purely functional counterparts

• Can express imperative computations elegantly!

Pros: Cons:

FUNCTIONAL PROGRAMMING

• Functions have no side effects • Variables are immutable once defined • Functions are first-class objects

9/30 • Easier to analyze/optimize • Can be less efficient than • No specified execution order well-designed imperative code → easy to parallelize • Some imperative data structures are inherently more efficient than their purely functional counterparts

Pros: Cons:

FUNCTIONAL PROGRAMMING

• Functions have no side effects • Variables are immutable once defined • Functions are first-class objects • Can express imperative computations elegantly!

9/30 • Easier to analyze/optimize • Can be less efficient than • No specified execution order well-designed imperative code → easy to parallelize • Some imperative data structures are inherently more efficient than their purely functional counterparts

FUNCTIONAL PROGRAMMING

• Functions have no side effects • Variables are immutable once defined • Functions are first-class objects • Can express imperative computations elegantly!

Pros: Cons:

9/30 • Can be less efficient than • No specified execution order well-designed imperative code → easy to parallelize • Some imperative data structures are inherently more efficient than their purely functional counterparts

FUNCTIONAL PROGRAMMING

• Functions have no side effects • Variables are immutable once defined • Functions are first-class objects • Can express imperative computations elegantly!

Pros: Cons: • Easier to analyze/optimize

9/30 • Can be less efficient than well-designed imperative code • Some imperative data structures are inherently more efficient than their purely functional counterparts

FUNCTIONAL PROGRAMMING

• Functions have no side effects • Variables are immutable once defined • Functions are first-class objects • Can express imperative computations elegantly!

Pros: Cons: • Easier to analyze/optimize • No specified execution order → easy to parallelize

9/30 • Some imperative data structures are inherently more efficient than their purely functional counterparts

FUNCTIONAL PROGRAMMING

• Functions have no side effects • Variables are immutable once defined • Functions are first-class objects • Can express imperative computations elegantly!

Pros: Cons: • Easier to analyze/optimize • Can be less efficient than • No specified execution order well-designed imperative code → easy to parallelize

9/30 FUNCTIONAL PROGRAMMING

• Functions have no side effects • Variables are immutable once defined • Functions are first-class objects • Can express imperative computations elegantly!

Pros: Cons: • Easier to analyze/optimize • Can be less efficient than • No specified execution order well-designed imperative code → easy to parallelize • Some imperative data structures are inherently more efficient than their purely functional counterparts

9/30 • Even higher abstraction than • In practice, need to understand functional programming execution details enough to • Avoid infinite loops in deduction • In theory, no need to worry • Obtain efficient programs about execution details at all

General program structure: • of facts, represented as logical predicates • Rules for deducing new facts from known facts • Execution driven by queries whether certain facts are true

Runtime system: • Engine to perform the deduction process efficiently

Pros: Cons:

LOGIC PROGRAMMING

10/30 • Even higher abstraction than • In practice, need to understand functional programming execution details enough to • Avoid infinite loops in deduction • In theory, no need to worry • Obtain efficient programs about execution details at all

Runtime system: • Engine to perform the deduction process efficiently

Pros: Cons:

LOGIC PROGRAMMING

General program structure: • Database of facts, represented as logical predicates • Rules for deducing new facts from known facts • Execution driven by queries whether certain facts are true

10/30 • Even higher abstraction than • In practice, need to understand functional programming execution details enough to • Avoid infinite loops in deduction • In theory, no need to worry • Obtain efficient programs about execution details at all

Pros: Cons:

LOGIC PROGRAMMING

General program structure: • Database of facts, represented as logical predicates • Rules for deducing new facts from known facts • Execution driven by queries whether certain facts are true

Runtime system: • Engine to perform the deduction process efficiently

10/30 • Even higher abstraction than • In practice, need to understand functional programming execution details enough to • Avoid infinite loops in deduction • In theory, no need to worry • Obtain efficient programs about execution details at all

LOGIC PROGRAMMING

General program structure: • Database of facts, represented as logical predicates • Rules for deducing new facts from known facts • Execution driven by queries whether certain facts are true

Runtime system: • Engine to perform the deduction process efficiently

Pros: Cons:

10/30 • In practice, need to understand execution details enough to • Avoid infinite loops in deduction • In theory, no need to worry • Obtain efficient programs about execution details at all

LOGIC PROGRAMMING

General program structure: • Database of facts, represented as logical predicates • Rules for deducing new facts from known facts • Execution driven by queries whether certain facts are true

Runtime system: • Engine to perform the deduction process efficiently

Pros: Cons: • Even higher abstraction than functional programming

10/30 • In practice, need to understand execution details enough to • Avoid infinite loops in deduction • Obtain efficient programs

LOGIC PROGRAMMING

General program structure: • Database of facts, represented as logical predicates • Rules for deducing new facts from known facts • Execution driven by queries whether certain facts are true

Runtime system: • Engine to perform the deduction process efficiently

Pros: Cons: • Even higher abstraction than functional programming • In theory, no need to worry about execution details at all 10/30 LOGIC PROGRAMMING

General program structure: • Database of facts, represented as logical predicates • Rules for deducing new facts from known facts • Execution driven by queries whether certain facts are true

Runtime system: • Engine to perform the deduction process efficiently

Pros: Cons: • Even higher abstraction than • In practice, need to understand functional programming execution details enough to • Avoid infinite loops in deduction • In theory, no need to worry • Obtain efficient programs about execution details at all 10/30 INTERMISSION: SCHEME AND PROLOG TUTORIALS

11/30 AN EXAMPLE WHERE FUNCTIONAL PROGRAMMING SHINES: MERGE SORT (1)

C++:

template voidmerge_sort(constIt&begin,constIt&end){ auton= end-begin; if(n< 2) return; automid=begin+n / 2; merge_sort(begin,mid); merge_sort(mid,end); std::vector::value_type> left(begin,mid); std::vector::value_type> right(mid,end); merge(left,right,begin); } 12/30 AN EXAMPLE WHERE FUNCTIONAL PROGRAMMING SHINES: MERGE SORT (2)

template void merge( const std::vector::value_type> &left, const std::vector::value_type> &right, It out) { auto l = left.begin(), r = right.begin(); while (l != left.end() && r != right.end()) { if (*r < *l) *out++ = *r++; else *out++ = *l++; } while (l != left.end()) *out++ = *l++; while (r != right.end()) *out++ = *r++; } 13/30 AN EXAMPLE WHERE FUNCTIONAL PROGRAMMING SHINES: MERGE SORT (3)

Haskell:

mergeSort :: Ord t => [t] -> [t] mergeSort [] = [] mergeSort [x] = [x] mergeSort xs = merge (mergeSort ls) (mergeSort rs) where n = length xs (ls, rs) = splitAt (n `div` 2) xs

merge :: Ord t => [t] -> [t] -> [t] merge [] rs = rs merge ls [] = ls merge ls@(l:ls') rs@(r:rs') | r < l = r : merge ls rs' | otherwise = l : merge ls' rs

14/30 AN EXAMPLE WHERE FUNCTIONAL PROGRAMMING SHINES: MERGE SORT (4)

Prolog:

list_sorted([], []). list_sorted([X], [X]). list_sorted(List, Sorted) :- list_left_right(List, Left, Right), list_sorted(Left, LeftSorted), list_sorted(Right, RightSorted), merged_left_right(Sorted, LeftSorted, RightSorted).

merged_left_right(Left, Left, []). merged_left_right([R|Right], [], [R|Right]). merged_left_right([L|Merged], [L|Left], [R|Right]) :- L #=< R, merged_left_right(Merged, Left, [R|Right]). merged_left_right([R|Merged], [L|Left], [R|Right]) :- R #< L, merged_left_right(Merged, [L|Left], Right).

15/30 AN EXAMPLE WHERE FUNCTIONAL PROGRAMMING SHINES: MERGE SORT (5)

list_left_right(List, Left, Right) :- phrase(parse_half(List, Left), List, Right).

parse_half([], []) --> []. parse_half([_], []) --> []. parse_half([_,_|List], [L|Left]) --> [L], parse_half(List, Left).

16/30 0 421 21 31 3 5

421 63 5

AN EXAMPLE WHERE IMPERATIVE PROGRAMMING SHINES: DYNAMIC DATA STRUCTURES (1)

Problem: Build a permutation of the {0, 1,..., n − 1} specified by indicating, for each element, after which element it is to be inserted.

Example:

1 2 3 4 5 6 Input: 0 0 1 0 3 2

Output: 0 4 2 6 1 3 5

17/30 0 421 21 631 31 53 5

421 63 5

AN EXAMPLE WHERE IMPERATIVE PROGRAMMING SHINES: DYNAMIC DATA STRUCTURES (1)

Problem: Build a permutation of the integers {0, 1,..., n − 1} specified by indicating, for each element, after which element it is to be inserted.

Example:

1 2 3 4 5 6 Input: 0 0 1 0 3 2

Output: 0

17/30 0 421 21 631 31 53 5

42 63 5

AN EXAMPLE WHERE IMPERATIVE PROGRAMMING SHINES: DYNAMIC DATA STRUCTURES (1)

Problem: Build a permutation of the integers {0, 1,..., n − 1} specified by indicating, for each element, after which element it is to be inserted.

Example:

1 2 3 4 5 6 Input: 0 0 1 0 3 2

Output: 0

1

17/30 0 42 21 631 31 53 5

421 63 5

AN EXAMPLE WHERE IMPERATIVE PROGRAMMING SHINES: DYNAMIC DATA STRUCTURES (1)

Problem: Build a permutation of the integers {0, 1,..., n − 1} specified by indicating, for each element, after which element it is to be inserted.

Example:

1 2 3 4 5 6 Input: 0 0 1 0 3 2

Output: 0 1

17/30 0 42 21 631 31 53 5

41 63 5

AN EXAMPLE WHERE IMPERATIVE PROGRAMMING SHINES: DYNAMIC DATA STRUCTURES (1)

Problem: Build a permutation of the integers {0, 1,..., n − 1} specified by indicating, for each element, after which element it is to be inserted.

Example:

1 2 3 4 5 6 Input: 0 0 1 0 3 2

Output: 0 1

2

17/30 0 421 21 631 31 53 5

421 63 5

AN EXAMPLE WHERE IMPERATIVE PROGRAMMING SHINES: DYNAMIC DATA STRUCTURES (1)

Problem: Build a permutation of the integers {0, 1,..., n − 1} specified by indicating, for each element, after which element it is to be inserted.

Example:

1 2 3 4 5 6 Input: 0 0 1 0 3 2

Output: 0 2 1

17/30 0 421 21 631 31 53 5

421 6 5

AN EXAMPLE WHERE IMPERATIVE PROGRAMMING SHINES: DYNAMIC DATA STRUCTURES (1)

Problem: Build a permutation of the integers {0, 1,..., n − 1} specified by indicating, for each element, after which element it is to be inserted.

Example:

1 2 3 4 5 6 Input: 0 0 1 0 3 2

Output: 0 2 1

3

17/30 0 421 21 61 31 53 5

421 63 5

AN EXAMPLE WHERE IMPERATIVE PROGRAMMING SHINES: DYNAMIC DATA STRUCTURES (1)

Problem: Build a permutation of the integers {0, 1,..., n − 1} specified by indicating, for each element, after which element it is to be inserted.

Example:

1 2 3 4 5 6 Input: 0 0 1 0 3 2

Output: 0 2 1 3

17/30 0 421 21 61 31 53 5

21 63 5

AN EXAMPLE WHERE IMPERATIVE PROGRAMMING SHINES: DYNAMIC DATA STRUCTURES (1)

Problem: Build a permutation of the integers {0, 1,..., n − 1} specified by indicating, for each element, after which element it is to be inserted.

Example:

1 2 3 4 5 6 Input: 0 0 1 0 3 2

Output: 0 2 1 3

4

17/30 0 421 21 631 31 53 5

421 63 5

AN EXAMPLE WHERE IMPERATIVE PROGRAMMING SHINES: DYNAMIC DATA STRUCTURES (1)

Problem: Build a permutation of the integers {0, 1,..., n − 1} specified by indicating, for each element, after which element it is to be inserted.

Example:

1 2 3 4 5 6 Input: 0 0 1 0 3 2

Output: 0 4 2 1 3

17/30 0 421 21 631 31 53 5

421 63

AN EXAMPLE WHERE IMPERATIVE PROGRAMMING SHINES: DYNAMIC DATA STRUCTURES (1)

Problem: Build a permutation of the integers {0, 1,..., n − 1} specified by indicating, for each element, after which element it is to be inserted.

Example:

1 2 3 4 5 6 Input: 0 0 1 0 3 2

Output: 0 4 2 1 3

5

17/30 0 421 21 631 31 3 5

421 63 5

AN EXAMPLE WHERE IMPERATIVE PROGRAMMING SHINES: DYNAMIC DATA STRUCTURES (1)

Problem: Build a permutation of the integers {0, 1,..., n − 1} specified by indicating, for each element, after which element it is to be inserted.

Example:

1 2 3 4 5 6 Input: 0 0 1 0 3 2

Output: 0 4 2 1 3 5

17/30 0 421 21 631 31 3 5

421 3 5

AN EXAMPLE WHERE IMPERATIVE PROGRAMMING SHINES: DYNAMIC DATA STRUCTURES (1)

Problem: Build a permutation of the integers {0, 1,..., n − 1} specified by indicating, for each element, after which element it is to be inserted.

Example:

1 2 3 4 5 6 Input: 0 0 1 0 3 2

Output: 0 4 2 1 3 5

6

17/30 0 421 21 31 3 5

421 63 5

AN EXAMPLE WHERE IMPERATIVE PROGRAMMING SHINES: DYNAMIC DATA STRUCTURES (1)

Problem: Build a permutation of the integers {0, 1,..., n − 1} specified by indicating, for each element, after which element it is to be inserted.

Example:

1 2 3 4 5 6 Input: 0 0 1 0 3 2

Output: 0 4 2 6 1 3 5

17/30 4 2 6

0 1 3 5

AN EXAMPLE WHERE IMPERATIVE PROGRAMMING SHINES: DYNAMIC DATA STRUCTURES (2)

C++: Linear time

std::vector dynamic_permute(const std::vector &refs) { int n = ref.size() + 1; std::list seq; std::vector::iterator> list_nodes(n); list_nodes[0] = seq.insert(seq.end(), 0); for (int i = 1; i < n; ++i) list_nodes[i] = seq.insert(next(list_nodes[ref[i]]), i); return std::vector(seq.begin(), seq.end()); }

18/30 4 2 6

1 3 5

AN EXAMPLE WHERE IMPERATIVE PROGRAMMING SHINES: DYNAMIC DATA STRUCTURES (2)

C++: Linear time

std::vector dynamic_permute(const std::vector &refs) { int n = ref.size() + 1; std::list seq; std::vector::iterator> list_nodes(n); list_nodes[0] = seq.insert(seq.end(), 0); for (int i = 1; i < n; ++i) list_nodes[i] = seq.insert(next(list_nodes[ref[i]]), i); return std::vector(seq.begin(), seq.end()); }

0 18/30 4 2 6

3 5

AN EXAMPLE WHERE IMPERATIVE PROGRAMMING SHINES: DYNAMIC DATA STRUCTURES (2)

C++: Linear time

std::vector dynamic_permute(const std::vector &refs) { int n = ref.size() + 1; std::list seq; std::vector::iterator> list_nodes(n); list_nodes[0] = seq.insert(seq.end(), 0); for (int i = 1; i < n; ++i) list_nodes[i] = seq.insert(next(list_nodes[ref[i]]), i); return std::vector(seq.begin(), seq.end()); }

0 1 18/30 4 6

3 5

AN EXAMPLE WHERE IMPERATIVE PROGRAMMING SHINES: DYNAMIC DATA STRUCTURES (2)

C++: Linear time

std::vector dynamic_permute(const std::vector &refs) { int n = ref.size() + 1; std::list seq; std::vector::iterator> list_nodes(n); list_nodes[0] = seq.insert(seq.end(), 0); for (int i = 1; i < n; ++i) list_nodes[i] = seq.insert(next(list_nodes[ref[i]]), i); return std::vector(seq.begin(), seq.end()); }

2

0 1 18/30 4 6

3 5

AN EXAMPLE WHERE IMPERATIVE PROGRAMMING SHINES: DYNAMIC DATA STRUCTURES (2)

C++: Linear time

std::vector dynamic_permute(const std::vector &refs) { int n = ref.size() + 1; std::list seq; std::vector::iterator> list_nodes(n); list_nodes[0] = seq.insert(seq.end(), 0); for (int i = 1; i < n; ++i) list_nodes[i] = seq.insert(next(list_nodes[ref[i]]), i); return std::vector(seq.begin(), seq.end()); }

2

0 1 18/30 4 6

5

AN EXAMPLE WHERE IMPERATIVE PROGRAMMING SHINES: DYNAMIC DATA STRUCTURES (2)

C++: Linear time

std::vector dynamic_permute(const std::vector &refs) { int n = ref.size() + 1; std::list seq; std::vector::iterator> list_nodes(n); list_nodes[0] = seq.insert(seq.end(), 0); for (int i = 1; i < n; ++i) list_nodes[i] = seq.insert(next(list_nodes[ref[i]]), i); return std::vector(seq.begin(), seq.end()); }

2

0 1 3 18/30 6

5

AN EXAMPLE WHERE IMPERATIVE PROGRAMMING SHINES: DYNAMIC DATA STRUCTURES (2)

C++: Linear time

std::vector dynamic_permute(const std::vector &refs) { int n = ref.size() + 1; std::list seq; std::vector::iterator> list_nodes(n); list_nodes[0] = seq.insert(seq.end(), 0); for (int i = 1; i < n; ++i) list_nodes[i] = seq.insert(next(list_nodes[ref[i]]), i); return std::vector(seq.begin(), seq.end()); }

4 2

0 1 3 18/30 6

5

AN EXAMPLE WHERE IMPERATIVE PROGRAMMING SHINES: DYNAMIC DATA STRUCTURES (2)

C++: Linear time

std::vector dynamic_permute(const std::vector &refs) { int n = ref.size() + 1; std::list seq; std::vector::iterator> list_nodes(n); list_nodes[0] = seq.insert(seq.end(), 0); for (int i = 1; i < n; ++i) list_nodes[i] = seq.insert(next(list_nodes[ref[i]]), i); return std::vector(seq.begin(), seq.end()); }

4 2

0 1 3 18/30 6

AN EXAMPLE WHERE IMPERATIVE PROGRAMMING SHINES: DYNAMIC DATA STRUCTURES (2)

C++: Linear time

std::vector dynamic_permute(const std::vector &refs) { int n = ref.size() + 1; std::list seq; std::vector::iterator> list_nodes(n); list_nodes[0] = seq.insert(seq.end(), 0); for (int i = 1; i < n; ++i) list_nodes[i] = seq.insert(next(list_nodes[ref[i]]), i); return std::vector(seq.begin(), seq.end()); }

4 2

0 1 3 5 18/30 AN EXAMPLE WHERE IMPERATIVE PROGRAMMING SHINES: DYNAMIC DATA STRUCTURES (2)

C++: Linear time

std::vector dynamic_permute(const std::vector &refs) { int n = ref.size() + 1; std::list seq; std::vector::iterator> list_nodes(n); list_nodes[0] = seq.insert(seq.end(), 0); for (int i = 1; i < n; ++i) list_nodes[i] = seq.insert(next(list_nodes[ref[i]]), i); return std::vector(seq.begin(), seq.end()); }

4 2 6

0 1 3 5 18/30 AN EXAMPLE WHERE IMPERATIVE PROGRAMMING SHINES: DYNAMIC DATA STRUCTURES (2)

C++: Linear time

std::vector dynamic_permute(const std::vector &refs) { int n = ref.size() + 1; std::list seq; std::vector::iterator> list_nodes(n); list_nodes[0] = seq.insert(seq.end(), 0); for (int i = 1; i < n; ++i) list_nodes[i] = seq.insert(next(list_nodes[ref[i]]), i); return std::vector(seq.begin(), seq.end()); }

4 2 6

0 1 3 5 18/30 0 3 1 2

When “updating” any node in a functional , all nodes with a path of pointers to it need to be replaced too. This makes standard pointer-based data structures difficult/impossible to implement functionally.

AN EXAMPLE WHERE IMPERATIVE PROGRAMMING SHINES: DYNAMIC DATA STRUCTURES (3)

Doing this without mutation:

0 1 2

19/30 0 1 2

When “updating” any node in a functional data structure, all nodes with a path of pointers to it need to be replaced too. This makes standard pointer-based data structures difficult/impossible to implement functionally.

AN EXAMPLE WHERE IMPERATIVE PROGRAMMING SHINES: DYNAMIC DATA STRUCTURES (3)

Doing this without mutation:

3

0 1 2

19/30 2

When “updating” any node in a functional data structure, all nodes with a path of pointers to it need to be replaced too. This makes standard pointer-based data structures difficult/impossible to implement functionally.

AN EXAMPLE WHERE IMPERATIVE PROGRAMMING SHINES: DYNAMIC DATA STRUCTURES (3)

Doing this without mutation:

0 3 1

0 1 2

19/30 When “updating” any node in a functional data structure, all nodes with a path of pointers to it need to be replaced too. This makes standard pointer-based data structures difficult/impossible to implement functionally.

AN EXAMPLE WHERE IMPERATIVE PROGRAMMING SHINES: DYNAMIC DATA STRUCTURES (3)

Doing this without mutation:

0 3 1 2

0 1 2

19/30 This makes standard pointer-based data structures difficult/impossible to implement functionally.

AN EXAMPLE WHERE IMPERATIVE PROGRAMMING SHINES: DYNAMIC DATA STRUCTURES (3)

Doing this without mutation:

0 3 1 2

0 1 2

When “updating” any node in a functional data structure, all nodes with a path of pointers to it need to be replaced too.

19/30 AN EXAMPLE WHERE IMPERATIVE PROGRAMMING SHINES: DYNAMIC DATA STRUCTURES (3)

Doing this without mutation:

0 3 1 2

0 1 2

When “updating” any node in a functional data structure, all nodes with a path of pointers to it need to be replaced too. This makes standard pointer-based data structures difficult/impossible to implement functionally.

19/30 WHAT ABOUT TRADITIONAL PERMUTING? (1)

Problem: Given a list of elements, each annotated with its desired position in the output list, build an array storing each element in the desired position.

Example:

Input: (2, a) (0, ) (3, c) (1, e) (4, d)

Output: b e a c d

20/30 Haskell:

permute :: [(Int, t)] -> [t] permute xs = elems (array (0, len xs - 1) xs)

WHAT ABOUT TRADITIONAL PERMUTING? (2)

C++:

template std::vector permute( const std::vector> &input) { std::vector output(input.size()); for (auto &item : input) output[item.first] = item.second; return output; }

21/30 WHAT ABOUT TRADITIONAL PERMUTING? (2)

C++:

template std::vector permute( const std::vector> &input) { std::vector output(input.size()); for (auto &item : input) output[item.first] = item.second; return output; }

Haskell:

permute :: [(Int, t)] -> [t] permute xs = elems (array (0, len xs - 1) xs)

21/30 AN EXAMPLE WHERE LOGIC PROGRAMMING SHINES: (1)

4 2 6 1 4 8 7 3 2 9 6 1 5 2 3 6 1 7 2 3 5 6 4 1 7 8 9 6 9 5 4 3 1 6 9 5 8 7 4 2 3 9 4 6 9 1 7 3 8 2 5 4 4 2 8 3 5 4 2 9 1 6 8 3 7 8 9 8 7 3 2 5 4 1 9 6 9 8 2 3 7 9 5 8 4 6 2 3 7 1 4 1 3 6 8 7 2 4 1 9 3 5 6 8 1 6 7 2 3 1 6 8 7 5 9 4 2

Sudoku

22/30 Elegant but (ridiculously) slow

rows_blocks([], []). rows_blocks([R1,R2,R3|Rows], [B1,B2,B3|Blocks]) :- rows3_blocks3([R1,R2,R3], [B1,B2,B3]).

rows3_blocks3([[R11,R12,R13|R1], [R21,R22,R23|R2], [R31,R32,R33|R3]], [[R11,R12,R13,R21,R22,R23,R31,R32,R33|Bs]) :- rows3_blocks3([R1,R2,R3], Bs).

AN EXAMPLE WHERE LOGIC PROGRAMMING SHINES: CONSTRAINT SATISFACTION (2)

Prolog:

sudoku(Rows) :- transpose(Rows, Columns), rows_blocks(Rows, Blocks), ([Rows, Columns, Blocks], Sets), maplist(permutation([1, 2, 3, 4, 5, 6, 7, 8, 9]), Sets).

23/30 Elegant but (ridiculously) slow

rows3_blocks3([[R11,R12,R13|R1], [R21,R22,R23|R2], [R31,R32,R33|R3]], [[R11,R12,R13,R21,R22,R23,R31,R32,R33|Bs]) :- rows3_blocks3([R1,R2,R3], Bs).

AN EXAMPLE WHERE LOGIC PROGRAMMING SHINES: CONSTRAINT SATISFACTION (2)

Prolog:

sudoku(Rows) :- transpose(Rows, Columns), rows_blocks(Rows, Blocks), append([Rows, Columns, Blocks], Sets), maplist(permutation([1, 2, 3, 4, 5, 6, 7, 8, 9]), Sets).

rows_blocks([], []). rows_blocks([R1,R2,R3|Rows], [B1,B2,B3|Blocks]) :- rows3_blocks3([R1,R2,R3], [B1,B2,B3]).

23/30 Elegant but (ridiculously) slow

AN EXAMPLE WHERE LOGIC PROGRAMMING SHINES: CONSTRAINT SATISFACTION (2)

Prolog:

sudoku(Rows) :- transpose(Rows, Columns), rows_blocks(Rows, Blocks), append([Rows, Columns, Blocks], Sets), maplist(permutation([1, 2, 3, 4, 5, 6, 7, 8, 9]), Sets).

rows_blocks([], []). rows_blocks([R1,R2,R3|Rows], [B1,B2,B3|Blocks]) :- rows3_blocks3([R1,R2,R3], [B1,B2,B3]).

rows3_blocks3([[R11,R12,R13|R1], [R21,R22,R23|R2], [R31,R32,R33|R3]], [[R11,R12,R13,R21,R22,R23,R31,R32,R33|Bs]) :- rows3_blocks3([R1,R2,R3], Bs).

23/30 AN EXAMPLE WHERE LOGIC PROGRAMMING SHINES: CONSTRAINT SATISFACTION (2)

Prolog: Elegant but (ridiculously) slow

sudoku(Rows) :- transpose(Rows, Columns), rows_blocks(Rows, Blocks), append([Rows, Columns, Blocks], Sets), maplist(permutation([1, 2, 3, 4, 5, 6, 7, 8, 9]), Sets).

rows_blocks([], []). rows_blocks([R1,R2,R3|Rows], [B1,B2,B3|Blocks]) :- rows3_blocks3([R1,R2,R3], [B1,B2,B3]).

rows3_blocks3([[R11,R12,R13|R1], [R21,R22,R23|R2], [R31,R32,R33|R3]], [[R11,R12,R13,R21,R22,R23,R31,R32,R33|Bs]) :- rows3_blocks3([R1,R2,R3], Bs).

23/30 blocks([], [], []). blocks([A1,A2,A3|As], [B1,B2,B3|Bs], [C1,C2,C3|Cs]) :- all_distinct([A1,A2,A3,B1,B2,B3,C1,C2,C3]), blocks(As,Bs,Cs).

What’s different? This uses efficient constraint propagation.

AN EXAMPLE WHERE LOGIC PROGRAMMING SHINES: CONSTRAINT SATISFACTION (3)

Prolog: Elegant and fast

sudoku(Rows) :- transpose(Rows, Columns), append(Rows, Vs), Vs ins 1..9, maplist(all_distinct, Rows), maplist(all_distinct, Columns), Rows = [As,Bs,Cs,Ds,Es,Fs,Gs,Hs,Is], blocks(As,Bs,Cs), blocks(Ds,Es,Fs), blocks(Gs,Hs,Is), label(Vs).

24/30 What’s different? This uses efficient constraint propagation.

AN EXAMPLE WHERE LOGIC PROGRAMMING SHINES: CONSTRAINT SATISFACTION (3)

Prolog: Elegant and fast

sudoku(Rows) :- transpose(Rows, Columns), append(Rows, Vs), Vs ins 1..9, maplist(all_distinct, Rows), maplist(all_distinct, Columns), Rows = [As,Bs,Cs,Ds,Es,Fs,Gs,Hs,Is], blocks(As,Bs,Cs), blocks(Ds,Es,Fs), blocks(Gs,Hs,Is), label(Vs).

blocks([], [], []). blocks([A1,A2,A3|As], [B1,B2,B3|Bs], [C1,C2,C3|Cs]) :- all_distinct([A1,A2,A3,B1,B2,B3,C1,C2,C3]), blocks(As,Bs,Cs).

24/30 This uses efficient constraint propagation.

AN EXAMPLE WHERE LOGIC PROGRAMMING SHINES: CONSTRAINT SATISFACTION (3)

Prolog: Elegant and fast

sudoku(Rows) :- transpose(Rows, Columns), append(Rows, Vs), Vs ins 1..9, maplist(all_distinct, Rows), maplist(all_distinct, Columns), Rows = [As,Bs,Cs,Ds,Es,Fs,Gs,Hs,Is], blocks(As,Bs,Cs), blocks(Ds,Es,Fs), blocks(Gs,Hs,Is), label(Vs).

blocks([], [], []). blocks([A1,A2,A3|As], [B1,B2,B3|Bs], [C1,C2,C3|Cs]) :- all_distinct([A1,A2,A3,B1,B2,B3,C1,C2,C3]), blocks(As,Bs,Cs).

What’s different? 24/30 AN EXAMPLE WHERE LOGIC PROGRAMMING SHINES: CONSTRAINT SATISFACTION (3)

Prolog: Elegant and fast

sudoku(Rows) :- transpose(Rows, Columns), append(Rows, Vs), Vs ins 1..9, maplist(all_distinct, Rows), maplist(all_distinct, Columns), Rows = [As,Bs,Cs,Ds,Es,Fs,Gs,Hs,Is], blocks(As,Bs,Cs), blocks(Ds,Es,Fs), blocks(Gs,Hs,Is), label(Vs).

blocks([], [], []). blocks([A1,A2,A3|As], [B1,B2,B3|Bs], [C1,C2,C3|Cs]) :- all_distinct([A1,A2,A3,B1,B2,B3,C1,C2,C3]), blocks(As,Bs,Cs).

What’s different? This uses efficient constraint propagation. 24/30 Python:

• SAT solver (250 LOC) • Encode puzzle as CNF (100 LOC) • Instantaneous answer • Could get faster if • Implemented in C++ • Using state-of-the-art SAT solver

AN EXAMPLE WHERE LOGIC PROGRAMMING SHINES: CONSTRAINT SATISFACTION (4)

Prolog:

• 12 LOC • Instantaneous answer • SWI Prolog • Free, well maintained, feature-rich, ISO compliant • Much slower than SICSTUS Prolog (commercial)

25/30 AN EXAMPLE WHERE LOGIC PROGRAMMING SHINES: CONSTRAINT SATISFACTION (4)

Prolog: Python:

• 12 LOC • SAT solver (250 LOC) • Instantaneous answer • Encode puzzle as CNF (100 LOC) • SWI Prolog • Instantaneous answer • Free, well maintained, • Could get faster if feature-rich, ISO compliant • Implemented in C++ • Much slower than SICSTUS • Using state-of-the-art SAT solver Prolog (commercial)

25/30 AN EXAMPLE WHERE LOGIC PROGRAMMING SHINES: CONSTRAINT SATISFACTION (5)

0 1 0 1 0 0 1 1 0 1 1 0 1 0 0 1 0 1 0 1 1 1 1 1 0 0 1 1 0 0 1 0 1 1 0 0 0 1 0 1 1 0 0 1 0 1 1 0 0 1 0 1 1 0 0 1 1 0 0 1 0 0 1 1 0 1 1 1 0 0 1 1 0 0 1 1 0 1 0 1 0 0 0 1 1 1 0 1 1 0 0 1 0 0 1 1 0 1 0 1 0 1 0 1 0 1 0 0 1 1 0 0 1 1 0 1 1 1 1 1 1 0 1 0 1 1 0 0 1 1 0 0 1 0 1 1 1 0 1 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 1 0 0 1 0 1 1 0 0 1 1 0 1 0 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 0 1 1 0 0 1 0 0 1 1 0 1 0 0 1 1 0 0 1 1 0 0 0 1 0 0 1 1 0 1 1 0 0 1 1 0 0 1 1 0 1 1 0 0 1 1 0 0 1 0 0 1 1

Binary Puzzle · No two identical rows/columns · #0s = #1s in each row/column

· No three consecutive 0s or 1s in any row or column 26/30 zero_one_balance(List) :- length(List,L), Half is L // 2, sum(List, #= Half).

not_same((List1,List2) :- maplist(diff, List1, List2, Diffs), sum(Diffs, #>, 0).

diff(A, B, Diff) :- Diff #<==> A #\= B.

pairs([_]) --> []. pairs([X|List]) --> no_triplets(List) :- pairs_(X, List), pairs(List). length(List,L), L < 3. no_triplets([A,B,C|List]) :- pairs_(_, []) --> []. A+B+C #> 0, A+B+C #< 3, pairs_(X, [Y|List]) --> no_triplets([B,C|List]). [(X,Y)], pairs_(X,List).

AN EXAMPLE WHERE LOGIC PROGRAMMING SHINES: CONSTRAINT SATISFACTION (6)

binary(Rows) :- append(Rows, Vs), Vs ins 0..1, transpose(Rows, Columns), maplist(no_triplets, Rows), maplist(no_triplets, Columns), maplist(zero_one_balance, Rows), maplist(zero_one_balance, Columns), phrase(pairs(Rows), Row_Pairs), phrase(pairs(Columns), Column_Pairs), maplist(not_same, Row_Pairs), maplist(not_same, Column_Pairs), label(Vs).

27/30 zero_one_balance(List) :- length(List,L), Half is L // 2, sum(List, #= Half).

not_same((List1,List2) :- maplist(diff, List1, List2, Diffs), sum(Diffs, #>, 0).

diff(A, B, Diff) :- Diff #<==> A #\= B.

pairs([_]) --> []. pairs([X|List]) --> pairs_(X, List), pairs(List).

pairs_(_, []) --> []. pairs_(X, [Y|List]) --> [(X,Y)], pairs_(X,List).

AN EXAMPLE WHERE LOGIC PROGRAMMING SHINES: CONSTRAINT SATISFACTION (6)

binary(Rows) :- append(Rows, Vs), Vs ins 0..1, transpose(Rows, Columns), maplist(no_triplets, Rows), maplist(no_triplets, Columns), maplist(zero_one_balance, Rows), maplist(zero_one_balance, Columns), phrase(pairs(Rows), Row_Pairs), phrase(pairs(Columns), Column_Pairs), maplist(not_same, Row_Pairs), maplist(not_same, Column_Pairs), label(Vs).

no_triplets(List) :- length(List,L), L < 3. no_triplets([A,B,C|List]) :- A+B+C #> 0, A+B+C #< 3, no_triplets([B,C|List]). 27/30 not_same((List1,List2) :- maplist(diff, List1, List2, Diffs), sum(Diffs, #>, 0).

diff(A, B, Diff) :- Diff #<==> A #\= B.

pairs([_]) --> []. pairs([X|List]) --> pairs_(X, List), pairs(List).

pairs_(_, []) --> []. pairs_(X, [Y|List]) --> [(X,Y)], pairs_(X,List).

AN EXAMPLE WHERE LOGIC PROGRAMMING SHINES: CONSTRAINT SATISFACTION (6)

binary(Rows) :- zero_one_balance(List) :- append(Rows, Vs), Vs ins 0..1, length(List,L), Half is L // 2, transpose(Rows, Columns), sum(List, #= Half). maplist(no_triplets, Rows), maplist(no_triplets, Columns), maplist(zero_one_balance, Rows), maplist(zero_one_balance, Columns), phrase(pairs(Rows), Row_Pairs), phrase(pairs(Columns), Column_Pairs), maplist(not_same, Row_Pairs), maplist(not_same, Column_Pairs), label(Vs).

no_triplets(List) :- length(List,L), L < 3. no_triplets([A,B,C|List]) :- A+B+C #> 0, A+B+C #< 3, no_triplets([B,C|List]). 27/30 pairs([_]) --> []. pairs([X|List]) --> pairs_(X, List), pairs(List).

pairs_(_, []) --> []. pairs_(X, [Y|List]) --> [(X,Y)], pairs_(X,List).

AN EXAMPLE WHERE LOGIC PROGRAMMING SHINES: CONSTRAINT SATISFACTION (6)

binary(Rows) :- zero_one_balance(List) :- append(Rows, Vs), Vs ins 0..1, length(List,L), Half is L // 2, transpose(Rows, Columns), sum(List, #= Half). maplist(no_triplets, Rows), maplist(no_triplets, Columns), not_same((List1,List2) :- maplist(zero_one_balance, Rows), maplist(diff, List1, List2, Diffs), maplist(zero_one_balance, Columns), sum(Diffs, #>, 0). phrase(pairs(Rows), Row_Pairs), phrase(pairs(Columns), Column_Pairs), diff(A, B, Diff) :- maplist(not_same, Row_Pairs), Diff #<==> A #\= B. maplist(not_same, Column_Pairs), label(Vs).

no_triplets(List) :- length(List,L), L < 3. no_triplets([A,B,C|List]) :- A+B+C #> 0, A+B+C #< 3, no_triplets([B,C|List]). 27/30 AN EXAMPLE WHERE LOGIC PROGRAMMING SHINES: CONSTRAINT SATISFACTION (6)

binary(Rows) :- zero_one_balance(List) :- append(Rows, Vs), Vs ins 0..1, length(List,L), Half is L // 2, transpose(Rows, Columns), sum(List, #= Half). maplist(no_triplets, Rows), maplist(no_triplets, Columns), not_same((List1,List2) :- maplist(zero_one_balance, Rows), maplist(diff, List1, List2, Diffs), maplist(zero_one_balance, Columns), sum(Diffs, #>, 0). phrase(pairs(Rows), Row_Pairs), phrase(pairs(Columns), Column_Pairs), diff(A, B, Diff) :- maplist(not_same, Row_Pairs), Diff #<==> A #\= B. maplist(not_same, Column_Pairs), label(Vs). pairs([_]) --> []. pairs([X|List]) --> no_triplets(List) :- pairs_(X, List), pairs(List). length(List,L), L < 3. no_triplets([A,B,C|List]) :- pairs_(_, []) --> []. A+B+C #> 0, A+B+C #< 3, pairs_(X, [Y|List]) --> no_triplets([B,C|List]). [(X,Y)], pairs_(X,List). 27/30 AN EXAMPLE WHERE LOGIC PROGRAMMING SHINES: CONSTRAINT SATISFACTION (7)

Prolog: Python:

• 31 LOC • SAT solver (250 LOC) • Around 7 secs to solve • Encode puzzle as CNF (150 LOC) • SWI Prolog • Around 70 secs to solve • Free, well maintained, • Could get faster if feature-rich, ISO compliant • Implemented in C++ • Much slower than SICSTUS • Using state-of-the-art SAT solver Prolog (commercial)

28/30 Fine-grained control High-level abstractions

C++ Python, Ruby, Java, Scala Haskell Prolog

“Trust me, I know what I’m doing” Strict compile-time checks

Python, Ruby C++, Java Scala Haskell

What do we want exactly?

EXPRESSIVENESS OF PROGRAMMING LANGUAGES

We want expressive programming languages that make programming easy: • Concise • Help to avoid common bugs • Help to express exactly what we want

29/30 Fine-grained control High-level abstractions

C++ Python, Ruby, Java, Scala Haskell Prolog

“Trust me, I know what I’m doing” Strict compile-time checks

Python, Ruby C++, Java Scala Haskell

EXPRESSIVENESS OF PROGRAMMING LANGUAGES

We want expressive programming languages that make programming easy: • Concise • Help to avoid common bugs • Help to express exactly what we want

What do we want exactly?

29/30 C++ Python, Ruby, Java, Scala Haskell Prolog

“Trust me, I know what I’m doing” Strict compile-time checks

Python, Ruby C++, Java Scala Haskell

EXPRESSIVENESS OF PROGRAMMING LANGUAGES

We want expressive programming languages that make programming easy: • Concise • Help to avoid common bugs • Help to express exactly what we want

What do we want exactly?

Fine-grained control High-level abstractions

29/30 Python, Ruby, Java, Scala Haskell Prolog

“Trust me, I know what I’m doing” Strict compile-time checks

Python, Ruby C++, Java Scala Haskell

EXPRESSIVENESS OF PROGRAMMING LANGUAGES

We want expressive programming languages that make programming easy: • Concise • Help to avoid common bugs • Help to express exactly what we want

What do we want exactly?

Fine-grained control High-level abstractions

C++

29/30 Haskell Prolog

“Trust me, I know what I’m doing” Strict compile-time checks

Python, Ruby C++, Java Scala Haskell

EXPRESSIVENESS OF PROGRAMMING LANGUAGES

We want expressive programming languages that make programming easy: • Concise • Help to avoid common bugs • Help to express exactly what we want

What do we want exactly?

Fine-grained control High-level abstractions

C++ Python, Ruby, Java, Scala

29/30 Prolog

“Trust me, I know what I’m doing” Strict compile-time checks

Python, Ruby C++, Java Scala Haskell

EXPRESSIVENESS OF PROGRAMMING LANGUAGES

We want expressive programming languages that make programming easy: • Concise • Help to avoid common bugs • Help to express exactly what we want

What do we want exactly?

Fine-grained control High-level abstractions

C++ Python, Ruby, Java, Scala Haskell

29/30 “Trust me, I know what I’m doing” Strict compile-time checks

Python, Ruby C++, Java Scala Haskell

EXPRESSIVENESS OF PROGRAMMING LANGUAGES

We want expressive programming languages that make programming easy: • Concise • Help to avoid common bugs • Help to express exactly what we want

What do we want exactly?

Fine-grained control High-level abstractions

C++ Python, Ruby, Java, Scala Haskell Prolog

29/30 Python, Ruby C++, Java Scala Haskell

EXPRESSIVENESS OF PROGRAMMING LANGUAGES

We want expressive programming languages that make programming easy: • Concise • Help to avoid common bugs • Help to express exactly what we want

What do we want exactly?

Fine-grained control High-level abstractions

C++ Python, Ruby, Java, Scala Haskell Prolog

“Trust me, I know what I’m doing” Strict compile-time checks

29/30 Python, Ruby Scala Haskell

EXPRESSIVENESS OF PROGRAMMING LANGUAGES

We want expressive programming languages that make programming easy: • Concise • Help to avoid common bugs • Help to express exactly what we want

What do we want exactly?

Fine-grained control High-level abstractions

C++ Python, Ruby, Java, Scala Haskell Prolog

“Trust me, I know what I’m doing” Strict compile-time checks

C++, Java 29/30 Scala Haskell

EXPRESSIVENESS OF PROGRAMMING LANGUAGES

We want expressive programming languages that make programming easy: • Concise • Help to avoid common bugs • Help to express exactly what we want

What do we want exactly?

Fine-grained control High-level abstractions

C++ Python, Ruby, Java, Scala Haskell Prolog

“Trust me, I know what I’m doing” Strict compile-time checks

Python, Ruby C++, Java 29/30 Scala

EXPRESSIVENESS OF PROGRAMMING LANGUAGES

We want expressive programming languages that make programming easy: • Concise • Help to avoid common bugs • Help to express exactly what we want

What do we want exactly?

Fine-grained control High-level abstractions

C++ Python, Ruby, Java, Scala Haskell Prolog

“Trust me, I know what I’m doing” Strict compile-time checks

Python, Ruby C++, Java Haskell 29/30 EXPRESSIVENESS OF PROGRAMMING LANGUAGES

We want expressive programming languages that make programming easy: • Concise • Help to avoid common bugs • Help to express exactly what we want

What do we want exactly?

Fine-grained control High-level abstractions

C++ Python, Ruby, Java, Scala Haskell Prolog

“Trust me, I know what I’m doing” Strict compile-time checks

Python, Ruby C++, Java Scala Haskell 29/30 Different programming languages may be better for different jobs.

Be eager to explore new programming languages!

• Outside your comfort zone! • It’s fun. • It makes you a better programmer, even in your favourite language. • Your favourite language may change.

SUMMARY

Programming languages are the tools we use to express computations.

30/30 Be eager to explore new programming languages!

• Outside your comfort zone! • It’s fun. • It makes you a better programmer, even in your favourite language. • Your favourite language may change.

SUMMARY

Programming languages are the tools we use to express computations.

Different programming languages may be better for different jobs.

30/30 SUMMARY

Programming languages are the tools we use to express computations.

Different programming languages may be better for different jobs.

Be eager to explore new programming languages!

• Outside your comfort zone! • It’s fun. • It makes you a better programmer, even in your favourite language. • Your favourite language may change.

30/30