ampex 1.2.1 → 2.0.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/README.markdown +13 -10
- data/lib/ampex.rb +2 -80
- metadata +6 -8
data/README.markdown
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
The Ampex (`&X`) library provides a Metavariable X that can be used in conjunction with the unary ampersand to create anonymous blocks in a slightly more readable way than the default. It was inspired by the clever `Symbol#to_proc` method which handles the most common case very elegantly, and discussion with Sam Stokes
|
1
|
+
The Ampex (`&X`) library provides a Metavariable X that can be used in conjunction with the unary ampersand to create anonymous blocks in a slightly more readable way than the default. It was inspired by the clever `Symbol#to_proc` method which handles the most common case very elegantly, and discussion with Sam Stokes about creating lazy enumerators in ruby.
|
2
2
|
|
3
3
|
Usage
|
4
4
|
-----
|
@@ -29,9 +29,6 @@ As everything in Ruby is a method call, you can create readable expressions with
|
|
29
29
|
["a", "b", "c"].map &(X * 2)
|
30
30
|
# => ["aa", "bb", "cc"]
|
31
31
|
|
32
|
-
[{}].each &X[1] = 2
|
33
|
-
# => [{1 => 2}]
|
34
|
-
|
35
32
|
You can use this in any place a block is expected, for example to create a lambda:
|
36
33
|
|
37
34
|
normalizer = lambda &X.to_s.downcase
|
@@ -67,15 +64,10 @@ Secondly, other arguments or operands will only be evaluated once, and not every
|
|
67
64
|
[1, 2].map{ |x| x + (i += 1) }
|
68
65
|
# => [2, 4]
|
69
66
|
|
70
|
-
Bugs
|
71
|
-
----
|
72
|
-
|
73
|
-
In normal usage there are no known bugs. That said, if you accidentally miss the `&` from in front of the `X`, in an expression that ends in an assignment (e.g. `X.formatter = :inspect`); then the `#to_proc` method of the object assigned will respond with the expression generated by that `X` the next time you call it from anywhere else in the same thread.
|
74
|
-
|
75
67
|
Epilogue
|
76
68
|
--------
|
77
69
|
|
78
|
-
`&X` has been tested on MRI ruby 1.8.6, 1.8.7
|
70
|
+
`&X` has been tested on MRI ruby 1.8.6, 1.8.7, 1.9.2, 1.9.3, jruby, and rubinius.
|
79
71
|
|
80
72
|
For bug-fixes or enhancements, please contact the author: Conrad Irwin <conrad.irwin@gmail.com>
|
81
73
|
|
@@ -83,7 +75,18 @@ For an up-to-date version, try <https://github.com/rapportive-oss/ampex>
|
|
83
75
|
|
84
76
|
This library is copyrighted under the MIT license, see LICENSE.MIT for details.
|
85
77
|
|
78
|
+
|
79
|
+
Backwards compatibility breakages
|
80
|
+
---------------------------------
|
81
|
+
|
82
|
+
Between version 1.2.1 and version 2.0.0, the support for assignment operations was removed from
|
83
|
+
ampex. These had a very non-obvious implementation, and it was impossible to support
|
84
|
+
assigning of falsey values; and did not work on rubinius.
|
85
|
+
|
86
86
|
See also
|
87
87
|
--------
|
88
88
|
|
89
|
+
* <https://cirw.in/blog/ampex> — a blog post that describes the ideas.
|
89
90
|
* <https://github.com/danielribeiro/RubyUnderscore> — which uses an underscore in place of `&X` and works by rewriting the syntax tree.
|
91
|
+
* <https://gist.github.com/1224361> — a patch for Rubinius that enables the underscore in a similar way.
|
92
|
+
* <http://blog.railsware.com/2012/03/13/ruby-2-0-enumerablelazy/> — The upcoming lazy enumerable support for Ruby 2.0.
|
data/lib/ampex.rb
CHANGED
@@ -14,10 +14,6 @@ else
|
|
14
14
|
end
|
15
15
|
|
16
16
|
class Metavariable < superclass
|
17
|
-
# Take a local copy of these as constant lookup is destroyed by BasicObject.
|
18
|
-
Metavariable = self
|
19
|
-
Thread = ::Thread
|
20
|
-
|
21
17
|
# When you pass an argument with & in ruby, you're actually calling #to_proc
|
22
18
|
# on the object. So it's Symbol#to_proc that makes the &:to_s trick work,
|
23
19
|
# and Metavariable#to_proc that makes &X work.
|
@@ -39,9 +35,8 @@ class Metavariable < superclass
|
|
39
35
|
# }
|
40
36
|
#
|
41
37
|
def method_missing(name, *args, &block)
|
42
|
-
|
43
|
-
Metavariable.
|
44
|
-
mv
|
38
|
+
raise ::NotImplementedError, "(&X = 'foo') is unsupported in ampex > 2.0.0" if name.to_s =~ /[^!=<>]=$/
|
39
|
+
::Metavariable.new { |x| @to_proc.call(x).__send__(name, *args, &block) }
|
45
40
|
end
|
46
41
|
|
47
42
|
# BlankSlate and BasicObject have different sets of methods that you don't want.
|
@@ -49,79 +44,6 @@ class Metavariable < superclass
|
|
49
44
|
instance_methods.each do |method|
|
50
45
|
undef_method method unless %w(method_missing to_proc __send__ __id__).include? method.to_s
|
51
46
|
end
|
52
|
-
|
53
|
-
private
|
54
|
-
|
55
|
-
# In order to support assignment via &X (expressions of the form &X['one'] = 2),
|
56
|
-
# we need to add 2.to_proc (because assignment in ruby always returns the operand)
|
57
|
-
#
|
58
|
-
# Luckily, we only need to do this for a very short time.
|
59
|
-
#
|
60
|
-
# When given an expression such as:
|
61
|
-
#
|
62
|
-
# ary.map(&X[args(a)] = :two)
|
63
|
-
#
|
64
|
-
# the order of execution is:
|
65
|
-
# args(a)
|
66
|
-
# X[_] = :two \_ need to patch here
|
67
|
-
# :two.to_proc _/ and un-patch here
|
68
|
-
# ary.map &_
|
69
|
-
#
|
70
|
-
# We go to some lengths to ensure that, providing the & and the X are adjacent,
|
71
|
-
# it's not possible to get different behaviour in the rest of the program; despite
|
72
|
-
# the temporary mutation of potentially global state.
|
73
|
-
#
|
74
|
-
# We can't really do anything if the & has been split from the X, consider:
|
75
|
-
#
|
76
|
-
# assigner = (X[0] = :to_i)
|
77
|
-
# assigner == :to_i
|
78
|
-
# # => true
|
79
|
-
# [1,2,3].map(&:to_i)
|
80
|
-
# # => NoMethodError: undefined method `[]=' for 1:Fixnum
|
81
|
-
#
|
82
|
-
# Just strongly encourage use of:
|
83
|
-
# assigner = lambda &X = :to_i
|
84
|
-
# assigner == :to_i
|
85
|
-
# # => false
|
86
|
-
# [1,2,3].map(&:to_i)
|
87
|
-
# # => [1,2,3]
|
88
|
-
#
|
89
|
-
def self.temporarily_monkeypatch(instance, method_name, &block)
|
90
|
-
|
91
|
-
Thread.exclusive do
|
92
|
-
@monkey_patch_count = @monkey_patch_count ? @monkey_patch_count + 1 : 0
|
93
|
-
stashed_method_name = :"#{method_name}_without_metavariable_#{@monkey_patch_count}"
|
94
|
-
thread = Thread.current
|
95
|
-
|
96
|
-
# Try to get a handle on the object's singleton class, but fall back to using
|
97
|
-
# its actual class where that is not possible (i.e. for numbers and symbols)
|
98
|
-
klass = (class << instance; self; end) rescue instance.class
|
99
|
-
klass.class_eval do
|
100
|
-
|
101
|
-
alias_method(stashed_method_name, method_name) rescue nil
|
102
|
-
define_method(method_name) do
|
103
|
-
|
104
|
-
todo = block
|
105
|
-
|
106
|
-
Thread.exclusive do
|
107
|
-
if self.equal?(instance) && thread.equal?(Thread.current)
|
108
|
-
|
109
|
-
klass.class_eval do
|
110
|
-
undef_method(method_name)
|
111
|
-
alias_method(method_name, stashed_method_name) rescue nil
|
112
|
-
undef_method(stashed_method_name) rescue nil
|
113
|
-
end
|
114
|
-
|
115
|
-
else
|
116
|
-
todo = method(stashed_method_name)
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
|
-
todo.call
|
121
|
-
end
|
122
|
-
end
|
123
|
-
end
|
124
|
-
end
|
125
47
|
end
|
126
48
|
|
127
49
|
X = Metavariable.new
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ampex
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 15
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
|
-
- 1
|
8
7
|
- 2
|
9
|
-
-
|
10
|
-
|
8
|
+
- 0
|
9
|
+
- 0
|
10
|
+
version: 2.0.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Conrad Irwin
|
@@ -15,8 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date:
|
19
|
-
default_executable:
|
18
|
+
date: 2012-05-20 00:00:00 Z
|
20
19
|
dependencies:
|
21
20
|
- !ruby/object:Gem::Dependency
|
22
21
|
name: blankslate
|
@@ -44,7 +43,6 @@ files:
|
|
44
43
|
- lib/ampex.rb
|
45
44
|
- README.markdown
|
46
45
|
- LICENSE.MIT
|
47
|
-
has_rdoc: true
|
48
46
|
homepage: http://github.com/rapportive-oss/ampex
|
49
47
|
licenses: []
|
50
48
|
|
@@ -74,7 +72,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
74
72
|
requirements: []
|
75
73
|
|
76
74
|
rubyforge_project:
|
77
|
-
rubygems_version: 1.
|
75
|
+
rubygems_version: 1.8.21
|
78
76
|
signing_key:
|
79
77
|
specification_version: 3
|
80
78
|
summary: Provides a meta-variable X which can be used to create procs more prettily
|