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.
- data/Manifest.txt +1 -0
- data/app_generators/clojure/USAGE +4 -1
- data/app_generators/clojure/clojure_generator.rb +1 -0
- data/app_generators/clojure/templates/test/learning/about_forms.clj +2 -4
- data/app_generators/clojure/templates/test/learning/about_functional_programming.clj +112 -0
- data/app_generators/clojure/templates/test/learning/about_sequences.clj +3 -8
- data/lib/shubox.rb +1 -1
- data/test/generators/test_clojure_generator.rb +1 -0
- metadata +4 -3
data/Manifest.txt
CHANGED
@@ -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
|
-
(
|
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)))))
|
data/lib/shubox.rb
CHANGED
@@ -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.
|
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.
|
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:
|
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
|