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.
Files changed (3) hide show
  1. data/README.markdown +13 -10
  2. data/lib/ampex.rb +2 -80
  3. metadata +6 -8
@@ -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 who created an earlier version.
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 and 1.9.2 and jruby 1.5.3. It is thread-safe.
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.
@@ -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
- mv = Metavariable.new { |x| @to_proc.call(x).__send__(name, *args, &block) }
43
- Metavariable.temporarily_monkeypatch(args.last, :to_proc) { mv.to_proc } if name.to_s =~ /[^!=<>]=$/
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: 29
4
+ hash: 15
5
5
  prerelease:
6
6
  segments:
7
- - 1
8
7
  - 2
9
- - 1
10
- version: 1.2.1
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: 2011-07-23 00:00:00 -07:00
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.6.2
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