npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@coplt/suspend

v0.2.2

Published

[![Node.js CI](https://github.com/coplt/suspend.js/actions/workflows/node.js.yml/badge.svg)](https://github.com/coplt/suspend.js/actions/workflows/node.js.yml) ![MIT](https://img.shields.io/github/license/coplt/suspend.js) [![NPM](https://img.shields.io/n

Downloads

59

Readme

Suspend.js

Node.js CI MIT NPM Github

Experimental suspend base support library, to support continuations like kotlin suspend

This library is for theoretical research

It is not recommended that you actually use this library

Examples

MaybeMonad

import { Continue, Suspend, ReadySuspend } from '@coplt/suspend'

type Maybe<T> = { val: T } | null

namespace Maybe {
    export function maybe<R>(f: (co: Continue<R, Maybe<R>>) => Suspend<Maybe<R>>): Maybe<R> {
        return Suspend.calc(f(new Continue(val => new ReadySuspend({ val }))))
    }

    export function bind<T, R>(m: Maybe<T>, co: Continue<T, Maybe<R>>): Suspend<Maybe<R>> {
        if (m == null) return new ReadySuspend(null)
        return co.suspend(m.val)
    }
}
  • Usage 1

    let i = 0
    const r = Maybe.maybe<string>(co => {
        i++
        console.log(1)
        return Maybe.bind(
            { val: 1 },
            new Continue(a => {
                i++
                console.log(2)
                return co.suspend(`${a}`)
            })
        )
    })
    expect(i).toBe(2)
    expect(r).toEqual({ val: '1' })
    // console.log: 1 2

    fake code using suspend sugar

    let i = 0
    const r = Maybe.maybe<string>(suspend () => {
        i++
        console.log(1)
        const a = Maybe.bind({ val: 1 })
        i++
        console.log(2)
        return `${a}`
    })
    expect(i).toBe(2)
    expect(r).toEqual({ val: '1' })
    // console.log: 1 2
  • Usage 2

    let i = 0
    const r = Maybe.maybe<string>(co => {
        i++
        console.log(1)
        return Maybe.bind(
            null, // return here
            new Continue(a => {
                i++
                console.log(2)
                return co.suspend(`${a}`)
            })
        )
    })
    expect(i).toBe(1)
    expect(r).toEqual(null)
    // console.log: 1

    fake code using suspend sugar

    let i = 0
    const r = Maybe.maybe<string>(suspend () => {
        i++
        console.log(1)
        const a = Maybe.bind(null) // return here
        i++
        console.log(2)
        return `${a}`
    })
    expect(i).toBe(1)
    expect(r).toEqual(null)
    // console.log: 1

Async

import { Async, Continue } from '@coplt/suspend'

function delay(ms: number) {
    return new Promise<void>(res => {
        setTimeout(res, ms)
    })
}
  • Usage 1

    const r = await Async.run<number>(co => {
        return Async.await(
            delay(0), // any Promise value
            new Continue(() => {
                return co.suspend(1)
            })
        )
    })
    expect(r).toBe(1)

    fake code using suspend sugar

     const r = await Async.run<number>(suspend () => {
        Async.await(delay(0)) // any Promise value
        return 1
    })
    expect(r).toBe(1)
  • Usage 2

    const r = await Async.run<number>(co => {
        return Async.delay(
            0,
            new Continue(() => {
                return co.suspend(1)
            })
        )
    })
    expect(r).toBe(1)

    fake code using suspend sugar

    const r = await Async.run<number>(suspend () => {
        Async.delay(0)
        return 1
    })
    expect(r).toBe(1)
  • Usage Throw 1

    try {
        await Async.run<number>(() => {
            return Async.delay(
                0,
                new Continue(() => {
                    throw 'err'
                })
            )
        })
        throw 'never'
    } catch (e) {
        expect(e).toBe('err')
    }

    fake code using suspend sugar

    try {
        await Async.run<number>(suspend () => {
            Async.delay(0)
            throw 'err'
        })
        throw 'never'
    } catch (e) {
        expect(e).toBe('err')
    }
  • Usage Throw 2

    await Async.run<number>(co => {
        if (Math.random() > 0.5) throw 'err'
        return Async.delay(
            0,
            new Continue(() => {
                return co.suspend(1)
            })
        )
    })

    fake code using suspend sugar

    await Async.run<number>(suspend () => {
        if (Math.random() > 0.5) throw 'err'
        Async.delay(0)
        return 1
    })

Seq

function* take<T>(n: number, iter: Iterable<T>): Iterable<T> {
    let i = 0
    for (const v of iter) {
        if (i >= n) return
        yield v
        i++
    }
}
  • Usage 1

    const r = [
        ...Sequence.seq<number>((ctx, co) => {
            return ctx.yield(
                1,
                new Continue(() => {
                    return ctx.yield(
                        2,
                        new Continue(() => {
                            return ctx.yield(3, co)
                        })
                    )
                })
            )
        }),
    ]
    expect(r).toEqual([1, 2, 3])

    fake code using suspend sugar

    const r = [
        ...Sequence.seq<number>(suspend ctx => {
            ctx.yield(1)
            ctx.yield(2)
            ctx.yield(3)
        }),
    ]
    expect(r).toEqual([1, 2, 3])
  • Usage 2

    const r = [
        ...Sequence.seq<number>((ctx, co) => {
            return ctx.yieldAll([1, 2, 3], co)
        }),
    ]
    expect(r).toEqual([1, 2, 3])

    fake code using suspend sugar

    const r = [
        ...Sequence.seq<number>(suspend ctx => {
            ctx.yieldAll([1, 2, 3])
        }),
    ]
    expect(r).toEqual([1, 2, 3])
  • Usage 3

    function fib(n: number) {
        return Sequence.seq<number>((ctx, co) => {
            let [i, x, y] = [0, 0, 1]
            const loop = (): Suspend<void> => {
                if (i >= n) return co.suspend(void 0)
                return ctx.yield(
                    y,
                    new Continue(() => {
                        ;[x, y] = [y, x + y]
                        i++
                        return loop()
                    })
                )
            }
            return loop()
        })
    }
    
    const r = [...fib(10)]
    expect(r).toEqual([1, 1, 2, 3, 5, 8, 13, 21, 34, 55])

    fake code using suspend sugar

    function fib(n: number) {
        return Sequence.seq<number>(suspend ctx => {
            let [i, x, y] = [0, 0, 1]
            for (;;) {
                if (i >= n) return
                ctx.yield(y)
                ;[x, y] = [y, x + y]
                i++
            }
        })
    }
    
    const r = [...fib(10)]
    expect(r).toEqual([1, 1, 2, 3, 5, 8, 13, 21, 34, 55])
  • Usage 4

    function partA(ctx: Sequence<number>, co: Continue<void>): Suspend<void> {
        return ctx.yield(1, new Continue(() => partB(ctx, co)))
    }
    function partB(ctx: Sequence<number>, co: Continue<void>): Suspend<void> {
        return ctx.yield(2, new Continue(() => partA(ctx, co)))
    }
    
    const r = [...take(5, Sequence.seq(partA))]
    expect(r).toEqual([1, 2, 1, 2, 1])

    fake code using suspend sugar

    suspend function partA(ctx: Sequence<number>): void {
        ctx.yield(1)
        return partB(ctx)
    }
    suspend function partB(ctx: Sequence<number>): void {
        ctx.yield(2)
        return partA(ctx)
    }
    
    const r = [...take(5, Sequence.seq(partA))]
    expect(r).toEqual([1, 2, 1, 2, 1])