question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

imitate was deemed necessary long ago before we had @cycle/state and other facilities. Internally, it requires significant “machinery” to work. For instance, see private methods _hasNoSinks (recursive!) and _pruneCycles.

Nowadays, I don’t see use of imitate, neither in the wild, neither in my apps. I would like to remove imitate, to decrease the size of xstream and make it faster too.

In this issue I’d like to hear from people if they use imitate or not. Of course if there’s still a real use case for it (not affected by the new facilities in Cycle.js), I’d like to hear it instead of just going ahead with this plan.

Issue Analytics

  • State:open
  • Created 3 years ago
  • Reactions:4
  • Comments:8 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
bgfistcommented, Sep 16, 2020

I think imitate could be replaced by defer like in rxjs, here’s my silly implementation for defer.

function defer<T>(create: () => Stream<T>) {
  let sub: Subscription;

  return xs.create<T>({
    start(observer) {
      sub = create().subscribe(observer);
    },
    stop() {
      sub?.unsubscribe();
    },
  });
}

and to use it like below:

const someOther$ = ...;

const a$ = someOther$.compose(sampleCombine(defer(()=> b$).startWith(...);
const b$ = a$.filter(...).map(...).startWith(..);

cause b$ is accessed in a closure, there’s no syntactics error. and a$/b$ must have an initial value(MemoryStream), otherwise both will be halting. this may cause infinite loop, but that depends on your logic.

and it’s really necessary for memory streams to depend on each other, cause in most cases both will filter out(in any way, like filter、sampleCombine、endWhen) those changes cause by themselves to avoid infinite loop.

1reaction
CarlLethcommented, Jul 31, 2020

I use xstream without cycles.js, and I use imitate often. I commonly have pairs of streams that look like (data: Stream<T>, updates: Stream<T => T>). Data gets broken down from high-level collections of objects into low-level fields, those low-level fields get mapped to input elements, then the input elements provide update streams that get built back up via merge. There’s a cycle: updates modify data, and data determines what updates are possible.

This is a simple use case; at least as simple as I can get it while still demonstrating everything. It relies on a streamCollection, a mutable collection that merges streams as they are added using imitate. stateMachine is just a fancy fold that applies the updates to the incoming data stream. m is mithril.js.

I’ve also included a diagram of what’s going on, which may or may not illustrate the point any better than the code. Blue dashed boxes are streams.

If you have a better solution that doesn’t require imitate (or cycle.js), I’m all ears.

function createBookTable(sourceData: Stream<Array<Book>>) {

    // Mutable collection of merged streams that relies on imitate
    const updates = new StreamCollection<(books: Array<Book>) => Array<Book>>()
    const liveData = stateMachine(sourceData, updates.stream);

    const viewModels = liveData.map(books => books.map(createBookVM));

    const tableVnodes = viewModels
        .map(arr => xs
            .combine(...arr.map(vm => vm.vnodes))
            .map(rows => m('table', rows))
        )
        .flatten();

    const arrayUpdates = viewModels
        .map(arr => xs.merge(...arr.map((vm, i) => vm.updates.map(update => (data: Array<Book>) => {
            const clone = [...data];
            clone[i] = update(data[i]);
            return clone;
        }))))
        .flatten();

    updates.add(arrayUpdates); // Stream.imitate happens here

    return {
        vnodes: tableVnodes,
        updates: updates.stream
    };
}

function createBookVM(book: Book) {
    const inputs = {
        author: new TextInput(book.author),
        title: new TextInput(book.title)
    };

    return {
        updates: xs.merge(
            inputs.author.updates.map(text => (book: Book) => <Book>Object.assign({}, book, { author: text })),
            inputs.title.updates.map(text => (book: Book) => <Book>Object.assign({}, book, { title: text }))
        ),
        vnodes: xs.combine(
            inputs.author.vnodes.map(input => m('td', input)),
            inputs.title.vnodes.map(input => m('td', input))
        ).map(cells => m('tr', cells))
    };
}

interface Book {
    author: string,
    title: string
}

class TextInput {
    updates: Stream<string>;
    vnodes: Stream<m.Vnode>;
    //...
}

reactive edit loop

Read more comments on GitHub >

github_iconTop Results From Across the Web

mimesis | art - Britannica
According to Plato, all artistic creation is a form of imitation: that which ... the musician are imitators of an imitation, twice removed...
Read more >
Imitate - definition of imitate by The Free Dictionary
2. do an impression of, take off (informal), mimic, do (informal), affect, copy, mock, parody, caricature, send ...
Read more >
Copycats imitate novel supply chain attack that hit tech giants
Today, a report from Sonatype reveals, other copycat actors are now imitating Birsan's research by flooding the npm repository with copycat ...
Read more >
Imitation by combination: preschool age children evidence ...
However, because models demonstrated an alternating technique where compartments were opened immediately after the removal of a defense, it is ...
Read more >
Spontaneous emergence, imitation and spread of ... - PubMed
In the last group the model preferred to remove the lid with her hands. Following these spontaneous differentiations of foraging techniques in the...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found