functions 0.0.3 → 0.0.4

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.
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ Yjc3YjRkZDYwYmMzZjZmYmUwMzVjMTVkZGQxYWJkMThlZWEyZWJiMg==
5
+ data.tar.gz: !binary |-
6
+ Y2ZmYjg4OGJiNTg1ZmQxY2M1MjMxNmZmMzZjNWE2ODU5NWY1YzljOA==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ NGRmMWYxMmY1ZTU0OWY1ZTM0ODk5ZmJhNTZkNjQwYmJmNWU3NmExZmViYWM3
10
+ NzQxOTYwMzliNTRhMDczNDE5OTRhZmYzYWE0MjhhNjZkODYyOTBiYTlkM2Y3
11
+ YzQwMmM2YjkxZTZkMjczNWM5YWVjNGQ0NmM2ODRmZjhiZjgxN2Q=
12
+ data.tar.gz: !binary |-
13
+ MDNmNDYxZDRlMDMzN2ZkM2U0ODY3MTkyZGMzN2JhMDAyMzA0ZGFkMmJiZWVi
14
+ NGRmYzFkZGY3OWI1ZjAzZjJiZDk0NmQ2M2JkZDI1ZjRjNWQyM2U4YTdmOGZj
15
+ ZjM5Nzg2NzlhZTVlYTNlMTMzOGFjYThjZTdkYzRkMTcxNmZiNDQ=
data/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  # Functional
2
2
 
3
3
  This library facilitates writing code in a more functional style inside Ruby.
4
+ How this is fun.
4
5
 
5
6
  ## Installation
6
7
 
@@ -39,10 +40,10 @@ The lambda style allows you to write functions like this
39
40
 
40
41
  Average = After.( [Sum,Length] ).( Divide )
41
42
 
42
- Gcd = ->(a,b) { (Divisors.(a) & Divisors.(b)).max }
43
+ Gcd = ->(a,b) { (Divisors.(a) & Divisors.(b)).max } # literal translation of the definition, just as an example
43
44
 
44
45
  # Gcd of an array
45
- GcdA1 = Max < Intersect < Map.(Divisors) # litteral translation of the definition
46
+ GcdA1 = Max < Intersect < Map.(Divisors) # literal translation of the definition
46
47
  GcdA2 = ReduceLeft.(Gcd) # faster
47
48
 
48
49
  # Lcm of an array in function of Lcm of a pair
@@ -76,6 +77,13 @@ The meta style allows you to write functions like this
76
77
 
77
78
  end
78
79
 
