Comments (13)
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.
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.
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.
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.
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.
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.
What do you see is the benefit of this approach over the existing way?
from callbag.
Readability
from callbag.
Also slightly more concrete type definitions
from callbag.
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.
Also i think there is some relation between Callbags and Monads.
from callbag.
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.
map, take, filter, etc look to me like Monad Transformers
from callbag.
Related Issues (20)
- Use named constants and non-zero power of two values for type parameter HOT 1
- Versioning HOT 1
- I'm missing something HOT 12
- Calling a sourceTalkback with 1 and data HOT 1
- How to handle additional websocket connection state HOT 1
- Consuming pullable sources needs careful handling to avoid stack overflow HOT 21
- Errors and Termination HOT 11
- Ability to discover what IDs a callbag supports HOT 8
- A more concise way HOT 6
- Are asynchronous handshakes permitted? HOT 1
- What if an exception is thrown during callbag execution? HOT 19
- sink termination propagation
- Confusion about spec HOT 7
- Control flow assumptions HOT 16
- Express variance in types HOT 12
- Ability to detect callbags
- Stricter types? HOT 1
- Missing index.js referenced from "main" in package.json breaks Vite HOT 1
- Why do we say sink is a callbag?
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from callbag.