nevalang / neva

🌊 Dataflow programming language with static types and implicit parallelism. Compiles to native code and Go
https://nevalang.org
MIT License
91 stars 7 forks source link

We can't build wrappers around components with DI #624

Open emil14 opened 4 months ago

emil14 commented 4 months ago

TLDR - If component uses interface we can't create another component that will do the same with but with some higher-order logic

E.g. we have builtin.Map and we need lists.Map around it. It would be natural to think that we should be able just reuse it inside but yet we have to reimplement it.

We can't do this

pub component Map2<T, Y>(data list<T>) (res list<Y>) {
    nodes { Iter<T>, Map<T, Y>, List<T> }
    :data -> iter -> map -> list -> :res
}

Because Map<T, Y> must be Map<T, Y>{...} (we need to pass dependency inside). So question is - where do we get that dependency? Answer is - there's no such place we can get it from.

User should pass it dependency. But we can't "drill" that dep to our node

pub component Map2<T, Y>(data list<T>) (res list<Y>) {
    nodes { handler IMapHandler, Iter<T>, Map<T, Y>, List<T> } // aaam... thanks?
    :data -> iter -> map -> list -> :res
}

Like what do we do with this handler? We don't use it in our own network and we... Wait a second...

emil14 commented 4 months ago

Allow bypass dependencies

Here's how it should work

If component has a dependency it means that it either uses it directly in the network or it passes it as a dependency to its own node (that ofc must be concrete node)

pub component Map<T, Y>(data list<T>) (res list<Y>) {
    nodes {
        handler IMapHandler,

        Iter<T>
        Map<T, Y>{handler}
        List<T>
    }

    :data -> iter -> map -> list -> :res
}

...

component Main(start) (stop) {
    nodes {
        Map{Decr<int>}
    }
    // ...
}