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

Is there something to know about Option<T>? #80

Closed
grepsuzette opened this issue Dec 4, 2021 · 2 comments
Closed

Is there something to know about Option<T>? #80

grepsuzette opened this issue Dec 4, 2021 · 2 comments

Comments

@grepsuzette
Copy link

grepsuzette commented Dec 4, 2021

Weird thing here:

import coconut.Ui.hxx;
import coconut.ui.*;
using tink.CoreApi;

class T implements coconut.data.Model  {
    public static function main() {
        var doc = js.Browser.document;
        var div = doc.createDivElement();
        js.Browser.document.body.appendChild( div);
        var world = new World();
        haxe.Timer.delay( ()->world.loadIt(), 1000 );
        var prov1 = new FruitsProvider(world.season);
        Renderer.mount( div, hxx('<V prov1={prov1} />'));
    }
}

class World implements coconut.data.Model {
    @:observable var season : Option<Season> = @byDefault None;
    @:transition public function loadIt() return { season: Some(new Season("autumn")) }
}

class Season implements coconut.data.Model {
    @:editable var name:String;
    public function new(name:String) this = { name:name }
}

class FruitsProvider implements coconut.data.Model {
    @:external var season: Option<Season>;
    public function new(season:Option<Season>) this = { season:season }   // HERE!
}

class V extends coconut.ui.View {
    @:attr var prov1 : FruitsProvider;
    function render()
        <>
            <p>Season: 
                <switch {prov1.season}>
                    <case {Some(season)}> {season.name}
                    <case {None}> unknown yet
                </switch>
            </p>
        </>
    ;
}
  • If constructor of FruitsProvider is kept as in the example,
    the name of the season will never show up ("unknown yet"):
    public function new(season:Option<Season>) this = { season:season }

  • But it will work if either:

    1. type is removed , public function new(season) this = { season:season }
    2. constructor is removed (in that case, built as new FruitsProvider({season:"winter"})))
@grepsuzette
Copy link
Author

grepsuzette commented Dec 5, 2021

After I posted this, I tried to remove the type in the constructor of one of my classes (been struggling for weeks, there were like 4 rewrites) and suddenly all the app works and updates magically!

The build macro for Model working around the constructor maybe has a bug?
(I hope it's a bug and not a type issue)

@back2dos
Copy link
Member

back2dos commented Dec 5, 2021

Yeah, this one is a bit tricky.

The problem here is that @:external consumes a coconut.data.Value which is essentially an Observable with a @:from macro cast that will wrap non-observable expressions in Observable.auto(() -> $expr).

If you remove the type hint, then season is inferred to Value<Option<Season>> (which is the correct type to use here).

Thus var prov1 = new FruitsProvider(world.season); compiles to var prov1 = new FruitsProvider(Observable.auto(() -> world.season));.

If you leave the type as it is, then you get var prov1 = new FruitsProvider(world.season); and that only passes the current value to the FruitsProvider and its constructor implementation will be generated with this = { season: Observable.auto(() -> season) } - observing a function argument does not cause updates.

Sorry for the trouble. The upcoming v1 will axe this footgun: #77

@back2dos back2dos closed this as completed Dec 5, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants