Could't find any example of a partial string matching.
Like this:
const parseAnswer =>
("y" + _) => YES,
("n" + _) => NO;
parseAnswer("yo") // YES
Is there anything planned already? Thanks!
Using the current readme syntax
function parseAnswer(answer) {
return case (answer) {
when _ if answer.startsWith('y') -> YES,
when _ if answer.startsWith('n') -> NO,
};
}
i think would do what you want?
Ok, I understand, thank you for the quick reply. Unfortunately, this is not a pattern-matching solution. It's a solution using guards, right?
Yes, that's right
Is there any language that currently supports partial string pattern matching without using guards?
In Haskell, where the basic string type is just a list of chars, you can do
parseAnswer ('y':_) = True
parseAnswer ('n':_) = False
main = print (parseAnswer "nope") -- Prints False
I guess in the JS-land you could also spread the string to an array first and then match against that
const parseAnswer = answer => case ([...answer]) {
when ['y', ..._] -> YES,
when ['n', ..._] -> NO,
}
Would be nice for the pattern to be a regular expression:
const parseAnswer = answer => case (answer) {
when /^y/i -> YES,
when /^n/i -> NO,
}
I wonder if capture groups could be used in some fashion with regexp conditions:
const parseArg = arg => case (arg) {
when /^--(?<name>\w+)[:=](?<value>.*)$/ -> { name, value },
when /^--(?<negate>no-)?(?<name>\w+)$/ -> { name, value: !negate }
}
That might not be feasible, however, since name, value, and negate wouldn't be lexically defined. Perhaps it might be possible if there was a symbol-based API to interact with matching and a way to intercept the match result:
// return something truthy for a match or falsy for not a match
RegExp.prototype[Symbol.whenMatch] = function (value) {
return this.exec(value);
}
const parseArg = arg => case (arg) {
when /^--(?<name>\w+)[:=](?<value>.*)$/ as ({ groups: { name, value } }) ->
{ name, value },
when /^--(?<negate>no-)?(?<name>\w+)$/ as ({ groups: { name, negate } }) ->
{ name, value: !negate }
}
i don't think we need to special case it: x if /whatever/.test(x) => .... it's also worth noting that some things don't make sense to do in matching, even if you technically could squeeze them in.
@rbuckton this seems like an argument to make capture group names the same as Identifiers 馃槈
I guess in the JS-land you could also spread the string to an array first and then match against that
const parseAnswer = answer => case ([...answer]) { when ['y', ..._] -> YES, when ['n', ..._] -> NO, }
@noppa's demo notifies me. If the matching case is a string, but the matching pattern is an array ['y', ...] in the case, should it go through the @@iterator to make the matching case an array?
I don't think we should expand iterators. Matching shouldn't cause side effects, which working through an iterator could do.
@devsnek to clarify, you mean that the match itself (i.e. just the LHS) shouldn't cause side-effects, correct?
@mpcsh yes, thanks for clarifying.
Note regexp with g/y have side effects.
So would any match that does a [[Get]], or a [[GetOwnPropertyKeys]] - i think that's just something we'll have to spec carefully, but is inevitable.
Everything useful has side-effects. In a dynamic language like ecmascript you're not going to get anything useful without side-effects. Even the object matching notation requires the construction of an object to match. I think you need to just let that go and assume the LHS will just simply be an expression or some limited set of expressions.
There's a lot you can do to put people down a good path but they're just going to have to understand that they can shoot themselves in the foot with silly code. Keep it simple.
Is there any language that currently supports partial string pattern matching without using guards?
Erlang/Elixir in the form of binary matching (which is the term you would want to use for lookups).
Another idea:
when `id-${id}` => ...
Matches all strings starts with "id-" and create a binding "id" for the rest of the strings.
This is like the frontend router library matching the URL
To clarify my comment above: for the purposes of matching I think non-destructive MOP operations are fine, we just shouldn't be explicitly advancing iterators and things like that (we can create a new iterator and advance through that of course).
The proposal has been updated in #174.
You can match exact strings with a string literal pattern, or an expression that evaluates to a string; you can match a string against a regex literal pattern or a regular expression object; and you can create your own custom matcher protocol if you want any other variant of string matching.
If, taking into account the updated proposal, you still have concerns, please file a new issue.
Most helpful comment
Would be nice for the pattern to be a regular expression: