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 +4 -4
- data/lib/funtools/cons.rb +92 -0
- data/lib/funtools/pattern-matching.rb +26 -11
- data/lib/funtools.rb +2 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0faa0f3d082df30457dbd13eae82d9d78b582cda
|
4
|
+
data.tar.gz: ea596071898a6e7eca90869cc3b31fba9165c8b6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
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
|
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
|
-
|
40
|
-
|
50
|
+
begin
|
51
|
+
return instance_exec(*args, &pattern)
|
52
|
+
rescue NoMatch
|
53
|
+
end
|
41
54
|
end
|
42
|
-
|
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
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
|
+
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-
|
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
|