church 0.0.1
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/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE +13 -0
- data/README.md +3 -0
- data/Rakefile +8 -0
- data/church.gemspec +22 -0
- data/lib/church/array.rb +83 -0
- data/lib/church/math.rb +42 -0
- data/lib/church/version.rb +3 -0
- data/lib/church.rb +3 -0
- data/spec/array_spec.rb +44 -0
- data/spec/math_spec.rb +87 -0
- data/spec/spec_helper.rb +1 -0
- metadata +95 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
2
|
+
Version 2, December 2004
|
3
|
+
|
4
|
+
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
|
5
|
+
|
6
|
+
Everyone is permitted to copy and distribute verbatim or modified
|
7
|
+
copies of this license document, and changing it is allowed as long
|
8
|
+
as the name is changed.
|
9
|
+
|
10
|
+
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
11
|
+
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
12
|
+
|
13
|
+
0. You just DO WHAT THE FUCK YOU WANT TO.
|
data/README.md
ADDED
data/Rakefile
ADDED
data/church.gemspec
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'church/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "church"
|
8
|
+
spec.version = Church::VERSION
|
9
|
+
spec.authors = ["Three If By Whiskey"]
|
10
|
+
spec.email = ["3ifbyw@gmail.com"]
|
11
|
+
spec.summary = %q{Church provides top-level constant Procs to do various and sundry kinds of functional programming.}
|
12
|
+
spec.homepage = ""
|
13
|
+
spec.license = "WTFPL"
|
14
|
+
|
15
|
+
spec.files = `git ls-files -z`.split("\x0")
|
16
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
17
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
|
+
spec.require_paths = ["lib"]
|
19
|
+
|
20
|
+
spec.add_development_dependency "bundler", "~> 1.5"
|
21
|
+
spec.add_development_dependency "rake"
|
22
|
+
end
|
data/lib/church/array.rb
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
module Church
|
2
|
+
# Returns the size of an array or string using recursion.
|
3
|
+
SIZE = -> coll {
|
4
|
+
coll == [] || coll == '' ? 0 : 1 + SIZE[coll[1..-1]]
|
5
|
+
}
|
6
|
+
|
7
|
+
# Returns the size of an array or string using iteration.
|
8
|
+
ISIZE = -> coll {
|
9
|
+
sz = 0
|
10
|
+
(slicer = -> {
|
11
|
+
sz += 1
|
12
|
+
(coll = coll[1..-1]) == [] || coll == '' ? sz : slicer[]
|
13
|
+
})[]
|
14
|
+
}
|
15
|
+
|
16
|
+
# Maps fn over coll recursively.
|
17
|
+
MAP = -> coll, &fn {
|
18
|
+
coll == [] ? [] : [fn[coll[0]]] + MAP[coll[1..-1], &fn]
|
19
|
+
}
|
20
|
+
|
21
|
+
# Maps fn over coll iteratively.
|
22
|
+
IMAP = -> coll, &fn {
|
23
|
+
sz = SIZE[coll]
|
24
|
+
ret = []
|
25
|
+
i = 0
|
26
|
+
|
27
|
+
(mapper = -> {
|
28
|
+
ret[i] = fn[coll[i]]
|
29
|
+
(i += 1) == sz ? ret : mapper[]
|
30
|
+
})[]
|
31
|
+
}
|
32
|
+
|
33
|
+
# Maps fn over coll iteratively and in-place, modifying the original collection.
|
34
|
+
MAP_BANG = -> coll, &fn {
|
35
|
+
sz = SIZE[coll]
|
36
|
+
i = 0
|
37
|
+
|
38
|
+
(mapper = -> {
|
39
|
+
coll[i] = fn[coll[i]]
|
40
|
+
(i += 1) == sz ? coll : mapper[]
|
41
|
+
})[]
|
42
|
+
}
|
43
|
+
|
44
|
+
# Reduces fn over coll iteratively.
|
45
|
+
REDUCE = -> coll, &fn {
|
46
|
+
sz = SIZE[coll]
|
47
|
+
ret = coll[0]
|
48
|
+
i = 1
|
49
|
+
|
50
|
+
(reducer = -> {
|
51
|
+
ret = fn[ret, coll[i]]
|
52
|
+
(i += 1) == sz ? ret : reducer[]
|
53
|
+
})[]
|
54
|
+
}
|
55
|
+
|
56
|
+
# Filters coll through fn using recursion.
|
57
|
+
FILTER = -> coll, &fn {
|
58
|
+
coll == [] ? [] : (fn[coll[0]] ? [coll[0]] : []) + FILTER[coll[1..-1], &fn]
|
59
|
+
}
|
60
|
+
|
61
|
+
# Filters coll through fn using iteration.
|
62
|
+
IFILTER = -> coll, &fn {
|
63
|
+
sz = SIZE[coll]
|
64
|
+
ret = []
|
65
|
+
i = 0
|
66
|
+
|
67
|
+
(filterer = -> {
|
68
|
+
fn[coll[i]] ? ret << coll[i] : 0
|
69
|
+
(i += 1) == sz ? ret : filterer[]
|
70
|
+
})[]
|
71
|
+
}
|
72
|
+
|
73
|
+
# Performs fn with each element of coll in turn.
|
74
|
+
EACH = -> coll, &fn {
|
75
|
+
sz = SIZE[coll]
|
76
|
+
i = 0
|
77
|
+
|
78
|
+
(eacher = -> {
|
79
|
+
fn[coll[i]]
|
80
|
+
(i += 1) == sz ? coll : eacher[]
|
81
|
+
})[]
|
82
|
+
}
|
83
|
+
end
|
data/lib/church/math.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
module Church
|
2
|
+
CMP = -> a, b {
|
3
|
+
a > b ? 1 : a < b ? -1 : 0
|
4
|
+
}
|
5
|
+
|
6
|
+
ADD = -> a, b {
|
7
|
+
b == 0 ? a : ADD[a + CMP[b, 0], b + CMP[0, b]]
|
8
|
+
}
|
9
|
+
|
10
|
+
SUB = -> a, b {
|
11
|
+
b == 0 ? a : SUB[a + (0 <=> b), b + (0 <=> b)]
|
12
|
+
}
|
13
|
+
|
14
|
+
MUL = -> a, b {
|
15
|
+
(mul_p = -> c, d {
|
16
|
+
d == b ? c + a * CMP[0, b] : mul_p[c + a * CMP[b, 0], d + CMP[b, 0]]
|
17
|
+
})[a * CMP[b, 0], 0]
|
18
|
+
}
|
19
|
+
|
20
|
+
DIV = -> a, b {
|
21
|
+
div_p = -> d {
|
22
|
+
d = ADD[d, CMP[b, 0]]
|
23
|
+
a = SUB[a, MUL[b, CMP[b, 0]]]
|
24
|
+
a >= MUL[b, CMP[b, 0]] ? div_p[d] : d
|
25
|
+
}
|
26
|
+
b > a ? 0 : div_p[0]
|
27
|
+
}
|
28
|
+
|
29
|
+
MOD = -> a, b {
|
30
|
+
MOD_p = -> {
|
31
|
+
a = SUB[a, MUL[b, CMP[b, 0]]]
|
32
|
+
a > b ? MOD_p[] : (b < 0 ? SUB[a, b] : a)
|
33
|
+
}
|
34
|
+
MOD_p[]
|
35
|
+
}
|
36
|
+
|
37
|
+
POW = -> a, b {
|
38
|
+
(POW_p = -> c, d {
|
39
|
+
d == b ? c : POW_p[MUL[a, c], ADD[d, 1]]
|
40
|
+
})[1, 0]
|
41
|
+
}
|
42
|
+
end
|
data/lib/church.rb
ADDED
data/spec/array_spec.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
include Church
|
4
|
+
|
5
|
+
describe 'SIZE' do
|
6
|
+
it "should return the size of a String" do
|
7
|
+
expect(SIZE['abc']).to be 3
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should return the size of an Array" do
|
11
|
+
expect(SIZE[[1, 2, 3]]).to be 3
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe 'MAP' do
|
16
|
+
it "should properly implement map as a top-level lambda" do
|
17
|
+
expect(MAP[[1, 2, 3], &-> c { c * 2 }]).to eq [2, 4, 6]
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should work with to_proc'd Symbols" do
|
21
|
+
expect(MAP[[1, 2, 3], &:even?]).to eq [false, true, false]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe 'MAP_BANG' do
|
26
|
+
let(:coll) { [1, 2, 3] }
|
27
|
+
|
28
|
+
it "should modify the original array" do
|
29
|
+
MAP_BANG[coll, &-> c { c * 2 }]
|
30
|
+
expect(coll).to eq [2, 4, 6]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe 'REDUCE' do
|
35
|
+
it "should properly implement reduce as a top-level lambda" do
|
36
|
+
expect(REDUCE[[1, 2, 3, 4], &:+]).to be 10
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe 'FILTER' do
|
41
|
+
it "should properly filter elements from collections" do
|
42
|
+
expect(FILTER[[1, 2, 3, 4], &:even?]).to eq [2, 4]
|
43
|
+
end
|
44
|
+
end
|
data/spec/math_spec.rb
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
include Church
|
4
|
+
|
5
|
+
describe 'ADD' do
|
6
|
+
it "should work with an LHS of 0" do
|
7
|
+
expect(ADD[0, 2]).to be 2
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should work with an RHS of 0" do
|
11
|
+
expect(ADD[3, 0]).to be 3
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should work with a negative LHS" do
|
15
|
+
expect(ADD[-2, 4]).to be 2
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should work with a negative RHS" do
|
19
|
+
expect(ADD[2, -4]).to be -2
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should work with two negatives" do
|
23
|
+
expect(ADD[-2, -4]).to be -6
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe 'SUB' do
|
28
|
+
it "should work with an LHS of 0" do
|
29
|
+
expect(SUB[0, 2]).to be -2
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should work with an RHS of 0" do
|
33
|
+
expect(SUB[3, 0]).to be 3
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should work with a negative LHS" do
|
37
|
+
expect(SUB[-2, 4]).to be -6
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should work with a negative RHS" do
|
41
|
+
expect(SUB[2, -4]).to be 6
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should work with two negatives" do
|
45
|
+
expect(SUB[-2, -4]).to be 2
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe 'MUL' do
|
50
|
+
it "should work with an LHS of 0" do
|
51
|
+
expect(MUL[0, 2]).to be 0
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should work with an RHS of 0" do
|
55
|
+
expect(MUL[3, 0]).to be 0
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should work with a negative LHS" do
|
59
|
+
expect(MUL[-2, 4]).to be -8
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should work with a negative RHS" do
|
63
|
+
expect(MUL[2, -4]).to be -8
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should work with two negatives" do
|
67
|
+
expect(MUL[-2, -4]).to be 8
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe 'DIV' do
|
72
|
+
it "should work with an LHS of 0" do
|
73
|
+
expect(DIV[0, 2]).to be 0
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should work with a negative RHS" do
|
77
|
+
expect(DIV[4, -2]).to be -2
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should divide numbers into themselves once" do
|
81
|
+
expect(DIV[3, 3]).to be 1
|
82
|
+
end
|
83
|
+
|
84
|
+
it "should truncate" do
|
85
|
+
expect(DIV[3, 4]).to be 0
|
86
|
+
end
|
87
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require File.expand_path('../../lib/church', __FILE__)
|
metadata
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: church
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Three If By Whiskey
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2014-03-17 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: bundler
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '1.5'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '1.5'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rake
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
description:
|
47
|
+
email:
|
48
|
+
- 3ifbyw@gmail.com
|
49
|
+
executables: []
|
50
|
+
extensions: []
|
51
|
+
extra_rdoc_files: []
|
52
|
+
files:
|
53
|
+
- .gitignore
|
54
|
+
- Gemfile
|
55
|
+
- LICENSE
|
56
|
+
- README.md
|
57
|
+
- Rakefile
|
58
|
+
- church.gemspec
|
59
|
+
- lib/church.rb
|
60
|
+
- lib/church/array.rb
|
61
|
+
- lib/church/math.rb
|
62
|
+
- lib/church/version.rb
|
63
|
+
- spec/array_spec.rb
|
64
|
+
- spec/math_spec.rb
|
65
|
+
- spec/spec_helper.rb
|
66
|
+
homepage: ''
|
67
|
+
licenses:
|
68
|
+
- WTFPL
|
69
|
+
post_install_message:
|
70
|
+
rdoc_options: []
|
71
|
+
require_paths:
|
72
|
+
- lib
|
73
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
74
|
+
none: false
|
75
|
+
requirements:
|
76
|
+
- - ! '>='
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: '0'
|
79
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
80
|
+
none: false
|
81
|
+
requirements:
|
82
|
+
- - ! '>='
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: '0'
|
85
|
+
requirements: []
|
86
|
+
rubyforge_project:
|
87
|
+
rubygems_version: 1.8.23
|
88
|
+
signing_key:
|
89
|
+
specification_version: 3
|
90
|
+
summary: Church provides top-level constant Procs to do various and sundry kinds of
|
91
|
+
functional programming.
|
92
|
+
test_files:
|
93
|
+
- spec/array_spec.rb
|
94
|
+
- spec/math_spec.rb
|
95
|
+
- spec/spec_helper.rb
|