Schizophrénie fractale



Non, je ne suis pas malade. Du moins c'est ce que dit la voix dans ma tête. Je suis toxicomane. Je suis sur l'aiguille depuis plus de 15 ans. J'utilise beaucoup, dur, jusqu'à ce que je m'évanouisse. J'en suis arrivé au point que dernièrement, je n'ai pas eu honte de mes amis, de ma femme ou de mes enfants ... Deux enfants! Je n'aime pas le badazhenny, j'aime propre, sans impuretés. J'ai beaucoup essayé au fil des ans, mais récemment j'ai arrêté de chercher. C'est drôle de réaliser que la même chose vous procure à la fois de la douleur et de la joie. J'aimerais aller en cure, j'en ai même envie, je sais même laquelle. Connaissez-vous ceux où vous continuez à utiliser, mais sous supervision?



typescript. — . , , . , , , , . -, , , , - . , , - , , ...



, es- — . ruby javascript, , - — yield? ! , — : ? ? /? Oh My God!



. , , - , , , . , , , , yield yield , , - . , . - , , ...



-. — react + mobx. , / , , , , , , , , … , , — , , , .



- . MV* , — . — * ! ? — , M , V , , , !



, typescript. , , Maximum call stack size exceeded — ? , , , , .



. . , , . Html- — , ? ? ? , , — , — — , ...



, , . — - . , . .



- " " — , , , . : " , — " — — "! !". ! ?)



- . . , , , , , . ? , — , , , , ? — 19 , , 1844 , 1862 , , . . , , . , - ? ? , , , , … … ? ? ?



! ! , , - . , . , . — , .



, , 3 , ~800 git- . yield*. -, . return ? , , , .



async function* SiriusA() {
    return '*A' //    
}

async function* SiriusB() {
    return '*B' //    
}

async function* Sirius() {
    // ['*A', '*B']    
    return [yield* SiriusA(), yield* SiriusB()]
}

async function* CanisMajor() {
    const sirius = yield* Sirius() // ['*A', '*B']
    //  -      
}


-. : " ? " — , . yield*. , return- " " yield-, — , , , . — , : " ", ~300 . , , - - , , . .





, . , , — . , , — .



, , , .., - , . — , .





@fract/core — — , : fractal fraction. , . , , npm yield*.



Hello world , ,



import { fractal, fraction } from '@fract/core'

const Title = fraction('Hello world')

const HelloWorld = fractal(async function* () {
    while (true) yield `App: ${yield* Title}`
})


, — , . — , , .use(data).





yield , yield* , — , yield* — , yield . pull & push.





, :



  1. yield return — , yield* ; , ,
  2. , , yield, ; return


return , yield — , "" .





, . , .





interface Frame<T> {
    data: T;
}


, . , - , .



interface LiveFrame<T> extends Frame<T> {
    next: Promise<LiveFrame<T>>;
}


— , : .





exec live. ( ) , .



import { exec, live } from '@fract/core'


exec<T>(target: Fractal<T> | AsyncGenerator<T>): Promise<Frame<T>>



, .



const frame = await exec(HelloWorld)

frame.data // 'App: Hello world'


live<T>(target: Fractal<T> | AsyncGenerator<T>): Promise<LiveFrame<T>>



, .



const frame = await live(HelloWorld)

frame.data // 'App: Hello world'

Title.use('Fractal Demo')

const nextFrame = await frame.next

nextFrame.data // 'App: Fractal Demo'




, ,



const Name = fraction('John')
const Age = fraction(33)
const Balance = fraction(100)

const Card = fractal(async function* () {
    while (true) {
        yield {
            balance: yield* Balance,
        }
    }
})

const User = fractal(async function* () {
    while (true) {
        yield {
            name: yield* Name,
            age: yield* Age,
            card: yield* Card,
        }
    }
})




const frame = await exec(Balance)
frame.data //> 100


const frame = await exec(Card)
frame.data //> {balance: 100}


const frame = await exec(User)
frame.data
/*
> {
    name: 'John',
    age: 33,
    wallet: {
        balance: 100
    }
}
*/


exec , live



const frame = await live(User)

console.log(frame.data)
/*
> {
    name: 'John',
    age: 33,
    card: {
        balance: 100
    }
}
*/

Name.use('Barry')
Balance.use(200)

const nextFrame = await frame.next

