Giter VIP home page Giter VIP logo

Comments (13)

niieani avatar niieani commented on June 14, 2024 3

I found readability of writing callbags using the low-level concepts to be quite challenging too, but I don't think there's need to change the standard. It just needed a few helpers that hide the low-level details of the standard, so the result is that it in-depth knowledge of the standard isn't necessary to understand a Source's, Operator's or Sink's behavior, or even to write one.

Here's my take on improving readability of callbags: https://github.com/niieani/callbag-toolkit

from callbag.

staltz avatar staltz commented on June 14, 2024 2

I think the readability argument is subjective, and not enough to change this spec. You're free to make another separate spec though.

from callbag.

HarikrishnanBalagopal avatar HarikrishnanBalagopal commented on June 14, 2024 1

What I mean by more concretized types is that I would like to relate Callbags and the functions that operate around Callbags like pipe, map, etc to existing type theory, Monad Transformers, Monads, Applicative Functors, Functors, etc.

I am not recommending classes and object oriented programming.

from callbag.

staltz avatar staltz commented on June 14, 2024

Hi @HarikrishnanBalagopal , as long as the implementation matches the spec, any implementation is allowed. But an object with methods is not valid under the spec.

from callbag.

HarikrishnanBalagopal avatar HarikrishnanBalagopal commented on June 14, 2024

What about this then?

Instead of the mutual greeting by sending 0 to each other with a Callbag for communication, this does it slightly differently.

Producers and Consumers are Callbags.

A Source contains a Producer factory, given a Consumer it will generate a new Producer and attach it to the Consumer.

A Sink contains a Consumer factory, given a Source it will generate a new Consumer and give the Consumer to the Source so it can attach a Producer to it.

So the command 0 instead of meaning "Start" now means "Connection established between Producer and Consumer" and is sent only from the producer to the consumer once immediately after attaching.

type Func = (...args: any[]) => any;
type Command = 0 | 1 | 2;

type Callbag = (cmd: Command, data?: any) => void;
type Producer = Callbag;
type Consumer = Callbag;

type Source = (c: Consumer) => void;
type Sink = (s: Source) => void;

type ToSource<T> = (x:T) => Source;
type FromSource<T> = (s:Source) => T;
type SourceTransformer = (s: Source) => Source;

type ToSink<T> = (x:T) => Sink;

function compose(...fs: Func[])
{
    return (x: any) =>
    {
        let res = x;
        for(let i = 0, n = fs.length; i < n; i++)res = fs[i](res);
        return res;
    };
}

const genericCallbag: Callbag = (c, d) => null;

const genericSource: Source = consumer =>
{
    const producer = genericCallbag;
    consumer(0, producer);
};

const genericSink: Sink = source =>
{
    const consumer = genericCallbag;
    source(consumer);
};

const pullableSource:ToSource<Iterable<any>> = iterable => (consumer =>
{
    const iterator = iterable[Symbol.iterator]();

    const producer: Callbag = (c, d) =>
    {
        switch(c)
        {
            case 0: break;
            case 1:
                const res = iterator.next();
                if(res.done)consumer(2);
                else consumer(1, res.value);
                break;
            case 2: break;
        }
    };

    consumer(0, producer);
});

const pullingSink:ToSink<Func> = f => (source =>
{
    let producer = genericCallbag;

    const consumer: Callbag = (cmd, data) =>
    {
        switch(cmd)
        {
            case 0: producer = data; producer(1); break;
            case 1: f(data); producer(1); break;
            case 2: break;
        }
    };

    source(consumer);
});

const map = (f: Func):SourceTransformer => (originalSource => consumer =>
{
    const mappedConsumer: Callbag = (cmd, data) =>
    {
        if(cmd === 1)return consumer(1, f(data));
        return consumer(cmd, data);
    }
    originalSource(mappedConsumer);
});

const take = (amount: number):SourceTransformer => (originalSource => consumer =>
{
    let taken = 0;
    let producer = genericCallbag;

    const boundedProducer: Callbag = (c, d) =>
    {
        if(c === 1)
        {
            if(taken < amount)
            {
                taken++;
                return producer(1, d);
            }
            else
            {
                producer(2);
                return consumer(2);
            }
        }
        if(c === 2)producer(2, d);
    };

    const boundedConsumer: Callbag = (cmd, data) =>
    {
        switch(cmd)
        {
            case 0:
                producer = data;
                consumer(0, boundedProducer);
                break;
            case 1: consumer(1, data); break;
            case 2: consumer(2); break;
        }
    }

    originalSource(boundedConsumer);
});

function* genMaker()
{
    let i = 0;
    while(i < i + 1)yield i++;
}

const gen = genMaker();

const log_square_of_first_4_from_iterable = compose(pullableSource, take(4), map(x => x * x), pullingConsumer(x => console.log(x)));

log_square_of_first_4_from_iterable(gen);

from callbag.

HarikrishnanBalagopal avatar HarikrishnanBalagopal commented on June 14, 2024

Note that above overflows stack if you try to take(2000), might be improved with tail call optimization but only Safari support proper tail calls.

from callbag.

staltz avatar staltz commented on June 14, 2024

What do you see is the benefit of this approach over the existing way?

from callbag.

HarikrishnanBalagopal avatar HarikrishnanBalagopal commented on June 14, 2024

Readability

from callbag.

HarikrishnanBalagopal avatar HarikrishnanBalagopal commented on June 14, 2024

Also slightly more concrete type definitions

from callbag.

HarikrishnanBalagopal avatar HarikrishnanBalagopal commented on June 14, 2024

Specifically this https://codesandbox.io/s/p5jwlp0x07 "try online" example given on the callbag-basics page was really unreadable given the simplicity of what it was doing. Also the type definitions seemed arbitrary and not generalized

from callbag.

HarikrishnanBalagopal avatar HarikrishnanBalagopal commented on June 14, 2024

Also i think there is some relation between Callbags and Monads.

from callbag.

StreetStrider avatar StreetStrider commented on June 14, 2024

Source, Sink… Looks like an attempt to implement all most.js biz on top of callbag (or other similar).

type Producer = Callbag;
type Consumer = Callbag;

Theese are just type aliases, aren't they? I'm not sure new distinct type («newtype», «opaque type») is created here. So no additional concretized typings here. Am I wrong?

I personally prefer simple functions over objects & classes for readability. The original spec falls in love with itself by its simplicity, minimalistic semantics and portability potential.

from callbag.

HarikrishnanBalagopal avatar HarikrishnanBalagopal commented on June 14, 2024

map, take, filter, etc look to me like Monad Transformers

from callbag.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.