-
-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathfunction.rb
More file actions
132 lines (117 loc) · 3.05 KB
/
Copy pathfunction.rb
File metadata and controls
132 lines (117 loc) · 3.05 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# frozen_string_literal: true
require 'dry/transformer/composite'
module Dry
module Transformer
# Transformation proc wrapper allowing composition of multiple procs into
# a data-transformation pipeline.
#
# This is used by Dry::Transformer to wrap registered methods.
#
# @api private
class Function
# Wrapped proc or another composite function
#
# @return [Proc,Composed]
#
# @api private
attr_reader :fn
# Additional arguments that will be passed to the wrapped proc
#
# @return [Array]
#
# @api private
attr_reader :args
# Additional keyword arguments that will be passed to the wrapped proc
#
# @return [Hash]
#
# @api private
attr_reader :kwargs
# @!attribute [r] name
#
# @return [<type] The name of the function
#
# @api public
attr_reader :name
# @api private
def initialize(fn, options = {})
@fn = fn
@args = options.fetch(:args, [])
@kwargs = options.fetch(:kwargs, {})
@name = options.fetch(:name, fn)
end
# Call the wrapped proc
#
# @param [Object] value The input value
#
# @alias []
#
# @api public
def call(*value, **additional_kwargs)
fn.call(*value, *args, **(kwargs).merge(additional_kwargs))
end
alias_method :[], :call
# Compose this function with another function or a proc
#
# @param [Proc,Function]
#
# @return [Composite]
#
# @alias :>>
#
# @api public
def compose(other)
Composite.new(self, other)
end
alias_method :+, :compose
alias_method :>>, :compose
# Return a new fn with curried args
#
# @return [Function]
#
# @api private
def with(*args, **additional_kwargs)
self.class.new(fn, name: name, args: args, kwargs: kwargs.merge(additional_kwargs))
end
# @api public
def ==(other)
return false unless other.instance_of?(self.class)
[fn, name, args, kwargs] == [other.fn, other.name, other.args, other.kwargs]
end
alias_method :eql?, :==
# Return a simple AST representation of this function
#
# @return [Array]
#
# @api public
def to_ast
[name, object_to_ast(args), object_to_ast(kwargs)]
end
# Converts a transproc to a simple proc
#
# @return [Proc]
#
def to_proc
if !args.empty?
proc { |*value| fn.call(*value, *args, **kwargs) }
else
fn.to_proc
end
end
private
# @api private
def object_to_ast(object)
case object
when Array
object.map { |item| object_to_ast(item) }
when Hash
object.each_with_object({}) { |(key, value), hash|
hash[object_to_ast(key)] = object_to_ast(value)
}
else
object.respond_to?(:to_ast) ? object.to_ast : object
end
end
end
end
end