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

OptionalOrNull() #150

Open
nblumhardt opened this issue Sep 7, 2022 · 2 comments
Open

OptionalOrNull() #150

nblumhardt opened this issue Sep 7, 2022 · 2 comments

Comments

@nblumhardt
Copy link
Member

To cleanly support defaulting optional reference type parsers to null I believe we need something like:

        public static TokenListParser<TKind, T?> OptionalOrNull<TKind, T>(
            this TokenListParser<TKind, T> parser)
        where T: notnull
        {
            return parser != null ? parser.Select(r => (T?)r).Or(Parse.Return<TKind, T?>(default)) : throw new ArgumentNullException(nameof (parser));
        }
    }
@samblackburn
Copy link

samblackburn commented Mar 17, 2023

We've hit the same problem (in our case we wanted TextParser rather than TokenListParser).

Unfortunately your suggestion doesn't seem to return a nullable when working with value types. This example compiles even though it assigns the result to a non-nullable variable:

using System;
using Superpower;
using Superpower.Parsers;

#nullable enable

public class Program
{
    public static void Main()
    {
        TextParser<char> a = Character.EqualTo('a');
        TextParser<char> shouldBeNullable = a.OptionalOrNull();
    }
}

public static class Extensions
{
    public static TextParser<T?> OptionalOrNull<T>(
        this TextParser<T> parser)
    {
        return parser != null
            ? parser.Select(r => (T?) r).Or(Parse.Return<T?>(default))
            : throw new ArgumentNullException(nameof(parser));
    }
}

The best solution I've found is to have 2 overloads of the extension method.

In the following sample, the return type is nullable as it should be:

using System;
using Superpower;
using Superpower.Parsers;

#nullable enable

public class Program
{
    public static void Main()
    {
        TextParser<char> a = Character.EqualTo('a');
        TextParser<char?> correctlyNullable = a.OptionalOrNull();
    }
}

internal static class TextParserClassExtensions
{
    public static TextParser<T?> OptionalOrNull<T>(this TextParser<T> parser)
        where T : class
    {
        return parser != null
            ? parser.Select(r => (T?) r).Or(Parse.Return<T?>(null))
            : throw new ArgumentNullException(nameof(parser));
    }
}

internal static class TextParserParserStructExtensions
{
    public static TextParser<T?> OptionalOrNull<T>(this TextParser<T> parser)
        where T : struct
    {
        return parser != null
            ? parser.Select(r => (T?) r).Or(Parse.Return<T?>(null))
            : throw new ArgumentNullException(nameof(parser));
    }
}

Hope this helps!
Sam Blackburn, Redgate Software

@nblumhardt
Copy link
Member Author

Thank you, Sam! Hoping I'll have a chance to loop back around to this soon.

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

2 participants