factbase 0.15.8 → 0.16.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.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +6 -0
- data/lib/factbase/cached/cached_term.rb +1 -0
- data/lib/factbase/indexed/indexed_term.rb +6 -4
- data/lib/factbase/query.rb +1 -1
- data/lib/factbase/tee.rb +2 -1
- data/lib/factbase/term.rb +10 -2
- data/lib/factbase/terms/lists.rb +57 -0
- data/lib/factbase/version.rb +1 -1
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8fa39d2285106eb0a074d6dbb21bf2d25c5f2307be35e12496bac61cb130e67b
|
4
|
+
data.tar.gz: 61081f7b97fd49dfbd92c4960b02eee002cbc3bd14db718d07b7c789fb6d690e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ab0927194278acc74075b9abc96d3a05a284ba05b8296680b79c2e7e8a2ed12b3cc73e303ce97c1471b29e3bc47b8db46590fe256dc948853acee675f5813062
|
7
|
+
data.tar.gz: d17d7750750e46eba2dfe73c6622ceb894f97425c97912c1cdcabf3821cd7f9822fd094d478dafd58fa546fb83c8a8efe5a5c12dc816c832f347da2d4ea0d156
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -176,6 +176,12 @@ It's also possible to use a sub-query in a shorter form than with the `agg`:
|
|
176
176
|
|
177
177
|
* `(empty q)` is true if the subquery `q` is empty
|
178
178
|
|
179
|
+
It's possible to post-process a list of facts, for `agg` and `join`:
|
180
|
+
|
181
|
+
* `(sorted p expr)` sorts them by the value of `p` property
|
182
|
+
* `(inverted expr)` reverses them
|
183
|
+
* `(head n expr)` takes only `n` facts from the head of the list
|
184
|
+
|
179
185
|
There are some system-level terms:
|
180
186
|
|
181
187
|
* `(env v1 v2)` returns the value of environment variable `v1` or the string
|
@@ -17,6 +17,7 @@ module Factbase::CachedTerm
|
|
17
17
|
# @return [bool] TRUE if matches
|
18
18
|
def evaluate(fact, maps, fb)
|
19
19
|
return super unless static? && !abstract?
|
20
|
+
return super if %i[head unique].include?(@op)
|
20
21
|
key = [maps.object_id, to_s]
|
21
22
|
before = @cache[key]
|
22
23
|
@cache[key] = super if before.nil?
|
@@ -19,7 +19,9 @@ module Factbase::IndexedTerm
|
|
19
19
|
# @param [Array<Hash>] maps Array of facts
|
20
20
|
# @param [Hash] params Key/value params to use
|
21
21
|
# @return [Array<Hash>|nil] Returns a new array, or NIL if the original array must be used
|
22
|
-
def predict(maps, params)
|
22
|
+
def predict(maps, fb, params)
|
23
|
+
m = :"#{@op}_predict"
|
24
|
+
return send(m, maps, fb, params) if respond_to?(m)
|
23
25
|
key = [maps.object_id, @operands.first, @op]
|
24
26
|
case @op
|
25
27
|
when :one
|
@@ -144,7 +146,7 @@ module Factbase::IndexedTerm
|
|
144
146
|
r = (maps & []) | j
|
145
147
|
else
|
146
148
|
@operands.each do |o|
|
147
|
-
n = o.predict(maps, params)
|
149
|
+
n = o.predict(maps, fb, params)
|
148
150
|
break if n.nil?
|
149
151
|
if r.nil?
|
150
152
|
r = n
|
@@ -159,7 +161,7 @@ module Factbase::IndexedTerm
|
|
159
161
|
when :or
|
160
162
|
r = nil
|
161
163
|
@operands.each do |o|
|
162
|
-
n = o.predict(maps, params)
|
164
|
+
n = o.predict(maps, fb, params)
|
163
165
|
if n.nil?
|
164
166
|
r = nil
|
165
167
|
break
|
@@ -171,7 +173,7 @@ module Factbase::IndexedTerm
|
|
171
173
|
r
|
172
174
|
when :not
|
173
175
|
if @idx[key].nil?
|
174
|
-
yes = @operands.first.predict(maps, params)
|
176
|
+
yes = @operands.first.predict(maps, fb, params)
|
175
177
|
if yes.nil?
|
176
178
|
@idx[key] = { r: nil }
|
177
179
|
else
|
data/lib/factbase/query.rb
CHANGED
@@ -44,7 +44,7 @@ class Factbase::Query
|
|
44
44
|
return to_enum(__method__, fb, params) unless block_given?
|
45
45
|
yielded = 0
|
46
46
|
params = params.transform_keys(&:to_s) if params.is_a?(Hash)
|
47
|
-
maybe = @term.predict(@maps, Factbase::Tee.new({}, params))
|
47
|
+
maybe = @term.predict(@maps, fb, Factbase::Tee.new({}, params))
|
48
48
|
maybe ||= @maps unless maybe.equal?(@maps)
|
49
49
|
maybe.each do |m|
|
50
50
|
extras = {}
|
data/lib/factbase/tee.rb
CHANGED
@@ -27,7 +27,8 @@ class Factbase::Tee
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def all_properties
|
30
|
-
@fact.
|
30
|
+
(@fact.is_a?(Hash) ? @fact.keys : @fact.all_properties) +
|
31
|
+
(@upper.is_a?(Hash) ? @upper.keys : @upper.all_properties)
|
31
32
|
end
|
32
33
|
|
33
34
|
others do |*args|
|
data/lib/factbase/term.rb
CHANGED
@@ -53,6 +53,9 @@ class Factbase::Term
|
|
53
53
|
require_relative 'terms/aggregates'
|
54
54
|
include Factbase::Aggregates
|
55
55
|
|
56
|
+
require_relative 'terms/lists'
|
57
|
+
include Factbase::Lists
|
58
|
+
|
56
59
|
require_relative 'terms/strings'
|
57
60
|
include Factbase::Strings
|
58
61
|
|
@@ -107,8 +110,13 @@ class Factbase::Term
|
|
107
110
|
# @param [Array<Hash>] maps Records to iterate, maybe
|
108
111
|
# @param [Hash] _params Params to use (keys must be strings, not symbols, with values as arrays)
|
109
112
|
# @return [Array<Hash>] Records to iterate
|
110
|
-
def predict(maps,
|
111
|
-
|
113
|
+
def predict(maps, fb, params)
|
114
|
+
m = :"#{@op}_predict"
|
115
|
+
if respond_to?(m)
|
116
|
+
send(m, maps, fb, params)
|
117
|
+
else
|
118
|
+
maps
|
119
|
+
end
|
112
120
|
end
|
113
121
|
|
114
122
|
# Does it match the fact?
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# SPDX-FileCopyrightText: Copyright (c) 2024-2025 Yegor Bugayenko
|
4
|
+
# SPDX-License-Identifier: MIT
|
5
|
+
|
6
|
+
require_relative '../../factbase'
|
7
|
+
|
8
|
+
# Lists management.
|
9
|
+
#
|
10
|
+
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
11
|
+
# Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
|
12
|
+
# License:: MIT
|
13
|
+
module Factbase::Lists
|
14
|
+
def sorted(_fact, _maps, _fb)
|
15
|
+
true
|
16
|
+
end
|
17
|
+
|
18
|
+
def sorted_predict(maps, fb, params)
|
19
|
+
assert_args(2)
|
20
|
+
prop = @operands[0]
|
21
|
+
raise "A symbol is expected as first argument of 'sorted'" unless prop.is_a?(Symbol)
|
22
|
+
term = @operands[1]
|
23
|
+
raise "A term is expected, but '#{term}' provided" unless term.is_a?(Factbase::Term)
|
24
|
+
fb.query(term, maps).each(fb, params).to_a
|
25
|
+
.reject { |m| m[prop].nil? }
|
26
|
+
.sort_by { |m| m[prop].first }
|
27
|
+
.map { |m| m.all_properties.to_h { |k| [k, m[k]] } }
|
28
|
+
end
|
29
|
+
|
30
|
+
def inverted(_fact, _maps, _fb)
|
31
|
+
true
|
32
|
+
end
|
33
|
+
|
34
|
+
def inverted_predict(maps, fb, params)
|
35
|
+
assert_args(1)
|
36
|
+
term = @operands[0]
|
37
|
+
raise "A term is expected, but '#{term}' provided" unless term.is_a?(Factbase::Term)
|
38
|
+
fb.query(term, maps).each(fb, params).to_a
|
39
|
+
.reverse
|
40
|
+
.map { |m| m.all_properties.to_h { |k| [k, m[k]] } }
|
41
|
+
end
|
42
|
+
|
43
|
+
def head(_fact, _maps, _fb)
|
44
|
+
true
|
45
|
+
end
|
46
|
+
|
47
|
+
def head_predict(maps, fb, params)
|
48
|
+
assert_args(2)
|
49
|
+
max = @operands[0]
|
50
|
+
raise "An integer is expected as first argument of 'sorted'" unless max.is_a?(Integer)
|
51
|
+
term = @operands[1]
|
52
|
+
raise "A term is expected, but '#{term}' provided" unless term.is_a?(Factbase::Term)
|
53
|
+
fb.query(term, maps).each(fb, params).to_a
|
54
|
+
.take(max)
|
55
|
+
.map { |m| m.all_properties.to_h { |k| [k, m[k]] } }
|
56
|
+
end
|
57
|
+
end
|
data/lib/factbase/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: factbase
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.16.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yegor Bugayenko
|
@@ -202,6 +202,7 @@ files:
|
|
202
202
|
- lib/factbase/terms/casting.rb
|
203
203
|
- lib/factbase/terms/debug.rb
|
204
204
|
- lib/factbase/terms/defn.rb
|
205
|
+
- lib/factbase/terms/lists.rb
|
205
206
|
- lib/factbase/terms/logical.rb
|
206
207
|
- lib/factbase/terms/math.rb
|
207
208
|
- lib/factbase/terms/meta.rb
|