functions 0.0.16 → 0.0.17

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.
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