shubox 0.9.1 → 0.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -17,6 +17,7 @@ app_generators/clojure/templates/project.ipr
17
17
  app_generators/clojure/templates/src/repl.clj
18
18
  app_generators/clojure/templates/test/learning/about_clojure_testing.clj
19
19
  app_generators/clojure/templates/test/learning/about_forms.clj
20
+ app_generators/clojure/templates/test/learning/about_functional_programming.clj
20
21
  app_generators/clojure/templates/test/learning/about_sequences.clj
21
22
  app_generators/clojure/templates/test/test_runner.clj
22
23
  app_generators/java/USAGE
@@ -12,4 +12,7 @@ Usage:
12
12
 
13
13
  If you have IntelliJ, install the La Clojure plugin, then open the IPR file to get started with adding
14
14
  your learning tests. If you have a different IDE, follow the instructions to import your application as
15
- existing source.
15
+ existing source.
16
+
17
+ You will start off with a failing test in about_functional_programming. Review the code there and swap
18
+ (?) with the correct implementation.
@@ -32,6 +32,7 @@ class ClojureGenerator < ShuboxAppGenerator
32
32
  m.file("test/learning/about_clojure_testing.clj", "test/learning/about_clojure_testing.clj")
33
33
  m.file("test/learning/about_forms.clj", "test/learning/about_forms.clj")
34
34
  m.file("test/learning/about_sequences.clj", "test/learning/about_sequences.clj")
35
+ m.file("test/learning/about_functional_programming.clj", "test/learning/about_functional_programming.clj")
35
36
  m.file("test/test_runner.clj", "test/test_runner.clj")
36
37
  m.file("build.xml", "build.xml")
37
38
  end
@@ -7,12 +7,10 @@
7
7
  "show that ratio is a built-in type" (/ 1 2) 1/2
8
8
  "use a floating-point literal for the dividend for decimal division" (/ 1 2.0) 0.5
9
9
  "obtain the integer quotient" (quot 22 7) 3
10
- "obtain the remainder" (rem 23 7) 2
11
- ))
10
+ "obtain the remainder" (rem 23 7) 2))
12
11
 
13
12
  (deftest strings
14
13
  (are [desc expression expected] (= expression expected)
15
14
  "convert a lowercase string to uppercase" (.toUpperCase "str") "STR"
16
- "append several strings - show that nil is ignored" (str 1 nil "two") "1two"
17
- ))
15
+ "append several strings - show that nil is ignored" (str 1 nil "two") "1two"))
18
16
 
