Skip to content

Commit

Permalink
Cleaning up names and places lab. Updating todo
Browse files Browse the repository at this point in the history
  • Loading branch information
abedra committed May 2, 2011
1 parent 30a24d9 commit 539009b
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 51 deletions.
95 changes: 53 additions & 42 deletions src/labs/names_and_places.clj
@@ -1,19 +1,13 @@
(ns ^{:skip-wiki true} labs.names-and-places (ns ^{:skip-wiki true}
(:use clojure.contrib.math labs.names-and-places
clojure.contrib.with-ns (:use [labrepl.util :only (c code repl-code)]
labrepl.util [solutions.dialect :only (canadianize)]
solutions.dialect) [clojure.contrib.with-ns :only (with-ns)]
(:require [clojure.contrib.math :as m]) clojure.contrib.math)
(:import [java.util Date Random])) (:require [clojure.contrib.math :as m])
(:import [java.util Date Random]))


(System/getProperties) (defn overview []

(defn cool
[])


(defn overview
[]
[[:h3 "Overview"] [[:h3 "Overview"]
[:p "In this lab you will learn to manage Clojure namespaces and Java packages. In short:" [:p "In this lab you will learn to manage Clojure namespaces and Java packages. In short:"
[:ul [:ul
Expand All @@ -22,8 +16,7 @@
[:li "use " [:code "use"] " to load and refer all in one step"] [:li "use " [:code "use"] " to load and refer all in one step"]
[:li "use " [:code "import"] " to refer to Java classes in the current namespace"]]]]) [:li "use " [:code "import"] " to refer to Java classes in the current namespace"]]]])


(defn require-section (defn require-section []
[]
[[:h3 "Require"] [[:h3 "Require"]
[:ol [:ol
[:li "You can load the code for any clojure library with " [:li "You can load the code for any clojure library with "
Expand All @@ -34,18 +27,20 @@
(code (dir clojure.contrib.math))] (code (dir clojure.contrib.math))]
[:li "Show using " [:code "lcm"] " to calculate the least common multiple:" [:li "Show using " [:code "lcm"] " to calculate the least common multiple:"
(repl-code (clojure.contrib.math/lcm 11 41))] (repl-code (clojure.contrib.math/lcm 11 41))]
[:li "Writing out the namespace prefix on every function call is a pain, so you can specify a shorter alias using " [:code "as"] ":" [:li "Writing out the namespace prefix on every function call is a pain, so you can specify a shorter alias using "
[:code "as"] ":"
(code (require '[clojure.contrib.math :as m]))] (code (require '[clojure.contrib.math :as m]))]
[:li "Calling the shorter form is much easier:" [:li "Calling the shorter form is much easier:"
(repl-code (m/lcm 120 1000))] (repl-code (m/lcm 120 1000))]
[:li "You can see all the loaded namespaces with" [:li "You can see all the loaded namespaces with"
(code (all-ns))]]]) (code (all-ns))]]])


(defn refer-and-use (defn refer-and-use []
[]
[[:h3 "Refer and Use"] [[:h3 "Refer and Use"]
[:ol [:ol
[:li "It would be even easier to use a function with no namespace prefix at all. You can do this by " [:i "referring"] " to the name, which makes a reference to the name in the current namespace:" [:li "It would be even easier to use a function with no namespace prefix at all. You
can do this by " [:i "referring"] " to the name, which makes a
reference to the name in the current namespace:"
(code (refer 'clojure.contrib.math))] (code (refer 'clojure.contrib.math))]
[:li "Now you can call " [:code "lcm"] " directly:" [:li "Now you can call " [:code "lcm"] " directly:"
(repl-code (lcm 16 30))] (repl-code (lcm 16 30))]
Expand All @@ -57,10 +52,14 @@
[:li "it brings in more names than you need, which can lead to name collisions"]] [:li "it brings in more names than you need, which can lead to name collisions"]]
"Instead, use the following style to specify only those names you want:" "Instead, use the following style to specify only those names you want:"
(code (use '[clojure.contrib.math :only (lcm)])) (code (use '[clojure.contrib.math :only (lcm)]))
"The " [:code ":only"] " option is available on all the namespace management forms. (There is also an " [:code ":exclude"] " which works as you might expect.)"] "The " [:code ":only"] " option is available on all the namespace
[:li "The variable " [:code "*ns*"] " always contains the current namespace, and you can see what names your current namespace refers to by calling" management forms. (There is also an " [:code ":exclude"] " which
works as you might expect.)"] [:li "The variable "
[:code "*ns*"] " always contains the current namespace, and you
can see what names your current namespace refers to by calling"
(code (ns-refers *ns*))] (code (ns-refers *ns*))]
[:li "The refers map is often pretty big. If you are only interested in one symbol, pass that symbol to the result of calling " [:code "ns-refers"] ": " [:li "The refers map is often pretty big. If you are only interested in one symbol, pass that symbol to
the result of calling " [:code "ns-refers"] ": "
(with-ns 'labs.names-and-places (with-ns 'labs.names-and-places
(repl-code ((ns-refers *ns*) 'dir)))]]]) (repl-code ((ns-refers *ns*) 'dir)))]]])


Expand All @@ -83,19 +82,25 @@
[:li "get the next random integer"] [:li "get the next random integer"]
[:li "cast it to a long"] [:li "cast it to a long"]
[:li "pass the long to the " [:code "Date"] " constructor"]] [:li "pass the long to the " [:code "Date"] " constructor"]]
"You don't have to write inside-out code in Clojure. The " [:code "->"] " macro takes its first form, and passes it as the first argument to its next form. The result then becomes the first argument of the next form, and so on. It is easier to read than to describe:" "You don't have to write inside-out code in Clojure. The " [:code "->"] " macro takes its
first form, and passes it as the first argument to its next form. The result then becomes
the first argument of the next form, and so on. It is easier to read than to describe:"
(repl-code (-> (Random.) (.nextInt) (long) (Date.)))]]]) (repl-code (-> (Random.) (.nextInt) (long) (Date.)))]]])


(defn load-and-reload (defn load-and-reload []
[]
[[:h3 "Load and Reload"] [[:h3 "Load and Reload"]
[:p "The REPL isn't for everything. For work you plan to keep, you will want to place your source code in a separate file. Here are the rules of thumb to remember when creating your own Clojure namespaces." [:p "The REPL isn't for everything. For work you plan to keep, you will want to place your source
code in a separate file. Here are the rules of thumb to remember when creating your own Clojure namespaces."
[:ol [:ol
[:li "Clojure namespaces (a.k.a. libraries) are equivalent to Java packages."] [:li "Clojure namespaces (a.k.a. libraries) are equivalent to Java packages."]
[:li "Clojure respects Java naming conventions for directories and files, but Lisp naming conventions for namespace names. So a Clojure namespace " [:code "com.my-app.utils"] " would live in a path named " [:code "com/my_app/utils.clj"] ". Note especially the underscore/hyphen distinction."] [:li "Clojure respects Java naming conventions for directories and files, but Lisp naming conventions
for namespace names. So a Clojure namespace " [:code "com.my-app.utils"] " would live in a path
named " [:code "com/my_app/utils.clj"] ". Note especially the underscore/hyphen distinction."]
[:li "Clojure files normally begin with a namespace declaration, e.g." [:li "Clojure files normally begin with a namespace declaration, e.g."
(code (ns com.my-app.utils))] (code (ns com.my-app.utils))]
[:li "The syntax for import/use/refer/require presented in the previous sections is for REPL use. Namespace declarations allow similar forms--similar enough to aid memory, but also different enough to confuse. The following forms at the REPL:" [:li "The syntax for import/use/refer/require presented in the previous sections is for REPL use.
Namespace declarations allow similar forms--similar enough to aid memory, but also different
enough to confuse. The following forms at the REPL:"
(code (use 'foo.bar) (code (use 'foo.bar)
(require 'baz.quux) (require 'baz.quux)
(import '[java.util Date Random])) (import '[java.util Date Random]))
Expand All @@ -105,35 +110,42 @@
(:require baz.quux) (:require baz.quux)
(:import [java.util Date Random]))) (:import [java.util Date Random])))
" Symbols become keywords, and quoting is no longer required."] " Symbols become keywords, and quoting is no longer required."]
[:li "At the time of this writing, the error messages for doing it wrong with namespaces are, well, opaque. Be careful."]]] [:li "At the time of this writing, the error messages for doing it wrong with namespaces are, well,
[:p "Now let's try creating a source code file. We aren't going to bother with explicit compilation for now. Clojure will automatically (and quickly) compile source code files on the classpath. Instead, we can just add Clojure (.clj) files to the " [:code "src"] " directory." opaque. Be careful."]]]
[:p "Now let's try creating a source code file. We aren't going to bother with explicit compilation
for now. Clojure will automatically (and quickly) compile source code files on the classpath.
Instead, we can just add Clojure (.clj) files to the " [:code "src"] " directory."
[:ol [:ol
[:li "Create a file named " [:code "student/dialect.clj"] " in the " [:code "src"] " directory, with the appropriate namespace declaration:" [:li "Create a file named " [:code "student/dialect.clj"] " in the " [:code "src"] " directory,
with the appropriate namespace declaration:"
(code (ns student.dialect))] (code (ns student.dialect))]
[:li "Now, implement a simple " [:code "canadianize"] " function that takes a string, and appends " [:code ", eh?"] [:li "Now, implement a simple " [:code "canadianize"] " function that takes a string, and appends "
[:code ", eh?"]
(code (defn canadianize (code (defn canadianize
[sentence] [sentence]
(str sentence ", eh")))] (str sentence ", eh")))]
[:li "From your REPL, use the new namespace:" [:li "From your REPL, use the new namespace:"
(code (use 'student.dialect))] (code (use 'student.dialect))]
[:li "Now try it out." [:li "Now try it out."
(let [canadianize (let [canadianize #(str % ", eh")]
#(str % ", eh")]
(repl-code (canadianize "Hello, world.")))] (repl-code (canadianize "Hello, world.")))]
[:li "Oops! We need to trim the period off the end of the input. Fortunately, " [:code "clojure.contrib.str-utils2"] " provides " [:code "chop"] ". Go back to " [:code "student/dialect.clj"] " and add require in " [:code "clojure.contrib.str-utils2"] ": " [:li "Oops! We need to trim the period off the end of the input. Fortunately, "
[:code "clojure.contrib.str-utils2"] " provides " [:code "chop"] ". Go back to "
[:code "student/dialect.clj"] " and add require in " [:code "clojure.contrib.str-utils2"] ": "
(code (ns student.dialect (code (ns student.dialect
(:require [clojure.contrib.str-utils2 :as s])))] (:require [clojure.contrib.str-utils2 :as s])))]
[:li "Now, update " [:code "canadianize"] " to use " [:code "chop"] ": " [:li "Now, update " [:code "canadianize"] " to use " [:code "chop"] ": "
(code (defn canadianize (code (defn canadianize
[sentence] [sentence]
(str (s/chop sentence) ", eh?")))] (str (s/chop sentence) ", eh?")))]
[:li "If you simply retry calling " [:code "canadianize"] " from the repl, you will not see your new change, because the code was already loaded. However, you can use namespace forms with " [:code "reload"] " ( or " [:code "reload-all"] ") to reload a namespace (and its dependencies)." [:li "If you simply retry calling " [:code "canadianize"] " from the repl, you will not see your
new change, because the code was already loaded. However, you can use namespace forms with "
[:code "reload"] " ( or " [:code "reload-all"] ") to reload a namespace (and its dependencies)."
(code (use :reload 'student.dialect))] (code (use :reload 'student.dialect))]
[:li "Now you should see the new version of " (c canadianize) ": " [:li "Now you should see the new version of " (c canadianize) ": "
(repl-code (canadianize "Hello, world."))]]]]) (repl-code (canadianize "Hello, world."))]]]])


(defn bonus (defn bonus []
[]
[[:h3 "Bonus"] [[:h3 "Bonus"]
[:ol [:ol
[:li "Canadianize was too easy. Implement " [:code "pig-latinize"] "."] [:li "Canadianize was too easy. Implement " [:code "pig-latinize"] "."]
Expand All @@ -146,5 +158,4 @@
(refer-and-use) (refer-and-use)
(import-section) (import-section)
(load-and-reload) (load-and-reload)
(bonus))) (bonus)))

18 changes: 9 additions & 9 deletions todo.org
@@ -1,10 +1,10 @@
#+TODO: MAYBE TODO IN-PROGRESS REVIEW DONE #+TODO: MAYBE TODO IN-PROGRESS REVIEW DONE
* TODO At the top of every lab, add a link back to the home page * Names and Places [0/2]
* TODO At the bottom of every lab, add a link back to the top ** TODO Substitute c.c.math for something in core
* TODO At the bottom of every lab, add a link back to the home page ** TODO Is c.c.with-ns necessary or does it need to be moved into a library
* TODO At the bottom of every lab, add a link to the next lab if applicable * Misc [0/5]
* TODO At the bottom of every lab, add a link to the previous lab if applicable ** TODO At the bottom of every lab, add a link back to the top
* MAYBE Create a wiki that has a page of instructions for each editor versus everything contained in the README ** TODO At the bottom of every lab, add a link back to the home page

** TODO At the bottom of every lab, add a link to the next lab if applicable
* MAYBE Update to latest clojure version (currently 1.3.0-alpha6) ** TODO At the bottom of every lab, add a link to the previous lab if applicable
* MAYBE Remove mini-browser lab (should it be it's own project?) ** TODO Create a wiki that has a page of instructions for each editor versus everything contained in the README

0 comments on commit 539009b

Please sign in to comment.