bijington/expressive

Support for custom types?

Opened this issue · 11 comments

First of all - thanks for the fantastic library!

Question: how can we support custom variable types? For example in addition to DateTime my code often refers to TimeCode variables (for broadcast TV work). It is my understanding that these types with various properties cannot be utilized in Expressive?

If custom is not possible, perhaps we can get involved in contributing to support some additional types.

Thank you!

Thank you for the kind compliments.

You can use any types in Expressive but you will have limited support within the existing functions/operators.

As an example you could add in a TimeSpan as a variable and then have custom functions to work with them.

What are you hoping to achieve with this custom type?

Thanks for getting back to me. Time codes are used extensively in film, television, and digital media in place of regular time stamps. The primary purpose is to have alignment with individual video pictures called "frames" as the sub-second unit of measure in video files and streams.

I am planning to open-source a pure C# time code library that my company has been using for quite a while now in production. If you could help me understand how to integrate it into Expressive properly, I think it could benefit many people in the industry.

For reference, time code is standardized by the SMPTE organization and is often referred to as SMPTE time code: https://en.wikipedia.org/wiki/SMPTE_timecode. For anyone using Expressive in this space, they would probably find immense value in having built-in support for time codes.

@bijington Do you think you could describe what it would take to add native support for our Time Code library? we would be interested in taking on the work ourselves. We've gotten things to work partially through registering custom functions but it's pretty limited.

@jheliker I will have a think on this and try to come back with an approach as quickly as I can. I have always wanted to consider being able to add in new types such as NodaTime, etc. perhaps this will be the time to start considering this.

It would also be really nice to move away from the helper classes that do a lot of the logic around operator support.

Just to clarify what exactly do you need to support these Time Codes with? operators (+, -, *, /, etc.) and functions? Do you need to be able to do something like [timecode1] + [timecode2]?

If you would be able to clarify what you need that may help my understanding of how we can achieve this

Thanks, @bijington !

For our Time Code class, we have full operator overloads already implemented including IComparable and IEquatable and would love to be able to leverage all of it with Expressive if possible...

Thanks, @bijington !

For our Time Code class, we have full operator overloads already implemented including IComparable and IEquatable and would love to be able to leverage all of it with Expressive if possible...

Would you be willing to share your class? If not that's totally fine. I've just been thinking on whether I can expose certain interfaces if there aren't underlying ones to solve this

Hey @bijington - we've open-sourced our time code library as of this morning, please take a look!
https://github.com/middlemansoftware/TimeCode

Hey @bijington any feedback on the Time Code library? If you've got a direction we can work in, would be glad to take on the effort of getting native time code support in Expressive. Thank you!

Hey @jheliker sorry things have got in the way of getting around to coming up with a design for this. My initial thinking is to follow a similar concept to the generic maths additions to C#.

I like the idea of having interfaces like IAdditionOperator or something similar that will allow a custom type to provide operator support. Then we wouldn't have to have native support but it should make it really easy to register support for custom types.

With your TimeCode type, do you expect to be able to add other types to it e.g. int?

@jheliker what version of .NET are you building against? I would love to be able to achieve something like this: https://learn.microsoft.com/en-us/dotnet/api/system.numerics.iadditionoperators-3?view=net-7.0 but it would require jumping all the way up to .NET 7.0

This is far from working but it proves a general concept I think could work:

public interface IAdditionOperator
{
    object Add(object right);
}

public class TimeCode : IAdditionOperator
{
    public object Add(object right)
    {
        if (right is TimeCode2 timeCode2)
        {
            return this + timeCode2;
        }

        // TODO: What to do here?
    }

    public static TimeCode operator +(TimeCode tc1, TimeCode tc2)
    {
        if (tc1 is null)
        {
            throw new ArgumentNullException(nameof(tc1));
        }

        return tc1.Add(tc2);
    }

    public TimeCode Add(TimeCode timeCode)
    {
        // Actual magic from TimeCode class.
    }
}

public class Numbers
{
    public object Add(object lhs, object rhs)
    {
        if (lhs is IAdditionOperator additionOperator)
        {
            return additionOperator.Add(rhs);
        }

        // Remaining add code...
    }
}
  • IAdditionOperator would be a new set of interfaces that Expressive would expose.
  • TimeCode is a minimal copy from your repo with the interface above implemented.
  • Number shows how the current class in Expressive could be modified.

What do you think?