andand 1.0.1 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt CHANGED
@@ -1,6 +1,8 @@
1
- == 1.0.1 2008-02-03
1
+ == 1.1.0 2008-02-03
2
2
 
3
3
  * 1 major enhancement:
4
4
  * Initial release
5
5
  * 2 tiny enhancement:
6
6
  * fixed specifications
7
+ * 3 minor enhancement
8
+ * tap is now a synonym for me
data/lib/andand.rb CHANGED
@@ -34,6 +34,8 @@ module AndAnd
34
34
  end
35
35
  end
36
36
 
37
+ alias :tap :me
38
+
37
39
  end
38
40
 
39
41
  end
@@ -1,8 +1,8 @@
1
1
  module Andand #:nodoc:
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 1
4
- MINOR = 0
5
- TINY = 1
4
+ MINOR = 1
5
+ TINY = 0
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  end
data/website/index.html CHANGED
@@ -5,7 +5,7 @@
5
5
  <link rel="stylesheet" href="stylesheets/screen.css" type="text/css" media="screen" />
6
6
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
7
7
  <title>
8
- andand
8
+ Object#andand
9
9
  </title>
10
10
  <script src="javascripts/rounded_corners_lite.inc.js" type="text/javascript"></script>
11
11
  <style>
@@ -30,10 +30,10 @@
30
30
  <body>
31
31
  <div id="main">
32
32
 
33
- <h1>andand</h1>
33
+ <h1>Object#andand</h1>
34
34
  <div id="version" class="clickable" onclick='document.location = "http://rubyforge.org/projects/andand"; return false'>
35
35
  <p>Get Version</p>
36
- <a href="http://rubyforge.org/projects/andand" class="numbers">1.0.1</a>
36
+ <a href="http://rubyforge.org/projects/andand" class="numbers">1.1.0</a>
37
37
  </div>
38
38
  <h1>&#x2192; &#8216;andand&#8217;</h1>
39
39
 
@@ -41,6 +41,16 @@
41
41
  <h2>What</h2>
42
42
 
43
43
 
44
+ <p><em>Object#andand</em> lets us write:</p>
45
+
46
+
47
+ <pre>
48
+ @phone = Location.find(:first, ...elided... ).andand.phone
49
+ </pre>And get a <em>guarded method invocation</em> or <em>safe navigation method</em>. This snippet performs a <code>.find</code> on the Location class, then sends <code>.phone</code> to the result <em>if the result is not nil</em>. If the result is nil, then the expression returns nil without throwing a NoMethodError.
50
+
51
+ <p>We also get an enhanced Object#tap method.</p>
52
+
53
+
44
54
  <h2>Installing</h2>
45
55
 
46
56
 
@@ -50,22 +60,67 @@
50
60
  <h2>The basics</h2>
51
61
 
52
62
 
