fun with vars

Download Fun With Vars

Post on 20-Jan-2015

1.777 views

Category:

Technology

2 download

Embed Size (px)

DESCRIPTION

A basic intro and exploration into Clojure's Vars... with some fun had with macros. This presentation was given during the Aug. 2009 meeting of the Bay Area Clojure Meetup (http://www.meetup.com/The-Bay-Area-Clojure-User-Group/). Thanks to Amit Rathore for help putting this together. Also, thanks to Runa.com for hosting the Meetup.

TRANSCRIPT

  • 1. FUN with VarsBay Area Clojure MeetupAug 6, 2009Kyle ObaRuna Employee #8@mudphonekyleoba@gmailTuesday, August 11, 2009

2. agenda # => ikouCLOJURE demonstration of the early stages of an online api lookup toolhow routing works in WEBBING why not start with a macro? how it turned out to be a Var problemREADER => EVALUATION => VARS in which you should remember THREE things 1. var is a special form 2. this is possible: symbol map Var binding value3. if a symbol is NOT RESOLVED to a value ON EVALUATION => BOOM! RECURTuesday, August 11, 2009 3. var = specialsym - Var - valueagenda unresolvd sym eval boom# => ikouCLOJURE demonstration of the early stages of an online api lookup toolhow routing works in WEBBING why not start with a macro? how it turned out to be a Var problemREADER => EVALUATION => VARS in which you should remember THREE things 1. var is a special form 2. this is possible: symbol map Var binding value3. if a symbol is NOT RESOLVED to a value ON EVALUATION => BOOM! RECURTuesday, August 11, 2009 4. ikouCLOJURE : routing (def routes-map {... "/doc/get" ikou-doc/get-doc"/docs/nd" ikou-doc/get-nd-doc "/docs/ns" ikou-doc/docs-for-ns"/names/ns" ikou-doc/names-for-ns ...}) Tuesday, August 11, 2009 5. ikouCLOJURE sort of demonstration Tuesday, August 11, 2009 6. ikouCLOJURE : routing (def routes-map {... "/doc/get" ikou-doc/get-doc"/docs/nd" ikou-doc/get-nd-doc "/docs/ns" ikou-doc/docs-for-ns"/names/ns" ikou-doc/names-for-ns ...}) Tuesday, August 11, 2009 7. ikouCLOJURE : routing (def routes-map {"/doc/get" ikou-doc/get-doc})FIRST TRY: a macro (why not?) (defmacro get-doc [thing]`(with-out-str(doc ~thing)))get-doc WORKS at the REPL but, it doesnt EVALUATE as part of the routes-map => java.lang.Exception: Can't take value of a macro at clojure.lang.Compiler.analyzeSymbol(Compiler.java:4684)Tuesday, August 11, 2009 8. ikouCLOJURE : to be absolutely clear about that macro thing (defmacro m-get-doc [thing]`(with-out-str(doc ~thing))) (defn get-doc-w [x](m-get-doc x)) this WONT EVALUATE it throws a java.lang.Exception: Unable to resolve var: x in this context[Thrown class clojure.lang.Compiler$CompilerException] Tuesday, August 11, 2009 9. ikouCLOJURE : to be absolutely clear that error even this WONT EVALUATE (defn bogus-doc [x] (doc x)) it throws a java.lang.Exception: Unable to resolve var: x in this context[Thrown class clojure.lang.Compiler$CompilerException] Tuesday, August 11, 2009 ask folks to remember, we got an ERROR here 10. ikouCLOJURE : unresolvable Var error why are we getting this error?java.lang.Exception: Unable to resolve var: x in this context[Thrown class clojure.lang.Compiler$CompilerException] Tuesday, August 11, 2009 11. Clojure.org: a small vocabulary lesson DATA STRUCTURES READER COMPILER EVALUATION SYMBOL VAR Tuesday, August 11, 2009 12. Clojure.org: http://clojure.org/readerCLOJURE DATA STRUCTURESClojure is a homoiconic language, which is a fancy term describing the fact that Clojure programs are represented by Clojure data structures.Clojure is dened in terms of the evaluation of data structures and not in terms of the syntax of character streams/les.That said, most Clojure programs begin life as text les, and it is the task of the reader to parse the text and produce the data structure the compiler will see. This is not merely a phase of the compiler. The reader, and the Clojure data representations, have utility on their own... WTF? AWESOME, right? Tuesday, August 11, 2009 Since its just Clojure data structures, programs can create programs Clojure programs could begin life as anything that leads to these data structures. 13. ninjasREALULTIMATEPOWER.NET Tuesday, August 11, 2009 this is why macros are possible this is why clojure (and lisps) have parens 14. Clojure.org: http://clojure.org/readerSRSLY. WHAT DID THAT MEAN?One might say the reader has syntax dened in terms of characters, and the Clojure language has syntax dened in terms of symbols, lists, vectors, maps etc.text -> READER -> clojure data structures -> COMPILER -> EVALUATION Tuesday, August 11, 2009 reader reads charaters (as forms) compiler reads clojure language as clojure data structures, which are the objects returned by the reader 15. Clojure.org: http://clojure.org/Evaluation EVALUATION Evaluation can occur in many contexts: Interactively, in the REPL On a sequence of forms read from a stream, via load or load-le Programmatically, via evaltext -> READER -> clojure data structures -> COMPILER -> EVALUATION Tuesday, August 11, 2009 16. var = specialsym - Var - value Clojure.org: http://clojure.org/Evaluationunresolvd sym eval boomEVALUATION Clojure programs are composed of expressions.Every form not handled specially by a special form or macro is considered by the compiler to be an expression, which is evaluated to yield a value......a single object is considered by the compiler, evaluated, and its result returned. If an expression needs to be compiled, it will be. There is no separate compilation step, nor any need to worry that a function you have dened is being interpreted. Clojure has no interpreter. Tuesday, August 11, 2009 THING TO REMEMBER #1: there are these special forms 17. var = special sym - Var - valueClojure.org: http://clojure.org/Evaluationunresolvd sym eval boomEVALUATIONSYMBOL Resolutionis namespace qualied? -> binding of named global varis package qualied? -> Java classelse, in order...1. is special form? -> special form stuff2. maps to class in current ns? -> Java class3. binds locally? -> value of local binding4. maps to Var? -> value of binding of the Var5. error If you remember, we were trying to gure out why we had that error... Tuesday, August 11, 2009 THING #2: if symbol maps to Var, then binding of Var is the evaluated value THING #3: if symbol is not evaluated to a value, this causes an error 18. back to the error so, we had that error... even this WONT EVALUATE(defn bogus-doc [x](doc x))it throws ajava.lang.Exception: Unable to resolve var: x in this context [Thrown class clojure.lang.Compiler$CompilerException]WHY? Tuesday, August 11, 2009 19. heres a hint doc is a macro which expands like souser> (macroexpand-1 '(doc map)) (clojure.core/print-doc (var map)) and print-doc works like this user> (print-doc #'map)-------------------------clojure.core/map([f coll] [f c1 c2] [f c1 c2 c3] [f c1 c2 c3 & colls])Returns a lazy sequence ... Tuesday, August 11, 2009 20. back to the error so, our offending fn is expands to(defn bogus-doc [x](print-doc (var x)))and it throws ajava.lang.Exception: Unable to resolve var: x in this context[Thrown class clojure.lang.Compiler$CompilerException]STILL WHY? Tuesday, August 11, 2009 21. back to the error now that we know more about symbol resolution and evaluation lets take a closer lookjava.lang.Exception: Unable to resolve var: x in this context[Thrown class clojure.lang.Compiler$CompilerException] Tuesday, August 11, 2009 so maybe the var special form in bogus-doc is causing the problem 22. var = specialsym - Var - value back to the error unresolvd sym eval boom real quick-like...what does def do?Var without binding user=> (def x) #'user/x user=> x java.lang.IllegalStateException: Var user/x is unbound.Var with binding user=> (def x 1) #'user/x user=> x 1 Tuesday, August 11, 2009 what then, is the var special form resolving x to (in bogus-doc)? 23. var = specialsym - Var - valueback to the errorunresolvd sym eval boomso, its the var special form when defn bogus-doc is evaluatedwhat does (var x) refer to?(defn bogus-doc [x] (doc x)) aka (defn bogus-doc [x] (print-doc (var x)))answer: nothingTuesday, August 11, 2009 answer: nothing hence the error 24. var = specialsym - Var - value an exampleunresolvd sym eval boom you can get my-doc to evaluate properly,if you declare y rst user> (declare y)#'user/y user> (defn my-doc [y] (doc y))#'user/my-doc but, whats this? user> (my-doc map)-------------------------user/ynil nilnil Tuesday, August 11, 2009 the doc info for map is not correct, it appears to be the doc info for user/y 25. var = specialsym - Var - valuewhat happened to y?unresolvd sym eval boomremember doc is a macro user> (macroexpand-1 '(doc lter))(clojure.core/print-doc (var lter)) var is a special formso... doc expands to (print-doc (var y)) at evaluation my-doc's print-doc argument is the Var #'user/y the "argument y" ISNT USEDTuesday, August 11, 2009 26. var = special sym - Var - valueanother example unresolvd sym eval boomanother way to say that (var y) isnt resolving to the fns arg user> (defn verbose-doc [y] (doc y) (println y))#'user/verbose-doc user> (verbose-doc map)-------------------------user/ynil nil#nil Tuesday, August 11, 2009 27. RECUR : ikouCLOJURE so, how do we x our original problem? I wanted to get the doc output for an input string. Tuesday, August 11, 2009 youve kicked that dead horse enough 28. RECUR : ikouCLOJURE this works... and you dont need a macro(defn get-doc [str-name] (with-out-str(print-doc (resolve (symbol str-name))))) Tuesday, August 11, 2009 29. var = specialsym - Var - valueRECUR : ikouCLOJUREunresolvd sym eval boomwhy not use "doc" ? doc is a macro that syntactically replacesthe form with a (var y) special form when evaluated(var y) will cause an error if it doesnt resolve to a value Tuesday, August 11, 2009 30. nally an interesting point "doc" info is just meta-data but where? on the Var, not on the object that's why print-doc takes a Var Tuesday, August 11, 2009 31. nally an example metadata sits on the varuser> (meta (var map)){:ns #, :name map, :le "clojure/core.clj", :line 1588, :arglists ([f coll] [f c1 c2] [f c1 c2 c3] [f c1 c2 c3 & colls]), :doc "Returns a lazy sequence consisting of the result of applying f to then set of rst items of each coll, followed by applying f to the setn