ex_aequo_base 0.1.17 → 0.2.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
  SHA256:
3
- metadata.gz: 427f016fdf311c7a305b83d2cc2ef8a1199f37940195b574afb9c0459206512e
4
- data.tar.gz: 9aa8f0cd446fe43423df6ae2c672c6a6318f176c3c93eeb4f018e524952cdb2d
3
+ metadata.gz: b07e39f7fa5cfc7d8dbd8db59b023f831ec214e3d281bc55f5430afb815c9028
4
+ data.tar.gz: 2fe81797ea2ed2a385dda8b8637aa8618ee2a4ff75fff224120d7cc09f0b6038
5
5
  SHA512:
6
- metadata.gz: c86372c80062a5009605cd1820cef0ee38c0c2524d3b373da9ef80619d0149f937976af1b98d85e973d316b8058db099e2c0eb0552136497f8a81606052e19b2
7
- data.tar.gz: a20308a7e791bc318001b7a92d965d281abd9ef7168a7890b0c8f20b8dc77c51b7ebef41ceada98d0d253e28db104dd0d657903e6a7ec7d5b76f56992de31ad2
6
+ metadata.gz: e011a5f3f439d0e2b8881885f6ac9bba59a7bdd8d7f0f65be791d24d3632ad644fb5d52b7c9addaa7ac57aab145cf08da2dd7ddc2aec72b4f25e9fbe81fe7773
7
+ data.tar.gz: c9ee6f3e9bb090efe94a8d17bdf82d1f5b97255376c542d57c2ac306efc4d52b4615abcb5ba3b77fd61c327134c82158e8e0d293b36a04b32d8e81edc1874b94
@@ -3,11 +3,13 @@ require_relative 'colorize'
3
3
  require_relative 'enumerable'
4
4
  require_relative 'fn'
5
5
  require_relative 'forwarder'
6
+ require_relative 'function'
6
7
  require_relative 'kernel'
7
8
  require_relative 'import_none'
8
9
  require_relative 'open_struct'
9
10
  require_relative 'regexp'
10
11
  require_relative 'string'
12
+ require_relative 'to_proc'
11
13
  # require_relative 'match_data'
12
14
  # Colorize = ExAequo::Base::Colorize
13
15
  # SPDX-License-Identifier: AGPL-3.0-or-later
@@ -6,7 +6,7 @@ module ExAequo
6
6
  module Base
7
7
  module Fn extend self
8
8
  extend Forwarder
9
- forward_all :curry, to: Helpers
9
+ forward_all :curry_send, :curry, to: Helpers
10
10
  end
11
11
  end
12
12
  end
@@ -3,52 +3,117 @@
3
3
  module ExAequo
4
4
  module Base
5
5
  module Fn
6
- Placeholder = BasicObject.new
6
+ PlaceholderClass = Class.new(BasicObject)
7
+ Placeholder = PlaceholderClass.new
7
8
 
8
9
  module Helpers extend self
9
- def curry(rcv, *positionals, **keywords, &blk)
10
- return _send_curry(*positionals, **keywords, &blk) if rcv == Placeholder
11
-
12
- _send_to(rcv, *positionals, **keywords, &blk)
10
+ def curry_send(*positionals, **keywords, &b)
11
+ -> (*args, **kwds, &blk) do
12
+ actual = _make_actual_params(positionals, args, keywords, kwds, arity: -1)
13
+ case actual
14
+ in {actual_args: [rcv, *actual_args], actual_kwds:, complete: true, **nil}
15
+ rcv.send(*actual_args, **actual_kwds, &(blk || b))
16
+ else
17
+ # This is a kludge to fix the simplecov missing branch _error_
18
+ actual in {actual_args: [_, *] => actual_args, actual_kwds:, complete: false, **nil}
19
+ curry_send(*actual_args, **actual_kwds, &(blk || b))
20
+ end
21
+ end
13
22
  end
14
23
 
15
- private
16
- def _make_actual_params(positionals, args, keywords, kwds, offset:)
17
- as = []
18
- ks = {}
19
- n = 0
24
+ def curry(*positionals, **keywords, &blk)
25
+ raise ArgumentError, "#{__method__} needs a block" unless blk
20
26
 
21
- positionals.each do
22
- if it == Placeholder
23
- as << args[n]
24
- n += 1
27
+ -> (*args, **kwds, &b) do
28
+ _make_actual_params(positionals, args, keywords, kwds, arity: blk.arity) => {actual_args:, actual_kwds:, complete:, **nil}
29
+ if complete
30
+ blk.(*actual_args, **actual_kwds, &b)
25
31
  else
26
- as << it
32
+ raise ArgumentError, "must not provide a block if function is still a partial application" if b
33
+ curry(*actual_args, **actual_kwds, &blk)
27
34
  end
28
35
  end
36
+ end
29
37
 
30
- keywords.each do |k, v|
31
- if v == Placeholder
32
- ks[k] = args[n]
33
- n += 1
34
- end
38
+ private
39
+ def _check_for_completeness(actual_args:, actual_kwds:, arity:)
40
+ if arity < 0
41
+ _check_for_min_completeness(actual_args:, actual_kwds:, arity: arity.abs.pred)
42
+ else
43
+ _check_for_exact_completeness(actual_args:, actual_kwds:, arity:)
35
44
  end
36
- as += Array(args[positionals.length-offset..])
37
- [as, keywords.merge(ks).merge(kwds)]
38
45
  end
39
46
 
40
- def _send_curry(*positionals, **keywords, &b)
41
- -> (rcv, *args, **kwds, &blk) do
42
- _make_actual_params(positionals, args, keywords, kwds, offset: 1) => actual_pos, actual_kwds
43
- rcv.send(*actual_pos, **actual_kwds, &(blk || b))
47
+ def _check_for_exact_completeness(actual_args:, actual_kwds:, arity:)
48
+ arity = arity - 1 unless actual_kwds.empty?
49
+ _check_for_placeholders(actual_args:, actual_kwds:) => {complete:, size:, **nil}
50
+ raise ArgumentError, "too many arguments arity = #{arity} but #{size} provided" if size > arity
51
+
52
+ return {actual_args:, actual_kwds:, complete:} if size == arity
53
+
54
+ {
55
+ actual_args: actual_args + [Placeholder] * (arity - size),
56
+ actual_kwds:,
57
+ complete: false
58
+ }
59
+ end
60
+
61
+ def _check_for_min_completeness(actual_args:, actual_kwds:, arity:)
62
+ _check_for_placeholders(actual_args:, actual_kwds:) => {complete:, size:, **nil}
63
+ return {actual_args:, actual_kwds:, complete:} if size >= arity
64
+
65
+ {
66
+ actual_args: actual_args + [Placeholder] * (arity - size),
67
+ actual_kwds:,
68
+ complete: false
69
+ }
70
+ end
71
+
72
+ def _check_for_placeholders(actual_args:, actual_kwds:)
73
+ size = actual_args.size
74
+ needed_kwds = actual_kwds.values.count { it == Placeholder }
75
+ complete = actual_args.none? { it == Placeholder }
76
+
77
+ complete &&= needed_kwds.zero?
78
+ {complete:, size:}
79
+ end
80
+
81
+ def _make_actual_params(curried_args, current_args, curried_kwds, current_kwds, arity:)
82
+ _make_actual_args(curried_args, current_args) in actual_args, remaining_args
83
+ _make_actual_kwds(curried_kwds, current_kwds, remaining_args) in actual_kwds, remaining_args
84
+
85
+ actual_args += remaining_args
86
+ actual_kwds = curried_kwds.merge(actual_kwds).merge(current_kwds)
87
+ _check_for_completeness(actual_args:, actual_kwds:, arity:)
88
+ end
89
+
90
+ def _make_actual_args(curried_args, actual_args)
91
+ as = []
92
+ curried_args.each do
93
+ if actual_args.empty?
94
+ as << it
95
+ elsif it == Placeholder
96
+ as << actual_args.first
97
+ actual_args = actual_args.drop(1)
98
+ else
99
+ as << it
100
+ end
44
101
  end
102
+ [as, actual_args]
45
103
  end
46
104
 
47
- def _send_to(rcv, *positionals, **keywords, &b)
48
- -> (*args, **kwds, &blk) do
49
- _make_actual_params(positionals, args, keywords, kwds, offset: 0) => actual_pos, actual_kwds
50
- rcv.send(*actual_pos, **actual_kwds, &(blk || b))
105
+ def _make_actual_kwds(curried_kwds, actual_kwds, remaining_args)
106
+ ks = {}
107
+ curried_kwds.each do |k, v|
108
+ if v == Placeholder
109
+ case remaining_args
110
+ in [arg, *remaining_args]
111
+ ks[k] = arg
112
+ else
113
+ end
114
+ end
51
115
  end
116
+ [ks, remaining_args]
52
117
  end
53
118
  end
54
119
  end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'fn/curry'
3
4
  require_relative 'to_proc'
4
5
  module ExAequo
5
6
  module Base
@@ -10,6 +11,11 @@ module ExAequo
10
11
  '!' => _not,
11
12
  }
12
13
 
