Expirements in coalescence



  • My job right now is awesome. That said, there's some weird stuff going on in our codebase, which seems appropriate to talk about here. Basically, years ago, we had some guys, apparently, who really liked functional programming. They got really interested in two particular concepts: railway oriented programming and branchless programming. They also wanted to get rid of null. The resulting code in our system is in my opinion needlessly complex and thoroughly :wtf:y, but I do see some value to some of that.

    C#9 introduced the ability to disable nullability by default, and with that enabled it as a parameter restriction. This enables some interesting stuff with extension methods. I decided to try implementing a few that bring the basics of some of the stuff we do at work to modern c#.

    First, the branchless: public static void If<T>(T? value, Action then, Action? orElse = null) and the variant with a U return and Func<T, U> parameters. This part is weird, and I don't know that I like it, but it was simple.

    The more interesting part is the coalescent linqy part. Implementations of select, where, and select many on T? , which allow things up to and including the following:

    var result =
        from customer in GetCustomer("Brian") 
        from product in GetProduct(44)
        from price in product.Price
        from name in customer.Name
        select new Purchase(price, name);
    

    Where the result will now be either an empty list or an instance of Purchase, regardless of whether any of the properties or methods return null.

    I think this is stupid overkill, but it was kind of fun, and protecting a constructor call in this way is beyond the abilities of the normal c# ?. . It may have value, but it's too weird for me to want to use in general I think.



  • I don't see how an If function is more readable than an if block


  • Considered Harmful

    @magnusmaster said in Expirements in coalescence:

    I don't see how an If function is more readable than an if block

    It's not about readability. It's about the e peen.


  • 🚽 Regular

    @Magus said in Expirements in coalescence:

    First, the branchless: public static void If<T>(T? value, Action then, Action? orElse = null) and the variant with a U return and Func<T, U> parameters. This part is weird, and I don't know that I like it, but it was simple.

    If that's an extension method, then I get it. But if it's not, then I think I agree with @magnusmaster. Not more readable than if(maybeNull ?? false).

    The Func<T,U> variant makes more sense though.

    🤔 Okay, the Action one also makes sense if value is evaluated only once. I was assuming the value is passed to either action, but the signature isn't Action<T>, so now I'm wondering whether that's a typo. But I'd still prefer an extension method, I think.


  • 🚽 Regular

    I've recently made my own expirements using System.Linq.Expression.
    So I'm not exactly unbiased here. I like this kind of e-peen.

    I've made a thing that lets me extract data from JSON into a DataTable .
    I'm not aware of Newtonsoft's library being able to deserialize to a DataTable unless there's a flat hierarchy. I'll be glad to be proven wrong; specially if it were possible to use JPath expressions to select from where to extract the data.

    I'm now considering doing something to generate SQL statements for a given class.

    :thonking: I'm mad enough to try to make something that converts XML to JSON.


  • Fake News

    @Zecc said in Expirements in coalescence:

    expirements

    That should almost certainly be experiments. hardwaregeek


  • 🚽 Regular

    @JBert I was referencing the thread title.



  • @Zecc said in Expirements in coalescence:

    I'm mad enough to try to make something that converts XML to JSON.

    XSLT can do that for you.


  • Discourse touched me in a no-no place

    @Carnage said in Expirements in coalescence:

    @Zecc said in Expirements in coalescence:

    I'm mad enough to try to make something that converts XML to JSON.

    XSLT can do that forto you.

    FTFY



  • @dkf said in Expirements in coalescence:

    @Carnage said in Expirements in coalescence:

    @Zecc said in Expirements in coalescence:

    I'm mad enough to try to make something that converts XML to JSON.

    XSLT can do that forto you.

    FTFY

    Hey, he said he's mad enough already!



  • @Zecc in this case, the If is more of an IfExists, and there are overloads that do more complicated things. Part of the goal, I believe, was that your compiled code has no ifs in the normal sense, making decompilation slightly more obfuscated. Because the ifs are probably in a different assembly.

    Honestly I'm far more interested in the other parts, since they allow for some interesting lazy evaluation on nullable objects.

    Still extremely bizarre though.


  • 🚽 Regular

    @Magus I remember someone making an experiment in if-less JavaScript a while ago. Something like:

    Boolean.prototype.if   = function(fn) {  this && this.valueOf()  && fn(); return this; };
    Boolean.prototype.else = function(fn) { (this && this.valueOf()) || fn(); return this; };
    
    (false)
      .if(() => console.log("'Tis true"))
      .else(() => console.log("'Tis false"));

  • BINNED

    @Zecc so you've replaced braces with parentheses by putting the if in a function call (or two, redundantly) and do some sort of continuation passing? I don't get the point.
    Also, if you do this, wouldn't you want an .ifelse taking two parameters that returns the result of the functors instead of the original boolean?

    The null coalescing in the OP sounds more interesting, but I'm already not familiar with what the language provided version can or cannot do.


  • 🚽 Regular

    @topspin said in Expirements in coalescence:

    I don't get the point.

    It was just someone doing something stupid for the heck of it.

    Sorry @Magus. I didn't mean to derail your thread.


  • BINNED

    @Zecc said in Expirements in coalescence:

    @topspin said in Expirements in coalescence:

    I don't get the point.

    It was just someone doing something stupid for the heck of it.

    Sorry @Magus. I didn't mean to derail your thread.

    I was just replying to you because it was the last post in the thread. Yours seems no different from OP's If<T>, so I don't get the point of that either.

    Of course "because I can" is good enough in itself if it's just playing around.



  • @topspin the language provided one essentially allows you to chain a bunch of ?. calls, such as a?.Child?.Child, which leaves you with either null or the final child type. You then often use ?? SomeDefault() ; to eliminate null if you have a default you want.

    What gets interesting with the one in the op is that you can bring multiple objects into the query, and use let and the select line to call basically any code you want along the way, and the end result will always be an empty list or one which contains the object you want to select, even if you're constructing that dependent on everything else not being null.

    The problem, other than the innate weirdness of it, is that in most cases, guarding against all those nulls explicitly may be better, if that's invalid input to whatever you're constructing. Which makes the primary use, imo, the optional construction of types with non nullable arguments.


Log in to reply