Your SlideShare is downloading. ×
Learn a language : LISP
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×

Saving this for later?

Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime - even offline.

Text the download link to your phone

Standard text messaging rates apply

Learn a language : LISP

2,215
views

Published on

Published in: Technology, Education

0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
2,215
On Slideshare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
2
Comments
0
Likes
1
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. Learn a language: Clojureby Tijs van der StormPreliminariesInstall Eclipse, if you haven’t already. To get a “main-stream” IDE for Clojure, install theCounterClockwise plugin for Eclipse. I use it with Eclipse Indigo, but I have no idea whetherother versions will work too.The webpage for the plugin can be found here:http://code.google.com/p/counterclockwise/. Use the Eclipse help menu to install extrasoftware, add the update site: http://ccw.cgrand.net/updatesite/.Select the Clojure plugin. Next, accept, next, finish, restart Eclipse. Then File->New… selectClojure project. Finish. To create a file, right-click on the project, select New->Other->Clojure namespace. To load/start a REPL (Read-Eval-Print-Loop) for the file, right-click theeditor, and select load into REPL. Your functions are now accessible in the REPL.Some notes on the IDE: Command history is accessed through Ctrl-up and -down. In an editor, check the context menu for shortcuts to (re)load the current file.Clojure resources Main site: http://www.clojure.org Quickref of clojure.core: http://clojuredocs.org/quickref/Clojure%20Core Index of clojure.core: http://clojuredocs.org/clojure_coreExercisesWarming upType the following expression in the REPL. (print "Hello world!") (+ 1 2) (+ 1 2 3 4) * (map (fn [x] (+ x 2)) [1 2 3 4]) (def f (fn [x] (+ x 2))) (defn g [x] (+ x 2)) (map f [1 2 3 4])) (vec (map f [1 2 3 4])))
  • 2. (vec (map f [1 2 3 4]))) (reduce * [1 2 3 4]) (if (> 2 1) yes no)Quoting () 4 (+ 3 4) [Hello world!] (quote (+ 3 x)) (list + 3 x) `(list + 3 x) (let [x 3] `(+ 3 ~x)) (let [x (4 5 6)] `(+ 3 ~@x)) (let [x (4 5 6)] (concat (list + 3) x))Functional programming 1. Write the factorial function. 2. Implement the Fizz Buzz Test (see C2 http://c2.com/cgi/wiki?FizzBuzzTest). Tip: use doseq and range . 3. Write the power function using recursion. 4. Write the power function using squaring (see Wikipedia http://en.wikipedia.org/wiki/Exponentiation_by_squaring) 5. Write the power function using reduce and repeat .Macro programmingIn Clojure, a macro is defined using defmacro : (defmacro m [a1 … an] body)Here, m is the name of macro, a1 … an are the formal parameters and body is the bodyof the macro. Macros are functions that return code. How the result is created does notmatter, but it is typical to use the quasiquote (backtick, `), unquote ( ~ ) and unquote splicing( ~@ ). Note that when a macro is invoked (m e1 … en) , the argument expressions e1 …en are not evaluated. In other words, the formal parameters a1 … an of m are bound tothe code trees of e1 … en . For instance, when calling (m (+ 1 2)) , a1 is bound to (+1 2) and not to 3 .Tips for debugging macros: Use macroexpand and macroexpand-1 with a quoted macro invocation as argument to inspect what a top-level macro expands to.
  • 3. To see complete expansion of a macro, first issue (use clojure.walk) at the REPL prompt, then you can use macroexpand-all .Assert statementWrite a macro that implements an assert statement, as found in Java. The macro should becalled as follows: (assert* cond "some message")The result of assert* should be nil). If the condition cond fails (i.e., returns false ornil ) an exception should be thrown with a message containing the literal expression condand the label string.Use throw to throw an exception, which can be created as follows (Exception. "somemessage") . Use the str function to concatenate strings. NB: the failing expression shouldbe in the message. Tip: unquotes ( ~ ) can be in quotes ( )…QuizDoes assert* have to be a macro? If so why? If not, how would you implement it?AsidePractical Common Lisp devotes a chapter to writing a simple unit-test framework usingmacros: http://www.gigamonkeys.com/book/practical-building-a-unit-test-framework.htmlLetThe let construct to introduce local variables is a built-in special form in Clojure. However,it is well-known that let can be implemented as a macro: an invocation of let expandsto a function application. Write such a macro. Your version of let ( let* ) should expand asfollows: (let* [var exp] body) => ((fn [var] body) exp)To simplify the exercise, you may assume that let only binds a single variable. If this is toosimple, implement another version that supports multiple bindings.Times
  • 4. TimesWrite a macro times that takes an expression e and a number n and expands to a doform that just executes the expression n times. E.g.: (times 5 hello) => (do hello hello hello hello hello)Tip: use the splicing unquote ~@ in combination with the core function repeat . Note that repeat generates an (lazily) infinite sequence, you have to provide the number ofrepetitions.Special powerPartial evaluation is a program optimization technique that can be applied if certainarguments to a function are statically known. A traditional example is the power function.Often, the exponent argument ( n in (power x n) ) is statically known. Can we specializethe power function for a fixed n ? Partial evaluation in general is not for the faint of heart,but using macros we can do this specifically for power.The goal is to write a macro that generates the code for a power function that is specializedfor some n . Let’s call it gen-power . Now, if (gen-power 3) returns a function f , then itshould hold that (= (f x) (power x 3)) for all x .Here’s an example of what the invocation (gen-power 3) could expand to: (fn* ([x] (clojure.core/* x (clojure.core/* x (clojure.core/* x 1)))))NB: fn* is an internal form Clojure to represent functions. Note that the * function hasbeen qualified with the namespace it is defined in. In the macro you can just use the normalfn and * to generate code.TipsSplit the solution in two parts: 1. The top-level macro creates the function and calls a sub-function (gen-body x n) , where x represents the name of the parameter of the created function, and where n is the exponent. 2. The gen-body function recursively creates an expression to multiply x n times.QuizArgue why the specialized power functions produced by gen-power would/should befaster than the general power function.
  • 5. Computing derivativesCheck out this page to refresh your derivative chops: http://en.wikipedia.org/wiki/DerivativeIn this exercise, the goal is to compute the derivative of restricted, but otherwise ordinaryClojure functions. The restrictions are: Functions take only 1 argument. The body of the function can only use * , + , the formal parameter of the function, and constant numbers. You may assume both * and + only have two arguments (although Clojure supports an arbitrary number).Basically, such functions describe simple polynomials. An example is the following: (fn [x] (+ (* 3 (* x x)) (+ (* 2 x) 1))))The derivative of this function is: (fn [x] (+ (* 6 x)) 2))The exercise is to write a macro that returns and expression that computes this function.NB: this does not mean that it is syntactically the same as the derivative shown above; itshould however give the same answers for the same inputs.The macro is invoked as follows: (deriv (fn [x] (+ (* 3 (* x x)) (+ (* 2 x) 1)))))TipsSplit your solution in two parts: 1. The top-level macro that analyzes the fn argument to obtain the name of the parameter and the body expression, passes it to 2), and upon return constructs a new fn with the same parameter. 2. The helper function diff that receives and expression e and a variable name v which computes the derivative expression.Some useful functions: (number? x) : returns true if x is a number. (symbol? x) : returns true if x is a symbol.
  • 6. (first x) , (second x) : return the first resp. second elements of a collection(vector or list) x . (nth x n) : return the n -th element of a collection x . (cond c1 e1 … cn en :else e) : cascading conditional; finds the first ci thatevaluates to true and evaluates ei . If no ci is found, evaluates e .