--
You received this message because you are subscribed to the Google Groups "meteor-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to meteor-core...@googlegroups.com.
To post to this group, send email to meteo...@googlegroups.com.
Visit this group at http://groups.google.com/group/meteor-core?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.
Riffing on that, though, what about a bare function can return true, false, or an Object. If it is true/false (or null or undefined, I guess), treat it like a predicate. If it returns an Object, treat it like a constructor function. It might be a bit confusing to explain, but I think it does what you mean in most cases. And it could save a lot of typing 'Match.Where'.
Riffing on that, though, what about a bare function can return true, false, or an Object. If it is true/false (or null or undefined, I guess), treat it like a predicate. If it returns an Object, treat it like a constructor function. It might be a bit confusing to explain, but I think it does what you mean in most cases. And it could save a lot of typing 'Match.Where'.I'm not following you... If I pass a function as a match pattern, you're going to call it and see if it returns an Object? How does this help with constructor tests? Can you give an example?
One potential weirdness around Match.Is is string objects. That is, without special care `Match.Is(String)` and `String` would do something different (new String(foo) is an Object, not a String). There's an XXX about boxed string objects in the code. I have no idea when people actually use boxed objects in the wild =)
Match.any = function (value) { return true; };
Match.Object = function (objectSpec) { return function () { ... }; }
check(value, Match.any);
check(value, new Match.Object({});
...
Namspacing: I don't like the idea of check being in the global namespace :)
Hrm... not so sure about adding 'string', 'boolean', 'number' and 'object' to the global namespace. It's true adding 'check' is already a deviation from our normal pattern of capitalized version of the package name, but I think having 'string' and 'String' both exist and mean different things may be a bit over the top / confusing for noobs.
I think having 'string' and 'String' both exist and mean different things may be a bit over the top / confusing for noobs.
String, Number, Boolean, undefined, null
Matches a primitive of the given type.
Any constructor function (eg, Date)
Matches any element that is an instance of that type.
We did constructor functions as it makes the syntax more parallel, eg check(x, String) and check(x, Date).
All the other checks are about enforcing something is of a type.
docType = {name: { type: 'string', required: true }, // Validation optionsemail: { type: 'email', required: true, errorMsg: 'please.enter.email' }, // Maybe future getText notation for languagesage: { type: 'number', min: 0, max: 120 },photo: { type: 'base64', maxLength: 1024*1024}};
Ok... Well, I'll just be a bit more concrete:
- I dont like check in global space so one could maybe be constructive and consider Match(foo, bar); instead of a global check
- The talk about adding global lowercase 'string' etc. gave me the goose... But after reading the actual code I see that its the builtin types used for the scheme
- I kind of agree with fritz - Throwing an error is a bit overkill - we kindof expect the validation to do two things fail/succes - false/true (otherwise we have to write a try catch every time...)
I've updated my proposed PR so that the function to register a constructor is now called "registerConstructor". I think it reads a lot better now.I moved the ability to use Date, RegExp, etc. up in the documentation (before they were buried down in the description of the constructor match pattern).
We'll still need to special case the basic javascript types. It looks like Date doesn't have any keys on it's prototype, presumably because its native and weird.
This is in some sense heuristic, but I think the cases where it doesn't work are very rare, why have an object with no methods?
What do you think? Can you whip up a PR with this technique?
We'll still need to special case the basic javascript types. It looks like Date doesn't have any keys on it's prototype, presumably because its native and weird.Actually its prototype keys just aren't enumerable:
> Object.getOwnPropertyNames(Date.prototype)
["constructor", "toString", "toDateString", "toTimeString", "toLocaleString", ...
>Object.keys(Date.prototype)
[]
Anyone can makes their keys not enumerable if they want to (it's not a native thing), though I don't know why the JavaScript library classes choose to.
This is in some sense heuristic, but I think the cases where it doesn't work are very rare, why have an object with no methods?You mean like Meteor.Error? :-)
What do you think? Can you whip up a PR with this technique?You'll need to test / get it to work on on whatever older versions of IE you want to support, I'm not set up to develop against them.
Ah, cool! Good to know. Looks like getOwnPropertyNames isn't supported in IE8, though. Perhaps there is another way to find the prototype's keys in IE8.
We've got scripts to run the unit tests in all browsers, and the match tests are pretty good so unit tests passing is good enough.
Since you've been so involved with this, I figured you'd want to see it through. If you'd rather hand it off at this point, though, I can get it done.
Are we saying "does F.prototype have any fields directly" or "are
there any methods anywhere up the chain"?
Here's a thought. Suppose `registerConstructor` was used to specify a constructor function as a pattern, but we also had a heuristic that warned if an apparent constructor function was being mistakenly used as a predicate (it hadn't been registered). Now we can be helpful and load the heuristic with all the cases we can think of (WebGLTexture defined? add it to the list!)... without relying on the heuristic being 100% correct in all cases.
If I were to tweak Nick/Geoff's proposal, I'd say make it so predicate functions aren't allowed to return anything typeof object. Then we will actually never call a constructor and succeed. The error message should point people towards using Match.InstanceOf.
Gosh, this is starting to sound really complicated, and hard to document.
Yeah, true. I think we're just trying to get closer to the brevity of assertions, like `assert(x > 0)`. I like defining types personally, and usually constraints like this have some basis in a type (`RevisionId = Match.Where(...)`), but if you can't use these types in any other way then I feel like I'm doing extra typing rather than saving typing. Maybe the answer is you don't use check(.) for stuff like this, you just check that x is a Number and then throw a more specific error if the value is bad.
(I'm not using a typeof object test, because constructors will usually return `undefined` when called without `new`).