lib/speculation/spec_impl/every_spec.rb in speculation-0.1.0 vs lib/speculation/spec_impl/every_spec.rb in speculation-0.2.0
- old
+ new
@@ -1,12 +1,10 @@
# frozen_string_literal: true
module Speculation
- using NamespacedSymbols.refine(self)
- using Conj
-
# @private
class EverySpec < SpecImpl
+ include NamespacedSymbols
S = Speculation
def initialize(predicate, options)
@predicate = predicate
@options = options
@@ -22,57 +20,57 @@
coll.count.between?(min, max)
end)
end
- @collection_predicate = ->(coll) { collection_predicates.all? { |f| f === coll } }
+ @collection_predicate = ->(coll) { collection_predicates.all? { |f| f.respond_to?(:call) ? f.call(coll) : f === coll } }
@delayed_spec = Concurrent::Delay.new { S.send(:specize, predicate) }
- @kfn = options.fetch(:kfn.ns, ->(i, _v) { i })
+ @kfn = options.fetch(ns(S, :kfn), ->(i, _v) { i })
@conform_keys, @conform_all, @kind, @gen_into, @gen_max, @distinct, @count, @min_count, @max_count =
- options.values_at(:conform_keys, :conform_all.ns, :kind, :into, :gen_max, :distinct, :count, :min_count, :max_count)
+ options.values_at(:conform_keys, ns(S, :conform_all), :kind, :into, :gen_max, :distinct, :count, :min_count, :max_count)
@gen_max ||= 20
@conform_into = @gen_into
# returns a tuple of [init add complete] fns
@cfns = ->(x) do
if Utils.array?(x) && (!@conform_into || Utils.array?(@conform_into))
- [:itself.to_proc,
+ [Utils.method(:itself),
->(ret, i, v, cv) { v.equal?(cv) ? ret : ret.tap { |r| r[i] = cv } },
- :itself.to_proc]
+ Utils.method(:itself)]
elsif Utils.hash?(x) && ((@kind && !@conform_into) || Utils.hash?(@conform_into))
- [@conform_keys ? Utils.method(:empty) : :itself.to_proc,
+ [@conform_keys ? Utils.method(:empty) : Utils.method(:itself),
->(ret, _i, v, cv) {
if v.equal?(cv) && !@conform_keys
ret
else
ret.merge((@conform_keys ? cv : v).first => cv.last)
end
},
- :itself.to_proc]
+ Utils.method(:itself)]
else
[->(init) { Utils.empty(@conform_into || init) },
- ->(ret, _i, _v, cv) { ret.conj(cv) },
- :itself.to_proc]
+ ->(ret, _i, _v, cv) { Utils.conj(ret, cv) },
+ Utils.method(:itself)]
end
end
end
def conform(value)
- return :invalid.ns unless @collection_predicate.call(value)
+ return ns(S, :invalid) unless @collection_predicate.call(value)
- spec = @delayed_spec.value
+ spec = @delayed_spec.value!
if @conform_all
init, add, complete = @cfns.call(value)
return_value = init.call(value)
value.each_with_index do |val, index|
conformed_value = spec.conform(val)
if S.invalid?(conformed_value)
- return :invalid.ns
+ return ns(S, :invalid)
else
return_value = add.call(return_value, index, val, conformed_value)
end
end
@@ -81,28 +79,28 @@
# OPTIMIZE: check if value is indexed (array, hash etc.) vs not indexed (list, custom enumerable)
limit = S.coll_check_limit
value.each_with_index do |item, index|
return value if index == limit
- return :invalid.ns unless S.valid?(spec, item)
+ return ns(S, :invalid) unless S.valid?(spec, item)
end
value
end
end
def explain(path, via, inn, value)
probs = collection_problems(value, @kind, @distinct, @count, @min_count, @max_count, path, via, inn)
return probs if probs
- spec = @delayed_spec.value
+ spec = @delayed_spec.value!
probs = value.lazy.each_with_index.flat_map { |v, i|
k = @kfn.call(i, v)
unless S.valid?(spec, v)
- S.explain1(@predicate, path, via, inn.conj(k), v)
+ S.explain1(@predicate, path, via, Utils.conj(inn, k), v)
end
}
probs = @conform_all ? probs.to_a : probs.take(S.coll_error_limit)
probs.compact
@@ -156,21 +154,23 @@
unless S.pvalid?(pred, x)
return S.explain1(pred, path, via, inn, x)
end
- if count && count != x.count
- return [{ :path => path, :pred => "count == x.count", :val => x, :via => via, :in => inn }]
+ if count && !Utils.count_eq?(x, count)
+ return [{ :path => path, :pred => [Utils.method(:count_eq?), [x, count]], :val => x, :via => via, :in => inn }]
end
if min_count || max_count
- if x.count.between?(min_count || 0, max_count || Float::Infinity)
- return [{ :path => path, :pred => "count.between?(min_count || 0, max_count || Float::Infinity)", :val => x, :via => via, :in => inn }]
+ min_count ||= 0
+ max_count ||= Float::INFINITY
+ unless Utils.count_between?(x, min_count, max_count)
+ return [{ :path => path, :pred => [Utils.method(:count_between?), [x, min_count, max_count]], :val => x, :via => via, :in => inn }]
end
end
- if distinct && !x.empty? && Utils.distinct?(x)
- [{ :path => path, :pred => "distinct?", :val => x, :via => via, :in => inn }]
+ if distinct && !x.empty? && !Utils.distinct?(x)
+ [{ :path => path, :pred => [Utils.method(:distinct?), [x]], :val => x, :via => via, :in => inn }]
end
end
end
end