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

Add: Fallible/sink(_:) #116

Closed
oscbyspro opened this issue Oct 15, 2024 · 3 comments
Closed

Add: Fallible/sink(_:) #116

oscbyspro opened this issue Oct 15, 2024 · 3 comments
Labels
addition oh, so shiny! brrr such code, much wow

Comments

@oscbyspro
Copy link
Owner

oscbyspro commented Oct 15, 2024

I'm working on more maintainable redemption arcs. Of note, this operation scales well:

var value = U8(3)
var error = false

value = value.decremented().sink(&error) // value:   2, error: false
value = value.decremented().sink(&error) // value:   1, error: false
value = value.decremented().sink(&error) // value:   0, error: false
value = value.decremented().sink(&error) // value: 255, error: true

extension Fallible {

    // Returns the `value` by setting the `remote` indicator on `error`.
    @inlinable public consuming func sink(_ remote: inout Bool) -> Value { ... }
}

Depending on how the new approach turns out, I may revisit mutating methods. We'll see.

Notes on Fallible/map(_:)

Fallible/map(_:) works in simple cases but it quickly devolves into a pyramid-of-doom.

@oscbyspro oscbyspro added addition oh, so shiny! brrr such code, much wow labels Oct 15, 2024
@oscbyspro oscbyspro added this to the Ultimathnum 0.11.0 milestone Oct 15, 2024
@oscbyspro oscbyspro changed the title Add: Fallible/sink(\_:) Add: Fallible/sink(_:) Oct 15, 2024
@oscbyspro
Copy link
Owner Author

oscbyspro commented Oct 15, 2024

Note that this method makes it straightforward to use a single error indicator for an entire algorithm in cases where the implicit error propagation approach uses one error indicator per named entity. In the exponentiation algorithm, for example, the power and multiplier both manage an error indicator. With this approach, you can just sink all multiplication errors.

@oscbyspro
Copy link
Owner Author

oscbyspro commented Oct 15, 2024

Generating the Bool is one of the pain-points. So I'll add some static sink(_:) too:

extension Fallible {

    /// Generates an `error` indicator then combines it at the end of the `action`.
    @inlinable public static func sink(_ action: (inout Bool) -> Value) -> Self { ... }

    /// Generates an `error` indicator then combines it at the end of the `action`.
    @inlinable public static func sink(_ action: (inout Bool) -> Self ) -> Self { ... }
}

Here's just some examples uses cases from one of my randomized multiplication tests:

let foo = Fallible<T>.sink {
    lhs.plus(rhs).sink(&$0).squared()
}

let bar = Fallible<T>.sink {
    let a: T = lhs.squared( ).sink(&$0)
    let b: T = lhs.times(rhs).sink(&$0).times(2).sink(&$0)
    let c: T = rhs.squared( ).sink(&$0)
    return a.plus(b).sink(&$0).plus(c )
}

@oscbyspro
Copy link
Owner Author

oscbyspro commented Oct 15, 2024

I'm not sure how easy it is to appreciate the simplicity of it vs (#117), but it's great.

oscbyspro added a commit that referenced this issue Oct 16, 2024
These static methods solve a pain-point of the sink(_:) approach.

I also conformed Bit to Recoverable (#92).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
addition oh, so shiny! brrr such code, much wow
Projects
None yet
Development

No branches or pull requests

1 participant