console.log(nextFrame.data)
/*
> {
    name: 'Barry',
    age: 33,
    card: {
        balance: 200
    }
}
*/


, , User ( ), undefined ( )



const App = fractal(async function* () {
    while (true) {
        console.log(yield* User)
        yield
    }
})

live(App) //  




— ,





, — .



, , — . , , — Promise<LiveFrame<T>>[], racers, , Promise.race(racers) — — racer , racers — .









Promise.race([
    // level 1 
    Promise.race([/* ... */]),
    Promise.race([/* ... */]),
    Promise.race([
        // level 2
        Promise.race([/* ... */]),
        Promise.race([/* ... */]),
        Promise.race([/* ... */]),
        Promise.race([/* ... */]),
        Promise.race([/* ... */]), 
        Promise.race([ 
            // level 3
            Promise.race([/* ... */]),
            Promise.race([/* ... */]) 
        ])
    ])
])


— " " , . " " , . ,



const Name = fraction('John')

const User = fractal(async function* () {
    while (true) {
        yield `User ${yield* Name}`
    }
})

const Title = fraction('Hello')

const Post = fractal(async function* () {
    while (true) {
        delay(5000) // -  
        yield `Post ${yield* Title}`
    }
})

const App = fractal(async function* () {
    while (true) {
        console.log(`App | ${yield* User} | ${yield* Post}`)
        yield
    }
})

live(App)

//> 'App | User John | Post Hello'

Name.use('Barry')
Title.use('Bye')

//> 'App | User Barry | Post Hello'
//  5 
//> 'App | User Barry | Post Bye'


Name Title, User Post , User , App PostApp , Post . App , Post . , "" .





. , . tmp(data), yield.



— "". , -, .



import { fractal, tmp } from '@fract/core'

const User = fractal(async function* () {
    yield tmp('Loading...')

    delay(5000) // -  

    while (true) {
        yield `User John`
    }
})

const App = fractal(async function* () {
    while (true) {
        console.log(yield* User)
        yield
    }
})

live(App)

//> 'Loading...'
//  5 
//> 'User John'


User "", , .. - . , User 'Loading...' , , .. yield tmp(...) , .



— , , -



import { fractal, tmp } from '@fract/core'

const Timer = fractal(async function* () {
    let i = 0

    while (true) {
        yield tmp(i++)
        await new Promise((r) => setTimeout(r, 1000))
    }
})

const App = fractal(async function* () {
    while (true) {
        console.log(yield* Timer)
        yield
    }
})

live(App)

//> 0
//> 1
//> 2
//> ...


Timer i , i, 1 . — , , .use(data), .





, . , — .



newEditor, , . Manager, ProfileId .





function newEditor(id) {
    return fractal(async function* () {
        const { name } = await loadUserInfo(id)
        const Name = fraction(name)

        while (true) {
            // -     
            //    
            yield <input 
                placeholder="Input name" 
                value={yield* Name} 
                onChange={(e) => Name.use(e.target.value)} 
            />
        }
    })
}

const ProfileId = fraction(1)

const Manager = fractal(async function* () {
    while (true) {
        const id = yield* ProfileId
        const Editor = newEditor(id)
        yield Editor // <--    Editor
    }
})

const App = fractal(async function* () {
    while (true) {
        yield yield* Manager
    }
})


- , - , Name. while(true) App, Manager. Editor, .





Manager ProfileId. Manager , Editor .



, — ProfileId - , Editor, id . .



const ProfileId = fraction(1)

const Manager = fractal(async function* () {
    let lastProfileId
    let Editor

    while (true) {
        const id = yield* ProfileId

        if (id !== lastProfileId) {
            lastProfileId = id
            Editor = newEditor(id)
        }

        yield yield* Editor
    }
})


, .



const BarryName = fractal(async function* () {
    while (true) yield 'Barry'
})

const Name = fraction('John')

const App = fractal(async function* () {
    while (true) {
        console.log(yield* Name)
        yield
    }
})

live(App)

//> 'John'
Name.use(BarryName)
//> 'Barry'


— , yield BarryName.





, , . , . .





import { factor } from '@fract/core'

const API_VERSION = factor('v2') // 'v2' | 'v3'
//   ^^^^  

/*      */

yield* API_VERSION('v3')    //   
yield* API_VERSION          // 'v3' - 
yield* API_VERSION.is('v3') // boolean - 

