Predicates
Ready-made predicate factories for Binder. A predicate is a function that
receives a candidate instance and returns true or false, optionally followed by extra values.
Binder forwards those extra values to your constructor, so a predicate both filters instances
and collects the attribute, child, player or part you were going to look up anyway.
The factories live in the Predicates sub-table of the module (and are also reachable as
Binder.Predicates.*). Most accept an optional warningName: when it is given, a failing
predicate prints a warning formatted with DEFAULT_WARN_FORMAT_STRING
(or your own warnFormatString) telling you which instance failed and why. Without a
warningName predicates fail silently.
local Binder = require(path.to.Binder)
local Predicates = require(path.to.Predicates).Predicates
-- Bind every Model tagged "Vendor" that has a numeric Price attribute and a
-- ProximityPrompt child; the constructor receives them in that order.
local vendors = Binder.new(function(model: Model, trove, price: number, prompt: ProximityPrompt)
trove:Connect(prompt.Triggered, function(player)
print(`{player.Name} paid {price}`)
end)
return trove
end, {
Tags = { "Vendor" },
ClassNames = { "Model" },
Predicate = Predicates.Combine {
Predicates.Attribute("Price", "number", "VendorBinder"),
Predicates.ChildWhichIsA("ProximityPrompt", "VendorBinder"),
},
AutoStart = true,
})
The module table is { DEFAULT_WARN_FORMAT_STRING, doPredicateWarning, Predicates = { ... }, T }, where T is the bundled t type-checking library for use as a
TypeValidator.
Credits: type validation is done with t, originally by Osyris. Wally installs it.
Installation and guide: Predicates package page.
Types
Predicate
type Predicate = (any) → (boolean,...any)
A function that receives the candidate (normally an Instance) and returns whether it passes,
followed by any extra values. Binder passes those extra values to the constructor after the
Trove. The first return value must be a real boolean.
TypeValidator
type TypeValidator = "any" | string | (value: any) → any?
Describes the type an attribute must have, for Attribute and
Attributes. Either a typeof name such as "number", "string", "Color3" or
"Vector3", the string "any" (accepts any non-nil value), or a function that receives the
value and either errors, returns a message, or returns true.
CAUTION
In the current version a function validator is always reported as failing, because the result
check treats every return value (including true) as an error. Use a type-name string until
this is fixed.
Properties
DEFAULT_WARN_FORMAT_STRING
This item is read only and cannot be modified. Read OnlyPredicates.DEFAULT_WARN_FORMAT_STRING: string
"[%s] Predicate failed for %s: %s". The string.format pattern used for predicate warnings
when no warnFormatString is supplied. The three %s receive the warning name, the instance's
full name and the failure message, in that order; a custom format string must accept the same
three arguments.
T
This item is read only and cannot be modified. Read OnlyPredicates.T: t
The bundled t runtime type-checking library, re-exported for convenience so you can
build validators without installing it separately (for example Predicates.T.numberPositive).
See the TypeValidator caution before using function validators with
Attribute.
Functions
doPredicateWarning
Predicates.doPredicateWarning(warningName: string?,--
Label for the warning (typically the name of your binder or script). Nil suppresses the warning.
warnFormatString: string?,--
string.format pattern with three %s; defaults to DEFAULT_WARN_FORMAT_STRING.
warning: string--
Why the predicate failed.
) → ()
Prints the standard predicate warning for instance. Does nothing when warningName is nil,
which is how every factory in this module stays quiet unless you opt in. Useful when writing
your own predicates so they warn in the same format as the built-in ones.
local function HasPrimaryPart(warningName: string?): Predicates.Predicate
return function(model: Model)
if not model.PrimaryPart then
Predicates.doPredicateWarning(model, warningName, nil, "Missing PrimaryPart")
return false
end
return true, model.PrimaryPart
end
end
Combine
Predicates.Combine() → Predicate--
A predicate that passes when every input passes and returns all their extra values.
Runs several predicates in order and passes only if all of them pass. The extra values of every predicate are concatenated in the same order, so a constructor receives the values of the first predicate, then the second, and so on. The first failing predicate short-circuits the rest.
Predicate = Predicates.Combine {
Predicates.Attribute("Speed", "number", "CarBinder"),
Predicates.Child("Seat", "VehicleSeat", "CarBinder"),
}
-- constructor(instance, trove, speed: number, seat: VehicleSeat)
Attribute
Predicates.Attribute(attribute: string,--
Name of the attribute to read.
) → Predicate--
Passes with the attribute value as its extra value.
Requires the instance to have the attribute attribute and returns its value as the extra
value. When typeValidator is given the value must also satisfy it.
CAUTION
The attribute is considered missing when its value is falsy, so a boolean attribute set to
false fails this predicate. Use a different representation (for example a number or string)
for flags that may be off.
Attributes
Predicates.Attributes(attributes: {[string]: TypeValidator},--
Attribute names mapped to the type each must have (use "any" to accept anything).
) → Predicate--
Passes with every attribute value as extra values.
Shorthand for Combine over one Attribute predicate per entry of
attributes. Every listed attribute must exist and match its validator; all of their values are
returned as extra values.
Child
Predicates.Child(name: string,--
Name of the child to find.
isA: string?,--
Class name the child must be (or inherit from); skipped when nil.
) → Predicate--
Passes with the child instance as its extra value.
Requires a direct child named name (found with FindFirstChild, so it does not wait) and
returns it as the extra value. When isA is given the child must also satisfy IsA(isA).
ChildWhichIsA
Predicates.ChildWhichIsA(isA: string,--
Class name the child must be or inherit from, e.g. "BasePart".
) → Predicate--
Passes with the matching child as its extra value.
Requires a direct child of class isA (via FindFirstChildWhichIsA, so subclasses count) and
returns the first one found as the extra value.
Descendant
Predicates.Descendant(query: string,--
Selector string passed to QueryDescendants.
) → Predicate--
Passes with the first matching descendant as its extra value.
Requires at least one descendant matching the selector query (evaluated with
Instance:QueryDescendants) and returns the first match as the extra value.
PrimaryPart
Predicates.PrimaryPart() → Predicate--
Passes with the primary part, or the inner predicate's extra values, as extra values.
Requires the instance to be a Model with a PrimaryPart set. Without primaryPartPredicate
the primary part is returned as the extra value. With it, the inner predicate is run against the
primary part and its extra values are returned instead of the part itself.
-- constructor receives (model, trove, primaryPart)
Predicates.PrimaryPart(nil, "TurretBinder")
-- constructor receives (model, trove, range: number) read from the primary part
Predicates.PrimaryPart(Predicates.Attribute("Range", "number", "TurretBinder"), "TurretBinder")
IsDescendantOf
Passes when the instance is a descendant of ancestor. Returns no extra values and never
warns. Handy inside ContextGate or Combine when a Binder's own
Ancestors filter is not enough.
Humanoid
Requires a Humanoid child and returns it as the extra value. Equivalent to
ChildWhichIsA("Humanoid", ...).
Character
Requires the instance to look like a character: a Humanoid child and a BasePart child named
HumanoidRootPart. Returns the Humanoid, then the HumanoidRootPart, as extra values.
Player
Finds the Player an instance belongs to and returns it as the extra value. It checks, in
order: the instance itself as a character model, the nearest Model ancestor as a character
model, and finally a Player ancestor (for things parented under Players.<Name>, such as
items in a Backpack or PlayerGui). Fails when none of those resolves to a player.
ContextGate
Picks a predicate based on where the code runs: serverPredicate on the server,
clientPredicate on the client. The chosen predicate's results (including extra values) are
returned unchanged, so a shared Binder module can demand different things on each side.
StudioOnly
Warns (when warningName is set) if the code is not running in Studio. Note that it always
returns true; it flags an instance that should not exist in a live game without blocking
the bind. Wrap it in your own predicate if you need it to actually reject.