Clojure 4 Sequences 5-Dec-18.

Slides:



Advertisements
Similar presentations
Closures & Environments CS153: Compilers Greg Morrisett.
Advertisements

Lists in Lisp and Scheme a. Lists are Lisp’s fundamental data structures, but there are others – Arrays, characters, strings, etc. – Common Lisp has moved.
Def f(n): if (n == 0): return else: print(“*”) return f(n-1) f(3)
More about functions Plus a few random things. 2 Tail recursion A function is said to be tail recursive if the recursive call is the very last thing it.
Tail Recursion. Problems with Recursion Recursion is generally favored over iteration in Scheme and many other languages – It’s elegant, minimal, can.
Getting started with ML ML is a functional programming language. ML is statically typed: The types of literals, values, expressions and functions in a.
ML: a quasi-functional language with strong typing Conventional syntax: - val x = 5; (*user input *) val x = 5: int (*system response*) - fun len lis =
Cs7100(Prasad)L11Clos1 Closures and Streams. Contemporary Interest in Closures The concept of closures was developed in the 1960s and was first fully.
Clojure 3 Recursion, Higher-order-functions 27-Aug-15.
Chapter 2 Control. "The Practice of Computing Using Python", Punch & Enbody, Copyright © 2013 Pearson Education, Inc. Repetition, quick overview.
Clojure “Lisp on the JVM”. 2 Versions of LISP Lisp is an old language with many variants LISP is an acronym for List Processing language Invented by John.
1 Lisp Functions –Built-in functions –Defining functions –Function Evaluation and Special Forms defun, if Control statements –Conditional if, cond –Repetition.
Functional Programming in Scheme and Lisp. Overview In a functional programming language, functions are first class objects. You can create them, put.
Functional Programming and Lisp. Overview In a functional programming language, functions are first class objects. In a functional programming language,
Solving N-Queens in Clojure
Clojure 4 Sequences 20-Oct-15. Clojure errors (NO_SOURCE_FILE:12) Useless--just means you’re running from the REPL shell java.lang.Exception: EOF while.
Practice session #6: 1. Sequence operations 2. Partial evaluation with currying 3. Lazy-lists.
Clojure 2 Feb 7,
Feb 7, 2015 Thinking in Clojure. Jumping in We’ll quickly go through Clojure’s data types, some basic functions, and basic syntax Then we’ll get to the.
PROGRAMMING LANGUAGES: PROLOG, CLOJURE, F# Jared Wheeler.
Why Clojure? Adrian Miron. Using Java since Found both on a CD from Professionally (getting payed :-) since 2001 Back then I knew nothing.
Java iteration statements ● Iteration statements are statements which appear in the source code only once, but it execute many times. ● Such kind of statements.
Clojure “Lisp Reloaded”. 2 Versions of LISP Lisp is an old language with many variants LISP is an acronym for List Processing language Lisp is alive and.
Milos Hauskrecht (PDF) Hieu D. Vu (PPT) LISP PROGARMMING LANGUAGE.
Basic Introduction to Lisp
A Different Solution  alternatively we can use the following algorithm: 1. if n == 0 done, otherwise I. print the string once II. print the string (n.
1 FP Foundations, Scheme In Text: Chapter Chapter 14: FP Foundations, Scheme Mathematical Functions Def: A mathematical function is a mapping of.
Clojure Macros. Homoiconicity All versions of Lisp, including Clojure, are homoiconic This means that there is no difference between the form of the data.
Artificial Intelligence and Lisp Lecture 6 LiU Course TDDC65 Autumn Semester,
Lets and Loops Tail Recursion.
Clojure “Lisp Reloaded”.
Introduction to Higher Order (Functional Programming) (Python) part 2
ML: a quasi-functional language with strong typing
6.001 SICP Variations on a Scheme
PPL Lazy Lists.
CSE 341 Lecture 5 efficiency issues; tail recursion; print
Lists in Lisp and Scheme
Closures and Streams cs784(Prasad) L11Clos
Mathematical Induction Recursion
Important Concepts from Clojure
Important Concepts from Clojure
Streams Sections 3.5.1,3.5.2 Pages
Clojure “Lisp Reloaded”.
Thinking in Clojure 23-Nov-18.
Clojure to Haskell (It’s mostly syntax).
Clojure 4 Sequences 27-Nov-18.
Lecture 18 Infinite Streams and
FP Foundations, Scheme In Text: Chapter 14.
Functions and Macros.
Lecture 18.
Thinking in Clojure 1-Jan-19.
Thinking in Clojure 1-Jan-19.
Square root Prime factorization
Python Tutorial for C Programmer Boontee Kruatrachue Kritawan Siriboon
6.001 SICP Streams – the lazy way
Streams, Delayed Evaluation and a Normal Order Interpreter
Clojure “Lisp Reloaded”.
Clojure “Lisp Reloaded”.
Clojure Macros.
Recursion, Higher-order-functions
Announcements Quiz 5 HW6 due October 23
Important Concepts from Clojure
Abstraction and Repetition
Clojure 2 22-Apr-19.
Closures and Streams cs7100(Prasad) L11Clos
To understand recursion, one must first understand recursion.
Clojure 3 1-Jun-19.
Thinking in Clojure 8-Jun-19.
Streams Contract is the same as pairs...
Presentation transcript:

Clojure 4 Sequences 5-Dec-18

Clojure errors (NO_SOURCE_FILE:12) Useless--just means you’re running from the REPL shell java.lang.Exception: EOF while reading (test.clj:139) You have an unclosed parenthesis somewhere Use a good text editor! In jEdit, Control-A Control-I will make the error obvious user=> (map (fn[x] (x * x)) (take 10 (iterate inc 1))) java.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IFn

Sequences In Clojure, almost every collection is a sequence user=> (cons 5 [1 2 3]) (5 1 2 3) ; Not [5 1 2 3] user=> (class '(1 2 3)) clojure.lang.PersistentList user=> (class [1 2 3]) clojure.lang.LazilyPersistentVector user=> (class (cons 5 [1 2 3])) clojure.lang.Cons user=> (class (rest (cons 5 [1 2 3]))) clojure.lang.LazilyPersistentVector$ChunkedSeq Most common operations apply to all kinds of sequences If necessary, use the seq function to convert any sequence to a seq

Persistence and laziness In Functional Programming, a persistent data structure is one that is itself immutable, but can be modified to create a “new” data structure The original and the new data structure share structure to minimize copying time and wasted storage A lazy data structure is one where parts of it do not exist until they are accessed This allows you to have “infinite” data structures

range, take, and drop user=> (range 10) (0 1 2 3 4 5 6 7 8 9) user=> (take 4 (range 10 20)) (10 11 12 13) user=> (drop 4 (range 10 20)) (14 15 16 17 18 19) user=> (range 1 10) (1 2 3 4 5 6 7 8 9) user=> (take 20 (range 1 10)) (1 2 3 4 5 6 7 8 9) user=> (drop 20 (range 1 10)) () user=> (take 4 "abcdefg") (\a \b \c \d) user=> (str (take 4 "abcdefg")) "clojure.lang.LazySeq@3babc3" user=> (apply str (take 4 "abcdefg")) "abcd"

iterate iterate takes a function f and a starting value n, and lazily produces the infinite series (n, f(n), f(f(n)), f(f(f(n))), ...) ; Don’t try this! user=> (iterate inc 1) (1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ...) ; But this is okay user=> (take 5 (iterate inc 1)) (1 2 3 4 5) ; Don’t try this! user=> (drop 5 (iterate inc 1)) (6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21...) ; But this is okay user=> (take 5 (drop 1000 (iterate inc 1))) (1001 1002 1003 1004 1005)

Fun with iterate user=> (take 10 (iterate (fn [x] (* 2 x)) 2)) (2 4 8 16 32 64 128 256 512 1024) (defn collatz-1 [n] (cond (= n 1) 1 (even? n) (/ n 2) (odd? n) (inc (* 3 n)) ) ) user=> (take 5 (iterate collatz-1 7)) (7 22 11 34 17) user=> (take 25 (iterate collatz-1 7)) (7 22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1 1 1 1 1 1 1 1 1) user=> (nth (iterate collatz-1 7) 4) 17

Fibonacci numbers user=> (defn next-pair [pair] (list (second pair) (+ (first pair) (second pair)))) #'user/next-pair user=> (next-pair '(1 1)) (1 2) user=> (next-pair '(1 2)) (2 3) user=> (take 10 (iterate next-pair '(0 1))) ((0 1) (1 1) (1 2) (2 3) (3 5) (5 8) (8 13) (13 21) (21 34) (34 55)) user=> (map second (take 10 (iterate next-pair '(0 1)))) (1 1 2 3 5 8 13 21 34 55)

Prime numbers user=> (defn divides [d n] (integer? (/ n d))) #'user/divides user=> (divides 4 24) true user=> (divides 5 24) false user=> (defn prime [n] (not-any? (fn [d] (divides d n)) (range 2 (dec n)))) #'user/prime user=> (take 20 (filter prime (iterate inc 2))) (2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71) user=> (defn composite [n] (some (fn [d] (divides d n)) (range 2 (dec n)))) #'user/composite user=> (take 20 (filter composite (iterate inc 1))) (4 6 8 9 10 12 14 15 16 18 20 21 22 24 25 26 27 28 30 32)

let and letfn user=> (defn hypotenuse [a b] (let [a2 (* a a) b2 (* b b)] (Math/sqrt (+ a2 b2)) ) ) #'user/hypotenuse user=> (hypotenuse 3 4) 5.0 user=> (hypotenuse 1 1) 1.4142135623730951 user=> (defn hypotenuse [a b] (letfn [(square [n] (* n n))] (Math/sqrt (+ (square a) (square b))))) #'user/hypotenuse user=> (hypotenuse 1 1) 1.4142135623730951

Debugging with do user=> (format "%d + %d is %d\n" 3 4 7) "3 + 4 is 7\n" user=> (print (format "%d + %d is %d\n" 3 4 7)) 3 + 4 is 7 nil user=> (defn hypotenuse [a b] (letfn [(square [n] (* n n))] (do (println (format "a = %d, b = %d" a b)) (Math/sqrt (+ (square a) (square b))) ) ) ) #'user/hypotenuse user=> (hypotenuse 3 4) a = 3, b = 4 5.0

List comprehensions I for macro Usage: (for seq-exprs body-expr) List comprehension. Takes a vector of one or more binding-form/collection-expr pairs, each followed by zero or more modifiers, and yields a lazy sequence of evaluations of expr. Collections are iterated in a nested fashion, rightmost fastest, and nested coll-exprs can refer to bindings created in prior binding-forms. Supported modifiers are: :let [binding-form expr ...], :while test, :when test. user=> (take 12 (for [x (range 100000000) y (range 1000000) :while (< y x)] [x y])) ([1 0] [2 0] [2 1] [3 0] [3 1] [3 2] [4 0] [4 1] [4 2] [4 3] [5 0] [5 1]) Source: http://clojure.github.com/clojure/clojure.core-api.html#clojure.core/for

List comprehensions II user=> (map (fn[x] (* x x)) (take 10 (iterate inc 1))) (1 4 9 16 25 36 49 64 81 100) user=> (for [x (take 10 (iterate inc 1))] (* x x)) (1 4 9 16 25 36 49 64 81 100) user=> (take 10 (for [x (iterate inc 1)] (* x x))) (1 4 9 16 25 36 49 64 81 100) user=> (for [x (iterate inc 1) :while (< x 11)] (* x x)) (1 4 9 16 25 36 49 64 81 100) user=> (for [x (range 1 11)] (* x x)) (1 4 9 16 25 36 49 64 81 100)

List comprehensions III user=> (for [x (range 1 11) :when (even? x)] (* x x)) (4 16 36 64 100) user=> (take 10 (for [x (iterate inc 1) :when (even? x)] (* x x))) (4 16 36 64 100 144 196 256 324 400) ; Don't do this: user=> (for [x (iterate inc 1) :when (even? x)] (* x x)) (4 16 36 64 100 144 196 256 324 400 484 576 676 784 ... user=> (for [x "abcde" y [1 2]] [x y]) ([\a 1] [\a 2] [\b 1] [\b 2] [\c 1] [\c 2] [\d 1] [\d 2] [\e 1] [\e 2]) user=> (for [word ["the" "quick" "brown" "fox" "jumps"]] (format "Word: %s" word) ) ("Word: the" "Word: quick" "Word: brown" "Word: fox" "Word: jumps")

Partial functions (partial f arg1 arg2 arg3 & more) Takes a function f and fewer than the normal arguments to f, and returns a fn that takes a variable number of additional args. When called, the returned function calls f with args + additional args. user=> (def hundred-times (partial * 100)) #'user/hundred-times user=> (hundred-times 5) 500

Prime, revisited user=> (defn prime [n] (not-any? (fn [d] (divides d n)) (range 2 (dec n)))) #'user/prime user=> (defn divisible [n d] (integer? (/ n d))) #'user/divisible user=> (divisible 24 3) true user=> (divisible 24 5) false user=> (defn prime [n] (not-any? (partial divisible n) (range 2 (dec n)))) #'user/prime user=> (prime 21) false user=> (prime 19) true

Member user=> (defn member [e coll] (cond (empty? coll) false (= e (first coll)) true :else (member e (rest coll)) ) ) #'user/member user=> (member 5 (range 1 10)) true user=> (member 5 (range 10 20)) false

Member, revisited user=> (some (partial = 5) (range 1 10)) true user=> (some (partial = 5) (range 10 20)) nil user=> (defn member [e coll] (some (partial = e) coll)) #'user/member user=> (member 5 (range 1 10)) true user=> (member 5 (range 10 20)) nil

Avoiding recursion Java is an object-oriented language You have a lot of classes available to you You should not write your own Stack class! Clojure is a very recursive language There are a lot of built-in functions that are recursive You should avoid recursion if Clojure will do it for you

Zip user=> (zip [1 2 3 4] [:a :b :c]) ((1 :a) (2 :b) (3 :c)) (defn zip [a b] (if (or (empty? a) (empty? b)) () (cons (list (first a) (first b)) (zip (rest a) (rest b))) ) ) user=> (zip [1 2 3 4] [:a :b :c]) ((1 :a) (2 :b) (3 :c)) user=> (zip '(1 2 3 4) '(:a :b :c)) ((1 :a) (2 :b) (3 :c)) user=> (def zip4 (partial zip [1 2 3 4])) #'user/zip4 user=> (zip4 "abcde") ((1 \a) (2 \b) (3 \c) (4 \d))

Best reference http://clojure.github.com/clojure/clojure.core-api.html

The End