andand 1.0.1 → 1.1.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 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