funtools 0.4.0 → 0.5.0

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
2
  SHA1:
3
- metadata.gz: 147a7fd803443d3bc56481e35023bfe25a9c6510
4
- data.tar.gz: 81b7a9752e0bc7af02b4a713e77fa0b88afa67e7
3
+ metadata.gz: 0faa0f3d082df30457dbd13eae82d9d78b582cda
4
+ data.tar.gz: ea596071898a6e7eca90869cc3b31fba9165c8b6
5
5
  SHA512:
6
- metadata.gz: 7991f402cc958d2872f038e2d48ad180224771a5488a7500744b97955b5a7db227f3b6d306bc6f13eb267391e84f6fb64ddd89ef4a8c791a2fd7bf5c1dc2b046
7
- data.tar.gz: b372da0baad485064622feceb0fecccae595a8b2273a6f20beadb61816055e7fc0daac467a0eba2577a12b7bf7ebd2f7a9a2d06aade9cc1325787ba9c856f1fd
6
+ metadata.gz: 5397fff059b62f1b280866424d72fcb28724ca691246cd7f350a0c0439b889dc0bcc57e31a4131b0b775400da0a348c00fad2028409e491fa44dc777cf6b1875
7
+ data.tar.gz: 510345cfabb0889d1debd002ac34624309358e040d02132824e97ebba5f59bd77347baa78550a9edd79664ecfb8b993e92a09b213850993e9efcda21fa6821ca
@@ -0,0 +1,92 @@
1
+ class Object
2
+ # Public: Wrap Cons.new to construct a new Cons cell.
3
+ #
4
+ # left - Any Object to be the left element of the cell.
5
+ # right - Any Object to be the right element of the cell.
6
+ #
7
+ # Returns a Cons cell.
8
+ def cons(left, right)
9
+ Cons.new(left, right)
10
+ end
11
+
12
+ # Public: Construct a list of nested Cons cells.
13
+ #
14
+ # first - Any Object to be the leftmost element of the list.
15
+ # second - Any Object to be the second element of the list (default: nil).
16
+ # rest - Any number of Objects to serve as elements in the list.
17
+ #
18
+ # Returns a list (nested Cons cells).
19
+ def list(first, second = nil, *rest)
20
+ set = (rest.empty? && second.nil?) ? [] : rest + [nil]
21
+ ([first, second] + set).reverse.reduce { |c, e| Cons.new(e, c) }
22
+ end
23
+ end
24
+
25
+ class Cons
26
+ include Enumerable
27
+
28
+ attr_reader :car, :cdr
29
+
30
+ alias :head :car
31
+ alias :tail :cdr
32
+
33
+ # Public: Create a Cons cell.
34
+ #
35
+ # left - Any Object to be the left element of the cell.
36
+ # right - Any Object to be the right element of the cell.
37
+ def initialize(left, right)
38
+ @car = left
39
+ @cdr = right
40
+ end
41
+
42
+ # Public: Iterate through each element of a Cons cell/list. Note that Cons
43
+ # cells will be yielded without inspecting their contents if they are in the
44
+ # left position of a parent Cons cell.
45
+ #
46
+ # Yields each element.
47
+ def each(&block)
48
+ block.(car)
49
+ right = cdr
50
+
51
+ while right
52
+ if right.is_a?(Cons)
53
+ if [right.car, right.cdr].grep(Cons).any? || right.cdr.nil?
54
+ block.(right.car)
55
+ right = right.cdr
56
+ else
57
+ block.(right)
58
+ right = nil
59
+ end
60
+ else
61
+ block.(right) unless right.nil?
62
+ right = nil
63
+ end
64
+ end
65
+ end
66
+
67
+ # Public: Determine whether two Cons cells/lists are equivalent.
68
+ #
69
+ # other - Object to be compared against.
70
+ #
71
+ # Returns true or false.
72
+ def ==(other)
73
+ return false unless other.is_a?(Cons)
74
+ to_a == other.to_a
75
+ end
76
+
77
+ # Public: Produce a string representation of a Cons cell/list.
78
+ #
79
+ # Returns a String.
80
+ def inspect
81
+ last = nil
82
+ r = [1].cycle.reduce([self]) do |c,_|
83
+ break c if c == last
84
+ last = c
85
+ c.flatten.map do |e|
86
+ e.is_a?(Cons) ? ['(', e.to_a.zip([' '].cycle).flatten[0..-2], ')'] :
87
+ e.nil? ? 'nil' : e
88
+ end
89
+ end.map(&:to_s).join
90
+ end
91
+ alias :to_s :inspect
92
+ end
@@ -7,20 +7,31 @@ class Object
7
7
  #
8
8
  # Returns nothing.
9
9
  def defpattern(sym)
10
+ match = ->(a, b) do
11
+ if([a,b].map { |o| o.is_a?(Enumerable) && a.class == b.class }.all?)
12
+ raise ArgumentError unless a.length == b.length
13
+
14
+ zipped = a.is_a?(Hash) ? a.sort.zip(b.sort) : a.zip(b)
15
+
16
+ zipped.reduce(true) do |c, e|
17
+ c && match.(*e)
18
+ end
19
+ else
20
+ a.nil? || a == b
21
+ end
22
+ end
23
+
10
24
  old_method = self.class.method(sym) if self.class.method_defined?(:sym)
11
25
  patterns = []
12
26
  self.class.send(:define_method, sym) do |*l, &b|
13
27
  patterns << ->(*n) do
14
28
  ->(*m) do
15
- flat_m = m.flatten
16
- flat_n = n.flatten
17
- if flat_m.length == flat_n.length
18
- e = flat_m.zip(n.flatten)
19
- unless e.reject { |e| e[0].nil? || e[0]==e[1] }.any?
20
- instance_exec(*flat_n, &b)
21
- end
29
+ if m.length == n.length
30
+ e = m.zip(n)
31
+ raise NoMatch if e.reject { |e| match.(*e) }.any?
32
+ instance_exec(*n, &b)
22
33
  end
23
- end.(l.flatten)
34
+ end.(*l)
24
35
  end
25
36
  end
26
37
 
@@ -36,10 +47,14 @@ class Object
36
47
  message ||= :define_singleton_method
37
48
  self.send(message, sym) do |*args|
38
49
  patterns.each do |pattern|
39
- result = instance_exec(*args, &pattern)
40
- return result unless result.nil?
50
+ begin
51
+ return instance_exec(*args, &pattern)
52
+ rescue NoMatch
53
+ end
41
54
  end
42
- nil
55
+ instance_exec { raise NoMatch }
43
56
  end
44
57
  end
45
58
  end
59
+
60
+ class NoMatch < ArgumentError; end
data/lib/funtools.rb CHANGED
@@ -1,7 +1,8 @@
1
+ require 'funtools/cons'
1
2
  require 'funtools/recursion'
2
3
  require 'funtools/composition'
3
4
  require 'funtools/pattern-matching'
4
5
 
5
6
  module Funtools
6
- VERSION = '0.4.0'
7
+ VERSION = '0.5.0'
7
8
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: funtools
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tina Wuest
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-09-14 00:00:00.000000000 Z
11
+ date: 2014-10-16 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Tools to assist in programming in a more functional style
14
14
  email: tina@wuest.me
@@ -18,6 +18,7 @@ extra_rdoc_files: []
18
18
  files:
19
19
  - lib/funtools.rb
20
20
  - lib/funtools/composition.rb
21
+ - lib/funtools/cons.rb
21
22
  - lib/funtools/pattern-matching.rb
22
23
  - lib/funtools/recursion.rb
23
24
  homepage: https://gitlab.com/wuest/funtools