functions 0.0.16 → 0.0.17

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: f9f07df0e596091bea7d6f8f57d4c877faf3d9bd
4
- data.tar.gz: 0642fda991a8aa220b809d22c474f9af47b4ed24
2
+ SHA256:
3
+ metadata.gz: d884db3d112ebd90fee4cf4ab66325b3800988821512fa097a5bd684dac6024b
4
+ data.tar.gz: 640c89f3e47031e0f0320c8c9eb8ad811af88779658c6cb0befef25222aaecad
5
5
  SHA512:
6
- metadata.gz: ea82380d54e0fbb0469c88f9d009662ef803e3d841f9638a894a30d964752b7f94eb0b68c7c04f86d965333cb4182786c322a4fec9d744fc47f41ab82786977e
7
- data.tar.gz: 6c3c534d39be490690e25761d09193355bc02a1496404fa222871eb5f71290b7e878f510839e690fb849eb6a927633e063cd8f5627c9327ddfc9290d9bab18a0
6
+ metadata.gz: ed27fb9cface5baeb4dd000385eda0886425549ec90db99ea2f2afdde51b019cae3f479790d3d5107f48695feded0225e5fed7a50cd2196684df00bf9714a88a
7
+ data.tar.gz: 5613d93811123dfbd9be92ff0e6c33101cb652af8ad8a4ca3afa4ec68c453ebd26317d5176bf09435f31d1b4d0b868a6d23b72d968aefc27c02c9ae10de63bdf
data/.rspec CHANGED
@@ -1,3 +1,2 @@
1
1
  --color
2
2
  --format progress
3
- # --default_path spec
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.1
4
+ - 2.0
data/Gemfile CHANGED
@@ -3,6 +3,12 @@ source 'https://rubygems.org'
3
3
  # Specify your gem's dependencies in functions.gemspec
4
4
  gemspec
5
5
 
6
+ # gem 'coveralls', require: false
7
+ # gem 'rake'
8
+
6
9
  group :test do
7
- gem 'test-unit'
10
+ # gem 'test-unit'
11
+ gem 'rake'
12
+ gem 'rspec'
13
+ gem 'coveralls', require: false
8
14
  end
data/README.md CHANGED
@@ -1,3 +1,11 @@
1
+
2
+ [![Gem Version](https://img.shields.io/gem/v/functions.svg)](https://rubygems.org/gems/functions)
3
+ [![Dependency Status](http://img.shields.io/gemnasium/koenhandekyn/functions.svg)](https://gemnasium.com/koenhandekyn/functions)
4
+ [![Build Status](http://img.shields.io/travis/koenhandekyn/functions.svg)](https://travis-ci.org/koenhandekyn/functions)
5
+ [![Code Climate](http://img.shields.io/codeclimate/github/koenhandekyn/functions.svg)](https://codeclimate.com/github/koenhandekyn/functions)
6
+ [![Coverage Status](https://img.shields.io/coveralls/koenhandekyn/functions.svg)](https://coveralls.io/r/koenhandekyn/functions)
7
+
8
+
1
9
  # Functional
2
10
 
3
11
  This library facilitates writing code in a more functional style inside Ruby.
data/Rakefile CHANGED
@@ -1,8 +1,22 @@
1
- require "bundler/gem_tasks"
2
- require 'rake/testtask'
1
+ # require "bundler/gem_tasks"
2
+ # require 'rake/testtask'
3
3
 
4
- Rake::TestTask.new do |t|
5
- t.libs << "test" << "."
6
- t.test_files = FileList['test/test*.rb']
7
- t.verbose = false
4
+ # Rake::TestTask.new do |t|
5
+ # t.libs << "test" << "."
6
+ # t.test_files = FileList['test/test*.rb']
7
+ # t.verbose = false
8
+ # end
9
+
10
+ require 'rspec/core/rake_task'
11
+
12
+ desc 'run the basic specs'
13
+ RSpec::Core::RakeTask.new(:spec) do |spec|
14
+ spec.rspec_opts = ['--options', 'spec/rspec.opts']
8
15
  end
16
+
17
+ desc 'do some basic performance tests'
18
+ task :performance do
19
+ load 'performance/prelude_performance.rb'
20
+ end
21
+
22
+ task default: [:spec, :performance]
@@ -0,0 +1,6 @@
1
+ gem 'functions', path: '..'
2
+
3
+ group :test do
4
+ gem 'rake'
5
+ gem 'rspec'
6
+ end
@@ -0,0 +1,22 @@
1
+ # require "bundler/gem_tasks"
2
+ # require 'rake/testtask'
3
+
4
+ # Rake::TestTask.new do |t|
5
+ # t.libs << "test" << "."
6
+ # t.test_files = FileList['test/test*.rb']
7
+ # t.verbose = false
8
+ # end
9
+
10
+ require 'rspec/core/rake_task'
11
+
12
+ desc 'run the example specs'
13
+ RSpec::Core::RakeTask.new(:spec) do |spec|
14
+ spec.rspec_opts = ['--options', 'spec/rspec.opts']
15
+ end
16
+
17
+ desc 'run the examples'
18
+ task :examples do
19
+ load 'prelude_lambda.rb'
20
+ end
21
+
22
+ task default: [:spec, :examples]
@@ -7,14 +7,14 @@ module PreludeLambdaUsage
7
7
  Power = ->(p,x) { x**p }.curry
8
8
  Square = Power.(2)
9
9
  Squares = Map.(Square)
10
- Sum_Of_Squares1 = Compose.(Sum).(Squares)
11
- Sum_Of_Squares2 = Sum < Squares
12
- Sum_Of_Squares = Sum_Of_Squares2
10
+ SumOfSquares1 = Compose.(Sum).(Squares)
11
+ SumOfSquares2 = Sum < Squares
12
+ SumOfSquares = SumOfSquares2
13
13
 
14
- Inc_With = ->(f, n, m) { n + f.(m) }.curry
15
- Sum_Of1 = ->(f,arr) { Foldl.( Inc_With.(f), 0, arr) }.curry
16
- Sum_Of2 = ->(f) { ->(arr) { Foldl.( Inc_With.(f), 0, arr) } }
17
- Sum_Of = Sum_Of1
14
+ IncWith = ->(f, n, m) { n + f.(m) }.curry
15
+ SumOf1 = ->(f,arr) { Foldl.( IncWith.(f), 0, arr) }.curry
16
+ SumOf2 = ->(f) { ->(arr) { Foldl.( IncWith.(f), 0, arr) } }
17
+ SumOf = SumOf1
18
18
 
19
19
  # Average variations
20
20
  Average1 = After.( Parallel.(Sum).(Length) ).( Divide )
@@ -22,9 +22,7 @@ module PreludeLambdaUsage
22
22
  Average3 = After.( [Sum,Length] ).( Divide )
23
23
 
24
24
  # Gcd variations
25
- Gcd1 = ->(a, b) {
26
- (1..[a,b].min).select { |c| a % c == 0 && b % c == 0 }.max
27
- }
25
+ Gcd1 = ->(a, b) { (1..[a,b].min).select { |c| a % c == 0 && b % c == 0 }.max }
28
26
  Gcd2 = ->(a,b) { (Divisors.(a) & Divisors.(b)).max }
29
27
 
30
28
  # GcdA variations
@@ -37,7 +35,6 @@ module PreludeLambdaUsage
37
35
  Dividers = Map.(Divisors)
38
36
  GcdA4 = Greatest < Common < Dividers
39
37
 
40
-
41
38
  # LcmA variations
42
39
  LcmA1 = ->(arr) { arr.inject { |a, r| Lcm.(a, r) } } # the lcm of an array as an iteration of the lcm over the elements
43
40
  LcmA2 = ReduceLeft.(Lcm) # the same but without arguments
@@ -5,37 +5,37 @@ include PreludeLambdaUsage
5
5
  describe PreludeLambdaUsage, "basic lambda prelude usage" do
6
6
 
7
7
  it "sums" do
8
- Sum_Of_Squares.([2, 3, 4]).should == 2*2+3*3+4*4
9
- Sum_Of.(Square).([2, 3, 1]).should == 2*2+3*3+1*1
8
+ expect(SumOfSquares.([2, 3, 4])).to eq(2*2+3*3+4*4)
9
+ expect(SumOf.(Square).([2, 3, 1])).to eq(2*2+3*3+1*1)
10
10
  end
11
11
 
12
12
  it "averages" do
13
- Average.([2, 3, 8]).should == 4
13
+ expect(Average.([2, 3, 8])).to eq(4)
14
14
  end
15
15
 
16
16
  it "flattens" do
17
- Flatten.([[1, 2, 3], [2, 3]]).should == [1, 2, 3, 2, 3]
17
+ expect(Flatten.([[1, 2, 3], [2, 3]])).to eq([1, 2, 3, 2, 3])
18
18
  end
19
19
 
20
20
  it "folds" do
21
- Foldl.(->(n, a) { n/a }, 1.0, [1.0, 2.0, 3.0]).should == 1.0/1.0/2.0/3.0
22
- Foldr.(->(n, a) { n/a }, 1.0, [1.0, 2.0, 3.0]).should == 1.0/3.0/2.0/1.0
21
+ expect(Foldl.(->(n, a) { n/a }, 1.0, [1.0, 2.0, 3.0])).to eq(1.0/1.0/2.0/3.0)
22
+ expect(Foldr.(->(n, a) { n/a }, 1.0, [1.0, 2.0, 3.0])).to eq(1.0/3.0/2.0/1.0)
23
23
  end
24
24
 
25
25
  it "knows about GCD alternatives" do
26
26
  # test variant implementations
27
- Gcd1.(4,8).should == 4
28
- Gcd2.(4,8).should == 4
29
- GcdA1.([4,8,2]).should eq(2)
30
- GcdA2.([4,8,2]).should eq(2)
31
- GcdA3.([4,8,2]).should eq(2)
32
- GcdA4.([4,8,2]).should eq(2)
27
+ expect(Gcd1.(4,8)).to eq(4)
28
+ expect(Gcd2.(4,8)).to eq(4)
29
+ expect(GcdA1.([4,8,2])).to eq(2)
30
+ expect(GcdA2.([4,8,2])).to eq(2)
31
+ expect(GcdA3.([4,8,2])).to eq(2)
32
+ expect(GcdA4.([4,8,2])).to eq(2)
33
33
  end
34
34
 
35
35
  it "knows about LCM variations" do
36
36
  # test variant implementations
37
- LcmA1.([12,9,2]).should eq(36)
38
- LcmA2.([12,9,2]).should eq(36)
37
+ expect(LcmA1.([12,9,2])).to eq(36)
38
+ expect(LcmA2.([12,9,2])).to eq(36)
39
39
  end
40
40
 
41
41
 
@@ -8,10 +8,10 @@ Gem::Specification.new do |gem|
8
8
  gem.version = Functions::VERSION
9
9
  gem.authors = ["Koen Handekyn"]
10
10
  gem.email = ["koen.handekyn@up-nxt.com"]
11
- gem.description = %q{functional programming in ruby}
11
+ gem.description = %q{A prelude library that belongs to the book "functional programming in ruby".}
12
12
  gem.summary = %q{functional programming in ruby}
13
13
  gem.homepage = "https://github.com/koenhandekyn/functions"
14
- gem.license = 'AGPL'
14
+ gem.license = 'LGPL-3.0+'
15
15
  gem.files = `git ls-files`.split($/)
16
16
  gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
17
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
@@ -16,13 +16,6 @@ class Hash
16
16
  Hash[self.map{|k, v| [k, v.is_a?(Hash) ? v.map_values_recurse(&b) : b.(v)] }]
17
17
  end
18
18
 
19
- # definition of maarten
20
- # def map_values &blk
21
- # res = {}
22
- # each {|k,v| res[k] = blk.call(v)}
23
- # res
24
- # end
25
-
26
19
  # TODO discuss if we should not map onto array as values can colide
27
20
  def map_keys
28
21
  Hash[self.map{|k, v| [yield(k), v] }]
@@ -32,21 +25,6 @@ class Hash
32
25
  Hash[self.map{|k, v| [b.(k), v.is_a?(Hash) ? v.map_keys_recurse(&b) : v ] }]
33
26
  end
34
27
 
35
- # def map_keys
36
- # each_with_object({}) { |h, (k,v)| h[yield(k)] = v }
37
- # end
38
-
39
- # def map_keys &blk
40
- # each_with_object({}) {|h, (k,v)| h[blk.(k)] = v}
41
- # end
42
-
43
- # definition of maarten
44
- # def map_keys &blk
45
- # res = {}
46
- # each {|k,v| res[blk.call(k)] = v}
47
- # res
48
- # end
49
-
50
28
  # map a hash into a hash
51
29
  def map_hash
52
30
  Hash[ self.map{|k, v| yield(k,v) } ]
@@ -54,8 +32,8 @@ class Hash
54
32
 
55
33
  # map a hash into a hash recursively.
56
34
  # the mapping function needs to check itself wether or not the value is hash and act appropriately
57
- def map_recursive(&b)
58
- Hash[ self.map{|k, v| b.(k, v.is_a?(Hash) ? v.map_recursive(&b) : v) } ]
35
+ def map_recurse(&b)
36
+ Hash[ self.map{|k, v| b.(k, v.is_a?(Hash) ? v.map_recurse(&b) : v) } ]
59
37
  end
60
38
 
61
39
  # map a hash into a hash recursively with a seperate key mapping and value mapping function
@@ -68,14 +46,6 @@ class Hash
68
46
  Hash[ self.map{|k, v| b.(k, ( v.is_a?(Hash) ? v.multi_map(&b) : v) ) }.flatten(1) ]
69
47
  end
70
48
 
71
- # def map_hash &blk
72
- # res = {}
73
- # each do |k,v|
74
- # kk, vv = blk.call(k,v)
75
- # res[kk] = vv
76
- # end
77
- # res
78
- # end
79
49
 
80
50
  end
81
51
 
@@ -8,15 +8,18 @@ module Functions
8
8
  # the constant function
9
9
  Const = ->(c, x) { c }
10
10
 
11
+ # make a function resilient to nil inputs
12
+ Maybe = ->(fn) { ->(x) { fn.(x) unless x.nil? } }
13
+
11
14
  # splits a list xs in peices of size n
12
- Split_In = ->(n, xs) { xs.each_slice((xs.length+1)/n).to_a }
15
+ SplitIn = ->(n, xs) { xs.each_slice((xs.length+1)/n).to_a }
13
16
 
14
17
  # splits a list in half
15
- Split_In_Half = Split_In.curry.(2)
18
+ SplitInHalf = SplitIn.curry.(2)
16
19
 
17
20
  # merges two ordered lists by a function f that compares the values
18
21
  # if no function is given the values are compared by the "<" operator
19
- Merge_By = ->(f, xs, ys) do
22
+ MergeBy = ->(f, xs, ys) do
20
23
 
21
24
  return xs if ys.empty?
22
25
  return ys if xs.empty?
@@ -24,13 +27,13 @@ module Functions
24
27
  x, *xt = xs
25
28
  y, *yt = ys
26
29
 
27
- return Merge_By.(f, xt, ys) >> x if f.nil? ? x <= y : f.(x) <= f.(y)
28
- return Merge_By.(f, xs, yt) >> y
30
+ return MergeBy.(f, xt, ys) >> x if f.nil? ? x <= y : f.(x) <= f.(y)
31
+ return MergeBy.(f, xs, yt) >> y
29
32
 
30
33
  end
31
34
 
32
35
  # merges two list by the natural comparison operator <
33
- Merge = Merge_By.partial(nil)
36
+ Merge = MergeBy.partial(nil)
34
37
 
35
38
  # composes two functions
36
39
  Compose = ->(f, g, x) { f.(g.(x)) }.curry
@@ -38,6 +41,8 @@ module Functions
38
41
  # manually curried version of the Compose function
39
42
  ComposeCurried = ->(f) { ->(g) { ->(x) { f.(g.(x)) } } }
40
43
 
44
+ Chain = ->(*fns) { fns.reduce { |f, g| lambda { |x| f.(g.(x)) } } }
45
+
41
46
  # composes two functions in reverse sequence
42
47
  After = ->(f, g, x) {
43
48
  f = Par.(f) if Array === f;
@@ -81,17 +86,17 @@ module Functions
81
86
 
82
87
  Zip = ->(a, b) { a.zip(b) }.curry
83
88
 
84
- Merge_Hash = ->(as, bs) { as.merge(bs) { |k, a, b| [a, b] } }.curry
89
+ MergeHash = ->(as, bs) { as.merge(bs) { |k, a, b| [a, b] } }.curry
85
90
 
86
- Zip_Hash_Left = ->(as, bs) { as.each_with_object({}) { |(k, a), h| h[k] = [a, bs[k]]; h } }.curry
91
+ ZipHashLeft = ->(as, bs) { as.each_with_object({}) { |(k, a), h| h[k] = [a, bs[k]]; h } }.curry
87
92
 
88
- Zip_Hash_Inner = ->(as, bs) { as.each_with_object({}) { |(k, a), h| b = bs[k]; h[k] = [a, b] if b; h } }.curry
93
+ ZipHashInner = ->(as, bs) { as.each_with_object({}) { |(k, a), h| b = bs[k]; h[k] = [a, b] if b; h } }.curry
89
94
 
90
- Zip_Hash_Right = ->(as, bs) { bs.each_with_object({}) { |(k, b), h| h[k] = [as[k], b]; h } }.curry
95
+ ZipHashRight = ->(as, bs) { bs.each_with_object({}) { |(k, b), h| h[k] = [as[k], b]; h } }.curry
91
96
 
92
97
  Map = ->(f, a) { a.map { |x| f.(x) } }.curry
93
98
 
94
- Map_Hash = ->(f, h) { Hash[h.map{|k, v| [k, f.(v)] }] }.curry
99
+ MapHash = ->(f, h) { Hash[h.map{|k, v| [k, f.(v)] }] }.curry
95
100
 
96
101
  Filter = ->(f, xs) { xs.select { |x| f.(x) } }.curry
97
102
 
@@ -101,23 +106,23 @@ module Functions
101
106
 
102
107
  Intersect = ->(as) { as.inject(:&) }
103
108
 
104
- Group = ->(f,a) { a.group_by(&f) }.curry
109
+ Group = ->(f,a) { a.group_by(&f) }.curry
105
110
 
106
111
  Values = Send.(:values)
107
112
 
108
113
  # TODO investigate semantics
109
- Partition = ->(f) { Group.(f) > Values }
114
+ Partition = ->(f) { Group.(f) > Values }
110
115
 
111
116
  FromTo = ->(from) { ->(to) { Range.new(from, to) } }
112
117
 
113
118
  FromOneTo = FromTo.(1)
114
119
 
115
- Count_By = ->(f,a) { a.inject( Hash.new(0) ) { |h,e| h[f.(e)] += 1; h } }.curry
116
- # count_by = ->(f) { group_by.( f ) < map_hash.( send.(:length) ) }
117
-
118
- Count = ->(a) { a.inject( Hash.new(0) ) { |h,e| h[e] += 1; h } } # probably a bit faster
120
+ CountBy = ->(f,a) { a.inject( Hash.new(0) ) { |h,e| h[f.(e)] += 1; h } }.curry
121
+ # count_by = ->(f) { group_by.( f ) < map_hash.( send.(:length) ) }
122
+
123
+ Count = ->(a) { a.inject( Hash.new(0) ) { |h,e| h[e] += 1; h } } # probably a bit faster
119
124
  # count = count_by.(identity) # alternative definition (generic)
120
125
 
121
126
  end
122
127
 
123
- end
128
+ end
@@ -2,18 +2,18 @@ module Functions
2
2
 
3
3
  module Prelude
4
4
 
5
- Merge_Sort_By = ->(f, xs) do
5
+ MergeSortBy = ->(f, xs) do
6
6
 
7
7
  return xs if xs.length <= 1 # stopcondition
8
8
 
9
- left, right = Split_In_Half.(xs)
10
- Merge_By.(f, Merge_Sort_By.(f, left), Merge_Sort_By.(f, right))
9
+ left, right = SplitInHalf.(xs)
10
+ MergeBy.(f, MergeSortBy.(f, left), MergeSortBy.(f, right))
11
11
  end
12
12
 
13
- Merge_Sort = Merge_Sort_By.partial(nil)
13
+ MergeSort = MergeSortBy.partial(nil)
14
14
  # = Merge_Sort_By.partial(Identity)
15
15
 
16
- Quick_Sort_By = ->(f, list) do
16
+ QuickSortBy = ->(f, list) do
17
17
 
18
18
  return [] if list.size == 0
19
19
  return list if list.size == 1
@@ -21,10 +21,10 @@ module Functions
21
21
  pivot, *xs = *list
22
22
  smaller_than = f.nil? ? ->(y) { y < pivot } : ->(y) { f.(y) < f.(pivot) }
23
23
  less, more = xs.partition &smaller_than
24
- Quick_Sort_By.(f, less) + [pivot] + Quick_Sort_By.(f, more)
24
+ QuickSortBy.(f, less) + [pivot] + QuickSortBy.(f, more)
25
25
  end
26
26
 
27
- Quick_Sort = Quick_Sort_By.partial(nil)
27
+ QuickSort = QuickSortBy.partial(nil)
28
28
  # = Quick_Sort_By.partial(Identity)
29
29
 
30
30
  end
@@ -1,3 +1,3 @@
1
1
  module Functions
2
- VERSION = "0.0.16"
2
+ VERSION = "0.0.17"
3
3
  end
@@ -8,7 +8,7 @@ include PreludeLambdaUsage
8
8
 
9
9
  [10, 100, 1000, 10000].each do |n|
10
10
  Benchmark.bm(40) do |b|
11
- b.report("Sum_Of_Squares(n=#{n}): ") { (100000/n).times { Sum_Of_Squares.((1..n).to_a) } }
11
+ b.report("Sum_Of_Squares(n=#{n}): ") { (100000/n).times { SumOfSquares.((1..n).to_a) } }
12
12
  end
13
13
  end
14
14
 
@@ -27,14 +27,14 @@ end
27
27
  [10, 100, 1000].each do |n|
28
28
  random_array = (0..n).to_a.shuffle
29
29
  Benchmark.bm(40) do |b|
30
- b.report("Merge_Sort(n=#{n}): ") { (100000/n).times { Merge_Sort.(random_array) } }
30
+ b.report("Merge_Sort(n=#{n}): ") { (100000/n).times { MergeSort.(random_array) } }
31
31
  end
32
32
  end
33
33
 
34
34
  [10, 100, 1000].each do |n|
35
35
  random_array = (0..n).to_a.shuffle
36
36
  Benchmark.bm(40) do |b|
37
- b.report("Quick_Sort(n=#{n}): ") { (100000/n).times { Quick_Sort.(random_array) } }
38
- b.report("Quick_Sort/identity(n=#{n}): ") { (100000/n).times { Quick_Sort_By.(Id, random_array) } }
37
+ b.report("Quick_Sort(n=#{n}): ") { (100000/n).times { QuickSort.(random_array) } }
38
+ b.report("Quick_Sort/identity(n=#{n}): ") { (100000/n).times { QuickSortBy.(Id, random_array) } }
39
39
  end
40
40
  end
@@ -1,131 +1,131 @@
1
- require 'functions/prelude_enumerable'
1
+ require 'spec_helper'
2
2
 
3
3
  describe "enumerable" do
4
4
 
5
5
  it "zip_map" do
6
- [1,2,3].zip([2,3,4]).map { |a,b| a+b }.should eq([3,5,7])
7
- [1,2,3].zip_map([2,3,4]) { |a,b| a+b }.should eq([3,5,7])
8
- [1,2,3].zip_map([2,3,4],[0,1,0]) { |a,b,c| a+b+c }.should eq([3,6,7])
9
- [1,2,3].zip_map([2,3,4]).with_index { |(a,b),n| a+b+n }.should eq([3,6,9])
6
+ expect([1,2,3].zip([2,3,4]).map { |a,b| a+b }).to eq([3,5,7])
7
+ expect([1,2,3].zip_map([2,3,4]) { |a,b| a+b }).to eq([3,5,7])
8
+ expect([1,2,3].zip_map([2,3,4],[0,1,0]) { |a,b,c| a+b+c }).to eq([3,6,7])
9
+ expect([1,2,3].zip_map([2,3,4]).with_index { |(a,b),n| a+b+n }).to eq([3,6,9])
10
10
  end
11
11
 
12
12
  it "transpose" do
13
- [[1,2,3]].transpose.should eq([[1],[2],[3]])
14
- [[1,2,3],[:a,:b,:c]].transpose.should eq([[1,:a],[2,:b],[3,:c]])
13
+ expect([[1,2,3]].transpose).to eq([[1],[2],[3]])
14
+ expect([[1,2,3],[:a,:b,:c]].transpose).to eq([[1,:a],[2,:b],[3,:c]])
15
15
  end
16
16
 
17
17
  it "zip, unzip" do
18
18
  ns = [1,2,3]
19
19
  as = [:a,:b,:c]
20
- ns.zip(as).unzip.should eq([ns, as])
20
+ expect(ns.zip(as).unzip).to eq([ns, as])
21
21
  end
22
22
 
23
23
  it "split_in" do
24
- [1,2,3].split_in(1).should eq([[1,2,3]])
25
- [1,2,3].split_in(2).should eq([[1,2],[3]])
26
- [1,2,3].split_in(3).should eq([[1],[2],[3]])
27
- [1,2,3].split_in(4).should eq([[1],[2],[3],[]]) # do we want this ? length 3 ? or lenght 4 ?
28
- [1,2,3].split_in_half.should eq([[1,2],[3]])
24
+ expect([1,2,3].split_in(1)).to eq([[1,2,3]])
25
+ expect([1,2,3].split_in(2)).to eq([[1,2],[3]])
26
+ expect([1,2,3].split_in(3)).to eq([[1],[2],[3]])
27
+ expect([1,2,3].split_in(4)).to eq([[1],[2],[3],[]]) # do we want this ? length 3 ? or lenght 4 ?
28
+ expect([1,2,3].split_in_half).to eq([[1,2],[3]])
29
29
  end
30
30
 
31
31
  it "merge" do
32
32
  # starts with ordered sets
33
- [1,3,5].merge([3,4,8]).should eq([1,3,3,4,5,8])
34
- [1,3,5].merge([2]).should eq([1,2,3,5])
35
- [].merge([1,2,3]).should eq([1,2,3])
36
- [1,2,3].merge([]).should eq([1,2,3])
37
- [3,2,1].merge([4,2,1]) { |a,b| a > b }.should eq([4,3,2,2,1,1])
33
+ expect([1,3,5].merge([3,4,8])).to eq([1,3,3,4,5,8])
34
+ expect([1,3,5].merge([2])).to eq([1,2,3,5])
35
+ expect([].merge([1,2,3])).to eq([1,2,3])
36
+ expect([1,2,3].merge([])).to eq([1,2,3])
37
+ expect([3,2,1].merge([4,2,1]) { |a,b| a > b }).to eq([4,3,2,2,1,1])
38
38
  end
39
39
 
40
40
  it "interleave" do
41
- %w(sex druggs rock roll).interleave([", "," and "," & "]).join("").should eq("sex, druggs and rock & roll")
42
- [3,1,4].interleave([:a,:d,:b]).should eq([3,:a,1,:d,4,:b])
43
- [3,1,4].interleave([:a,:d]).should eq([3,:a,1,:d,4])
44
- [3,1,4].interleave([:a]).should eq([3,:a,1,4])
45
- [3,1,4].interleave([]).should eq([3,1,4])
41
+ expect(%w(sex druggs rock roll).interleave([", "," and "," & "]).join("")).to eq("sex, druggs and rock & roll")
42
+ expect([3,1,4].interleave([:a,:d,:b])).to eq([3,:a,1,:d,4,:b])
43
+ expect([3,1,4].interleave([:a,:d])).to eq([3,:a,1,:d,4])
44
+ expect([3,1,4].interleave([:a])).to eq([3,:a,1,4])
45
+ expect([3,1,4].interleave([])).to eq([3,1,4])
46
46
  end
47
47
 
48
48
  it "zip_hash" do
49
49
  ab = {a: 'a', b: 'b'}
50
50
  ad = {a: 'a', d: 'd'}
51
51
  cb = {c: 'c', b: 'b'}
52
- ab.zip_hash_left(ad).should eq({a: ['a','a'], b:['b',nil]})
53
- ab.zip_hash_left(cb).should eq({a: ['a',nil], b:['b','b']})
54
- ad.zip_hash_left(cb).should eq({a: ['a',nil], d:['d',nil]})
55
- ab.zip_hash_inner(ad).should eq({a:['a','a']})
56
- ab.zip_hash_inner(cb).should eq({b:['b','b']})
57
- ad.zip_hash_inner(cb).should eq({})
52
+ expect(ab.zip_hash_left(ad)).to eq({a: ['a','a'], b:['b',nil]})
53
+ expect(ab.zip_hash_left(cb)).to eq({a: ['a',nil], b:['b','b']})
54
+ expect(ad.zip_hash_left(cb)).to eq({a: ['a',nil], d:['d',nil]})
55
+ expect(ab.zip_hash_inner(ad)).to eq({a:['a','a']})
56
+ expect(ab.zip_hash_inner(cb)).to eq({b:['b','b']})
57
+ expect(ad.zip_hash_inner(cb)).to eq({})
58
58
  end
59
59
 
60
60
  it "map_values" do
61
61
  ab = {a: 1, b: 2}
62
- ab.map_values { |x| x*2}.should == {a: 2, b: 4}
63
- ab.map_values { |x| x.even? }.should == {a: false, b: true}
62
+ expect(ab.map_values { |x| x*2}).to eq({a: 2, b: 4})
63
+ expect(ab.map_values { |x| x.even? }).to eq({a: false, b: true})
64
64
  end
65
65
 
66
66
  it "map_values_recurse" do
67
67
  abcde = {a: 1, b: 2, c: { d: 1, e: 0 } }
68
- abcde.map_values_recurse { |x| x*2}.should == {a: 2, b: 4, c: { d: 2, e: 0}}
69
- abcde .map_values_recurse { |x| x.even? }.should == {a: false, b: true, c: { d:false, e: true}}
68
+ expect(abcde.map_values_recurse { |x| x*2}).to eq({a: 2, b: 4, c: { d: 2, e: 0}})
69
+ expect(abcde.map_values_recurse { |x| x.even? }).to eq({a: false, b: true, c: { d:false, e: true}})
70
70
  end
71
71
 
72
72
  it "map_keys" do
73
73
  ab = {a: 1, b: 2}
74
- ab.map_keys { |k| k.to_s }.should == {"a" => 1, "b" => 2}
75
- ab.map_keys { |k| k.to_s[0].ord }.should == { 97 => 1, 98 => 2 }
76
- ab.map_keys { |k| k.to_s.length }.should == { 1 => 2 }
74
+ expect(ab.map_keys { |k| k.to_s }).to eq({"a" => 1, "b" => 2})
75
+ expect(ab.map_keys { |k| k.to_s[0].ord }).to eq({ 97 => 1, 98 => 2 })
76
+ expect(ab.map_keys { |k| k.to_s.length }).to eq({ 1 => 2 })
77
77
  end
78
78
 
79
79
  it "map_keys_recurse" do
80
80
  abcde = {a: 1, b: 2, c: { d: 1, e: 0 } }
81
- abcde.map_keys_recurse { |k| k.to_s }.should == {"a" => 1, "b" => 2, "c" => { "d" => 1, "e" => 0 }}
81
+ expect(abcde.map_keys_recurse { |k| k.to_s }).to eq({"a" => 1, "b" => 2, "c" => { "d" => 1, "e" => 0 }})
82
82
  end
83
83
 
84
84
  it "map_hash" do
85
85
  ab = {a: 1, b: 2}
86
- ab.map_hash { |k,v| [k.to_s, v*2] }.should == {"a" => 2, "b" => 4}
87
- ab.map_hash { |k,v| [k.to_s[0].ord, v.even?] }.should == {97 => false, 98 => true}
88
- ab.map_hash { |k,v| [k.to_s.length, v.even?] }.should == {1 => true}
86
+ expect(ab.map_hash { |k,v| [k.to_s, v*2] }).to eq({"a" => 2, "b" => 4})
87
+ expect(ab.map_hash { |k,v| [k.to_s[0].ord, v.even?] }).to eq({97 => false, 98 => true})
88
+ expect(ab.map_hash { |k,v| [k.to_s.length, v.even?] }).to eq({1 => true})
89
89
  end
90
90
 
91
91
  it "map_recursive" do
92
92
  abcde = {a: 1, b: 2, c: { d: 1, e: 0 } }
93
- abcde.map_recursive { |k,v| v.is_a?(Hash) ? [k.to_s, v] : [k.to_s, v*2] }.should == {"a" => 2, "b" => 4, "c" => { "d" => 2, "e" => 0 }}
94
- abcde.map_recursive { |k,v| v.is_a?(Hash) ? [k.to_s[0].ord, v] : [k.to_s[0].ord, v.even?] }.should == {97 => false, 98 => true, 99 => { 100 => false, 101 => true }}
95
- abcde.map_recursive { |k,v| v.is_a?(Hash) ? [k.to_s.length, v] : [k.to_s.length, v.even?] }.should == {1 => true, 1 => { 1=>true } }
93
+ expect(abcde.map_recurse { |k,v| v.is_a?(Hash) ? [k.to_s, v] : [k.to_s, v*2] }).to eq({"a" => 2, "b" => 4, "c" => { "d" => 2, "e" => 0 }})
94
+ expect(abcde.map_recurse { |k,v| v.is_a?(Hash) ? [k.to_s[0].ord, v] : [k.to_s[0].ord, v.even?] }).to eq({97 => false, 98 => true, 99 => { 100 => false, 101 => true }})
95
+ expect(abcde.map_recurse { |k,v| v.is_a?(Hash) ? [k.to_s.length, v] : [k.to_s.length, v.even?] }).to eq({1 => { 1=>true } })
96
96
  end
97
97
 
98
98
  it "map_keys_and_values" do
99
-
99
+
100
100
  s = ->(x) { x.to_s }
101
101
  s_ord = ->(x) { x.to_s[0].ord }
102
102
  s_length = ->(x) { x.to_s.length }
103
103
  times_2 = ->(x) { x * 2 }
104
104
  even = ->(x) { x.even? }
105
-
105
+
106
106
  abcde = {a: 1, b: 2, c: { d: 1, e: 0 } }
107
107
 
108
- abcde.map_keys_and_values(s, times_2).should == {"a" => 2, "b" => 4, "c" => { "d" => 2, "e" => 0 }}
109
- abcde.map_keys_and_values(s_ord, even).should == {97 => false, 98 => true, 99 => { 100 => false, 101 => true }}
110
- abcde.map_keys_and_values(s_length, even).should == {1 => true, 1 => { 1=>true } }
108
+ expect(abcde.map_keys_and_values(s, times_2)).to eq({"a" => 2, "b" => 4, "c" => { "d" => 2, "e" => 0 }})
109
+ expect(abcde.map_keys_and_values(s_ord, even)).to eq({97 => false, 98 => true, 99 => { 100 => false, 101 => true }})
110
+ expect(abcde.map_keys_and_values(s_length, even)).to eq({1 => { 1=>true } })
111
111
 
112
112
  end
113
113
 
114
114
  it "counted_set" do
115
- [1,2,3,2,2,1,2].counted_set.should eq({1 => 2, 2 => 4, 3 => 1})
116
- ['a','b','a','d'].counted_set.should eq({'a' => 2, 'b' => 1, 'd' => 1})
115
+ expect([1,2,3,2,2,1,2].counted_set).to eq({1 => 2, 2 => 4, 3 => 1})
116
+ expect(['a','b','a','d'].counted_set).to eq({'a' => 2, 'b' => 1, 'd' => 1})
117
117
  end
118
118
 
119
119
  it "grouped_by" do
120
- [1,2,3,2,2,1,2].grouped_by { |x| x.odd? }.should eq([[1,3,1],[2,2,2,2]])
121
- %w(some words are longer then others).grouped_by { |x| x.length > 3 }.should eq([%w(some words longer then others),%w(are)])
120
+ expect([1,2,3,2,2,1,2].grouped_by { |x| x.odd? }).to eq([[1,3,1],[2,2,2,2]])
121
+ expect(%w(some words are longer then others).grouped_by { |x| x.length > 3 }).to eq([%w(some words longer then others),%w(are)])
122
122
  end
123
123
 
124
- it "multimap" do
124
+ it "multi_map" do
125
125
 
126
126
  folders = { 'main[2]' => { 'child[3]' => 'leaf', 'simple' => 'leaf' } }
127
127
 
128
- multiply_folder = -> (k,v) do
128
+ multiply_folder = ->(k,v) do
129
129
  match = k.match(/(.*)\[(\d+)\]/)
130
130
  k, count = match ? [match[1], match[2].to_i] : [k, nil]
131
131
  if count
@@ -136,8 +136,8 @@ describe "enumerable" do
136
136
  end
137
137
 
138
138
  multiplied = folders.multi_map &multiply_folder
139
- multiplied.length.should eq(2)
140
- multiplied['main_1'].length.should eq(4)
139
+ expect(multiplied.length).to eq(2)
140
+ expect(multiplied['main_1'].length).to eq(4)
141
141
 
142
142
  end
143
- end
143
+ end
@@ -1,44 +1,42 @@
1
- require 'functions'
2
-
3
- include Functions::Prelude
1
+ require 'spec_helper'
4
2
 
5
3
  describe Functions::Prelude, "math" do
6
4
 
7
5
  it "divides" do
8
- Divide.([9,2]).should eq(9/2)
9
- Divide.([8,2,2]).should eq(8/2/2)
6
+ expect(Divide.([9,2])).to eq(9/2)
7
+ expect(Divide.([8,2,2])).to eq(8/2/2)
10
8
  end
11
9
 
12
10
  it "power" do
13
- Power.(2,3).should eq(9)
14
- Power.(0,3).should eq(1)
15
- Power.(3,2).should eq(8)
11
+ expect(Power.(2,3)).to eq(9)
12
+ expect(Power.(0,3)).to eq(1)
13
+ expect(Power.(3,2)).to eq(8)
16
14
  end
17
15
 
18
16
  it "knows about divisors" do
19
- IsDivisor.(8,2).should eq(true)
20
- IsDivisor.(8,3).should eq(false)
21
- Divisors.(12).sort.should eq([1,2,3,4,6,12])
17
+ expect(IsDivisor.(8,2)).to eq(true)
18
+ expect(IsDivisor.(8,3)).to eq(false)
19
+ expect(Divisors.(12).sort).to eq([1,2,3,4,6,12])
22
20
  end
23
21
 
24
22
  it "knows about range building" do
25
- FromOneTo.(3).should eq(1..3)
26
- FromOneTo.(3).to_a.should eq([1,2,3])
27
- FromTo.(2).(8).to_a.should eq([2,3,4,5,6,7,8])
23
+ expect(FromOneTo.(3)).to eq(1..3)
24
+ expect(FromOneTo.(3).to_a).to eq([1,2,3])
25
+ expect(FromTo.(2).(8).to_a).to eq([2,3,4,5,6,7,8])
28
26
  end
29
27
 
30
28
  it "knows about gcd" do
31
- Gcd.(12,9).should eq(3)
32
- Gcd.(4,8).should eq(4)
33
- GcdA.([12,9,6]).should eq(3)
34
- GcdA.([4,8,2]).should eq(2)
29
+ expect(Gcd.(12,9)).to eq(3)
30
+ expect(Gcd.(4,8)).to eq(4)
31
+ expect(GcdA.([12,9,6])).to eq(3)
32
+ expect(GcdA.([4,8,2])).to eq(2)
35
33
  end
36
34
 
37
35
  it "knows about lcm" do
38
- Lcm.(12,9).should eq(36)
39
- Lcm.(6,8).should eq(24)
40
- LcmA.([12,9]).should eq(36)
41
- LcmA.([12,9,2]).should eq(36)
36
+ expect(Lcm.(12,9)).to eq(36)
37
+ expect(Lcm.(6,8)).to eq(24)
38
+ expect(LcmA.([12,9])).to eq(36)
39
+ expect(LcmA.([12,9,2])).to eq(36)
42
40
  end
43
41
 
44
42
  end
@@ -1,6 +1,4 @@
1
- require 'functions'
2
-
3
- include Functions::Prelude
1
+ require 'spec_helper'
4
2
 
5
3
  describe Functions::Prelude, "basic" do
6
4
 
@@ -10,52 +8,52 @@ describe Functions::Prelude, "basic" do
10
8
 
11
9
  it "composes" do
12
10
  sum_of_squares = Compose.(Sum).(Squares)
13
- sum_of_squares.([2, 3, 4]).should eq(4+9+16)
11
+ expect(sum_of_squares.([2, 3, 4])).to eq(4+9+16)
14
12
  end
15
13
 
16
14
  it "has a compose operator" do
17
15
  sum_of_squares = Sum < Squares
18
- sum_of_squares.([2, 3, 4]).should eq(4+9+16)
16
+ expect(sum_of_squares.([2, 3, 4])).to eq(4+9+16)
19
17
  end
20
18
 
21
19
  it "folds" do
22
20
  inc_with = ->(f, n, m) { n + f.(m) }.curry
23
21
  sum_of = ->(f, arr) { Foldl.(inc_with.(f), 0, arr) }.curry
24
- sum_of.(Square).([1,2,3]).should eq(1+4+9)
22
+ expect(sum_of.(Square).([1,2,3])).to eq(1+4+9)
25
23
  end
26
24
 
27
25
  it "composes using after with implicit parallel" do
28
26
  average = After.([Sum, Length]).(Divide)
29
- average.([2, 3, 8]).should eq((2+3+8)/3)
27
+ expect(average.([2, 3, 8])).to eq((2+3+8)/3)
30
28
  end
31
29
 
32
30
  it "mixes parallel with after operator" do
33
31
  average = Parallel.(Sum, Length) > Divide
34
- average.([2, 3, 8]).should eq((2+3+8)/3)
32
+ expect(average.([2, 3, 8])).to eq((2+3+8)/3)
35
33
  end
36
34
 
37
35
  it "mixes par with after operator" do
38
36
  average = Par.([Sum, Length]) > Divide
39
- average.([2, 3, 8]).should eq((2+3+8)/3)
37
+ expect(average.([2, 3, 8])).to eq((2+3+8)/3)
40
38
  end
41
39
 
42
40
  it "flattens arrays" do
43
- Flatten.([[1, 2, 3], [2, 3]]).should eq([1,2,3,2,3])
41
+ expect(Flatten.([[1, 2, 3], [2, 3]])).to eq([1,2,3,2,3])
44
42
  end
45
43
 
46
44
  it "sorts arrays" do
47
- Quick_Sort.([3,3,5,6,7,1,2]).should == [1,2,3,3,5,6,7]
48
- Quick_Sort.([1,1,1,1,1,1,1]).should == [1,1,1,1,1,1,1]
49
- Merge_Sort.([3,3,5,6,7,1,2]).should == [1,2,3,3,5,6,7]
45
+ expect(QuickSort.([3,3,5,6,7,1,2])).to eq([1,2,3,3,5,6,7])
46
+ expect(QuickSort.([1,1,1,1,1,1,1])).to eq([1,1,1,1,1,1,1])
47
+ expect(MergeSort.([3,3,5,6,7,1,2])).to eq([1,2,3,3,5,6,7])
50
48
  end
51
49
 
52
50
  it "merges hashes" do
53
51
  a = { a: 'a', b: 'b' }
54
52
  b = { a: '1', c: '3' }
55
- Merge_Hash.(a,b).should == { a: ['a','1'], b: 'b', c: '3' }
56
- Zip_Hash_Left.(a,b).should == { a: ['a','1'], b: ['b', nil] }
57
- Zip_Hash_Right.(a,b).should == { a: ['a','1'], c: [nil, '3'] }
58
- Zip_Hash_Inner.(a,b).should == { a: ['a','1'] }
53
+ expect(MergeHash.(a,b)).to eq({ a: ['a','1'], b: 'b', c: '3' })
54
+ expect(ZipHashLeft.(a,b)).to eq({ a: ['a','1'], b: ['b', nil] })
55
+ expect(ZipHashRight.(a,b)).to eq({ a: ['a','1'], c: [nil, '3'] })
56
+ expect(ZipHashInner.(a,b)).to eq({ a: ['a','1'] })
59
57
  end
60
58
 
61
- end
59
+ end
@@ -1,13 +1,15 @@
1
- # This file was generated by the `rspec --init` command. Conventionally, all
2
- # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
- # Require this file using `require "spec_helper"` to ensure that it is only
4
- # loaded once.
5
- #
6
- # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
1
+ require 'coveralls'
2
+ Coveralls.wear!
3
+
4
+ require 'functions'
5
+
7
6
  RSpec.configure do |config|
8
- config.treat_symbols_as_metadata_keys_with_true_values = true
7
+
9
8
  config.run_all_when_everything_filtered = true
10
9
  config.filter_run :focus
10
+ config.raise_errors_for_deprecations!
11
+
12
+ include Functions::Prelude
11
13
 
12
14
  # Run specs in random order to surface order dependencies. If you find an
13
15
  # order dependency and want to debug it, you can fix the order by providing
@@ -1,4 +1,6 @@
1
- require 'examples/prelude_lambda'
1
+ $LOAD_PATH << 'lib'
2
+
3
+ require_relative '../examples/spec/prelude_lambda_spec'
2
4
 
3
5
  require 'minitest/autorun'
4
6
  require 'minitest/benchmark'
metadata CHANGED
@@ -1,16 +1,17 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: functions
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.16
4
+ version: 0.0.17
5
5
  platform: ruby
6
6
  authors:
7
7
  - Koen Handekyn
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-04-08 00:00:00.000000000 Z
11
+ date: 2018-12-01 00:00:00.000000000 Z
12
12
  dependencies: []
13
- description: functional programming in ruby
13
+ description: A prelude library that belongs to the book "functional programming in
14
+ ruby".
14
15
  email:
15
16
  - koen.handekyn@up-nxt.com
16
17
  executables: []
@@ -19,11 +20,13 @@ extra_rdoc_files: []
19
20
  files:
20
21
  - ".gitignore"
21
22
  - ".rspec"
23
+ - ".travis.yml"
22
24
  - Gemfile
23
25
  - LICENSE.txt
24
26
  - README.md
25
27
  - Rakefile
26
- - examples/multi_hash_map_recursive.rb
28
+ - examples/Gemfile
29
+ - examples/Rakefile
27
30
  - examples/prelude_lambda.rb
28
31
  - examples/spec/prelude_lambda_spec.rb
29
32
  - functions.gemspec
@@ -47,7 +50,7 @@ files:
47
50
  - test/test_prelude_performance.rb
48
51
  homepage: https://github.com/koenhandekyn/functions
49
52
  licenses:
50
- - AGPL
53
+ - LGPL-3.0+
51
54
  metadata: {}
52
55
  post_install_message:
53
56
  rdoc_options: []
@@ -65,7 +68,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
65
68
  version: '0'
66
69
  requirements: []
67
70
  rubyforge_project:
68
- rubygems_version: 2.2.1
71
+ rubygems_version: 2.7.3
69
72
  signing_key:
70
73
  specification_version: 4
71
74
  summary: functional programming in ruby
@@ -1,19 +0,0 @@
1
- require_relative '../lib/functions'
2
-
3
- folders = {
4
- 'main[2]' => { 'child[3]' => 'leaf'}
5
- }
6
-
7
- def multiply_folder(k,v)
8
- match = k.match(/(.*)\[(\d+)\]/)
9
- k, count = match ? [match[1], match[2].to_i] : [k, nil]
10
- if count
11
- (1..count).map { |i| ["#{k}_#{i}",v] }
12
- else
13
- [[k,v]]
14
- end
15
- end
16
-
17
- multiplied = folders.multi_map_hash_recursive &multiply_folder
18
-
19
- puts multiplied