ick 0.2.4 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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:
|