Class: Plumb::Not
Instance Attribute Summary collapse
-
#children ⇒ Object
readonly
Returns the value of attribute children.
-
#errors ⇒ Object
readonly
Returns the value of attribute errors.
Class Method Summary collapse
-
.new(step = nil, errors: nil) ⇒ Object
Double negation cancels:
Not(Not(X))is justX— it accepts exactly whatXdoes.
Instance Method Summary collapse
- #[](step) ⇒ Not
- #call(result) ⇒ Object
-
#initialize(step = nil, errors: nil) ⇒ Not
constructor
A new instance of Not.
-
#subtype_of?(other) ⇒ Boolean
Negation is contravariant: Not(A) <= Not(B) when B <= A, because excluding a wider set produces a narrower complement.
-
#value_preserving? ⇒ Boolean
True because negation only changes validity.
- #with_children(children) ⇒ Object
Methods included from Composable
#&, #/, #>>, #absorb_input, #absorb_output, #accepted_type, #as_node, #build, #check, #defer, #fusable_step?, #fuse_with, #generate, #idempotent?, included, #input_type, #invalid, #invoke, #match, #metadata, #not, #output_type, #pipeline, #policy, resolve_operand, #static, #subtype_identity, #to_json_schema, #to_mermaid, #to_plumb_type, #to_s, #transform, #value, #where, #with, wrap, #|
Methods included from Callable
Constructor Details
#initialize(step = nil, errors: nil) ⇒ Not
Returns a new instance of Not.
25 26 27 28 29 30 31 32 33 |
# File 'lib/plumb/not.rb', line 25 def initialize(step = nil, errors: nil) @step = Composable.wrap(step) @errors = errors || "must not be #{step.inspect}" # Store the *wrapped* step (as every container does), so `Not[String]` and # `Not[Types::String]` are the same node — and so the subtype engine isn't # fooled into treating a raw-class child as an atomic leaf. @children = [@step].freeze freeze end |
Instance Attribute Details
#children ⇒ Object (readonly)
Returns the value of attribute children.
9 10 11 |
# File 'lib/plumb/not.rb', line 9 def children @children end |
#errors ⇒ Object (readonly)
Returns the value of attribute errors.
9 10 11 |
# File 'lib/plumb/not.rb', line 9 def errors @errors end |
Class Method Details
.new(step = nil, errors: nil) ⇒ Object
Double negation cancels: Not(Not(X)) is just X — it accepts exactly
what X does. So wrapping an existing Not returns the inner type instead
of nesting (covering both #not and Not[]). A custom error message
keeps the Not, since collapsing would discard it.
15 16 17 18 19 20 |
# File 'lib/plumb/not.rb', line 15 def self.new(step = nil, errors: nil) wrapped = Composable.wrap(step) return wrapped.children.first if errors.nil? && wrapped.is_a?(self) super end |
Instance Method Details
#call(result) ⇒ Object
59 60 61 62 63 |
# File 'lib/plumb/not.rb', line 59 def call(result) result = @step.call(result) # In-place inversion — no fork here, the cursor is ours to flip. result.valid? ? result.invalid!(errors: @errors) : result.valid! end |
#subtype_of?(other) ⇒ Boolean
Negation is contravariant: Not(A) <= Not(B) when B <= A, because excluding a wider set produces a narrower complement.
45 46 47 48 49 50 |
# File 'lib/plumb/not.rb', line 45 def subtype_of?(other) return true if self == other return Plumb::Subtyping.subtype?(other.children.first, @step) if other.is_a?(Not) super end |
#value_preserving? ⇒ Boolean
Returns true because negation only changes validity.
53 |
# File 'lib/plumb/not.rb', line 53 def value_preserving? = true |
#with_children(children) ⇒ Object
23 |
# File 'lib/plumb/not.rb', line 23 def with_children(children) = self.class.new(children.first, errors: errors) |