The document discusses pattern matching and predicate dispatch in dynamic programming languages. It notes that dynamic typing can lead to errors, and that traditional object-oriented typing is often too coarse-grained. The document proposes an approach using pattern matching and predicate dispatch to specify allowed types and behaviors more precisely without static types. It describes compiling pattern matching to decision trees, how patterns are implemented as protocols, and provides examples of pattern matching for sequences, maps, and using guards.
This document appears to be notes from a presentation on Clojure. It discusses key features of Clojure like how it differs from Lisp, its use of REPL for documentation, lambda functions and macros. A large portion of the document covers concurrency in Clojure, explaining concepts like STM, atoms and agents. It provides examples of using Clojure's STM functions like ref, deref, alter and compares them to handling concurrency in other languages like Scala. The notes conclude by mentioning side-effects and comparing Clojure to other JVM languages.
Macros are essential in Clojure and are used to provide fundamental operations like "when". Macros receive unevaluated code and return data structures for Clojure to evaluate. Writing macros involves building lists to represent code. Care must be taken to avoid issues like variable capture and double evaluation. While powerful, macros can lead to overly complex code if overused.
This document summarizes Carlo Sciolla's presentation on Clojure given to the Amsterdam Clojurians. Sciolla discusses his background and motivation for exploring functional programming. He then provides an introduction to Clojure, explaining its Lisp roots and key concepts like immutable data structures, sequences, and the read-eval-print loop. Sciolla also gives an example function to count the letters in a string to demonstrate how real problems can be solved in Clojure despite its immutable design.
The document discusses refactoring code that sends different types of requests to a server using macros. Initially, a function is used to send requests, but it results in duplicate code. A macro is then used to generate code for sending different request types in a generic way. However, using a symbol for the parameter map causes issues at compile time, since the macro evaluator does not know the runtime values. The macro is updated to accept a list of expected parameter fields to generate setting code for each one. This allows the parameter map to remain a symbol without needing its runtime value.
This document appears to be notes from a presentation on Clojure. It discusses key features of Clojure like how it differs from Lisp, its use of REPL for documentation, lambda functions and macros. A large portion of the document covers concurrency in Clojure, explaining concepts like STM, atoms and agents. It provides examples of using Clojure's STM functions like ref, deref, alter and compares them to handling concurrency in other languages like Scala. The notes conclude by mentioning side-effects and comparing Clojure to other JVM languages.
Macros are essential in Clojure and are used to provide fundamental operations like "when". Macros receive unevaluated code and return data structures for Clojure to evaluate. Writing macros involves building lists to represent code. Care must be taken to avoid issues like variable capture and double evaluation. While powerful, macros can lead to overly complex code if overused.
This document summarizes Carlo Sciolla's presentation on Clojure given to the Amsterdam Clojurians. Sciolla discusses his background and motivation for exploring functional programming. He then provides an introduction to Clojure, explaining its Lisp roots and key concepts like immutable data structures, sequences, and the read-eval-print loop. Sciolla also gives an example function to count the letters in a string to demonstrate how real problems can be solved in Clojure despite its immutable design.
The document discusses refactoring code that sends different types of requests to a server using macros. Initially, a function is used to send requests, but it results in duplicate code. A macro is then used to generate code for sending different request types in a generic way. However, using a symbol for the parameter map causes issues at compile time, since the macro evaluator does not know the runtime values. The macro is updated to accept a list of expected parameter fields to generate setting code for each one. This allows the parameter map to remain a symbol without needing its runtime value.
Continuation Passing Style and Macros in Clojure - Jan 2012Leonardo Borges
The document discusses continuation-passing style (CPS) in Clojure, where control is passed explicitly as a continuation argument to each function, and provides examples of implementing the Pythagorean theorem and Fibonacci sequence in CPS; it also explains how macros can be used to avoid deep nesting when accessing nested values and demonstrates a macro for this use case.
Stefan Richter - Writing simple, readable and robust code: Examples in Java, ...AboutYouGmbH
Stefan Richter gave a presentation on writing simple, readable, and robust code using examples in Java, Clojure, and Go. He discussed his programming experience and showed how Martin Fowler used Java to parse a fixed-length file format into objects. Richter then demonstrated how the same task could be accomplished more concisely in Common Lisp and Clojure using macros to define domain-specific languages. He argued that macros are a powerful feature of Lisp-like languages.
This document provides a summary of Jacek Laskowski as the main sponsor of a Clojure conference. It lists his background and experience including being a functional apprentice of Clojure, founder and co-leader of a JUG, conference organizer, member of Apache Software Foundation and IBM. It also lists his blog and Twitter accounts.
Macros are functions that are supplied with Clojure and defined by users. Argument forms are passed as data to the macro function, which returns a new data structure as a replacement for the macro call. Many things that are built-in to other languages are implemented as macros in Clojure.
This document provides a summary of an introduction to the Clojure programming language. It discusses what Clojure is, its timeline and adoption, functional programming concepts, concurrency features using Software Transactional Memory, the Lisp ideology it is based on including homoiconicity and its macro system. It also provides an overview of getting started with Clojure including using the REPL, basic syntax like symbols and keywords, data types, sequences, functions, and Java interoperability. Resources for learning more about Clojure are also listed.
Talk about DSL, How to write DSL in Clojure, How to use Instaparse (simplest library for parsing grammars) and how we use Clojure and Instaparse in Zoomdata
This document provides an introduction to Clojure, a Lisp dialect that runs on the Java Virtual Machine. It discusses key Clojure concepts like immutable data structures, functional programming with first-class functions, and macros. Examples are given of using Clojure for list processing, building applications with frameworks like Cascalog for logic programming and Compojure for web development. Garbage collection in Clojure is also briefly mentioned.
Continuation Passing Style and Macros in Clojure - Jan 2012Leonardo Borges
The document discusses continuation-passing style (CPS) in Clojure, where control is passed explicitly as a continuation argument to each function, and provides examples of implementing the Pythagorean theorem and Fibonacci sequence in CPS; it also explains how macros can be used to avoid deep nesting when accessing nested values and demonstrates a macro for this use case.
Stefan Richter - Writing simple, readable and robust code: Examples in Java, ...AboutYouGmbH
Stefan Richter gave a presentation on writing simple, readable, and robust code using examples in Java, Clojure, and Go. He discussed his programming experience and showed how Martin Fowler used Java to parse a fixed-length file format into objects. Richter then demonstrated how the same task could be accomplished more concisely in Common Lisp and Clojure using macros to define domain-specific languages. He argued that macros are a powerful feature of Lisp-like languages.
This document provides a summary of Jacek Laskowski as the main sponsor of a Clojure conference. It lists his background and experience including being a functional apprentice of Clojure, founder and co-leader of a JUG, conference organizer, member of Apache Software Foundation and IBM. It also lists his blog and Twitter accounts.
Macros are functions that are supplied with Clojure and defined by users. Argument forms are passed as data to the macro function, which returns a new data structure as a replacement for the macro call. Many things that are built-in to other languages are implemented as macros in Clojure.
This document provides a summary of an introduction to the Clojure programming language. It discusses what Clojure is, its timeline and adoption, functional programming concepts, concurrency features using Software Transactional Memory, the Lisp ideology it is based on including homoiconicity and its macro system. It also provides an overview of getting started with Clojure including using the REPL, basic syntax like symbols and keywords, data types, sequences, functions, and Java interoperability. Resources for learning more about Clojure are also listed.
Talk about DSL, How to write DSL in Clojure, How to use Instaparse (simplest library for parsing grammars) and how we use Clojure and Instaparse in Zoomdata
This document provides an introduction to Clojure, a Lisp dialect that runs on the Java Virtual Machine. It discusses key Clojure concepts like immutable data structures, functional programming with first-class functions, and macros. Examples are given of using Clojure for list processing, building applications with frameworks like Cascalog for logic programming and Compojure for web development. Garbage collection in Clojure is also briefly mentioned.
3. ๏ Dynamic programming languages are
powerful, productive
Thursday, August 18, 11 2
4. ๏ Dynamic programming languages are
powerful, productive
๏ Errors from dynamic typing are not fun
Thursday, August 18, 11 2
5. ๏ Dynamic programming languages are
powerful, productive
๏ Errors from dynamic typing are not fun
๏ Too much type information is “trapped
inside”
Thursday, August 18, 11 2
6. ๏ Dynamic programming languages are
powerful, productive
๏ Errors from dynamic typing are not fun
๏ Too much type information is “trapped
inside”
๏ We can do better without resorting to
static types
Thursday, August 18, 11 2
7. closed versus open
(cond
(map? x) ...
(vector? x) ...
(list? x) ...
:else ...)
Thursday, August 18, 11 3
9. we want to enumerate what is
allowed
duck-typing doesn’t let us specify a
specific set of things which are
allowed
Thursday, August 18, 11 5
10. we want to enumerate what is
allowed
duck-typing doesn’t let us specify a
specific set of things which are
allowed
๏ Types are often too coarse a granularity
for the kind of dispatch we would like to
specify
Thursday, August 18, 11 5
11. we want to enumerate what is
allowed
duck-typing doesn’t let us specify a
specific set of things which are
allowed
๏ Types are often too coarse a granularity
for the kind of dispatch we would like to
specify
๏ Duck-typing can be a source of pain.
Thursday, August 18, 11 5
12. we want to enumerate what is
allowed
duck-typing doesn’t let us specify a
specific set of things which are
allowed
๏ Types are often too coarse a granularity
for the kind of dispatch we would like to
specify
๏ Duck-typing can be a source of pain.
๏ Pre and post conditions are also
“trapped inside” functions
Thursday, August 18, 11 5
13. we often reach into a
data structure to pull it
part ...
but isn’t this just like
what we do w/ cond +
map? vector?
(cond
(= (first s) 1) ...
(= (first s) 2) ...
(= (second s) :foo) ...
...)
Thursday, August 18, 11 6
14. destructuring does make
it more convenient... but
something is still missing
(let [[x & r] s]
(cond
(= x 1) ...
(= x 2) ...
(= (second s) :foo) ...
...))
Thursday, August 18, 11 7
15. this where we are today
with match...
we’ll talk about this but
note that this is very
much a chocolate fudge
machine infused cond
(match [x]
[[1 & r]] ...
[[2 & r]] ...
[[_ :foo & r]] ...
...)
Thursday, August 18, 11 8
16. but this is where we’d
like to be
(extend-pred foo [[1 & r]] ...)
(extend-pred foo [[2 & r]] ...)
(extend-pred foo [[_ :foo & r]] ...)
Thursday, August 18, 11 9
18. Goals
๏ As fast or faster than destructuring for
matches with few cases
Thursday, August 18, 11 10
19. Goals
๏ As fast or faster than destructuring for
matches with few cases
๏ Pattern matching should follow
destructuring syntax when possible
Thursday, August 18, 11 10
20. Goals
๏ As fast or faster than destructuring for
matches with few cases
๏ Pattern matching should follow
destructuring syntax when possible
๏ Extensible (!)
Thursday, August 18, 11 10
21. Goals
๏ As fast or faster than destructuring for
matches with few cases
๏ Pattern matching should follow
destructuring syntax when possible
๏ Extensible (!)
๏ Testbed for predicate dispatch
Thursday, August 18, 11 10
24. ๏ Popular feature among functional
programming languages - Standard ML,
Erlang, Haskell, OCaml, Scala
Thursday, August 18, 11 12
25. ๏ Popular feature among functional
programming languages - Standard ML,
Erlang, Haskell, OCaml, Scala
๏ Literature on efficient pattern matching
in the ML language family is extensive
Thursday, August 18, 11 12
26. ๏ Popular feature among functional
programming languages - Standard ML,
Erlang, Haskell, OCaml, Scala
๏ Literature on efficient pattern matching
in the ML language family is extensive
๏ Decisions trees and backtracking
automata popular approaches
Thursday, August 18, 11 12
33. ๏ Compiling Pattern Matching to Good
Decision Trees
Thursday, August 18, 11 16
34. ๏ Compiling Pattern Matching to Good
Decision Trees
๏ Simple compilation algorithm
Thursday, August 18, 11 16
35. ๏ Compiling Pattern Matching to Good
Decision Trees
๏ Simple compilation algorithm
๏ Big idea is choosing which column to
test based on the notion of “necessity”
from lazy pattern matching
Thursday, August 18, 11 16
36. How it works in match
Thursday, August 18, 11 17
37. false and true are literals, _ is a
wildcard pattern, it will match
anything
(match [x y z]
[_ false true] 1
[false true _ ] 2
[_ _ false] 3
[_ _ true] 4
:else 5)
Thursday, August 18, 11 18
38. x y z
[_ f t] 1
[f t _] 2
[_ _ f] 3
[_ _ t] 4
[_ _ _] 5
Thursday, August 18, 11 19
39. top down evaluation
order, we don’t need to
test anything below a
wildcard
x y z
[_ f t] 1
[f t _] 2
[_ _ f] 3
[_ _ t] 4
[_ _ _] 5
Thursday, August 18, 11 20
40. y column has the largest
useful (non-wildcard)
patterns
y
[_ f t] 1
[f t _] 2
[_ _ f] 3
[_ _ t] 4
[_ _ _] 5
Thursday, August 18, 11 21
41. swap y column to the
front, now we need to
specialize
y x z
[f _ t] 1
[t f _] 2
[_ _ f] 3
[_ _ t] 4
[_ _ _] 5
Thursday, August 18, 11 22
44. we remove the rows that
x z
don’t match the value for
y. we drop the y column.
here are the next
2
pattern matrices for the
t wo values of y
[f _]
t [_
[_
f]
t]
3
4
[_ _] 5
x z
[_ t] 1
f [_
[_
f]
t]
3
4
[_ _] 5
Thursday, August 18, 11 25
46. we can take that
process and produce a
nested conditional.
(cond note that the order
(= y false) (cond testing matches
what we saw in
(= z false) (let [] 3) previous slides
(= z true) (let [] 1)
:else (throw (java.lang.Exception. "Found
FailNode")))
(= y true) (cond
(= x false) (let [] 2)
:else (cond
(= z false) 3
(= z true) 4
:else (throw
(java.lang.Exception.
"Found FailNode"))))
:else (cond
(= z false) (let [] 3)
(= z true) (let [] 4)
:else (throw (java.lang.Exception. "Found FailNode"))))
Thursday, August 18, 11 27
48. ๏ a pattern matrix is composed of pattern
rows
Thursday, August 18, 11 28
49. ๏ a pattern matrix is composed of pattern
rows
๏ pattern rows contain all the specified
patterns in addition to an action
Thursday, August 18, 11 28
50. ๏ a pattern matrix is composed of pattern
rows
๏ pattern rows contain all the specified
patterns in addition to an action
๏ pattern rows must all be of the same size
(equal number of patterns)
Thursday, August 18, 11 28
52. ๏ Patterns in match are implemented as
deftypes
Thursday, August 18, 11 29
53. ๏ Patterns in match are implemented as
deftypes
๏ The key protocol for a pattern to extend
is ISpecializeMatrix which defines a
single protocol fn - specialize-matrix
Thursday, August 18, 11 29
54. ๏ Patterns in match are implemented as
deftypes
๏ The key protocol for a pattern to extend
is ISpecializeMatrix which defines a
single protocol fn - specialize-matrix
๏ The pattern produces the new matrix
after specialization. This may involve
introducing new occurrences.
Thursday, August 18, 11 29
55. what are occurrences?
y x z
[f _ t]
[t f _]
[_ _ f]
[_ _ t]
Thursday, August 18, 11 30
56. consider this seq pattern
match
(match [x]
[[1 & r] 1
[[2 & r] 2
[[3 & r] 3)
Thursday, August 18, 11 31
57. x
[[1 & r]]
[[2 & r]]
[[3 & r]]
Thursday, August 18, 11 32
58. when the matrix is specialized by
SeqPattern we get this new pattern
matrix. We have the occurrence that
represents the head of the list and
the tail of the list.
xh xt
[1 r]
[2 r]
[3 r]
Thursday, August 18, 11 33
62. ๏ We end up with a tree of switch nodes.
Each switch nodes represents a
occurrence/binding and a multiway test
which points to other switch nodes, leaf
nodes, or fail nodes.
Thursday, August 18, 11 36
63. ๏ We end up with a tree of switch nodes.
Each switch nodes represents a
occurrence/binding and a multiway test
which points to other switch nodes, leaf
nodes, or fail nodes.
๏ This is the decision tree.
Thursday, August 18, 11 36
65. Seq pattern matching
note that the length of the
seq patterns do no matter!
(match [x]
[[1] :a0
[[1 2]] :a1
[[1 2 nil nil nil]] :a2
:else :a3)
Thursday, August 18, 11 38
66. note the rest pattern syntax
support just like destructuring.
notice that we can introduce
bindings anywhere we would
use a wildcard
(match [x]
[[1]] :a0
[[_ 2 & [a & b]]] [:a1 a b]
:else :a2)
Thursday, August 18, 11 39
68. we can restrict that only
maps with the exact keys will
match
(match [x]
[{_ :a 2 :b :only [:a :b]}] :a0
[{1 :a c :c}] :a1
[{3 :c d :d 4 :e}] :a2
:else :a3)
Thursday, August 18, 11 41
69. or patterns!
(match [x y z]
[[1 (3 | 4) 3]] :a0
[[1 (2 | 3) 3]] :a1
:else :a2)
Thursday, August 18, 11 42
71. sometimes you want to
match a specific
portion and bind that
to a local name
(match [v]
[[3 1]] :a0
[[([1 a] :as b)]] [:a1 a b]
:else :a2)
Thursday, August 18, 11 44
72. you can pattern match
Java classes!
(extend-type java.util.Date
IMatchLookup
(val-at* [this k not-found]
(case k
:year (.getYear this)
:month (.getMonth this)
:date (.getDate this)
:hours (.getHours this)
:minutes (.getMinutes this)
not-found)))
Thursday, August 18, 11 45
73. (let [d (java.util.Date. 2010 10 1 12 30)]
(match [d]
[{2009 :year a :month}] [:a0 a]
[{(2010 | 2011) :year b :month}] [:a1 b]))
Thursday, August 18, 11 46
75. problems
๏ Pattern matching is closed
Thursday, August 18, 11 47
76. problems
๏ Pattern matching is closed
๏ We want the matching to happen at the
level of our most powerful abstraction -
functions
Thursday, August 18, 11 47
77. problems
๏ Pattern matching is closed
๏ We want the matching to happen at the
level of our most powerful abstraction -
functions
๏ Without open dispatch, all we have is a
chocolate fudge machine powered cond
Thursday, August 18, 11 47
80. problems
๏ Hard coded dispatch function
Thursday, August 18, 11 49
81. problems
๏ Hard coded dispatch function
๏ In order to specify complex matches we
have to construct a collection
Thursday, August 18, 11 49
82. problems
๏ Hard coded dispatch function
๏ In order to specify complex matches we
have to construct a collection
๏ For complex matches, performance is less
than we would like
Thursday, August 18, 11 49
84. future directions
๏ Vector patterns: for any data type that
supports random access and fast
“slicing” - PersistentVector, primitive
arrays, buffers, etc.
Thursday, August 18, 11 50
85. future directions
๏ Vector patterns: for any data type that
supports random access and fast
“slicing” - PersistentVector, primitive
arrays, buffers, etc.
๏ Predicate Dispatch (huh?)
Thursday, August 18, 11 50
92. Goals
๏ move the matching to level of function, as with
multimethods
Thursday, August 18, 11 53
93. Goals
๏ move the matching to level of function, as with
multimethods
๏ this change is in conflict with the semantics of
pattern matching - pattern matching is ordered
Thursday, August 18, 11 53
94. Goals
๏ move the matching to level of function, as with
multimethods
๏ this change is in conflict with the semantics of
pattern matching - pattern matching is ordered
๏ We need some way to know where to put new
pattern rows in the matrix
Thursday, August 18, 11 53
96. A Sketch
๏ Use core.logic to order the pattern rows
Thursday, August 18, 11 54
97. A Sketch
๏ Use core.logic to order the pattern rows
๏ A high performance in-memory DAG
representation of the decision tree
Thursday, August 18, 11 54
98. A Sketch
๏ Use core.logic to order the pattern rows
๏ A high performance in-memory DAG
representation of the decision tree
๏ Perhaps we can go the route of deftype-
inline patterns get best performance
Thursday, August 18, 11 54
100. Challenges
๏ How much of the pattern matching
syntax can we bring over?
Thursday, August 18, 11 55
101. Challenges
๏ How much of the pattern matching
syntax can we bring over?
๏ How close can we get to the performance
of static code?
Thursday, August 18, 11 55
102. Challenges
๏ How much of the pattern matching
syntax can we bring over?
๏ How close can we get to the performance
of static code?
๏ Can we limit the scope of changes to
namespaces?
Thursday, August 18, 11 55