Comments (13)
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.
@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.
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.
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.
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.
There's also a -iterator
function in CLJS (which is a protocol method really) whose name we could re-use...
from squint.
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, anddone
is a property that signals the iterator is exhausted.Iterable
: an object that has theSymbol.iterator
method on it, which can be called to create a newIterator
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.
Hmmm but null
is not iterable, so passing nil
or an empty collection to any seq functions will throw in that case.
from squint.
Unless those explicitly support nil
?
from squint.
@borkdude In the PR I just opened, I am trying the following:
seq
is the Clojure-like: takes a collection and returns anIterable
of that collection, ornil
if it's emptyiterable
takes a collection and returns anIterable
of that collection, even if it's emptyseqable?
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.
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.
I think the only thing left is to add the rest of the sequence functions, which I can create more issues for
from squint.
@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)
- optimize function definitions for esbuild HOT 6
- `squint/core` Shuffle function suggestions HOT 2
- `squint/core` Prefer slice over pop HOT 4
- cljs is not defined when using `case` HOT 3
- Squint remove ":" for keyword value HOT 16
- class definitions not showing in repl HOT 14
- `nil` keys in map HOT 3
- zipmaps are disordered HOT 3
- `nil` causes a crash in html rendering HOT 1
- html renderer crashes when rendering nil from variable
- How to emit try catch? HOT 3
- REPL fails with `(extends class-1)` in defclass HOT 10
- `html` spread `nil` HOT 1
- Support `js$console` for requiring global libs
- (:query req) or (get req :query) not working on express request object
- could squint be used as a clojurescript compiler to javascript, output of which works with Scittle? HOT 3
- Macros get resolved as normal functions HOT 1
- HTML is not escaped in dynamic expression HOT 1
- logical not is not working
- squint run disfunctional on windows
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from squint.