-
Notifications
You must be signed in to change notification settings - Fork 27
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
Return value is not chained? #47
Comments
You need to yield the component in order to make it work function* main() {
yield label('Please enter your name:');
yield input();
return {};
} Here is why:
function main() {
return input()
} If you want to chain a lot of components together you use the handy function main() {
return go(function*() {
yield label('Please enter your name:')
yield input();
return {};
});
} because we ended up using function* main() {
yield label('Please enter your name:')
yield input();
return {};
} The reason why your top example doesn't work is because in The reason why your bottom example works must be due to a bug. It seems that |
So this producers errors: import { runComponent, elements } from "../../src"
const { label, span, input, div } = elements
function main() {
return input()
}
runComponent("#mount", main); ERROR in ./hello-world/index.ts
(11,24): error TS2345: Argument of type '() => Component<InitialOutput<{ actionDefinitions: { focus: (element: HTMLElement) => void; }; be...' is not assignable to parameter of type 'Child<{}>'.
Type '() => Component<InitialOutput<{ actionDefinitions: { focus: (element: HTMLElement) => void; }; be...' is not assignable to type '() => Iterator<any>'.
Type 'Component<InitialOutput<{ actionDefinitions: { focus: (element: HTMLElement) => void; }; behavior...' is not assignable to type 'Iterator<any>'.
Property 'next' is missing in type 'Component<InitialOutput<{ actionDefinitions: { focus: (element: HTMLElement) => void; }; behavior...'. The same for the other plain function. There seems to be some problem when passing functions directly to the The |
That is because runComponent("#mount", main()); |
Ah this feels confusing. Would there be any problem to recognise a function and call it? |
I can see how that is confusing. Maybe we should remove the overload so that always requires a const main = go(function* () {
yield label('Please enter your name:')
yield input();
return {};
});
runCompoent(main); Maybe that is less confusing as it makes it more obvious that |
Thank you, I was confusing the So it feels somewhat confusing to treat them differently the yields from the return value. I was assuming some more uniform behavior, where it would not matter. That way the user would not have to think, which is always nice :) Would you see any problem with that approach? |
Yes. Then users would have to return a monad in their generator function. And do-notation most often ends with a pure value and not a monad (that's why If we changed it, a model couldn't look like this: function* model({ ... }) {
...
return { .. };
} It would have to look like this: function* model({ ... }) {
...
return Now.of({ .. });
} And a view couldn't look like this: function* view({ ... }) {
...
return { ... output ... };
} It would have to look like this. function* view({ ... }) {
...
return Component.of({ ... output ... });
} It would be a lot more cumbersome to use I think. |
I would only keep the Say if you really want to model a dialogue, where components appear in real time as the user types and hits return. That is actually a very important functionality that is painful to get with most frameworks, so having that type of use for generators would be neat! Say I declare my component as const main = function* () {
yield div("Welcome to our dating advice")
yield lable("Please type your name")
const {value: name} = yield input()
yield div(["Hello ", name, "how old are you?"])
const {value: age} = yield input()
...
} That would evolve as the questions proceed with more elements to appear in real time. That would be another "role" for the generators as I previously suggested. Would it make sense? |
I see. If the components are distinguishable from other values (e.g. via Symbol props), All other values can be collected in array in the order of their Right now, I am forced to give names to my outputs, which is kind of hurting their reusability. I would say, on the conceptual level, since the yields appear sequentially, And if you like to merge them into object, you can easily do it by passing objects Would it be a crazy idea? |
I have compared with how the The Jabz const safeDiv = (n, m) => m === 0 ? nothing : just(n / m);
go(function*() {
const a = yield find(isEven, list1);
const b = yield find(isEven, list2);
const c = yield safeDiv(a, b)
return a + b + c;
}); but does not seem to say anything about the lists, nor about the result of this computation. Transferring to the Component monad case here, that should mean function* main() {
yield label('Please enter your name:');
yield input();
return {};
} It does not seem to be wrapped in the monad here, does it? |
const safeDiv = (n, m) => m === 0 ? nothing : just(n / m);
go(function*() {
const a = yield find(isEven, list1);
const b = yield find(isEven, list2);
const c = yield safeDiv(a, b)
return a + b + c;
});
No, It is not the list/array monad. According to Jabz documentation, Chaining a Maybe is like saying: "Calculate this unless you get a
yes, this is correct.
it means that if |
@limemloh I can see that switching to the de-sugared So just to check: go(function*() {
const a = yield just(2)
return 1
}); desugars to just(2).chain(() => 1)
// => just(1) go(function* {
yield div('Hello')
return 1
}) desugars to div('Hello').chain(() => 1)
// => div('Hello') decorated with 'output' = 1 go(function* {
yield div('Hello')
}) is the same as go(function* {
yield div('Hello')
return undefined
}) which desugars to div('Hello').chain(() => undefined)
// => div('Hello') decorated with 'output' = undefined
function* main() {
yield label('Please enter your name:')
return input()
} when wrapped with label('Please enter your name:').chain(() => input())
// label(...) decorated with 'output' = input() So the component is sent to the
function* main() {
return input()
} when wrapped in input() because there is nothing to chain,
function* main() {
return yield input()
} is a shortcut for the more digestible function* main() {
const a = yield input()
return a
} which desugars to input().chain(a => a)
// => input() keeping its complete output whereas function* main() {
yield input()
} desugars to input().chain(() => undefined)
//=> input() with output undefined BTW, none of the tests for the Please correct me if there is still any flaw in my reasoning :) |
You are almost corret 😄 One must return a monad in
The last
It was a bug. It should be fixed in the latest version of Jabz.
I think that is right. But, not returning is equivalent to returning |
Oh, so you are using JS Both clever and surprising. ;) A normal JavaScripter using generators with That component is a function of its parent, adds a bit of complexity too. |
I like that idea. The only problem I see is that a component might do more than just concatenate DOM fragments. |
@limemloh |
I was expecting both elements to show up but only first one did:
It does show up when I remove the yield:
A bug or feature? :)
The text was updated successfully, but these errors were encountered: