Ad
  • Default User Avatar

    This is covered by the following part of the description:

    Any other pattern matches if pattern[matchesSymbol](input) is truthy. The matchesSymbol variable is preloaded, and the solution must use it to define one or more properties, each on a standard prototype (e.g. Object.prototype).

    To expand: patternMatch is supposed to use [matchesSymbol] on whatever it's given, and with its logic written that way you then need to define [matchesSymbol] properties on built-in prototypes for it to behave correctly. Technically you could just define Object.prototype[matchesSymbol], but it wouldn't be a very good way to do it.

  • Default User Avatar

    The test you mentioned does look incorrect to me, but I can't reproduce the issue or figure out how it might have happened.

    I've re-validated my own solution a few times with no issues, so if you are getting a lot of randomised test failures it is probably an issue with your solution.

  • Default User Avatar

    This comment is hidden because it contains spoiler information about the solution

  • Default User Avatar

    toString isn't considered and isn't supposed to have an effect on anything, but valueOf matters and is hinted at by the description at one point.

  • Default User Avatar

    This should be covered by the primitive tests.

  • Default User Avatar

    What this is saying is that there is no special handling for a non-existent property and it should be treated the same as if it existed but had an undefined value. Sometimes things behave differently based on that, i.e. in some cases, if we have the following code:

    const objA = { prop: undefined };
    const objB = {};
    

    Some things will treat objA and objB differently, even though objA.prop and objB.prop are both undefined. We don't want any special handling here, so the patterns { prop: undefined } and { prop: () => true } should match both objA and objB.

  • Default User Avatar

    Possibly the confusion here is because that test is checking for [matchesSymbol] on Number (a function) and not Number.prototype.

  • Default User Avatar

    As with Symbols, Sets are supposed to be compared with ===. The __name thing is used by the tests for display purposes, it isn't supposed to be accessed by the solution.

  • Default User Avatar

    Technically every comparison is specified - anything that isn't explicitly covered in the description is supposed to use the fallback logic at the bottom of the Details section (i.e. basically ===).

  • Default User Avatar

    The whole [matchesSymbol] thing is just a bit odd to me. A simple method would work perfectly well, and would no longer require Symbol use and understanding--which is not what this kata is about.

    The idea is that a symbol is the better approach because it guarantees there will be no name conflicts (i.e. things don't break if we have a user-defined type with a matches method that does something different, or matches gets added to the RegExp object and doesn't do what we want it to). Understanding of more advanced JavaScript concepts is intended to be part of the kata's challenge.

    "Why [matchesSymbol]? Using matchesSymbol enables custom pattern-matching behavior for user-defined types." Well... it doesn't; we have to implement it. Having a simple method would work exactly the same way.

    It enables it because it allows you to implement it. It's providing a hook for custom pattern matching behavior - if one doesn't exist then you can't define your own pattern matching logic for your own types.

    "If we have the following class...then the following code will work." Again, no it won't, because we have to implement that. There's nothing inherent to using a Symbol for this that means this works, when not using a Symbol would mean it wouldn't work. It's just a choice you made for some reason.

    I mean, the class implements [matchesSymbol], so it will work. :)

    You could even just leave this whole thing out and let the user implement it however they wish to. Just tell them what the main patternMatch() function needs to do, and let them do it however they wish. That would be exactly the same amount of challenge, they can choose if they want to split code across the prototypes or not, etc.

    IIRC I originally wrote it that way, but then I realized basically everyone will build something that isn't extensible, which wouldn't be ideal. I redefined everything in terms of [matchesSymbol] so that a passing solution has to be extensible.

    Technically the [matchesSymbol] handling could be required only for custom stuff, but I think it's better if everything is consistent.

    If you keep the prototype method idea, you could give a clear list of prototypes to implement the method for instead of leaving it to the user to figure out. That doesn't add to the challenge, it's just not explicitly defined in an easy to read manner.

    The hope is that it can be figured out by looking at the bullet points in the Details section. If you treat the Details section as a technical spec/strange form of pseudocode, you should find that it actually spells out most of a working solution for you.

    "A function matches if: ..." Doesn't say if both conditions must be true, or at least one of them must be true.

    It's at least one. I'll update the description to clarify. EDIT: Done.

    "An array matches if...[all] elements match their corresponding element in the input" Unclear what is meant by "match" here.

    See above point about the Details section being like a technical spec - you should find that "match" always has the same meaning throughout, i.e. in this case it's expecting you to recursively apply the full matching logic.

    Perhaps the issue is, you started by talking about patterns matching values. But further down you're talking about values matching values

    The idea is that there is no distinction - a pattern is always a value.

    "{ nonExistent: undefined } matches {}" It's not clear which is the "pattern" and which is the "input" in that text.

    Back to the point about Details being like a spec - "X matches Y" terms always have the same meaning, i.e. it's "<pattern> matches <input>".

    Unclear why I would need that _() function instead of just returning true. I guess maybe some sort of "functional" thing, or monads, or whatever... but if the user wants to write the code that way, they'll know how to write const _ = () => true;. Not a big deal, just felt superfluous to me.

    It makes things more concise and brings the "syntax" in line with what you find for pattern matching in a lot of other languages. It's a pre-defined variable so your solution shouldn't need to do anything about it.

  • Custom User Avatar

    Because of these random tests, I don't think I'll be able to fully get them all to pass. There's usually only a few, but the number varies from run to run, so I'd only be getting lucky if I did pass it all. And when I look into the cases that don't pass, I don't think they're quite right by the looks of it.

    So... it's a shame--I've sunk a few hours into this challenge, and it was pretty interesting. But I guess this is where I stop. ;/

  • Custom User Avatar

    It seems some of the tests have patterns that are simple objects, with set "matches" methods. Presumably we're meant to just call whatever the object's "matches" method is--regardless of where it has come from. I think that's how I'm doing it, but it wasn't clear to be from the description that how it must work.

    It's explicitly saying you must set such methods on the prototypes. But that's not even necessary if you're just calling the method on the value you're given. So again, just a bit muddled with the potential of overlooking or misreading it.

  • Custom User Avatar

    I was given this by the randomised tests:

    assert.strictEqual(patternMatch(
      [ [], [ [Array], {}, [Object] ], [ [Array], [Object], [Array] ] ],
      [ [], [Array], [Array] ], true
    ), true);
    

    But I think it's incorrect. The pattern is expecting an array of 3 items:

    • First item is an array of 0 items.
    • Second item is an array of 1 item, an array (doesn't matter what it contains).
    • Third item is an array of 1 item, containing an array (doesn't matter what it contains).

    The input is an array containing 3 items:

    • First item is an array of 0 items. [Pass]
    • Second item is an array containing 3 items. [Fail]

    ...Right?

  • Custom User Avatar

    This comment is hidden because it contains spoiler information about the solution

  • Custom User Avatar

    Or even String objects with a set .toString method which messes things up, for example? Not sure how you want such things handled though.

  • Loading more items...