Coder Social home page Coder Social logo

Seqs & iterators about squint HOT 13 CLOSED

lilactown avatar lilactown commented on August 19, 2024 3
Seqs & iterators

from squint.

Comments (13)

lilactown avatar lilactown commented on August 19, 2024 1

It looks like destructuring uses the iterable protocol, so we can easily do

export function first(coll) {
  // destructuring uses iterable protocol
  let [first] = coll;
  return first;
}

export function rest(coll) {
  let [_, ...rest] = coll;
  return rest;
}

and get the behavior we want, fast.

from squint.

borkdude avatar borkdude commented on August 19, 2024 1

@lilactown So far this makes a ton of sense to me :)

Perhaps add a bit to the README about differences to ClojureScript, basically what you said in your last comment

from squint.

lilactown avatar lilactown commented on August 19, 2024

I'm not sure yet how this relates to things like first, rest and cons. first could take an iterable, create an iterator and return the first, throwing away the iterator. rest could copy map and convert the iterable to an array before returning. 🤔

from squint.

lilactown avatar lilactown commented on August 19, 2024

A downside I've found in implementing & using this in tests is that objects (as created via {:a 1}) does not implement the Iterable protocol. So you cannot pass an object created via {:a 1} as a collection to map, reduce, etc.

You can get access to an iterator via functions like Object.keys, Object.values and Object.entries.

A thought I have: provide a helper function iterable which coerces the value passed to it as something iterable, very similar to seq. For arrays, sets, maps and anything else that already implements the Iterable method, it would pass through unchanged. If the value is an object, it will return Object.entries(o). This can be used internally in reduce, map, etc. to allow them to be used on objects without having to extend the iteratable protocol to them.

Thoughts?

from squint.

borkdude avatar borkdude commented on August 19, 2024

An internal function is always ok. Not sure if we should expose this. Perhaps we could expose it as seq, which would return nil if the iterator was empty, like in Clojure...?

from squint.

borkdude avatar borkdude commented on August 19, 2024

There's also a -iterator function in CLJS (which is a protocol method really) whose name we could re-use...

from squint.

lilactown avatar lilactown commented on August 19, 2024

Writing down some notes for posterity:

  • Iterator: an object with the structure {next, done, value}. next() when called progresses the iterator, value is a property that contains the current value, and done is a property that signals the iterator is exhausted.
  • Iterable: an object that has the Symbol.iterator method on it, which can be called to create a new Iterator object

The thing that makes this tricky is that the for...of comprehension and JS destructuring expect an Iterable, not an Iterator object. So working with a raw Iterator object is also not a complete replacement of ISeq.

Perhaps seq would make sense if it took an Iterable, checked to see if it's empty, and returned nil if so. It could also support nil punning. I'm starting to like that idea @borkdude.

from squint.

lilactown avatar lilactown commented on August 19, 2024

Hmmm but null is not iterable, so passing nil or an empty collection to any seq functions will throw in that case.

from squint.

borkdude avatar borkdude commented on August 19, 2024

Unless those explicitly support nil?

from squint.

lilactown avatar lilactown commented on August 19, 2024

@borkdude In the PR I just opened, I am trying the following:

  • seq is the Clojure-like: takes a collection and returns an Iterable of that collection, or nil if it's empty
  • iterable takes a collection and returns an Iterable of that collection, even if it's empty
  • seqable? can be used to check if you can call either one

first, rest, map, reduce et al. use iterable to avoid having to do explicit nil checks, which they would need to do if they called seq.

from squint.

borkdude avatar borkdude commented on August 19, 2024

Alright, I think we could close this now, probably, since we pretty much locked down the seq + iterator behavior, unless you have something to add @lilactown ?

from squint.

lilactown avatar lilactown commented on August 19, 2024

I think the only thing left is to add the rest of the sequence functions, which I can create more issues for

from squint.

brandonstubbs avatar brandonstubbs commented on August 19, 2024

@lilactown I am catching up on all of this, just leaving this here for thought Reading this and the transducers issue it's exactly your thoughts, let me know if you want any help with anything

function _first([x]) {
  return x;
}

function _toArray(iterable) {
  const array = [];
  for (const x of iterable) {
    array.push(x);
  }
  return array;
}

function* _map(iterable, f) {
  for (const x of iterable) {
    yield f(x); 
  }
}

function* _filter(iterable, pred) {
  for (const x of iterable) {
    if (pred(x)) {
      yield x;
    }
  }
}

function map(f, coll) {
  return _toArray(_map(coll, f));
}

function filter(pred, coll) {
  return _toArray(_filter(coll, pred))
}

console.log(map((v) => v + 1,new Array(1, 2)))
console.log(filter((v) => v === 2, new Array(1, 2)))

function transformer(iterable) {
  return {
    first: () => _first(iterable),
    map: f => transformer(_map(iterable, f)),
    filter: pred => transformer(_filter(iterable, pred)),
    toArray: () => _toArray(iterable),
    [Symbol.iterator]: () => iterable[Symbol.iterator](),
  }
}

console.log(
  transformer(new Array(1, 2))
    .map(v => v + 1)
    .filter(v => v == 2)
    .first()
);

console.log(
  transformer(new Array(1, 2))
    .map(v => v + 1)
    .filter(v => v == 2)
    .toArray()
);

from squint.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.