14
+ def apply(fn_desc=nil, &blk)
15
+ fun = mk_fun_or(fn_desc, &blk)
16
+ -> (args) { fun.(*args) }
17
+ end
18
+
13
19
  def mk_fun(fn_desc)
14
20
  case fn_desc
15
21
  in String
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ExAequo
4
+ module Base
5
+ class Function
6
+ module ClassMethods
7
+ def curried(*args, **kwds, &blk)
8
+ new(Fn.curry(*args, **kwds, &blk), level: 3)
9
+ end
10
+
11
+ def sending(*args, **kwds, &blk)
12
+ new(Fn.curry_send(*args, **kwds, &blk), level: 3)
13
+ end
14
+ end
15
+ extend ClassMethods
16
+ end
17
+ end
18
+ end
19
+ # SPDX-License-Identifier: AGPL-3.0-or-later
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ExAequo
4
+ module Base
5
+ class Function
6
+ module CombinatorMethods
7
+ define_method :> do |other|
8
+ self.class.new(name: "(#{name} > #{other})") do |*args, **kwds, &blk|
9
+ other.(self.(*args, **kwds, &blk))
10
+ end
11
+ end
12
+ end
13
+ include CombinatorMethods
14
+ end
15
+ end
16
+ end
17
+ # SPDX-License-Identifier: AGPL-3.0-or-later
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'ex_aequo/base/fn'
4
+ require 'ex_aequo/base/function/class_methods'
5
+ require 'ex_aequo/base/function/combinator_methods'
6
+ module ExAequo
7
+ module Base
8
+ class Function
9
+ attr_reader :arity, :function, :name
10
+
11
+ def call(*args, **kwds, &blk)
12
+ function.(*args, **kwds, &blk)
13
+ rescue StandardError => e
14
+ raise(e, e.message + " in #{name}")
15
+ end
16
+
17
+ def named(name)
18
+ @name = name
19
+ self
20
+ end
21
+
22
+ def to_proc = function
23
+
24
+ def to_s = name
25
+
26
+ private
27
+ def initialize(func_desc=nil, name: nil, level: 1, &blk)
28
+ raise ArgumentError, "must not provide function description and a blk" if func_desc && blk
29
+ raise ArgumentError, "must provide either a function description or a blk" unless func_desc || blk
30
+ @function = blk ? blk : Fn.mk_fun(func_desc)
31
+ @arity = function.arity
32
+ @level = level
33
+ @name = name || _mk_name
34
+ end
35
+
36
+ def _mk_name
37
+ @name = caller[@level]
38
+ end
39
+ end
40
+ end
41
+ end
42
+ # SPDX-License-Identifier: AGPL-3.0-or-later
@@ -4,6 +4,7 @@ require_relative 'all'
4
4
 
5
5
  Colorize = ExAequo::Base::Colorize
6
6
  Forwarder = ExAequo::Base::Forwarder
7
+ Function = ExAequo::Base::Function
7
8
 
8
9
  require_relative 'fn/all'
9
10
 
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ class UnboundMethod
4
+ def to_proc
5
+ ->(rcv, *a, **k, &b) do
6
+ self.bind(rcv).(*a, **k, &b)
7
+ end
8
+ end
9
+ end
10
+ # SPDX-License-Identifier: AGPL-3.0-or-later
@@ -2,7 +2,7 @@
2
2
 
3
3
  module ExAequo
4
4
  module Base
5
- VERSION = '0.1.17'
5
+ VERSION = '0.2.0'
6
6
  end
7
7
  end
8
8
  # SPDX-License-Identifier: AGPL-3.0-or-later
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ex_aequo_base
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.17
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Dober
@@ -62,6 +62,9 @@ files:
62
62
  - lib/ex_aequo/base/fn/curry.rb
63
63
  - lib/ex_aequo/base/fn/helpers.rb
64
64
  - lib/ex_aequo/base/forwarder.rb
65
+ - lib/ex_aequo/base/function.rb
66
+ - lib/ex_aequo/base/function/class_methods.rb
67
+ - lib/ex_aequo/base/function/combinator_methods.rb
65
68
  - lib/ex_aequo/base/import_all.rb
66
69
  - lib/ex_aequo/base/import_none.rb
67
70
  - lib/ex_aequo/base/kernel.rb
@@ -78,6 +81,7 @@ files:
78
81
  - lib/ex_aequo/base/to_proc/regexp.rb
79
82
  - lib/ex_aequo/base/to_proc/string.rb
80
83
  - lib/ex_aequo/base/to_proc/true_class.rb
84
+ - lib/ex_aequo/base/to_proc/unbound_method.rb
81
85
  - lib/ex_aequo/base/version.rb
82
86
  homepage: https://codeberg.org/lab419/rb_ex_aequo_base
83
87
  licenses: