Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pattern matching based on generic type #178

Closed
colin-jack opened this issue Jan 30, 2015 · 11 comments
Closed

Pattern matching based on generic type #178

colin-jack opened this issue Jan 30, 2015 · 11 comments

Comments

@colin-jack
Copy link

One use for pattern matching could be to choose appropriate code path based on a generic type. Say we want to map objects of types Foo and Bar to a new object of type Target. However the code that needs to do the mapping doesn't know if we have a Foo, a Bar, or something else:

        public class Target { ... }

        public class Foo { ... }

        public class Bar { ... }

        public class FooMapper {
            public Target Map(Foo mapFrom) {...}
        }

        public class BarMapper {
            public Target Map(Bar mapFrom) {...}
        }

        private Target Map<TFrom>(TFrom mappingFrom) = TFrom match { 
            case Foo => new FooMapper().Map(mappingFrom) // NOTE: No need to cast mappingFrom, we only match the case if its a Foo so no need to do "FooMapper().Map((Foo)mappingFrom)"
            case Bar => new BarMapper().Map(mappingFrom)
            default => throw new InvalidOprationException(..); // NOTE: or maybe no match implicitly produces exception
        }

There are alternatives already but I think this Scala style matching shows whats happening quite cleanly. Obviously you could add type constraints too:

    private Target Map<TFrom>(TFrom mappingFrom) where TFrom: IModel = TFrom match { 

@Pilchie
Copy link
Member

Pilchie commented Jan 30, 2015

If you look at the notes in Issue #98, it already discusses a proposal for pattern matching, including support for algebraic data types. In fact, there is already a prototype of some of it. @gafter Will likely be putting up a formal proposal issue for it soon.

@gafter
Copy link
Member

gafter commented Sep 10, 2015

@Pilchie The switch expression in this proposal is switching on a generic type parameter, not an expression. What is proposed is not covered by the existing proposal.

@gafter
Copy link
Member

gafter commented Sep 13, 2015

@colin-jack Does #206 cover the use cases this is intended to address?

@colin-jack
Copy link
Author

@gafter
Ta for replying.

I think I did look at #206 at time and didn't think it covered my case. My memory of it has faded in meantime though so I think I'd need to really sit down and re-read in detail.

@colin-jack colin-jack reopened this Dec 24, 2015
@alrz
Copy link
Contributor

alrz commented Dec 24, 2015

@colin-jack

    private Target Map<TFrom>(TFrom mappingFrom) = TFrom match { 
        case Foo => new FooMapper().Map(mappingFrom) // NOTE: No need to cast mappingFrom, we only match the case if its a Foo so no need to do "FooMapper().Map((Foo)mappingFrom)"
        case Bar => new BarMapper().Map(mappingFrom)
        default => throw new InvalidOprationException(..); // NOTE: or maybe no match implicitly produces exception
    }

This example doesn't make sense. You are matching type parameter itself and then use mappingForm which is of that type. Actually, this method even doesn't need to be generic at all. You should perform pattern-matching on mappingForm itself.

        private Target Map(object mappingFrom) => mappingFrom switch( 
            case Foo foo: new FooMapper().Map(foo),
            case Bar bar: new BarMapper().Map(bar),
            case *: throw new InvalidOprationException()
        );

@colin-jack
Copy link
Author

I'm not sure I follow, you say the example doesn't make sense but your issues seems to just be with the specific syntax. I'll thus assume it is the syntax that's the issue...

I'm not sure I really follow what you mean about matching type parameter. On generics though, yup it doesn't need to be generic in that case. However at time I logged the issue there was no clear syntax for any of this and for the single example I chose to make the method generic just in case you wanted to apply additional constraints. I've not thought about that aspect much though.

Your example looks odd to my eyes, I understand it but compared to the Scala matching approach I find it a bit ugly. I haven't kept up with what's being suggested though, so if that switch approach is what's chosen then I'd learn to live with it.

@alrz
Copy link
Contributor

alrz commented Dec 24, 2015

@colin-jack I'm not proposing any new syntax, this is the current syntax mentioned in the spec draft. So nothing with your syntax or mine. the problem is with this line TFrom match, there're chances that you could perform pattern matching on Type, but in your example you don't need to, because you want the final variable of the pattern type, e.g. Foo or Bar. My example above written according to the currently proposed spec for pattern matching and it does solve the problem that you've mentioned in this thread.

@colin-jack
Copy link
Author

@alrz
On generics, get you. I do wonder whether in some cases it might be useful to add generic constraints, and I think limiting what objects can be passed in would add clarity..but if it wasn't supported it'd be no big loss to me.

Get you on syntax, its a pity some of the linked to pages don't have more examples as it'd help make them more accessible. Anyway your example meets my needs so when its supported I'll be laughing, hurrah.

@alrz
Copy link
Contributor

alrz commented Dec 25, 2015

@colin-jack you would be able to use generics and constraints with no doubt, but you should switch on the parameter itself rather than its type. with constraints I presume your patterns also need to be pattern compatible with the resultant constrainted type.

@colin-jack
Copy link
Author

@alrz
Brilliant ta, sounds like it'll meet my needs perfectly.

@gafter
Copy link
Member

gafter commented Aug 15, 2016

@colin-jack Since the existing form of pattern-matching addresses your use case, we're not going to take this suggestion to address your use case with pattern-matching on the type parameter.

@gafter gafter closed this as completed Aug 15, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants