Информация об изменениях

Сообщение Re[2]: Базовое отличие ООП от ФП от 06.03.2024 15:37

Изменено 06.03.2024 15:42 Разраб

Re[2]: Базовое отличие ООП от ФП
Здравствуйте, Sinclair, Вы писали:

S>Здравствуйте, Разраб, Вы писали:

Р>>Появляется неявный контекст, "за лесом не видно деревьев".

S>Принципиальное отличие в наличии изменяемого состояния, для которого необходима идентифицируемость (identity).

S>Всё остальное — непринципиально. Если его нет, то объект — это просто набор функций, которые объединены (или не объединены) общим замыканием. Интерфейс становится кортежем функций, а класс — синоним конструктора.
Дело в том, что ООП делает состояние и управление им неявным, взять хотя бы классический WPF, он полагается на магические пропертя и рефлексию.
Но сейчас уже набирает силу ФРП, и оно делает многие вещи более простым способом
open Avalonia
open Avalonia.Controls
open Avalonia.Markup.Xaml
open FSharp.Control.Reactive
open Avalonia.Threading

type AppState =
    { Count: int
      EnableTimer: bool }

    static member Zero = { Count = 0; EnableTimer = true }

type MainWindow() as this =
    inherit Window()
    do this.InitializeComponent()

    member private this.InitializeComponent() =
#if DEBUG
        this.AttachDevTools()
#endif
        AvaloniaXamlLoader.Load(this)

        let count = Subject.behavior (AppState.Zero)

        let tb = this.FindControl<TextBlock>("info")
        let btn = this.FindControl<Button>("inc")
        let inc = fun (x: AppState) -> { x with Count = x.Count + 1 }

        btn.Click.Add(fun _ ->
            if count.Value.EnableTimer then
                count.OnNext(
                    { count.Value with
                        Count = count.Value.Count + 1
                        EnableTimer = false }
                )
            else
                count.OnNext(inc count.Value))

        count.Subscribe(fun x -> Dispatcher.UIThread.Invoke(fun _ -> tb.Text <- $"Count: {x.Count}"))
        |> ignore

        task {
            while count.Value.EnableTimer do
                do! Async.Sleep 1000
                count.OnNext(inc count.Value)
        }
        |> ignore
Re[2]: Базовое отличие ООП от ФП
Здравствуйте, Sinclair, Вы писали:

S>Здравствуйте, Разраб, Вы писали:

Р>>Появляется неявный контекст, "за лесом не видно деревьев".

S>Принципиальное отличие в наличии изменяемого состояния, для которого необходима идентифицируемость (identity).

S>Всё остальное — непринципиально. Если его нет, то объект — это просто набор функций, которые объединены (или не объединены) общим замыканием. Интерфейс становится кортежем функций, а класс — синоним конструктора.
Дело в том, что ООП делает состояние и управление им неявным, взять хотя бы классический WPF, он полагается на магические пропертя и рефлексию.
Но сейчас уже набирает силу ФРП, и оно делает многие вещи более простым способом(еще можно глянуть solidjs)
open Avalonia
open Avalonia.Controls
open Avalonia.Markup.Xaml
open FSharp.Control.Reactive
open Avalonia.Threading

type AppState =
    { Count: int
      EnableTimer: bool }

    static member Zero = { Count = 0; EnableTimer = true }

type MainWindow() as this =
    inherit Window()
    do this.InitializeComponent()

    member private this.InitializeComponent() =
#if DEBUG
        this.AttachDevTools()
#endif
        AvaloniaXamlLoader.Load(this)

        let count = Subject.behavior (AppState.Zero)

        let tb = this.FindControl<TextBlock>("info")
        let btn = this.FindControl<Button>("inc")
        let inc = fun (x: AppState) -> { x with Count = x.Count + 1 }

        btn.Click.Add(fun _ ->
            if count.Value.EnableTimer then
                count.OnNext(
                    { count.Value with
                        Count = count.Value.Count + 1
                        EnableTimer = false }
                )
            else
                count.OnNext(inc count.Value))

        count.Subscribe(fun x -> Dispatcher.UIThread.Invoke(fun _ -> tb.Text <- $"Count: {x.Count}"))
        |> ignore

        task {
            while count.Value.EnableTimer do
                do! Async.Sleep 1000
                count.OnNext(inc count.Value)
        }
        |> ignore