63
+ <h3>Object#andand</h3>
64
+
65
+
66
+ <p>Ruby programmers are familiar with the two <em>guarded assignment</em> operators <code>&#38;&#38;=</code> and <code>||=</code>. The typical use for them is when you have a variable that might be nil. For example:</p>
67
+
68
+
69
+ <pre>
70
+ first_name &#38;&#38;= @first_name.trim
71
+ @phone ||= '612-777-9311'
72
+ </pre>You are trimming the first name provided it isn’t nil, and you are assigning ‘612-777-9311’ to the phone if it <em>is</em> nil (or false, but that isn’t important right now). The other day we were discussing the guards and we agreed that we wished there was a <em>guarded method invocation</em> operator. Here’s an example of when you would use it:
73
+
74
+ <pre>
75
+ @phone = Location.find(:first, ...elided... )&#38;&#38;.phone
76
+ </pre>Meaning, search the location table for the first record matching some criteria, and if you find a location, get its phone. If you don’t, get nil. (Groovy provides this exact functionality, although Groovy uses <code>?.</code> instead of <code>&#38;&#38;.</code>) However, <code>&#38;&#38;.</code> won’t work because <code>&#38;&#38;.</code> is not a real Ruby operator.
77
+
78
+ <p>Object#andand let&rsquo;s us write:</p>
79
+
80
+
81
+ <pre>
82
+ @phone = Location.find(:first, ...elided... ).andand.phone
83
+ </pre>And get the same effect as:
84
+
85
+ <pre>
86
+ @phone = -&gt;(loc){ loc &#38;&#38; loc.phone }.call(Location.find(:first, ...elided... ))
87
+ </pre>Note that because you accept any method using Ruby’s method invocation syntax, you can accept methods with parameters and/or blocks:
88
+
89
+ <pre>
90
+ list_of_lists.detect { ...elided... }.andand.inject(42) { ...elided ... }
91
+ </pre>Object#andand emphasizes syntactic regularity: the goal was to make an <code>&#38;&#38;.</code> operation that worked like <code>&#38;&#38;=</code>. <code>&#38;&#38;=</code> looks just like normal assignment, you can use any expression on the <span class="caps">RHS</span>, only the semantics are different. The andand method also works just like a normal method invocation, only the semantics are modified.
92
+
93
+ <h3>Enhanced Object#tap</h3>
94
+
95
+
96
+ <p>Ruby 1.9 introduces <a href="http://moonbase.rydia.net/mental/blog/programming/eavesdropping-on-expressions">Object#tap</a>. This library implements Object#tap for Ruby 1.8 <strong>and</strong> enhances it. As in Ruby 1.9, you can call <code>.tap</code> with a block:</p>
97
+
98
+
99
+ <pre>
100
+ blah.sort.grep( /foo/ ).tap { |xs| p xs }.map { |x| x.blah }
101
+ </pre> But like its sibling <code>.andand</code>, you can now call <code>.tap</code> with a method as well:
102
+
103
+ <pre>
104
+ [1, 2, 3, 4, 5].tap.pop.map { |n| n * 2 }
105
+ =&gt; [2, 4, 6, 8]
106
+ </pre>
107
+
53
108
  <h2>Demonstration of usage</h2>
54
109
 
55
110
 
56
- <h2>Forum</h2>
111
+ <p>See above.</p>
57
112
 
58
113
 
59
- <p><a href="http://groups.google.com/group/andand">http://groups.google.com/group/andand</a></p>
114
+ <h2>A little more background</h2>
60
115
 
61
116
 
62
- <p><span class="caps">TODO</span> &#8211; create Google Group &#8211; andand</p>
117
+ <p><a href="http://weblog.raganwald.com/2008/01/objectandand-objectme-in-ruby.html">Object#andand &#38; Object#me in Ruby</a></p>
63
118
 
64
119
 
65
120
  <h2>How to submit patches</h2>
66
121
 
67
122
 
68
- <p>Read the <a href="http://drnicwilliams.com/2007/06/01/8-steps-for-fixing-other-peoples-code/">8 steps for fixing other people&#8217;s code</a> and for section <a href="http://drnicwilliams.com/2007/06/01/8-steps-for-fixing-other-peoples-code/#8b-google-groups">8b: Submit patch to Google Groups</a>, use the Google Group above.</p>
123
+ <p>Read the <a href="http://drnicwilliams.com/2007/06/01/8-steps-for-fixing-other-peoples-code/">8 steps for fixing other people&#8217;s code</a>.</p>
69
124
 
70
125
 
71
126
  <p>The trunk repository is <code>svn://rubyforge.org/var/svn/andand/trunk</code> for anonymous access.</p>
@@ -74,15 +129,15 @@
74
129
  <h2>License</h2>
75
130
 
76
131
 
77
- <p>This code is free to use under the terms of the <span class="caps">MIT</span> license.</p>
132
+ <p>This code is free to use under the terms of the <a href="http://en.wikipedia.org/wiki/MIT_License"><span class="caps">MIT</span> license</a>.</p>
78
133
 
79
134
 
80
135
  <h2>Contact</h2>
81
136
 
82
137
 
83
- <p>Comments are welcome. Send an email to <a href="mailto:FIXME"><span class="caps">FIXME</span> full name</a> email via the <a href="http://groups.google.com/group/andand">forum</a></p>
138
+ <p>Comments are welcome. Send an email to <a href="mailto:raganwald+rubyforge@gmail.com">Reginald Braithwaite</a>.</p>
84
139
  <p class="coda">
85
- <a href="FIXME email">FIXME full name</a>, 3rd February 2008<br>
140
+ <a href="http://weblog.raganwald.com">Reginald Braithwaite</a>, 10th February 2008<br>
86
141
  Theme extended from <a href="http://rb2js.rubyforge.org/">Paul Battley</a>
87
142
  </p>
88
143
  </div>
data/website/index.txt CHANGED
@@ -1,10 +1,16 @@
1
- h1. andand
1
+ h1. Object#andand
2
2
 
3
3
  h1. &#x2192; 'andand'
4
4
 
5
-
6
5
  h2. What
7
6
 
7
+ _Object#andand_ lets us write:
8
+
9
+ <pre>
10
+ @phone = Location.find(:first, ...elided... ).andand.phone
11
+ </pre>And get a _guarded method invocation_ or _safe navigation method_. This snippet performs a @.find@ on the Location class, then sends @.phone@ to the result _if the result is not nil_. If the result is nil, then the expression returns nil without throwing a NoMethodError.
12
+
13
+ We also get an enhanced Object#tap method.
8
14
 
9
15
  h2. Installing
10
16
 
@@ -12,28 +18,65 @@ h2. Installing
12
18
 
13
19
  h2. The basics
14
20
 
21
+ h3. Object#andand
15
22
 
16
- h2. Demonstration of usage
23
+ Ruby programmers are familiar with the two _guarded assignment_ operators @&&=@ and @||=@. The typical use for them is when you have a variable that might be nil. For example:
24
+
25
+ <pre>
26
+ first_name &&= @first_name.trim
27
+ @phone ||= '612-777-9311'
28
+ </pre>You are trimming the first name provided it isn’t nil, and you are assigning ‘612-777-9311’ to the phone if it _is_ nil (or false, but that isn’t important right now). The other day we were discussing the guards and we agreed that we wished there was a _guarded method invocation_ operator. Here’s an example of when you would use it:
29
+
30
+ <pre>
31
+ @phone = Location.find(:first, ...elided... )&&.phone
32
+ </pre>Meaning, search the location table for the first record matching some criteria, and if you find a location, get its phone. If you don’t, get nil. (Groovy provides this exact functionality, although Groovy uses @?.@ instead of @&&.@) However, @&&.@ won’t work because @&&.@ is not a real Ruby operator.
33
+
34
+ Object#andand let&rsquo;s us write:
17
35
 
36
+ <pre>
37
+ @phone = Location.find(:first, ...elided... ).andand.phone
38
+ </pre>And get the same effect as:
18
39
 
40
+ <pre>
41
+ @phone = ->(loc){ loc && loc.phone }.call(Location.find(:first, ...elided... ))
42
+ </pre>Note that because you accept any method using Ruby’s method invocation syntax, you can accept methods with parameters and/or blocks:
43
+
44
+ <pre>
45
+ list_of_lists.detect { ...elided... }.andand.inject(42) { ...elided ... }
46
+ </pre>Object#andand emphasizes syntactic regularity: the goal was to make an @&&.@ operation that worked like @&&=@. @&&=@ looks just like normal assignment, you can use any expression on the RHS, only the semantics are different. The andand method also works just like a normal method invocation, only the semantics are modified.
47
+
48
+ h3. Enhanced Object#tap
49
+
50
+ Ruby 1.9 introduces "Object#tap":http://moonbase.rydia.net/mental/blog/programming/eavesdropping-on-expressions. This library implements Object#tap for Ruby 1.8 *and* enhances it. As in Ruby 1.9, you can call @.tap@ with a block:
51
+
52
+ <pre>
53
+ blah.sort.grep( /foo/ ).tap { |xs| p xs }.map { |x| x.blah }
54
+ </pre> But like its sibling @.andand@, you can now call @.tap@ with a method as well:
55
+
56
+ <pre>
57
+ [1, 2, 3, 4, 5].tap.pop.map { |n| n * 2 }
58
+ => [2, 4, 6, 8]
59
+ </pre>
60
+
61
+ h2. Demonstration of usage
19
62
 
20
- h2. Forum
63
+ See above.
21
64
 
22
- "http://groups.google.com/group/andand":http://groups.google.com/group/andand
65
+ h2. A little more background
23
66
 
24
- TODO - create Google Group - andand
67
+ "Object#andand & Object#me in Ruby":http://weblog.raganwald.com/2008/01/objectandand-objectme-in-ruby.html
25
68
 
26
69
  h2. How to submit patches
27
70
 
28
- Read the "8 steps for fixing other people's code":http://drnicwilliams.com/2007/06/01/8-steps-for-fixing-other-peoples-code/ and for section "8b: Submit patch to Google Groups":http://drnicwilliams.com/2007/06/01/8-steps-for-fixing-other-peoples-code/#8b-google-groups, use the Google Group above.
71
+ Read the "8 steps for fixing other people's code":http://drnicwilliams.com/2007/06/01/8-steps-for-fixing-other-peoples-code/.
29
72
 
30
- The trunk repository is <code>svn://rubyforge.org/var/svn/andand/trunk</code> for anonymous access.
73
+ The trunk repository is @svn://rubyforge.org/var/svn/andand/trunk@ for anonymous access.
31
74
 
32
75
  h2. License
33
76
 
34
- This code is free to use under the terms of the MIT license.
77
+ This code is free to use under the terms of the "MIT license":http://en.wikipedia.org/wiki/MIT_License.
35
78
 
36
79
  h2. Contact
37
80
 
38
- Comments are welcome. Send an email to "FIXME full name":mailto:FIXME email via the "forum":http://groups.google.com/group/andand
81
+ Comments are welcome. Send an email to "Reginald Braithwaite":mailto:raganwald+rubyforge@gmail.com.
39
82
 
@@ -37,7 +37,7 @@
37
37
  </div>
38
38
  <%= body %>
39
39
  <p class="coda">
40
- <a href="FIXME email">FIXME full name</a>, <%= modified.pretty %><br>
40
+ <a href="http://weblog.raganwald.com">Reginald Braithwaite</a>, <%= modified.pretty %><br>
41
41
  Theme extended from <a href="http://rb2js.rubyforge.org/">Paul Battley</a>
42
42
  </p>
43
43
  </div>
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.0
3
3
  specification_version: 1
4
4
  name: andand
5
5
  version: !ruby/object:Gem::Version
6
- version: 1.0.1
7
- date: 2008-02-09 00:00:00 -05:00
6
+ version: 1.1.0
7
+ date: 2008-02-10 00:00:00 -05:00
8
8
  summary: adds guarded method invocation to Ruby
9
9
  require_paths:
10
10
  - lib