named_proc 1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,22 @@
1
+ The MIT LICENSE
2
+
3
+ Copyright (c) 2011 Jan Lelis
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,95 @@
1
+ = MultiBlock
2
+
3
+ MultiBlock is a mini framework for passing multiple blocks to methods. It uses "named procs" to accomplish this in a nice way. The receiving method can either yield all blocks, or just call specific ones, identified by order or name.
4
+
5
+ These gem was build during a codebrawl contest. You might also take a look at the other entries: http://codebrawl.com/contests/methods-taking-multiple-blocks
6
+
7
+ == Setup
8
+
9
+ gem install multi_block
10
+
11
+ == Named Procs
12
+ A named proc acts like a normal proc, but has got a name attribute. You can create it by calling a method with the desired name on +proc+:
13
+
14
+ >> a = proc.even?{ |e| e.even? }
15
+ => #<NamedProc:0x00000001ffc340@(irb):1>
16
+ >> a.name
17
+ => :even?
18
+ >> a[42]
19
+ => false
20
+
21
+ In the same way, you can create lambdas:
22
+
23
+ >> b = lambda.doubler{ |e| e * 2 }
24
+ => #<NamedProc:0x000000020685e0@(irb):7 (lambda)>
25
+ >> b.name
26
+ => :doubler
27
+ >> b[21]
28
+ => 42
29
+ >> b.lambda?
30
+ => true
31
+
32
+ == MultiBlock Usage
33
+ === Defining methods that use multiple blocks
34
+
35
+ The first argument given to yield always defines the desired block(s). The other arguments get directly passed to the block(s). So these are example calls to the block:
36
+
37
+ yield # calls all given procs without args
38
+ yield :success # calls :success proc without args
39
+ yield :success, "Code Brawl!" # calls :success proc with message
40
+ yield 1 # calls first proc (:success in this case)
41
+ yield [:success, :bonus] # calls :success and :bonus without args
42
+ yield [:success, :bonus], "Code Brawl!" # calls both procs with same arg
43
+ yield success: "Code Brawl!", # calls each keyed proc,
44
+ error: [500, "Internal Brawl Error"] # values are the args
45
+
46
+ Consider these two example methods:
47
+
48
+ def ajax
49
+ yield rand(6) != 0 ? :success : :error # calls the :success block if everything worked well
50
+ end
51
+
52
+ def dice
53
+ random_number = rand(6)
54
+ yield random_number, random_number + 1 # calls the n-th block
55
+ end
56
+
57
+ === Calling methods with multiple blocks
58
+
59
+ It's done by calling the +blocks+ helper method:
60
+
61
+ ajax &blocks[
62
+ proc.success do puts "Yeah!" end,
63
+ proc.error do puts "Error..." end,
64
+ ]
65
+
66
+ The dice method could, for example, be called in this way:
67
+
68
+ dice &blocks[
69
+ proc{ ":(" },
70
+ proc{ ":/" },
71
+ proc{ ":O" },
72
+ proc{ ":b" },
73
+ proc{ ":P" },
74
+ proc{ rand(42) != 0 ? ":)" : ":D"},
75
+ ]
76
+
77
+ == Bonus sugar: Array extension
78
+
79
+ If you like the slim <tt>&to_proc</tt> operator, you can further optimize the syntax by calling:
80
+
81
+ Array.send :include, MultiBlock::Array
82
+
83
+ Now, it's getting real hot:
84
+
85
+ do_something, some_argument, &[
86
+ proc.easy_way do
87
+ # do it the easy way
88
+ end,
89
+
90
+ proc.complex_way do
91
+ # use complex heuristics, etc.
92
+ end,
93
+ ]
94
+
95
+ == J-_-L
@@ -0,0 +1,54 @@
1
+ # encoding: utf-8
2
+
3
+ # Class for a proc that's got a name
4
+ class NamedProc < Proc
5
+ attr_reader :name
6
+
7
+ def initialize(name)
8
+ @name = name
9
+ super
10
+ end
11
+
12
+ # create one from a given proc/lambda object
13
+ def self.create(name, block, lambda = false)
14
+ name = name.to_sym
15
+ # sorry for this ugly hack, is there a better way to lambdafy?
16
+ block = Module.new.send(:define_method, name.to_sym, &block) if lambda
17
+
18
+ new(name, &block)
19
+ end
20
+
21
+ # Proxy object to ease named proc initialization
22
+ module Proxy
23
+ Proc = BasicObject.new
24
+ def Proc.method_missing(name, &block) NamedProc.create(name, block) end
25
+
26
+ Lambda = BasicObject.new
27
+ def Lambda.method_missing(name, &block) NamedProc.create(name, block, true) end
28
+ end
29
+
30
+ # Mixing in low level method "links"
31
+ module Object
32
+ private
33
+
34
+ # create a proc with name if given
35
+ def proc
36
+ if block_given?
37
+ super
38
+ else
39
+ NamedProc::Proxy::Proc
40
+ end
41
+ end
42
+
43
+ # same for lambda
44
+ def lambda
45
+ if block_given?
46
+ super
47
+ else
48
+ NamedProc::Proxy::Lambda
49
+ end
50
+ end
51
+ end
52
+
53
+ ::Object.send :include, NamedProc::Object
54
+ end
@@ -0,0 +1,18 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require 'rubygems' unless defined? Gem
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "named_proc"
6
+ s.version = 1.0
7
+ s.authors = ["Jan Lelis"]
8
+ s.email = "mail@janlelis.de"
9
+ s.homepage = "https://gist.github.com/4b2f5fd0b45118e46d0f"
10
+ s.summary = "NamedProc: Like anonymous procs, but have a name."
11
+ s.description = "NamedProc: Like anonymous procs, but have a name. Example: lambda.codebrawl {} # creates an empty lambda with the name :codebrawl"
12
+ s.required_ruby_version = '>= 1.9.2'
13
+ s.files = Dir.glob %w{named_proc.gemspec lib/named_proc.rb spec/named_proc_spec.rb}
14
+ s.extra_rdoc_files = ["README.rdoc", "LICENSE.txt"]
15
+ s.license = 'MIT'
16
+ s.add_development_dependency 'rspec'
17
+ s.add_development_dependency 'rspec-core'
18
+ end
@@ -0,0 +1,34 @@
1
+ # encoding: utf-8
2
+ require_relative '../lib/named_proc'
3
+
4
+ describe "proc" do
5
+ it "creates a new proc as usual when called with a block" do
6
+ a = proc{}
7
+ a.should be_instance_of Proc
8
+ a.lambda?.should == false
9
+ end
10
+
11
+ it "creates a named proc when a method gets called on it" do
12
+ a = proc.brawl{}
13
+ a.should be_a Proc
14
+ a.should be_instance_of NamedProc
15
+ a.lambda?.should == false
16
+ a.name == :brawl
17
+ end
18
+ end
19
+
20
+ describe "lambda" do
21
+ it "creates a new lambda as usual when called with a block" do
22
+ a = lambda{}
23
+ a.should be_instance_of Proc
24
+ a.lambda?.should == true
25
+ end
26
+
27
+ it "creates a named lambda when a method gets called on it" do
28
+ a = lambda.brawl{}
29
+ a.should be_a Proc
30
+ a.should be_instance_of NamedProc
31
+ a.lambda?.should == true
32
+ a.name == :brawl
33
+ end
34
+ end
metadata ADDED
@@ -0,0 +1,75 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: named_proc
3
+ version: !ruby/object:Gem::Version
4
+ version: '1.0'
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Jan Lelis
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-10-24 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: &9105880 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: *9105880
25
+ - !ruby/object:Gem::Dependency
26
+ name: rspec-core
27
+ requirement: &9105320 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *9105320
36
+ description: ! 'NamedProc: Like anonymous procs, but have a name. Example: lambda.codebrawl
37
+ {} # creates an empty lambda with the name :codebrawl'
38
+ email: mail@janlelis.de
39
+ executables: []
40
+ extensions: []
41
+ extra_rdoc_files:
42
+ - README.rdoc
43
+ - LICENSE.txt
44
+ files:
45
+ - named_proc.gemspec
46
+ - lib/named_proc.rb
47
+ - spec/named_proc_spec.rb
48
+ - README.rdoc
49
+ - LICENSE.txt
50
+ homepage: https://gist.github.com/4b2f5fd0b45118e46d0f
51
+ licenses:
52
+ - MIT
53
+ post_install_message:
54
+ rdoc_options: []
55
+ require_paths:
56
+ - lib
57
+ required_ruby_version: !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ! '>='
61
+ - !ruby/object:Gem::Version
62
+ version: 1.9.2
63
+ required_rubygems_version: !ruby/object:Gem::Requirement
64
+ none: false
65
+ requirements:
66
+ - - ! '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ requirements: []
70
+ rubyforge_project:
71
+ rubygems_version: 1.8.11
72
+ signing_key:
73
+ specification_version: 3
74
+ summary: ! 'NamedProc: Like anonymous procs, but have a name.'
75
+ test_files: []