pied_piper 0.1.3 → 0.1.4
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.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +51 -10
- data/lib/pied_piper/kernel.rb +2 -0
- data/lib/pied_piper/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d579aeffae1f032f9ee5e820ddbbaa907cdf9126aa053dbbd97d7d31e38cc24b
|
|
4
|
+
data.tar.gz: ca5279f4ddbf50304fa72029a5f3d871beb79f2e90b16f67da14d6bc19a723e4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 0c210a151538ab94ef386fd7fa463007545b4a2329b67e59c717c5b2055b9abb854ea661034b6190db1f5965b2d63d238bd783377ba7cc641425df704986de5b
|
|
7
|
+
data.tar.gz: 9a98bd3b029ff085f5d96cc7c1ffa1a915b3e64ec1a3b9d51069597d1c18dd2180a0e7f31049e2faa58129b6ca2602d9b8bb76d854d34ad925eccbf7f6c93f23
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
|
@@ -6,13 +6,15 @@ The inspiration for this gem were `|>` pipes and functional programming in [Elix
|
|
|
6
6
|
|
|
7
7
|
After trying to introduce the same `|>` pipe operator in Ruby, which I found out isn't possible due to syntactic reasons ( without hacking the underlying C code ), I settled for another well-known pipe operator, the `|` Unix pipe operator.
|
|
8
8
|
|
|
9
|
-
If you want to read about the inspiration for the name `PiedPiper`, it's an old german fairy tale, the [Pied Piper of Hamelin](https://en.wikipedia.org/wiki/Pied_Piper_of_Hamelin),
|
|
9
|
+
If you want to read about the inspiration for the name `PiedPiper`, it's an old german fairy tale, the [Pied Piper of Hamelin](https://en.wikipedia.org/wiki/Pied_Piper_of_Hamelin), a guy who played pipe and hypnotized and lured all children out of town with his music and they were never be seen again.
|
|
10
|
+
|
|
11
|
+
Another thing worth seeing, regarding "Pied Piper" and coding, is [Silicon Valley - Company Name](https://www.youtube.com/watch?v=QJ70b-WRHlU). It's hilarious :-D ( Thanks, Michael! )
|
|
10
12
|
|
|
11
13
|
Despite the word "pipe" there's also another common thing between the fairy tale and pipes in this gem:
|
|
12
14
|
|
|
13
15
|
There's a "piper" object who lures "children" (other objects) away ( through pipes ) until they never be seen again ( are transformed into other objects ). :-)
|
|
14
16
|
|
|
15
|
-
If you never worked with pipes, this little analogy may help to understand what's happening.
|
|
17
|
+
If you never worked with pipes, this little analogy may help, to understand what's happening.
|
|
16
18
|
|
|
17
19
|
Have fun with PiedPiper and don't let him lure you away... :-)
|
|
18
20
|
|
|
@@ -58,7 +60,7 @@ Our initial object (e.g: `"rats and kids"`), is passed around through each pipe
|
|
|
58
60
|
|
|
59
61
|
### Symbol/String Pipes
|
|
60
62
|
|
|
61
|
-
|
|
63
|
+
The easiest way to create a pipe is using symbols or strings. This will call the method with the same name as the Symbol/String on the wrapped object:
|
|
62
64
|
|
|
63
65
|
```ruby
|
|
64
66
|
p = piper("rats and kids")
|
|
@@ -67,7 +69,11 @@ p | :upcase | p.end
|
|
|
67
69
|
# => "RATS AND KIDS"
|
|
68
70
|
```
|
|
69
71
|
|
|
70
|
-
|
|
72
|
+
More about `p.end` below.
|
|
73
|
+
|
|
74
|
+
### Chaining Pipes
|
|
75
|
+
|
|
76
|
+
Pipes can be chained of course:
|
|
71
77
|
|
|
72
78
|
```ruby
|
|
73
79
|
p = piper("rats and kids")
|
|
@@ -78,11 +84,13 @@ p | :upcase | :reverse | p.end
|
|
|
78
84
|
|
|
79
85
|
### Ending Pipes
|
|
80
86
|
|
|
81
|
-
Note: Since "piping" is not a native Ruby syntax feature, rather than a method call in disguise (e.g: `
|
|
87
|
+
Note: Since "piping" is not a native Ruby syntax feature, rather than a method call in disguise (e.g: `"foo".|(:upcase)`), the underlying `PiedPiper` class, which wraps the initial object (e.g: `"foo"`) and on which the pipe functionality is called, is just a wrapper for the initial object which handles piping logic.
|
|
82
88
|
|
|
83
|
-
Everytime you
|
|
89
|
+
Everytime you transformed an object through a pipe you create a new object of class `PiedPiper`, which wraps the mutated inital object again (e.g: from `"foo"` to `"FOO"`).
|
|
84
90
|
|
|
85
|
-
|
|
91
|
+
This way, we can build pipe-chains of arbitrary length, but at the end of each pipe-chain, the piped object has to be "unwrapped" again by some kind of "terminator" object.
|
|
92
|
+
|
|
93
|
+
This happens by "terminating" the pipe-chain with the `.end` method, which is defined on every piped object, or by just writing `PiedPiper::EndOfPipe` or if you have required `pied_piper/kernel` you can just write `p_end`.
|
|
86
94
|
|
|
87
95
|
```ruby
|
|
88
96
|
p = piper("rats and kids")
|
|
@@ -99,13 +107,46 @@ p | :upcase | p_end # when PiedPiper::Kernel was required
|
|
|
99
107
|
|
|
100
108
|
It would be possible to avoid writing `p.end` at the end of the chain, by implementing the gem in another way, but that would have included to monkey-patch existing Ruby classes, since the `|` method is already implemented by some of them.
|
|
101
109
|
|
|
102
|
-
I decided against that, since I only wanted to add pipe functionality and not alter existing behaviour in any way.
|
|
110
|
+
I decided against that, since I only wanted to add pipe functionality and not alter existing Ruby behaviour in any way.
|
|
103
111
|
|
|
104
112
|
Thus the `PiedPiper` class was born.
|
|
105
113
|
|
|
106
|
-
|
|
114
|
+
### Ruby and its Kernel module
|
|
115
|
+
|
|
116
|
+
If you want to add pipe functionality everywhere, we already talked about how to implement it above by requiring `pied_piper/kernel".
|
|
117
|
+
|
|
118
|
+
This will provide pipe functionality on every object which has `Object` in one of its superclasses ( thus practically every object in Ruby besides `BasicObject` ) with the least amount of monkey-patching/side-effects, since we only add one Kernel method named `piper` and don't alter existing behaviour.
|
|
119
|
+
|
|
120
|
+
In case you didn't know:
|
|
121
|
+
|
|
122
|
+
`Object` includes `Kernel` as a module.
|
|
123
|
+
|
|
124
|
+
Methods who are intended to be globally available, like `puts` and `gets`, and who aren't intended to be available with an explicit receiver like `"foo".puts` are defined as private instance methods on `Kernel`.
|
|
125
|
+
|
|
126
|
+
Private instance methods can only be called with an implicit receiver (implicit self) in Ruby.
|
|
127
|
+
|
|
128
|
+
That's why things like this work, because were always "inside" an object:
|
|
129
|
+
|
|
130
|
+
```ruby
|
|
131
|
+
puts self
|
|
132
|
+
# main
|
|
133
|
+
# nil
|
|
134
|
+
|
|
135
|
+
# implicit receiver for puts
|
|
136
|
+
puts "foo"
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
but this doesn't:
|
|
140
|
+
|
|
141
|
+
```ruby
|
|
142
|
+
# explicit receiver for puts
|
|
143
|
+
self.puts "foo"
|
|
144
|
+
# => NoMethodError: private method `puts' called for main:Object
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
So if you want to provide functionality that's available everywhere like `puts` the usual approach is to define a private instance method on Kernel.
|
|
107
148
|
|
|
108
|
-
|
|
149
|
+
That's what has been done with the `piper` and `p_end` method :-)
|
|
109
150
|
|
|
110
151
|
### Array Pipes
|
|
111
152
|
|
data/lib/pied_piper/kernel.rb
CHANGED
data/lib/pied_piper/version.rb
CHANGED