Methods covered in this file: .match, .set, .fallback, and .evaluate.
Polyfunc.js aims to be a clean library. Do Poly.match( followed by a type schema. Call .set on that
in order to specify the callback function if the type schema was matched. The function you pass to set
will be passed the arguments, and whatever it returns will ultimately be what the whole chain returns.
E.g.,
Poly.match('number').set((a) => a * 2).evaluate(5); // returns 10After specifying all your callbacks, run .evaluate() with all of your arguments
So, e.g.,
function test(a, b, c) {
Poly.match('*').set(() => console.log("one argument"))
.match('*', 'number').set(() => console.log("anything followed by number"))
.match('*', '*', '*').set(() => console.log("three arguments"))
.evaluate(a, b, c);
}
test({}); // "one argument"
test(null, 2); // "anything followed by number"
test([], "", 3); // "three arguments"Know that once a pattern is matched, the whole chain terminates. So,
let matcher = Poly.match('number').set(() => console.log("number"))
.match('*').set(() => console.log("anything else"));
matcher.evaluate(0); // "number"
matcher.evaluate(""); // "anything else"Also, Polyfunc does have type safety for TypeScript users. If using TypeScript, you MUST specify the chain's return type on the first call. Here's the first example written in TypeScript. Note: It could be made safer by adding a fallback function.
let matcher = Poly.match<string>('number').set(() => "number")
.match('*').set(() => "anything else");
console.log(matcher.evaluate(0)); // "number"
console.log(matcher.evaluate("")); // "anything elseNow, here are the types you can match:
"string" | "symbol" | "number" | "boolean" | "bigint" | "array" | "hash" | "object" | "nulled" | "regexp" | "function" | "class" | "functional" | "*"The wildcard '*' matches literally everything.
Here are some differences:
- Objects
arrayonly matches arrays. So,[]is accepted, but{}is not.hashonly matches hashmaps (also called dictionaries). So,[]is NOT accepted, but{}is.objectmatches both. So,{}AND[]are accepted.- Note that even though
typeof /some_regexp/andtypeof nullare both "object", they will never be accepted byarray,hash, orobject.
- Functions
functionmatches functions and NOT classes.classmatches classes and NOT functions.functionalmatches both functions AND classes.
Add a question mark to any type to say that it is allowed to be nullable. E.g., .match("number").set(...).evaluate() will not call the function, but
.match("number?").set(...).evaluate() will.
Add multiple types to an array in order to match at least one of them to a value. E.g.,
.match(["number", "string"]).set(...).evaluate(1) calls the same function as if you had said ..evaluate("some string")
You can also pass in your own class or function, and Polyfunc will check whether or not a value is an instance of that class or function. E.g.,
class MyClass {}
Poly.match(MyClass).set(() => "Custom class given").evaluate(new MyClass()); // returns "Custom class given"And, you can obviously use this in an array of multiple types. E.g.,
class MyClass {}
let matcher = Poly.match([MyClass, 'number']).set(() => "Class or number given");
matcher.evaluate(new MyClass()); // returns "Class or number given"
matcher.evaluate(4); // returns "Class or number given"Lastly, you can use .fallback to specify a default function if no patterns matched. E.g.,
let matcher = Poly.match('string').set(() => "some string")
.fallback((a) => a * 2);
matcher.evaluate(""); // Returns "some string"
matcher.evaluate(5); // Returns 10 because a string wasn't matched, so the fallback was usedHere's a slightly more complex example of .fallback using multiple patterns. Remember: the .fallback function
is only called if NO patterns were matched.
let matcher = Poly.match('string').set(() => "some string")
.match('number', 'hash').set(() => "dictionary given")
.fallback((a) => a * 2);
matcher.evaluate(""); // Returns "some string"
matcher.evaluate({}); // Returns "dictionary given"
matcher.evaluate(5); // Returns 10 because a string wasn't matched, so the fallback was used