ampex 0.0.2

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 (4) hide show
  1. data/LICENSE.MIT +19 -0
  2. data/README.markdown +60 -0
  3. data/lib/ampex.rb +85 -0
  4. metadata +78 -0
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2010 Conrad Irwin <conrad.irwin@gmail.com>
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
@@ -0,0 +1,60 @@
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.
2
+
3
+ At its simplest, `&X` can be used as a drop-in replacement for `Symbol#to_proc`:
4
+
5
+ [1,2,3].map &X.to_s
6
+ # => ["1", "2", "3"]
7
+
8
+ However the real strength in the library comes from allowing you to call methods with arguments:
9
+
10
+ [1,"2",3].select &X.is_a?(String)
11
+ # => ["2"]
12
+
13
+ And, as everything in ruby is a method, create readable expressions without the noise of a one-argument block:
14
+
15
+ [{1 => 2}, {1 => 3}].map &X[1]
16
+ # => [2, 3]
17
+
18
+ [1,2,3].map &-X
19
+ # => [-1, -2, -3]
20
+
21
+ ["a", "b", "c"].map &(X * 2)
22
+ # => ["aa", "bb", "cc"]
23
+
24
+ As an added bonus, the effect is transitive — you can chain method calls:
25
+
26
+ [1, 2, 3].map &X.to_f.to_s
27
+ # => ["1.0", "2.0", "3.0"]
28
+
29
+ There are two things to watch out for:
30
+
31
+ Firstly, `&X` can only appear on the left:
32
+
33
+ [1, 2, 3].map &(X + 1)
34
+ # => [2, 3, 4]
35
+
36
+ [1, 2, 3].map &(1 + X) # WRONG
37
+ # => TypeError, "coerce must return [x, y]"
38
+
39
+ [[1],[2]].map &X.concat([2])
40
+ # => [[1, 2], [2, 2]]
41
+
42
+ [[1],[2]].map &[2].concat(X) # WRONG
43
+ # => TypeError, "Metavariable#to_ary should return Array"
44
+
45
+ Secondly, other arguments or operands will only be evaluated once, and not every time:
46
+
47
+ i = 0
48
+ [1, 2].map &(X + (i += 1)) # WRONG
49
+ # => [2, 3]
50
+
51
+ i = 0
52
+ [1, 2].map{ |x| x + (i += 1) }
53
+ # => [2, 4]
54
+
55
+
56
+ For bug-fixes or enhancements, please contact the author: Conrad Irwin <conrad.irwin@gmail.com>
57
+
58
+ For an up-to-date version, try http://github.com/rapportive-oss/ampex
59
+
60
+ This library is copyrighted under the MIT license, see LICENSE.MIT for details.
@@ -0,0 +1,85 @@
1
+ require 'blankslate'
2
+
3
+ # Copyright 2010 Conrad Irwin <conrad.irwin@gmail.com> MIT License
4
+ #
5
+ # For detailed usage notes, please see README.markdown
6
+ #
7
+ class Metavariable < BlankSlate
8
+ def initialize(parent=nil, &block)
9
+ @block = block
10
+ @parent = parent
11
+ end
12
+
13
+ def method_missing(name, *args, &block)
14
+ Metavariable.new(self) { |x| x.send(name, *args, &block) }
15
+ end
16
+
17
+ def to_proc
18
+ lambda do |x|
19
+ if @block
20
+ x = @parent.to_proc.call(x) if @parent
21
+ @block.call x
22
+ else
23
+ x
24
+ end
25
+ end
26
+ end
27
+
28
+ def metavariable_precedence
29
+ @parent unless @block
30
+ end
31
+ end
32
+
33
+ class CallByName < BlankSlate
34
+ def initialize(obj, parent=nil, name=nil, args=nil, block=nil)
35
+ @obj = obj
36
+ @parent = parent
37
+ @name = name
38
+ @args = args
39
+ @block = block
40
+ end
41
+
42
+ def method_missing(name, *args, &block)
43
+ CallByName.new(nil, self, name, args, block)
44
+ end
45
+
46
+ def unwind_callbyname(*args)
47
+ provided.map{|x| Metavariable === x ? called[x.metavariable_precedence] : x}
48
+ if @parent
49
+ @parent.unwind_callbyname(*args).send(@name, *CallByName.merge_args(@args, args), &@block)
50
+ else
51
+ @obj
52
+ end
53
+ end
54
+
55
+ def to_proc
56
+ if @parent
57
+ lambda { |*args| unwind_callbyname(*args) }
58
+ else
59
+ lambda { |*args| @obj }
60
+ end
61
+ end
62
+
63
+ def self.merge_args(provided, called)
64
+ end
65
+ end
66
+
67
+
68
+ class Regexp
69
+ def [](obj)
70
+ CallByName.new(obj)
71
+ end
72
+ end
73
+
74
+ module Kernel
75
+ def X
76
+ Metavariable.new(0)
77
+ end
78
+ end
79
+
80
+ K = Metavariable.new(0)
81
+ V = Metavariable.new(1)
82
+ W = Regexp.new""
83
+ X =
84
+ Y = Metavariable.new(1)
85
+ Z = Metavariable.new(2)
metadata ADDED
@@ -0,0 +1,78 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ampex
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 2
9
+ version: 0.0.2
10
+ platform: ruby
11
+ authors:
12
+ - Conrad Irwin
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-11-17 00:00:00 +00:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: blankslate
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 0
30
+ version: "0"
31
+ type: :runtime
32
+ version_requirements: *id001
33
+ description: Why would you want to write { |x| x['one'] } when you can write &X['one'], why indeed.
34
+ email: conrad.irwin@gmail.com
35
+ executables: []
36
+
37
+ extensions: []
38
+
39
+ extra_rdoc_files: []
40
+
41
+ files:
42
+ - lib/ampex.rb
43
+ - README.markdown
44
+ - LICENSE.MIT
45
+ has_rdoc: true
46
+ homepage: http://github.com/rapportive-oss/ampex
47
+ licenses: []
48
+
49
+ post_install_message:
50
+ rdoc_options: []
51
+
52
+ require_paths:
53
+ - lib
54
+ required_ruby_version: !ruby/object:Gem::Requirement
55
+ none: false
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ segments:
60
+ - 0
61
+ version: "0"
62
+ required_rubygems_version: !ruby/object:Gem::Requirement
63
+ none: false
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ segments:
68
+ - 0
69
+ version: "0"
70
+ requirements: []
71
+
72
+ rubyforge_project:
73
+ rubygems_version: 1.3.7
74
+ signing_key:
75
+ specification_version: 3
76
+ summary: Provides a meta-variable X which can be used to create procs more prettily
77
+ test_files: []
78
+