factbase 0.15.8 → 0.16.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/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 +4 -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 +42 -0
- data/lib/factbase/terms/ordering.rb +8 -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: 96133055dc92095960ab4b258f4a144105393d2a86e11f96c3199ff24d35653a
|
4
|
+
data.tar.gz: f93590d550bf7b54aaa235e43557173d57af37abdc9e0a37491cf68c654e2c1e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2a532d7b59b0fa32d5662c420fb1d0de409d1c9cdf52fd6cf42c3020fd20a2008679019cf853a49e7ac1b0c9207d87134ffe1f23693f652a99188c8c6bd518f2
|
7
|
+
data.tar.gz: 67df97f44bdfbbcdba5cb5b7cec6a2f62cf9b4049f0a3d643382d797d9ec2997160ac231e871a18642c8fbd903387412e6c741d367f4e4362019d3a45a4cf6e3
|
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,7 @@ 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
23
|
key = [maps.object_id, @operands.first, @op]
|
24
24
|
case @op
|
25
25
|
when :one
|
@@ -144,7 +144,7 @@ module Factbase::IndexedTerm
|
|
144
144
|
r = (maps & []) | j
|
145
145
|
else
|
146
146
|
@operands.each do |o|
|
147
|
-
n = o.predict(maps, params)
|
147
|
+
n = o.predict(maps, fb, params)
|
148
148
|
break if n.nil?
|
149
149
|
if r.nil?
|
150
150
|
r = n
|
@@ -159,7 +159,7 @@ module Factbase::IndexedTerm
|
|
159
159
|
when :or
|
160
160
|
r = nil
|
161
161
|
@operands.each do |o|
|
162
|
-
n = o.predict(maps, params)
|
162
|
+
n = o.predict(maps, fb, params)
|
163
163
|
if n.nil?
|
164
164
|
r = nil
|
165
165
|
break
|
@@ -171,7 +171,7 @@ module Factbase::IndexedTerm
|
|
171
171
|
r
|
172
172
|
when :not
|
173
173
|
if @idx[key].nil?
|
174
|
-
yes = @operands.first.predict(maps, params)
|
174
|
+
yes = @operands.first.predict(maps, fb, params)
|
175
175
|
if yes.nil?
|
176
176
|
@idx[key] = { r: nil }
|
177
177
|
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,42 @@
|
|
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
|
+
end
|
@@ -31,4 +31,12 @@ module Factbase::Ordering
|
|
31
31
|
end
|
32
32
|
pass
|
33
33
|
end
|
34
|
+
|
35
|
+
def head(*)
|
36
|
+
max = @operands[0]
|
37
|
+
raise "An integer is expected as first argument of 'head'" unless max.is_a?(Integer)
|
38
|
+
@passed = 0 if @passed.nil?
|
39
|
+
@passed += 1
|
40
|
+
@passed <= max
|
41
|
+
end
|
34
42
|
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.0
|
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
|