ick 0.2.4 → 0.3.0
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/History.txt +2 -0
- data/Manifest.txt +3 -1
- data/config/hoe.rb +3 -1
- data/lib/ick.rb +3 -1
- data/lib/ick/letn.rb +52 -0
- data/lib/ick/sugar.rb +2 -2
- data/lib/ick/syntax.rb +16 -0
- data/lib/ick/version.rb +2 -2
- data/test/test_letn.rb +17 -0
- data/website/180seconds.html +1 -1
- data/website/index.html +18 -5
- data/website/index.txt +13 -2
- data/website/inside.html +47 -2
- data/website/inside.txt +35 -0
- metadata +16 -6
- data/test/test_not.rb +0 -5
data/History.txt
CHANGED
data/Manifest.txt
CHANGED
@@ -10,7 +10,9 @@ lib/ick/advisor.rb
|
|
10
10
|
lib/ick/base.rb
|
11
11
|
lib/ick/bizarro.rb
|
12
12
|
lib/ick/guard.rb
|
13
|
+
lib/ick/letn.rb
|
13
14
|
lib/ick/sugar.rb
|
15
|
+
lib/ick/syntax.rb
|
14
16
|
lib/ick/tee.rb
|
15
17
|
lib/ick/version.rb
|
16
18
|
lib/ick/wrap.rb
|
@@ -26,7 +28,7 @@ test/test_180_seconds.rb
|
|
26
28
|
test/test_advisor.rb
|
27
29
|
test/test_helper.rb
|
28
30
|
test/test_ick.rb
|
29
|
-
test/
|
31
|
+
test/test_letn.rb
|
30
32
|
website/180seconds.html
|
31
33
|
website/180seconds.txt
|
32
34
|
website/index.html
|
data/config/hoe.rb
CHANGED
@@ -58,7 +58,9 @@ hoe = Hoe.new(GEM_NAME, VERS) do |p|
|
|
58
58
|
|
59
59
|
# == Optional
|
60
60
|
p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
|
61
|
-
|
61
|
+
p.extra_deps = [
|
62
|
+
['ruby2ruby', '>= 1.1.8']
|
63
|
+
] # An array of rubygem dependencies [name, version], e.g. [ ['active_support', '>= 1.3.1'] ]
|
62
64
|
|
63
65
|
#p.spec_extras = {} # A hash of extra values to set in the gemspec.
|
64
66
|
|
data/lib/ick.rb
CHANGED
data/lib/ick/letn.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'ruby2ruby'
|
3
|
+
|
4
|
+
module Ick
|
5
|
+
|
6
|
+
module LetnLambda
|
7
|
+
|
8
|
+
def letn_lambda(names_to_values, proc)
|
9
|
+
sorted_names = (names_to_values || {}).keys.map { |name| name.to_s }.sort
|
10
|
+
letn_body = <<LETN_BODY
|
11
|
+
lambda { |#{sorted_names.join(', ')}|
|
12
|
+
#{proc.to_ruby[/^proc \{(.*)\}$/m, 1]}
|
13
|
+
}
|
14
|
+
LETN_BODY
|
15
|
+
Kernel.eval(letn_body, proc.binding)
|
16
|
+
end
|
17
|
+
|
18
|
+
def rewritten(names_to_values, proc)
|
19
|
+
sorted_symbols = (names_to_values || {}).keys.map { |name| name.to_s }.sort.map { |name| name.to_sym }
|
20
|
+
lambda { |names_to_values|
|
21
|
+
letn_lambda(names_to_values, proc).call(*sorted_symbols.map { |sym| names_to_values[sym] })
|
22
|
+
}
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
# naïve implementation
|
28
|
+
class Letn < Syntax
|
29
|
+
|
30
|
+
include LetnLambda
|
31
|
+
|
32
|
+
def rewrite(names_to_values, proc)
|
33
|
+
rewritten(names_to_values, proc)
|
34
|
+
end
|
35
|
+
|
36
|
+
evaluates_in_calling_environment and returns_result
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
class Cletn < Letn
|
41
|
+
|
42
|
+
include LetnLambda
|
43
|
+
|
44
|
+
def rewrite(names_to_values, proc)
|
45
|
+
@lambda ||= rewritten(names_to_values, proc)
|
46
|
+
end
|
47
|
+
|
48
|
+
evaluates_in_calling_environment and returns_result
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
data/lib/ick/sugar.rb
CHANGED
data/lib/ick/syntax.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
module Ick
|
2
|
+
|
3
|
+
class Syntax < Base
|
4
|
+
|
5
|
+
def rewrite(value, proc)
|
6
|
+
raise 'implemented by subclass or by calling meta-method!'
|
7
|
+
end
|
8
|
+
|
9
|
+
def invoke(value = nil, &proc)
|
10
|
+
rewritten_proc = rewrite(value, proc)
|
11
|
+
super(value, &rewritten_proc)
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
data/lib/ick/version.rb
CHANGED
data/test/test_letn.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper.rb'
|
2
|
+
|
3
|
+
class TestLetn < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def test_empty_body
|
6
|
+
assert_nil letn(:foo => 'bar') { }
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_one_parameter
|
10
|
+
assert_equal('expected', letn(:foo => 'expected') { foo })
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_two_parameters
|
14
|
+
assert_equal(3, letn(:one => 1, :two => 2) { one + two })
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
data/website/180seconds.html
CHANGED
@@ -33,7 +33,7 @@
|
|
33
33
|
<h1>Ick in 180 seconds or less</h1>
|
34
34
|
<div id="version" class="clickable" onclick='document.location = "http://rubyforge.org/projects/ick"; return false'>
|
35
35
|
<p>Get Version</p>
|
36
|
-
<a href="http://rubyforge.org/projects/ick" class="numbers">0.
|
36
|
+
<a href="http://rubyforge.org/projects/ick" class="numbers">0.3.0</a>
|
37
37
|
</div>
|
38
38
|
<h2>Transforming your code</h2>
|
39
39
|
|
data/website/index.html
CHANGED
@@ -33,7 +33,7 @@
|
|
33
33
|
<h1>Invocation Construction Kit</h1>
|
34
34
|
<div id="version" class="clickable" onclick='document.location = "http://rubyforge.org/projects/ick"; return false'>
|
35
35
|
<p>Get Version</p>
|
36
|
-
<a href="http://rubyforge.org/projects/ick" class="numbers">0.
|
36
|
+
<a href="http://rubyforge.org/projects/ick" class="numbers">0.3.0</a>
|
37
37
|
</div>
|
38
38
|
<h1>→ ‘ick’</h1>
|
39
39
|
|
@@ -60,9 +60,6 @@
|
|
60
60
|
|
61
61
|
<pre>sudo gem install ick</pre>
|
62
62
|
|
63
|
-
<p>You can also see <a href="180seconds.html">Ick in 180 seconds or less</a></p>
|
64
|
-
|
65
|
-
|
66
63
|
<h2>Block Structured Ruby</h2>
|
67
64
|
|
68
65
|
|
@@ -146,6 +143,22 @@
|
|
146
143
|
</pre></p>
|
147
144
|
|
148
145
|
|
146
|
+
<h2>New in Version 0.3!</h2>
|
147
|
+
|
148
|
+
|
149
|
+
<p>Ick version 0.3 includes an experiemental form of let, <code>letn</code>, that allows you to bind multiple variables:</p>
|
150
|
+
|
151
|
+
|
152
|
+
<p><pre class='syntax'>
|
153
|
+
<span class="ident">letn</span><span class="punct">(</span>
|
154
|
+
<span class="symbol">:person</span> <span class="punct">=></span> <span class="constant">Person</span><span class="punct">.</span><span class="ident">find</span><span class="punct">(</span><span class="symbol">:first</span><span class="punct">,</span> <span class="punct">...),</span>
|
155
|
+
<span class="symbol">:place</span> <span class="punct">=></span> <span class="constant">City</span><span class="punct">.</span><span class="ident">select</span> <span class="punct">{</span> <span class="punct">...</span> <span class="punct">},</span>
|
156
|
+
<span class="symbol">:thing</span> <span class="punct">=></span> <span class="punct">%w(</span><span class="string">ever loving blue eyed</span><span class="punct">))</span> <span class="punct">{</span>
|
157
|
+
<span class="punct">"</span><span class="string"><span class="expr">#{person.name}</span> lives in <span class="expr">#{place}</span> where he is known as the '<span class="expr">#{thing}</span> thing.'</span><span class="punct">"</span>
|
158
|
+
<span class="punct">}</span>
|
159
|
+
</pre></p>
|
160
|
+
|
161
|
+
|
149
162
|
<p>The Object#andand-style syntax is most useful when you’re just using it for a single method invocation, such as:</p>
|
150
163
|
|
151
164
|
|
@@ -246,7 +259,7 @@
|
|
246
259
|
|
247
260
|
<p>Comments are welcome. Send an email to <a href="mailto:raganwald+rubyforge@gmail.com">Reginald Braithwaite</a>. And you can always visit <a href="http://weblog.raganwald.com/">weblog.raganwald.com</a> to see what’s cooking.</p>
|
248
261
|
<p class="coda">
|
249
|
-
<a href="http://weblog.raganwald.com/">Reginald Braithwaite</a>,
|
262
|
+
<a href="http://weblog.raganwald.com/">Reginald Braithwaite</a>, 9th May 2008<br>
|
250
263
|
Theme extended from <a href="http://rb2js.rubyforge.org/">Paul Battley</a>
|
251
264
|
</p>
|
252
265
|
</div>
|
data/website/index.txt
CHANGED
@@ -18,8 +18,6 @@ h2. Getting Started
|
|
18
18
|
|
19
19
|
<pre>sudo gem install ick</pre>
|
20
20
|
|
21
|
-
You can also see "Ick in 180 seconds or less":180seconds.html
|
22
|
-
|
23
21
|
h2. Block Structured Ruby
|
24
22
|
|
25
23
|
Although Ruby borrows many of its features from Lisp and its syntax from Algol, it does not have block-local variables. In other words, if you declare a variable anywhere inside of a method, that variable is visible everywhere in that method. This is a problem, because it encourages writing methods where the instance variables create lot of dependencies between different expressions. Those methods can be hard to understand and refactor.
|
@@ -83,6 +81,19 @@ maybe(Person.find(:first, ...)) { |p|
|
|
83
81
|
}
|
84
82
|
</pre>
|
85
83
|
|
84
|
+
h2. New in Version 0.3!
|
85
|
+
|
86
|
+
Ick version 0.3 includes an experiemental form of let, @letn@, that allows you to bind multiple variables:
|
87
|
+
|
88
|
+
<pre syntax="ruby">
|
89
|
+
letn(
|
90
|
+
:person => Person.find(:first, ...),
|
91
|
+
:place => City.select { ... },
|
92
|
+
:thing => %w(ever loving blue eyed)) {
|
93
|
+
"#{person.name} lives in #{place} where he is known as the '#{thing} thing.'"
|
94
|
+
}
|
95
|
+
</pre>
|
96
|
+
|
86
97
|
The Object#andand-style syntax is most useful when you're just using it for a single method invocation, such as:
|
87
98
|
|
88
99
|
<pre syntax="ruby">
|
data/website/inside.html
CHANGED
@@ -33,7 +33,7 @@
|
|
33
33
|
<h1>Inside the Invocation Construction Kit</h1>
|
34
34
|
<div id="version" class="clickable" onclick='document.location = "http://rubyforge.org/projects/ick"; return false'>
|
35
35
|
<p>Get Version</p>
|
36
|
-
<a href="http://rubyforge.org/projects/ick" class="numbers">0.
|
36
|
+
<a href="http://rubyforge.org/projects/ick" class="numbers">0.3.0</a>
|
37
37
|
</div>
|
38
38
|
<h2>More about the four block structures</h2>
|
39
39
|
|
@@ -98,6 +98,51 @@
|
|
98
98
|
<p>(The four methods were inspired by <a href="http://blog.rubyenrails.nl/articles/2008/02/18/our-daily-method-10-object-r-rs-ds-s">Michiel de Mare’s</a> post on the same subject, although Ick’s nomenclature is not compatible with Michiel’s. Michiel’s #rsss, #rrss, #rsds, and #rrds are called #returning, #let, #inside, and #my in Ick.)</p>
|
99
99
|
|
100
100
|
|
101
|
+
<h3>letn</h3>
|
102
|
+
|
103
|
+
|
104
|
+
<p>Ick version 0.3 includes an experiemental form of #let, #letn, that allows you to bind multiple variables:</p>
|
105
|
+
|
106
|
+
|
107
|
+
<p><pre class='syntax'>
|
108
|
+
<span class="ident">letn</span><span class="punct">(</span>
|
109
|
+
<span class="symbol">:person</span> <span class="punct">=></span> <span class="constant">Person</span><span class="punct">.</span><span class="ident">find</span><span class="punct">(</span><span class="symbol">:first</span><span class="punct">,</span> <span class="punct">...),</span>
|
110
|
+
<span class="symbol">:place</span> <span class="punct">=></span> <span class="constant">City</span><span class="punct">.</span><span class="ident">select</span> <span class="punct">{</span> <span class="punct">...</span> <span class="punct">},</span>
|
111
|
+
<span class="symbol">:thing</span> <span class="punct">=></span> <span class="punct">%w(</span><span class="string">ever loving blue eyed</span><span class="punct">))</span> <span class="punct">{</span>
|
112
|
+
<span class="punct">"</span><span class="string"><span class="expr">#{person.name}</span> lives in <span class="expr">#{place}</span> where he is known as the '<span class="expr">#{thing}</span> thing.'</span><span class="punct">"</span>
|
113
|
+
<span class="punct">}</span>
|
114
|
+
</pre></p>
|
115
|
+
|
116
|
+
|
117
|
+
<p>You must have the <a href="http://seattlerb.rubyforge.org/ruby2ruby/">ruby2ruby gem</a> installed to use #letn. You know the drill:</p>
|
118
|
+
|
119
|
+
|
120
|
+
<pre>sudo gem install ruby2ruby</pre>
|
121
|
+
|
122
|
+
<p>Like #let, #letn <em>evaluates_in_value_environment</em> and <em>returns_result</em>. You can roll your own variations if you want something else. If you’re familiar with Lisp, #letn is a lot like Lisp’s simplest let macro. But not like letrec or let*. If you don’t know the difference, then #letn will not suprise you. Basically, the binding of values to names works a lot like you would expect a hash to behave.</p>
|
123
|
+
|
124
|
+
|
125
|
+
<p>For example, if I wrote:</p>
|
126
|
+
|
127
|
+
|
128
|
+
<p><pre class='syntax'>
|
129
|
+
<span class="ident">a</span> <span class="punct">=</span> <span class="constant">nil</span>
|
130
|
+
<span class="ident">a</span> <span class="punct">=</span> <span class="punct">{</span> <span class="symbol">:foo</span> <span class="punct">=></span> <span class="ident">call_something_else</span><span class="punct">(),</span> <span class="symbol">:bash</span> <span class="punct">=></span> <span class="ident">a</span><span class="punct">[</span><span class="symbol">:foo</span><span class="punct">]</span> <span class="punct">}</span>
|
131
|
+
</pre></p>
|
132
|
+
|
133
|
+
|
134
|
+
<p>You would consider this bad code, wouldn’t you? There’s no expectation that the espressions are evaluated in any particular order. It’s the same with #letn. This is probably a bad idea:</p>
|
135
|
+
|
136
|
+
|
137
|
+
<p><pre class='syntax'>
|
138
|
+
<span class="ident">foo</span> <span class="punct">=</span> <span class="constant">nil</span>
|
139
|
+
<span class="ident">letn</span><span class="punct">(</span><span class="symbol">:foo</span> <span class="punct">=></span> <span class="ident">call_something_else</span><span class="punct">(),</span> <span class="symbol">:bash</span> <span class="punct">=></span> <span class="ident">foo</span><span class="punct">)</span> <span class="punct">{</span> <span class="punct">...</span> <span class="punct">}</span>
|
140
|
+
</pre></p>
|
141
|
+
|
142
|
+
|
143
|
+
<p><code>bash</code> is not going to be bound to the return value of <code>call_something_else</code>, it’s going to be bound to nil. The variables you bind are only visible inside the block.</p>
|
144
|
+
|
145
|
+
|
101
146
|
<h3>What about #try and #maybe?</h3>
|
102
147
|
|
103
148
|
|
@@ -312,7 +357,7 @@ Ick::Wrap.instance.invoke_wrapped(Person.find(:first, ...), MyWrapper, :foo, :ba
|
|
312
357
|
|
313
358
|
<p>Comments are welcome. Send an email to <a href="mailto:raganwald+rubyforge@gmail.com">Reginald Braithwaite</a>. And you can always visit <a href="http://weblog.raganwald.com/">weblog.raganwald.com</a> to see what’s cooking.</p>
|
314
359
|
<p class="coda">
|
315
|
-
<a href="http://weblog.raganwald.com/">Reginald Braithwaite</a>, 9th
|
360
|
+
<a href="http://weblog.raganwald.com/">Reginald Braithwaite</a>, 9th May 2008<br>
|
316
361
|
Theme extended from <a href="http://rb2js.rubyforge.org/">Paul Battley</a>
|
317
362
|
</p>
|
318
363
|
</div>
|
data/website/inside.txt
CHANGED
@@ -48,6 +48,41 @@ The method #inside returns the value and evaluates the block in the value's envi
|
|
48
48
|
|
49
49
|
(The four methods were inspired by "Michiel de Mare's":http://blog.rubyenrails.nl/articles/2008/02/18/our-daily-method-10-object-r-rs-ds-s post on the same subject, although Ick’s nomenclature is not compatible with Michiel’s. Michiel’s #rsss, #rrss, #rsds, and #rrds are called #returning, #let, #inside, and #my in Ick.)
|
50
50
|
|
51
|
+
h3. letn
|
52
|
+
|
53
|
+
Ick version 0.3 includes an experiemental form of #let, #letn, that allows you to bind multiple variables:
|
54
|
+
|
55
|
+
<pre syntax="ruby">
|
56
|
+
letn(
|
57
|
+
:person => Person.find(:first, ...),
|
58
|
+
:place => City.select { ... },
|
59
|
+
:thing => %w(ever loving blue eyed)) {
|
60
|
+
"#{person.name} lives in #{place} where he is known as the '#{thing} thing.'"
|
61
|
+
}
|
62
|
+
</pre>
|
63
|
+
|
64
|
+
You must have the "ruby2ruby gem":http://seattlerb.rubyforge.org/ruby2ruby/ installed to use #letn. You know the drill:
|
65
|
+
|
66
|
+
<pre>sudo gem install ruby2ruby</pre>
|
67
|
+
|
68
|
+
Like #let, #letn _evaluates_in_value_environment_ and _returns_result_. You can roll your own variations if you want something else. If you're familiar with Lisp, #letn is a lot like Lisp's simplest let macro. But not like letrec or let*. If you don't know the difference, then #letn will not suprise you. Basically, the binding of values to names works a lot like you would expect a hash to behave.
|
69
|
+
|
70
|
+
For example, if I wrote:
|
71
|
+
|
72
|
+
<pre syntax="ruby">
|
73
|
+
a = nil
|
74
|
+
a = { :foo => call_something_else(), :bash => a[:foo] }
|
75
|
+
</pre>
|
76
|
+
|
77
|
+
You would consider this bad code, wouldn't you? There's no expectation that the espressions are evaluated in any particular order. It's the same with #letn. This is probably a bad idea:
|
78
|
+
|
79
|
+
<pre syntax="ruby">
|
80
|
+
foo = nil
|
81
|
+
letn(:foo => call_something_else(), :bash => foo) { ... }
|
82
|
+
</pre>
|
83
|
+
|
84
|
+
@bash@ is not going to be bound to the return value of @call_something_else@, it's going to be bound to nil. The variables you bind are only visible inside the block.
|
85
|
+
|
51
86
|
h3. What about #try and #maybe?
|
52
87
|
|
53
88
|
The methods #try and #maybe are both implemented as _evaluates_in_calling_environment_, because that is least surprising. But when you're rolling your own, you might want to change that to make things more sugary. For example, here is a different version of #try:
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.0
|
|
3
3
|
specification_version: 1
|
4
4
|
name: ick
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.
|
7
|
-
date: 2008-
|
6
|
+
version: 0.3.0
|
7
|
+
date: 2008-05-09 00:00:00 -04:00
|
8
8
|
summary: Invocation Construction Kit
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -42,7 +42,9 @@ files:
|
|
42
42
|
- lib/ick/base.rb
|
43
43
|
- lib/ick/bizarro.rb
|
44
44
|
- lib/ick/guard.rb
|
45
|
+
- lib/ick/letn.rb
|
45
46
|
- lib/ick/sugar.rb
|
47
|
+
- lib/ick/syntax.rb
|
46
48
|
- lib/ick/tee.rb
|
47
49
|
- lib/ick/version.rb
|
48
50
|
- lib/ick/wrap.rb
|
@@ -58,7 +60,7 @@ files:
|
|
58
60
|
- test/test_advisor.rb
|
59
61
|
- test/test_helper.rb
|
60
62
|
- test/test_ick.rb
|
61
|
-
- test/
|
63
|
+
- test/test_letn.rb
|
62
64
|
- website/180seconds.html
|
63
65
|
- website/180seconds.txt
|
64
66
|
- website/index.html
|
@@ -73,7 +75,7 @@ test_files:
|
|
73
75
|
- test/test_advisor.rb
|
74
76
|
- test/test_helper.rb
|
75
77
|
- test/test_ick.rb
|
76
|
-
- test/
|
78
|
+
- test/test_letn.rb
|
77
79
|
rdoc_options:
|
78
80
|
- --main
|
79
81
|
- README.txt
|
@@ -91,5 +93,13 @@ extensions: []
|
|
91
93
|
|
92
94
|
requirements: []
|
93
95
|
|
94
|
-
dependencies:
|
95
|
-
|
96
|
+
dependencies:
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: ruby2ruby
|
99
|
+
version_requirement:
|
100
|
+
version_requirements: !ruby/object:Gem::Version::Requirement
|
101
|
+
requirements:
|
102
|
+
- - ">="
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: 1.1.8
|
105
|
+
version:
|