//    
// c    
yield* API_VERSION()
yield* API_VERSION          // 'v2' 


, . , api API_VERSION api .



const Page = fractal(async function* () {
    const apiVersion = yield* API_VERSION

    while (true) {
        yield `Work on api "${apiVersion}"`
    }
})

const Modern = fractal(async function* () {
    yield* API_VERSION('v3')
    //     api v3

    while (true) {
        yield yield* Page
    }
})

const Legacy = fractal(async function* () {
    yield* API_VERSION('v2')
    //     api v2

    while (true) {
        yield yield* Page
    }
})

const App = fractal(async function* () {
    while (true) {
        console.log(`
            Modern: ${yield* Modern}
            Legacy: ${yield* Legacy}
        `)
        yield
    }
})

live(App)

/*
> `
    Modern: Work on api "v3"
    Legacy: Work on api "v2"
`
*/


! , , ,





const Top = fractal(async function* () {
    yield* API_VERSION('v3')

    while (true) {
        yield yield* Middle
    }
})

const Middle = fractal(async function* () {
    yield* API_VERSION       // 'v3' -    Top
    yield* API_VERSION('v2') // ,    
    yield* API_VERSION       //       'v3'

    while (true) {
        yield yield* Bottom
    }
})

const Bottom = fractal(async function* () {
    yield* API_VERSION       // 'v2' -   Middle

    while (true) {
        yield /*...*/
    }
})




— , . , , , .





const APP_STORE = 'APP'

function newApp({ name = 'Hello world' } /* AppState {name: string} */) {
    const Name = fraction(name)

    return fractal(async function* App() {
        while (true) {
            switch (yield* MODE) {
                case 'asString':
                    yield `App ${yield* Name}`
                    continue
                case 'asData':
                    yield { name: yield* Name } // as AppState {name: string}
                    continue
            }
        }
    })
}

const Dispatcher = fractal(async function* () {
    //      
    const data = JSON.parse(localStorage.getItem(APP_STORE) || '{}')

    //    
    const App = newApp(data)

    //       'asString'
    const AsString = fractal(async function* () {
        yield* MODE('asString')
        while (true) yield yield* App
    })

    //       'asData'
    const AsData = fractal(async function* () {
        yield* MODE('asData')
        while (true) yield yield* App
    })

    while (true) {
        const asString = yield* AsString //     
        const asData = yield* AsData     //     
        // 
        console.log(asString)
        // 
        localStorage.setItem(APP_STORE, JSON.stringify(asData))
        yield
    }
})


: App MODE, AsString AsData, Dispatcher. , — , .





( ). — , , — , . — , . , , api ..



MV* MVVM MVP



, MV* MVVM MVP .. . , ,





— , , — .





javascript , , .



import { fractal, factor } from '@fract/core'

// app.js
export const API_URI = factor()
export const THEME = factor('light')

export const App = fractal(async function* () {
    const apiUri = yield* API_URI
    const theme = yield* THEME

    if (!apiUri) {
        //  
        throw new Error('Factor API_URI is not defined')
    }

    while (true) {
        /*...*/
    }
})


, .



code splitting



, await. , " " . — , js , . , ...



, . , ,





, , , (). , , , — , — , .



, , webpack, ,



// ./user.js
export const User = fractal(async function* () {
    while (true) yield `User John`
})

// ./app.js
export const App = fractal(async function* () {
    //  ,     
    const { User } = await import('./user')

    while (true) yield `User ${yield* User}`
})


, , , IntelliSense .





, , TodoMVC. , , … — , , , . - — . , — . - , , , , . ...



. , , , , , , , — . , , .



, . , . react styled-components — , , .







  • ,
  • jsx -> html , react , , diff ,
  • — ? , , ,
  • grahpql, - - yield* gql'...'
  • open source — ,
  • :) , — readme




, - noname- , , , , .



, , - , - react- , @fract/react-alive



import { fractal } from '@fract/core'
import { Alive } from '@fract/react-alive'

const App = fractal(async function* () {
    while (true) {
        yield <div>Hello world</div>
    }
})

function Render() {
    return <Alive target={App} />
}


— , , yield*? @fract/browser-pathname. , window.location.pathname, redirect(p: string) . , , , -.





— . , , . , react , , , , — .





, , . , .



, .



" — " ©




All Articles