@@ -0,0 +1,112 @@
1
+ (ns learning.about-functional-programming
2
+ (:use clojure.test))
3
+
4
+ ; An example of breaking down existing code as learning tests,
5
+ ; as well as setting up a learning test that you can practice.
6
+
7
+ ; From Stu Halloway's Programming Clojure
8
+
9
+ (defn fibo []
10
+ (map first (iterate (fn [[a b]] [b (+ a b)]) [0 1])))
11
+
12
+ (deftest fibo-is-an-infinite-sequence
13
+ (are [x expected] (= x expected)
14
+ (take 7 (fibo)) '(0 1 1 2 3 5 8)
15
+ (nth (fibo) 5) 5
16
+ (rem (nth (fibo) 10000) 100000) 66875
17
+ (rem (nth (fibo) 100000) 100000) 46875
18
+ ; This one takes a few seconds
19
+ ; (rem (nth (fibo) 1000000) 1000000) 546875
20
+ ))
21
+
22
+ ; This is succinct, but not exactly intuitive if you're new to Clojure.
23
+ ; Let's break it down.
24
+
25
+ ; Basic forms: (+ a b)
26
+ (deftest addition-as-basic-form
27
+ (is (= 5 (+ 2 3))))
28
+
29
+ ; Vectors: [b (+ a b)]
30
+ (defn next-pair [[a b]]
31
+ [b (+ a b)])
32
+
33
+ (deftest seq-functions-work-on-vectors
34
+ (are [x expected] (= x expected)
35
+ (next-pair [1 2]) [2 3]
36
+ (next-pair [3 5]) [5 8]))
37
+
38
+ ; Now we can start seeing the logic of considering each fib
39
+ ; as a pair.
40
+
41
+ ; Replace additive-vector with the fn special form: (fn [[a b]] [b (+ a b)])
42
+ (deftest fn-creates-anonymous-functions
43
+ (let [next-pair-fn (fn [[a b]] [b (+ a b)])]
44
+ (are [x expected] (= x expected)
45
+ (next-pair-fn [1 2]) [2 3]
46
+ (next-pair-fn [3 5]) [5 8])))
47
+
48
+ ; we see from page 118: You can think of iterate as the infinite extension of range
49
+ ; Let's experiment:
50
+ (deftest range-is-finite
51
+ (are [x expected] (= x expected)
52
+ (range 1 10 2) '(1 3 5 7 9)
53
+ (range 0 20 5) '(0 5 10 15)))
54
+
55
+ ; iterate and lazy sequences
56
+ ; Given that this will introduce an infinite sequence, we'll need to
57
+ ; heed the advice about creating a finite view onto the infinite collection.
58
+ ; There are a few examples of such methods in our original unit test, and
59
+ ; this is a good opportunity to start experimenting with them.
60
+ (deftest iterate-over-infinite-sequences-with-lazy-seqs
61
+ (let [fib (iterate (fn [[a b]] [b (+ a b)]) [0 1])]
62
+ (are [desc x expected] (= x expected)
63
+ "" (first fib) [0 1]
64
+ "" (take 3 fib) '([0 1] [1 1] [1 2])
65
+ "nth returns the value at the index" (nth fib 3) [2 3]
66
+ )))
67
+
68
+ ; So we can now produce pairs of fibonacci numbers.
69
+ ; But we only want the first values of each pair.
70
+ ; (doc map) at the REPL tells us why we need map:
71
+ ; Returns a lazy sequence consisting of the result of applying f to the
72
+ ; set of first items of each coll...
73
+ ; let's do some simple experiments
74
+ (deftest using-map
75
+ (are [desc x expected] (= x expected)
76
+ "double the values in a range" (map (fn [n] (* 2 n)) (range 0 6)) '(0 2 4 6 8 10)
77
+ ))
78
+
79
+ ; seeing that map takes a function and applies it to each member of a sequence, it's
80
+ ; now easy to see what our original fibo function is doing.
81
+ ; Let's recap:
82
+ ; We define an anonymous function that takes two arguments, a and b, and returns b and the sum of a and b as a vector.
83
+ ; Iterate begins with the values 0 and 1 and continues forever, applying the function to each value to calculate the next.
84
+ ; This produces pairs of Fibonacci numbers.
85
+ ; Since we only want the first values of each pair, we transform the result using map by applying first to each of the pairs
86
+ ; in the sequence. This result is itself a lazy sequence, so we must use functions like take and nth to realize the sequence
87
+ ; and retrieve the values in which we're interested.
88
+ ; Given the terseness of the code and the verbiage of the English translation, we begin to see why people say Clojure is
89
+ ; so expressive!
90
+
91
+ ; In the style of Ruby koans, here's a way to start reviewing the implementation so you can practice.
92
+
93
+ ; Let's give ourselves a utility method to make the tests more readable.
94
+ (defn ? []
95
+ 0)
96
+
97
+ ; What would you write to get the following learning tests to pass?
98
+ (deftest review-session
99
+ (are [desc x expected] (= x expected)
100
+ "addition as basic form" (?) 5
101
+ "generate the sequence of odd integers from 1 to 10" (?) '(1 3 5 7 9)
102
+ "generate the factors of five less than 20" (?) '(0 5 10 15)
103
+ ))
104
+
105
+ ; Having just seen these, you probably saw right away that we need to replace our (?)'s with
106
+ ; (+ 3 2), (range 1 10 2), and (range 0 20 5). How about the definition of the fibo function? Can you write it from
107
+ ; memory? Go ahead, try...I'll wait.
108
+ ; Did you get it?
109
+ ; Now how about if you saw these tomorrow? After a week from now? A month?
110
+ ; By answering these (?)'s, you're forced to retrieve the information you've just seen.
111
+ ; It turns out that this retrieval step is a powerful learning tool.
112
+
@@ -6,19 +6,14 @@
6
6
  ; first, rest, cons on lists
7
7
  (first '(1 2 3)) 1
8
8
  (rest '(1 2 3)) '(2 3)
9
- (cons 0 '(1 2 3)) '(0 1 2 3)
10
- ))
9
+ (cons 0 '(1 2 3)) '(0 1 2 3)))
11
10
 
12
11
  (deftest seq-functions-work-on-vectors
13
12
  (are [x expected] (= x expected)
14
13
  ; first, rest, cons on vectors
15
14
  (first [1 2 3]) 1
16
15
  (rest [1 2 3]) [2 3]
17
- (cons 0 [1 2 3]) [0 1 2 3]
18
- ))
16
+ (cons 0 [1 2 3]) [0 1 2 3]))
19
17
 
20
18
  (deftest rest-and-cons-returns-a-seq-not-a-vector
21
- (are [x expected] (= x expected)
22
- ; call class on rest to prove that lists and vectors are seqs
23
- (class (rest [1 2 3])) clojure.lang.LazilyPersistentVector$ChunkedSeq
24
- ))
19
+ (is (= (rest [1 2 3]) (rest '(1 2 3)))))
@@ -5,7 +5,7 @@ $:.unshift(File.dirname(__FILE__) + '/../cleaner_generators') unless
5
5
  $:.include?(File.dirname(__FILE__) + '/../cleaner_generators') || $:.include?(File.expand_path(File.dirname(__FILE__) + '../cleaner_generators'))
6
6
 
7
7
  module Shubox
8
- VERSION = '0.9.1'
8
+ VERSION = '0.9.2'
9
9
  end
10
10
 
11
11
  require 'test_unit_cleaner/lib/test_unit_cleaner'
@@ -36,6 +36,7 @@ class TestClojureGenerator < Test::Unit::TestCase
36
36
  assert_directory_exists "test"
37
37
  assert_directory_exists "test/learning"
38
38
  assert_generated_file "test/learning/about_clojure_testing.clj"
39
+ assert_generated_file "test/learning/about_functional_programming.clj"
39
40
  assert_generated_file "test/learning/about_forms.clj"
40
41
  assert_generated_file "test/test_runner.clj"
41
42
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shubox
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.1
4
+ version: 0.9.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bobby Norton
@@ -9,8 +9,8 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-11-01 01:00:00 -05:00
13
- default_executable:
12
+ date: 2010-02-17 00:00:00 -06:00
13
+ default_executable: shubox
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: newgem
@@ -67,6 +67,7 @@ files:
67
67
  - app_generators/clojure/templates/src/repl.clj
68
68
  - app_generators/clojure/templates/test/learning/about_clojure_testing.clj
69
69
  - app_generators/clojure/templates/test/learning/about_forms.clj
70
+ - app_generators/clojure/templates/test/learning/about_functional_programming.clj
70
71
  - app_generators/clojure/templates/test/learning/about_sequences.clj
71
72
  - app_generators/clojure/templates/test/test_runner.clj
72
73
  - app_generators/java/USAGE