80
+ ## License
81
+
82
+ This code is currently copyrighted under the AGPL license.
83
+ See <http://www.gnu.org/licenses/agpl.html> for more information.
84
+
85
+ ![AGPL license](http://www.gnu.org/graphics/agplv3-155x51.png)
86
+
79
87
  ## Contributing
80
88
 
81
89
  1. Fork it
@@ -4,69 +4,55 @@ module PreludeMetaUsage
4
4
 
5
5
  include Functions::PreludeMeta
6
6
 
7
- def power(x, p)
8
- x ** p
9
- end
7
+ # returns x to the power of p
8
+ def power(x, p) x ** p end
10
9
 
11
- def square(x)
12
- power(x, 2)
13
- end
10
+ # returns x^2
11
+ def square(x) power(x, 2) end
14
12
 
15
- def_map :squares, :square
13
+ # returns the list of the squares
14
+ def squares(a) map(a, :square) end
16
15
 
17
- def squares_bis(a)
18
- map(a, :square)
19
- end
16
+ define :squares_bis, as: { map: :square }
20
17
 
21
- def_map :squares_tris, ->(x) { x**2 }
18
+ # test
19
+ # def_map :squares, :square
20
+ # def_map :squares_tris, ->(x) { x**2 }
21
+ # define :squares, as: { map: ->(x) { x**2 } }
22
22
 
23
- define :squares_quater, as: { map: ->(x) { x**2 } }
23
+ # returns all elements of an enumerable that are even
24
+ define :evens, as: { filter: :even? }
24
25
 
25
- define :squares_quinquies, as: { map: :square }
26
+ # def_filter :evens, :even?
26
27
 
27
- def_filter :evens, :even?
28
-
29
- # same as above
30
28
  # filter :evens, :even?
31
29
 
32
- def_filter :odds, ->(x) { ! x.even? }
30
+ define :odds, as: { filter: :odd? }
33
31
 
34
- define :evens_bis, as: { filter: :even? }
32
+ # def_filter :odds, ->(x) { ! x.even? }
35
33
 
36
- def_compose :sum_of_squares, :sum, :squares
34
+ def sum_of_squares(a) compose(:sum, :squares, a) end
37
35
 
38
- def sum_of_squares_bis(a)
39
- compose(:sum, :squares, a)
40
- end
36
+ define :sum_of_squares_bis, as: { compose: [:sum, :squares] }
41
37
 
42
- define :sum_of_squares_tris, as: { compose: [:sum, :squares] }
38
+ # compose :sum_of_squares, :sum, :squares
43
39
 
44
- def average_bis(a)
45
- after([:sum, :length], :divide, a)
46
- end
40
+ def average_bis(a) after([:sum, :length], :divide, a) end
47
41
 
48
42
  define :average_tris, as: { :after => [ :sum_length, :divide ] }
49
43
 
50
- def_after :average_quater, :sum_length, :divide
44
+ # after :average_quater, :sum_length, :divide
51
45
 
52
- def inc_with(f, n, m)
53
- m + f(f).(n)
54
- end
46
+ def inc_with(f, n, m) m + f(f).(n) end
55
47
 
56
- # can this be improved on ?
57
- # a definition as composition ?
58
- def sum_of(f, a)
59
- a.inject(0) { |r, x| r + f(f).(x) }
60
- end
48
+ def sum_of(f, a) a.inject(0) { |r, x| r + f(f).(x) } end
61
49
 
62
- def add(a,b)
63
- a+b
64
- end
50
+ def add(a,b) a+b end
65
51
 
66
- def_foldl :sum_bis, :add, 0
52
+ define :sum_bis, as: { foldl: [:add, 0]}
67
53
 
68
- define :sum_tris, as: { foldl: [:add, 0]}
54
+ # foldl :sum_bis, :add, 0
69
55
 
70
- define foldl: [:add, 0], as: :sum_quater
56
+ # define foldl: [:add, 0], as: :sum_quater
71
57
 
72
58
  end
@@ -7,53 +7,27 @@ describe PreludeMetaUsage, "basic meta prelude usage" do
7
7
  it "squares" do
8
8
  squares([1, 2, 3]).should == [1, 4, 9]
9
9
  squares_bis([1, 2, 3]).should == [1, 4, 9]
10
- squares_tris([1, 2, 3]).should == [1, 4, 9]
11
- squares_quater([1, 2, 3]).should == [1, 4, 9]
12
- squares_quinquies([1, 2, 3]).should == [1, 4, 9]
13
10
  end
14
11
 
15
12
  it "evens and odds" do
16
13
  evens([1, 2, 3, 4, 5]).should == [2, 4]
17
- evens_bis([1, 2, 3, 4, 5]).should == [2, 4]
18
14
  odds([1, 2, 3, 4, 5]).should == [1, 3, 5]
19
15
  end
20
16
 
21
- it "takes sums of squares and more" do
22
- sum_of_squares([2, 3, 4]).should == 2*2+3*3+4*4
23
- sum_of_squares_bis([2, 3, 4]).should == 2*2+3*3+4*4
24
- sum_of_squares_tris([2, 3, 4]).should == 2*2+3*3+4*4
17
+ it "takes sums of squares" do
25
18
  sum_of(:square, [2, 3, 1]).should == 2*2+3*3+1*1
26
19
  sum_of(->(x) { x*x }, [2, 3, 1]).should == 2*2+3*3+1*1
27
- sum([1, 2, 3]).should == 1+2+3
20
+ sum_of_squares([2, 3, 4]).should == 2*2+3*3+4*4
21
+ sum_of_squares_bis([2, 3, 4]).should == 2*2+3*3+4*4
22
+ end
23
+
24
+ it "takes sums by some variant definitions" do
28
25
  sum_bis([1, 2, 3]).should == 1+2+3
29
- sum_tris([1, 2, 3]).should == 1+2+3
30
- sum_quater([1, 2, 3]).should == 1+2+3
31
26
  end
32
27
 
33
- it "takes averages" do
34
- average([2, 3, 8]).should == 4
28
+ it "takes averages by some variant definitions" do
35
29
  average_bis([2, 3, 8]).should == 4
36
30
  average_tris([2, 3, 8]).should == 4
37
- average_quater([2, 3, 8]).should == 4
38
- end
39
-
40
- it "folds" do
41
- foldl(->(n, a) { n/a }, 1.0, [1.0, 2.0, 3.0]).should == 1.0/1.0/2.0/3.0
42
- foldr(->(n, a) { n/a }, 1.0, [1.0, 2.0, 3.0]).should == 1.0/3.0/2.0/1.0
43
- end
44
-
45
- it "mins and maxes" do
46
- min([1, 2, 3]).should == 1
47
- max([1, 2, 3]).should == 3
48
- end
49
-
50
- it "makes ranges" do
51
- from_to(2, 3).should == (2..3)
52
- from_one_to(3).should == (1..3)
53
- end
54
-
55
- it "intersects arrays" do
56
- intersect([[1, 2, 3], [2, 3, 4], [2, 3, 8]]).should == [2, 3]
57
31
  end
58
32
 
59
33
  end
@@ -2,14 +2,20 @@ module Functions
2
2
 
3
3
  module Prelude
4
4
 
5
+ # the identity function
5
6
  Id = ->(x) { x }
6
7
 
8
+ # the constant function
7
9
  Const = ->(c, x) { c }
8
10
 
11
+ # splits a list xs in peices of size n
9
12
  Split_In = ->(n, xs) { xs.each_slice((xs.length+1)/n).to_a }
10
13
 
14
+ # splits a list in half
11
15
  Split_In_Half = Split_In.curry.(2)
12
16
 
17
+ # merges two lists by a function f that compares the values
18
+ # if no function is given the values are compared by the "<" operator
13
19
  Merge_By = ->(f, xs, ys) do
14
20
 
15
21
  return xs if ys.empty?
@@ -23,37 +29,49 @@ module Functions
23
29
 
24
30
  end
25
31
 
32
+ # merges two list by the natural comparison operator <
26
33
  Merge = Merge_By.partial(nil)
27
34
 
35
+ # composes two functions
28
36
  Compose = ->(f, g, x) { f.(g.(x)) }.curry
29
37
 
30
- # Manually curried version
31
- # ComposeCurried = ->(f) { ->(g) { ->(x) { f.(g.(x)) } } }
38
+ # manually curried version of the Compose function
39
+ ComposeCurried = ->(f) { ->(g) { ->(x) { f.(g.(x)) } } }
32
40
 
41
+ # composes two functions in reverse sequence
33
42
  After = ->(f, g, x) {
34
43
  f = Par.(f) if Array === f;
35
44
  g = Par.(g) if Array === g;
36
45
  g.(f.(x))
37
46
  }.curry
38
47
 
39
- # Manually Curried Version
40
- # AfterCurried = ->(f) { ->(g) { ->(x) {
41
- # f = Par.(f) if Array === f;
42
- # g = Par.(g) if Array === g;
43
- # g.(f.(x))
44
- # } } }
48
+ # manually curried Version of the After composition function
49
+ AfterCurried = ->(f) { ->(g) { ->(x) {
50
+ f = Par.(f) if Array === f;
51
+ g = Par.(g) if Array === g;
52
+ g.(f.(x))
53
+ } } }
45
54
 
55
+ # sends the message m to an object o
56
+ #
57
+ # @param [Symbol] the method to be called on the object o
58
+ # @return the result of calling the message m on the object o
46
59
  Send = ->(m, o) { o.send(m) }.curry
47
60
 
61
+ # Flattens an array
62
+ #
63
+ # @param [#flatten] the array to flatten
48
64
  Flatten = Send.(:flatten)
49
- # Flatten = ->(a) { a.flatten }
50
65
 
66
+ # Reverses an array
67
+ #
68
+ # @param [#reverse] the array to reverse
51
69
  Reverse = Send.(:reverse)
52
- # Reverse = ->(a) { a.reverse }
53
70
 
71
+ # Returns the length
54
72
  Length = Send.(:length)
55
- # Length = ->(x) { x.length }
56
73
 
74
+ #
57
75
  Foldl = ->(f, i, a) { a.inject(i) { |r, x| f.(r, x) } }.curry
58
76
 
59
77
  ReduceLeft = ->(f, a) { a.inject { |r, x| f.(r, x) } }.curry
@@ -66,7 +84,7 @@ module Functions
66
84
 
67
85
  Map = ->(f, a) { a.map { |x| f.(x) } }.curry
68
86
 
69
- Filter = ->(xs, f) { xs.select { |x| f.(x) } }.curry
87
+ Filter = ->(f, xs) { xs.select { |x| f.(x) } }.curry
70
88
 
71
89
  Parallel = ->(f, g, x) { [f.(x), g.(x)] }.curry
72
90
 
@@ -10,6 +10,9 @@ class Array
10
10
  end
11
11
 
12
12
  class Proc
13
+ def self.compose(f, g)
14
+ ->(*args) { g[f[*args]] }
15
+ end
13
16
  # Composition of Procs (functions): (f+g)(x) = f(g(x))
14
17
  def +(g)
15
18
  # Prelude::Compose.(self,g)
@@ -29,4 +32,4 @@ class Proc
29
32
  def partial(a)
30
33
  self.curry.(a)
31
34
  end
32
- end
35
+ end
@@ -16,7 +16,7 @@ module Functions
16
16
 
17
17
  IsDivisor = ->(a, c) { a % c == 0 }
18
18
 
19
- Divisors = ->(a) { Filter.(FromOneTo.(a), IsDivisor.partial(a)) }
19
+ Divisors = ->(a) { Filter.(IsDivisor.partial(a), FromOneTo.(a)) }
20
20
 
21
21
  Gcd = ->(a, b) { b == 0 ? a : Gcd.(b, a % b) } # euclid algorithm
22
22
 
@@ -15,6 +15,7 @@ module Functions
15
15
 
16
16
  Quick_Sort_By = ->(f, list) do
17
17
  return [] if list.size == 0
18
+ return list if list.size == 1
18
19
  pivot, *xs = *list
19
20
  smaller_than = f.nil? ? ->(y) { y < pivot } : ->(y) { f.(y) < f.(pivot) }
20
21
  less, more = xs.partition &smaller_than
@@ -47,13 +47,13 @@ module Functions
47
47
  module_eval(code)
48
48
  end
49
49
 
50
- alias :def_compose :compose
50
+ #alias :def_compose :compose
51
51
 
52
52
  def after(c, f, g)
53
53
  compose(c, g, f)
54
54
  end
55
55
 
56
- alias :def_after :after
56
+ #alias :def_after :after
57
57
 
58
58
  def parallel(c, f, g)
59
59
  m = create_proc_method(c, f, :f)
@@ -66,7 +66,7 @@ module Functions
66
66
  module_eval(code)
67
67
  end
68
68
 
69
- alias :def_parallel :parallel
69
+ #alias :def_parallel :parallel
70
70
 
71
71
  def foldl(c, f, i)
72
72
  m = create_proc_method(c, f)
@@ -78,7 +78,7 @@ module Functions
78
78
  module_eval(code)
79
79
  end
80
80
 
81
- alias :def_foldl :foldl
81
+ #alias :def_foldl :foldl
82
82
 
83
83
  def reduce_left(c, f)
84
84
  m = create_proc_method(c, f)
@@ -90,7 +90,7 @@ module Functions
90
90
  module_eval(code)
91
91
  end
92
92
 
93
- alias :def_reduce_left :reduce_left
93
+ #alias :def_reduce_left :reduce_left
94
94
 
95
95
  def foldr(c, f, i)
96
96
  m = create_proc_method(c, f)
@@ -102,7 +102,7 @@ module Functions
102
102
  module_eval(code)
103
103
  end
104
104
 
105
- alias :def_foldr :foldr
105
+ #alias :def_foldr :foldr
106
106
 
107
107
  def reduce_right(c, f)
108
108
  m = create_proc_method(c, f)
@@ -114,7 +114,7 @@ module Functions
114
114
  module_eval(code)
115
115
  end
116
116
 
117
- alias :def_reduce_right :reduce_right
117
+ #alias :def_reduce_right :reduce_right
118
118
 
119
119
  def map(c, f)
120
120
  m = create_proc_method(c, f)
@@ -126,7 +126,7 @@ module Functions
126
126
  module_eval(code)
127
127
  end
128
128
 
129
- alias :def_map :map
129
+ #alias :def_map :map
130
130
 
131
131
  def filter(c, f)
132
132
  m = create_proc_method(c, f)
@@ -138,7 +138,7 @@ module Functions
138
138
  module_eval(code)
139
139
  end
140
140
 
141
- alias :def_filter :filter
141
+ #alias :def_filter :filter
142
142
 
143
143
  def method(m)
144
144
  code = %Q{
@@ -222,21 +222,21 @@ module Functions
222
222
 
223
223
  def_method :flatten
224
224
 
225
- #def flatten(a)
226
- # a.flatten
227
- #end
228
-
225
+ # @return calls the length method on the object
229
226
  def_method :length
230
227
 
231
- #def length(a)
232
- # a.length
233
- #end
234
-
228
+ # @param object the target object
229
+ # @return calls the reverse method on the object
235
230
  def_method :reverse
236
231
 
237
- #def reverse(a)
238
- # a.reverse
239
- #end
232
+ # @param object [#min] the object to call the min method on
233
+ # @return calls the min method on the Enumerable
234
+ def_method :min
235
+
236
+ # @param [#max] the object to call the max method on
237
+ # @return [Integer] the maximum
238
+ def_method :max
239
+
240
240
 
241
241
  def foldl(f, i, a)
242
242
  a.inject(i) { |r, x| f(f).(r, x) }
@@ -280,15 +280,12 @@ module Functions
280
280
 
281
281
  define :average, as: { :after => [ :sum_length, :divide ] }
282
282
 
283
- # TODO write with operator :& ?
284
- # def_reduce_left :intersect, ->(a,b) { a&b } # short
285
- # reduce_left :intersect, ->(a,b) { a&b } # longer
286
283
  define :intersect, as: {reduce_left: ->(a, b) { a&b }} # longest
287
284
 
288
- def_method :min
289
-
290
- def_method :max
291
-
285
+ # creates a range
286
+ #
287
+ # param from [Fixnum] the start of the range
288
+ # param to [Fixnum] the end of the range
292
289
  def from_to(from, to)
293
290
  Range.new(from, to)
294
291
  end
@@ -3,4 +3,15 @@ class Array
3
3
  def >> a
4
4
  self.unshift a
5
5
  end
6
+ end
7
+
8
+ module Kernel
9
+
10
+ def tailrecurse(&b)
11
+ result = []
12
+ loop do
13
+ result = b.(*result)
14
+ end
15
+ end
16
+
6
17
  end
@@ -1,3 +1,3 @@
1
1
  module Functions
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.4"
3
3
  end
@@ -43,4 +43,10 @@ describe Functions::Prelude, "basic" do
43
43
  Flatten.([[1, 2, 3], [2, 3]]).should eq([1,2,3,2,3])
44
44
  end
45
45
 
46
+ 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]
50
+ end
51
+
46
52
  end
metadata CHANGED
@@ -1,15 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: functions
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
5
- prerelease:
4
+ version: 0.0.4
6
5
  platform: ruby
7
6
  authors:
8
7
  - Koen Handekyn
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-04-10 00:00:00.000000000 Z
11
+ date: 2013-10-17 00:00:00.000000000 Z
13
12
  dependencies: []
14
13
  description: functional programming in ruby
15
14
  email:
@@ -46,27 +45,26 @@ files:
46
45
  - test/test_prelude_performance.rb
47
46
  homepage: https://github.com/koenhandekyn/functions
48
47
  licenses: []
48
+ metadata: {}
49
49
  post_install_message:
50
50
  rdoc_options: []
51
51
  require_paths:
52
52
  - lib
53
53
  required_ruby_version: !ruby/object:Gem::Requirement
54
- none: false
55
54
  requirements:
56
55
  - - ! '>='
57
56
  - !ruby/object:Gem::Version
58
57
  version: '0'
59
58
  required_rubygems_version: !ruby/object:Gem::Requirement
60
- none: false
61
59
  requirements:
62
60
  - - ! '>='
63
61
  - !ruby/object:Gem::Version
64
62
  version: '0'
65
63
  requirements: []
66
64
  rubyforge_project:
67
- rubygems_version: 1.8.24
65
+ rubygems_version: 2.1.9
68
66
  signing_key:
69
- specification_version: 3
67
+ specification_version: 4
70
68
  summary: functional programming in ruby
71
69
  test_files:
72
70
  - spec/prelude_lambda_math_spec.rb
@@ -74,3 +72,4 @@ test_files:
74
72
  - spec/prelude_meta_spec.rb
75
73
  - spec/spec_helper.rb
76
74
  - test/test_prelude_performance.rb
75
+ has_rdoc: