funtools 0.6.0 → 0.6.1

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.
Files changed (4) hide show
  1. checksums.yaml +4 -4
  2. data/lib/funtools.rb +1 -1
  3. data/lib/funtools/types.rb +56 -39
  4. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b6162644033dfb0b9f74e9160309669f04c2515f
4
- data.tar.gz: 05e8411ba686b59b795d704d7137d8d5eaa70cf2
3
+ metadata.gz: 85c1455381faf2166f294f26ce8b18012c1865e3
4
+ data.tar.gz: 1a36bf917be530c0081faff2d9c5dfa3890bf985
5
5
  SHA512:
6
- metadata.gz: d8b8d0ae31a9584ac89608d90612fad08965d96e64a4bf94009d5d5658ff8e2b68581f3b14380c69e5e4e665792998e1be68448fb876fd2ae3485537c71d4660
7
- data.tar.gz: fabe23f7ac2a025750a415a2a4485f1aeb58c585f39acc5090f2e81062407505d45159117226c4750f7fbaeb2a499712a2b1ba26ea18fa7348b7d3d3f89c7dc4
6
+ metadata.gz: dcb8af919e949195458d5481baa423b03434d05f12d05eb6ef6585066a680db4c7ce7f7bfc28e0bad684f9287ab920cf0959c7be9a9d7277ccff62361845719c
7
+ data.tar.gz: 0b7c58ed9c8e6f69e995dfaf9bf0d4120cdc4d64ab0f27506b9bf75af5b85ef7907f156cd7bebb0a97dd6b829ac7479aca995f26f5be090fe75dec4c5cfb794f
@@ -5,5 +5,5 @@ require 'funtools/composition'
5
5
  require 'funtools/pattern-matching'
6
6
 
7
7
  module Funtools
8
- VERSION = '0.6.0'
8
+ VERSION = '0.6.1'
9
9
  end
@@ -1,15 +1,63 @@
1
1
  class Object
2
- # Public: Define a method in the current scope which will execute a given
3
- # block recursively until a fixpoint is reached.
2
+ # Internal: Check a value to make sure it conforms to a given type.
3
+ #
4
+ # value - Value to be checked against types.
5
+ # type - Type definition to be used for type checking.
6
+ #
7
+ # Raises TypeError if the value does not match the expected type.
8
+ # Returns value.
9
+ check_type = ->(value, type) do
10
+ case type
11
+ when Class, Module
12
+ unless value.is_a?(type)
13
+ raise(TypeError, "Expected #{type}; got #{value.class}")
14
+ end
15
+ when Enumerable
16
+ unless type.map { |kind| value.is_a?(kind) }.any?
17
+ raise(TypeError, "Expected one of: #{type.join(', ')}; got #{value.class}")
18
+ end
19
+ else
20
+ raise(TypeError, "Unable to test type against #{type.class}")
21
+ end
22
+ value
23
+ end
24
+
25
+ # Internal: Align a set of expected types with the arguments given in a
26
+ # method call.
27
+ #
28
+ # typedefs - Array of types against which arguments should be checked.
29
+ # a - Array of arguments passed to a given method.
30
+ #
31
+ # Returns a 2-dimensional Array containing [Typedef, Value].
32
+ align_types = ->(typedefs, a) do
33
+ pivot = typedefs.index(typedefs.select { |k,n| k == :rest }.flatten)
34
+
35
+ if pivot
36
+ types_min = pivot + 1
37
+ args_num = a.length - types_min
38
+ rest_min = a.length - (args_num + 1)
39
+
40
+ typedefs[0...pivot].to_a.zip(a[0...pivot].to_a) +
41
+ a[pivot, args_num].to_a.zip([typedefs[pivot]].cycle).map(&:reverse) +
42
+ typedefs[types_min..-1].to_a.zip(a[rest_min..-1].to_a)
43
+ else
44
+ typedefs.zip(a)
45
+ end.reject { |t, v| v.nil? && t.first == :opt }.map { |t, v| [v, t.last] }
46
+ end
47
+
48
+ # Public: Define a method in the current scope which wraps an already-defined
49
+ # method, enforcing a type check on all arguments and the return value.
4
50
  #
5
51
  # sym - Symbol defining the name of the method to be created.
6
- # block - Block containing the logic for the function to be created.
52
+ # args - Zero or more types specified to correspond to arguments expected to
53
+ # be passed to the method in question.
54
+ # ret - Type the method in question is expected to return.
7
55
  #
8
56
  # Returns nothing.
9
- def settype(sym, *args, ret)
57
+ define_method(:settype) do |sym, *args, ret|
10
58
  message = :define_method if respond_to?(:define_method, true)
11
59
  message ||= :define_singleton_method
12
- old_method = self.method(sym)
60
+ old_method = begin method(sym) rescue instance_method(sym) end
13
61
  params = old_method.parameters
14
62
 
15
63
  typedefs = old_method.parameters.select do |kind,_|
@@ -18,41 +66,10 @@ class Object
18
66
  [req.first, args[index]]
19
67
  end
20
68
 
21
- check_type = ->(value, type) do
22
- case type
23
- when Class, Module
24
- unless value.is_a?(type)
25
- raise(TypeError, "Expected #{type}; got #{value.class}")
26
- end
27
- when Enumerable
28
- unless type.map { |kind| value.is_a?(kind) }.any?
29
- raise(TypeError, "Expected one of: #{type.join(', ')}; got #{value.class}")
30
- end
31
- else
32
- raise(TypeError, "Unable to test type against #{type.class}")
33
- end
34
- value
35
- end
36
-
37
- align_types = ->(a) do
38
- pivot = typedefs.index(typedefs.select { |k,n| k == :rest }.flatten)
39
-
40
- if pivot
41
- types_min = pivot + 1
42
- args_num = a.length - types_min
43
- rest_min = a.length - (args_num + 1)
44
-
45
- typedefs[0...pivot].to_a.zip(a[0...pivot].to_a) +
46
- a[pivot, args_num].to_a.zip([typedefs[pivot]].cycle).map(&:reverse) +
47
- typedefs[types_min..-1].to_a.zip(a[rest_min..-1].to_a)
48
- else
49
- typedefs.zip(a)
50
- end.reject { |t, v| v.nil? && t.first == :opt }.map { |t, v| [v, t.last] }
51
- end
52
-
53
69
  self.send(message, sym) do |*n, &b|
54
- align_types.(n).each { |pair| check_type.(*pair) }
55
- check_type.(old_method.(*n, &b), ret)
70
+ method = old_method.is_a?(Method) ? old_method : old_method.bind(self)
71
+ align_types.(typedefs, n).each { |pair| check_type.(*pair) }
72
+ check_type.(method.(*n, &b), ret)
56
73
  end
57
74
  end
58
75
  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.6.0
4
+ version: 0.6.1
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-10-28 00:00:00.000000000 Z
11
+ date: 2014-11-05 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