Giter VIP home page Giter VIP logo

list's People

Contributors

adagen avatar alejandronanez avatar andarist avatar dangh avatar dependabot[bot] avatar dubzzz avatar emmanueltouzery avatar etienne-dldc avatar greenkeeper[bot] avatar jasonsooter avatar jourdain avatar lesar avatar limemloh avatar lindekaer avatar littlehaker avatar macgyver avatar mikaelbr avatar monsieurman avatar paldepind avatar screendriver avatar skaterdad avatar styfle avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

list's Issues

Export functions as methods on the List class

Hi paldepind, thanks for making this interesting library.

I wonder why you chose to make functions as stand-alone and not property methods on the List class? This would make them a little more convenient to use, i.e. xs.filter(p) instead of L.filter(xs, p).

/Dan

NonEmptyList

I used funkia/list on a larger project and was generally very happy with it. One big missing piece for me was the availability of a NonEmptyList. Having this available helps reduce a lot of code concerned with checking if a list is empty or not, because in many situations an empty list would be an application error and should be caught far out in the API layer, not in the app's core code.

The fp-ts NonEmptyArray is a good starting point for how this should work.

little bug

I think you have exchange row 18 with 19 in:
make-proxies
so there is a comma problem in package.json

I have a strange warning too

WARNING in ./node_modules/list/dist/es/index.js
(Emitted value instead of an instance of Error) Cannot find source file '../../src/index.ts': Error:
Can't resolve '../../src/index.ts' in '/functionalHyperscriptTodoList/node_modules/list/dist/es'

regards

list will not release items for GC

such code:

      // do a cheap slice by setting prefix length
      bits = setPrefix(prefixSize - from, bits);

is not quite OK. list should wipe pointers to the items to enable them to be garbage collected, otherwise we have in effect a memory leak.. Items are unreachable for list users but list holds them in memory.

multi-field sort

Hi,

First, great lib πŸ‘

I wanted to know if you were planning on adding a method allowing to sort on multiple fields?
I played with your codebase, and I implemented (naΓ―vely) it like this:

type SortOption<T> = {
  by: (item: T) => string | number
  reverse?: boolean
}

function sortByMultipleFields(opts: SortOption<T>[], l: List): List {
  if (l.length === 0) {
    return l;
  }
  let arr = l;

  arr = [].concat(l.prefix, l.suffix) // quick and dirty...

  arr.sort((a, b) => {
    for (let index = 0; index < opts.length; index++) {
      const { by, reverse = false } = opts[index];

      if (by(a) < by(b)) return reverse ? 1 : -1;
      if (by(a) > by(b)) return reverse ? -1 : 1;
    }

    return 0;
  });

  let newL = emptyPushable();
  for (let i = 0; i < arr.length; ++i) {
    push(arr[i], newL);
  }
  return newL;
}
exports.sortByMultipleFields = sortByMultipleFields;

Then, you can use it like this:

const items = L.list(
  { id: 2, name: 'bb' },
  { id: 1, name: 'bb' },
  { id: 2, name: 'aa' },
  { id: 1, name: 'aa' }
)

const sortedItems = items.sortByMultipleFields([
  { by: i => i.id }, // first I want the items sorted by their id
  { by: i => i.name, reverse: true }, // then, by their name, but in reverse order
])

// sortedItems = [
// { id: 1, name: 'bb },
// { id: 1, name: 'aa },
// { id: 2, name: 'bb },
// { id: 2, name: 'aa' },
// ]

list throws

I got this stack when playing with list in my fuzzer (2.0.14) =>

 TypeError: Cannot read property 'sizes' of undefined
  at sliceRight (node_modules/list/dist/index.js:1220:49)
  at sliceRight (node_modules/list/dist/index.js:1227:21)
  at slice (node_modules/list/dist/index.js:1347:28)
  at Object.take (node_modules/list/dist/index.js:1360:12)
  at Vector.take (dist/src/Vector.js:613:29)
  at Array.<anonymous> (dist/tests/Seq.js:362:62)
  at Context.<anonymous> (dist/tests/Seq.js:384:28)

presumably that should never happen. I have no reproduction for now.

How to import?

I know it is a stupid question, but

import * as L from "list";

not work.

I am using typescript 2.7.2 and this is a package.json bit:

  "engines": {
    "node": "9.11.1"
  },
  "dependencies": {
    "@types/ramda": "^0.25.0",
    "classnames": "^2.2.5",
    "hyperscript": "^2.0.2",
    "hyperscript-helpers": "^3.0.3",
    "inferno": "^5.0.1",
    "inferno-hyperscript": "^5.0.1",
    "inferno-redux": "^5.0.1",
    "list": "^2.0.7",
    "ramda": "^0.25.0",
    "redux": "^3.7.2",
    "reselect": "^3.0.1",
    "type-to-reducer": "^1.1.0"
  },
  "devDependencies": {
    "@types/classnames": "^2.2.3",
    "awesome-typescript-loader": "^4.0.1",
    "clean-webpack-plugin": "^0.1.17",
    "css-loader": "^0.28.11",
    "ejs-loader": "^0.3.1",
    "extract-text-webpack-plugin": "3",
    "file-loader": "^1.1.11",
    "html-webpack-plugin": "^3.1.0",
    "source-map-loader": "^0.2.3",
    "style-loader": "^0.20.3",
    "typescript": "^2.7.2",
    "uglifyjs-webpack-plugin": "^1.1.6",
    "webpack": "3",
    "webpack-bundle-analyzer": "^2.11.1",
    "webpack-cli": "2",
    "webpack-dev-middleware": "3",
    "webpack-dev-server": "2",
    "webpack-merge": "4.1.1",
    "xml-loader": "^1.2.1"
  }

if I try this

import { List } from "list";

not work too.

some message:

No declaration file was found for the 'list' module. A '.../functionalHyperscriptTodoList/node_modules/list/dist/index.js' is implicitly assigned an 'any' type.
Try npm install @ types / list if it exists or add a new declaration file with extension d.ts containingdeclare module 'list';

what is my error?
regards

at least one other bug in the list

so i've been a been worried because of the bug I found previously in list and decided to write a fuzzer to search for bugs. The fuzzer is relavitely easier to write for me because I have several collections with the same API (vector, linkedlist, stream).

And actually it found at least one bug in list 2.0.14. There could be several, it's hard to tell. I've extracted a reproduction from a run of the fuzzer where the reproduction was a little shorter... But obviously it's not exactly a minimal reproduction.

Here's the reproduction, I run actions on both list and a plain JS array. The actions should result in the same result, but they don't.

notice that both lists have the same value up to the last computation. So in the end to convince yourself there's a bug you only need to review the last lines.

The final lists are completely different, list returning a list starting with [ 2704, 2688, 2672, .. and JS arrays by [ 1136, 1128, 1120, ....

const L = require("list")

let f = L.list()
let g = []

function arrayOfLength(l:number) {
    const r = [];
    for (let i=0;i<l;i++) {
        r.push(i);
    }
    return r;
}

f = L.map(x=>x*2, f)
g = g.map(x=>x*2)

f = L.concat(f, L.from(arrayOfLength(176)));
g = [...g,...arrayOfLength(176)];

f = L.concat(f, L.from(arrayOfLength(230)));
g = [...g,...arrayOfLength(230)];

f = L.take(24, f);
g = g.slice(0,24)

f = L.take(116, f);
g = g.slice(0,116)

f = L.concat(f, L.from(arrayOfLength(125)));
g = [...g, ...arrayOfLength(125)];

f = L.map(x=>x*2, f)
g = g.map(x=>x*2)

f = L.concat(f, L.from(arrayOfLength(192)));
g = [...g, ...arrayOfLength(192)];

f = L.concat(f, L.from(arrayOfLength(211)));
g = [...g, ...arrayOfLength(211)];

f = L.concat(L.from(arrayOfLength(243)), f);
g = [...arrayOfLength(243),...g];

f = L.map(x=>x*2, f)
g = g.map(x=>x*2)

f = L.reverse(f)
g = g.reverse()

f = L.concat(f, L.from(arrayOfLength(236)));
g = [...g, ...arrayOfLength(236)];

f = L.reverse(f)
g = g.reverse()

f = L.concat(f, L.from(arrayOfLength(231)));
g = [...g, ...arrayOfLength(231)];

f = L.map(x=>x*2, f)
g = g.map(x=>x*2)

f = L.drop(81, f)
g = g.slice(81)

f = L.map(x=>x*2, f)
g = g.map(x=>x*2)

f = L.concat(f, L.from(arrayOfLength(142)));
g = [...g, ...arrayOfLength(142)];

f = L.reverse(f)
g = g.reverse()

f = L.map(x=>x*2, f)
g = g.map(x=>x*2)

f = L.concat(f, L.from(arrayOfLength(112)));
g = [...g, ...arrayOfLength(112)];

f = L.concat(f, L.from(arrayOfLength(121)));
g = [...g, ...arrayOfLength(121)];

// up to here both lists are equal

f = L.drop(230, f)
g = g.slice(230)

console.log(L.toArray(f))
console.log(g)

Access the index on map() operations

Hi

My use case frequently involves mapping a list of raw data into a UI representation that offers the ability to modify elements. For instance mapping a list into table rows, where the user may modify or delete rows. I was thinking having the index available when mapping would allow me to efficiently update the list on that index.

One could use List.zipWith(f, list, List.range(0,List.length(list))) or avoid the index and use List.find but maybe there is a place for a dedicated mapWithIndex function as that should theoretically be more efficient?

Does anyone else have similar use-cases and what is your solution?

Finally, thanks for a great lib!

groupWith seems broken

I tried to use groupWith like so:

import * as L from "list/methods";

const xs = L.list({ x: 1 }, { x: 2 }, { x: 3 }, { x: 1 }, { x: 2 }, { x: 3 });
const groupedXs = xs.groupWith((a, b) => {
  console.log(a.x, b.x);
  return a.x === b.x;
});

I would have expected this result: list(list({x: 1}, {x: 1}), list({x: 2}, {x: 2}), list({x: 3}, {x: 3})).

But I just got the original list back, nested: list(list({x: 1}), list({x: 2}), list({x: 3}), list({x: 1}), list({x: 2}), list({x: 3})).

What's happening becomes more clear from the console.log, which shows what's being compared:

1 2
2 3
3 1
1 2
2 3

fold vs reduce argument order

Hi guys,

first, I just wanted to congradulate you on some very impressive work!

have you guys thought about the argument order on fold operations?

for the sake of compliance with existing JS, fantasy-land specifies the argument order for reduce to be (accumulation, currentValue).
However, functional conventions is to always have the collection argument last(e.g. ramda), to encourage function composition, example:

const a = list(0,1,2,3,4,)
const b = list(5,6,7,8,9)

let ten = L.foldl(L.append, a, b) // reuse existing function
// list(0,2,3,4,5,6,7,8,9)

ten = L.reduce((items, value) => L.append(value, items), a, b); // requires an additional step
// list(0,2,3,4,5,6,7,8,9)

it makes more sense to me to keep ramda style argument ordering for foldl/foldr and follow fantasyland for reduce/reduceRight

thoughts?

support sanctuary-show

> var {list} = require ('list')
> var show = require ('sanctuary-show')

Current behaviour:

> show (list ('foo', 'bar', 'baz'))
'{"bits": 3, "length": 3, "offset": 0, "prefix": [0], "root": undefined, "suffix": ["foo", "bar", "baz"]}'

Suggested behaviour:

> show (list ('foo', 'bar', 'baz'))
'list ("foo", "bar", "baz")'

This would require defining a @@show method which applies show to each of the list's elements.

sort incompatible with Ramda and not curried.

I saw on the main page list is compatible with ramda's sort function, but have run into problems converting some code to list.

const L = require('list/curried')
const R = require('ramda')

const array = [
  { id: 1 },
  { id: 3 },
  { id: 2 },
]

const list = L.fromArray(array)

// ramda sort array
R.sort((a, b) => a.id - b.id, array) //=> [ { id: 1 }, { id: 2 }, { id: 3 } ]

// ramda sort list
R.sort((a, b) => a.id - b.id, list) //=> [ , , ]

// list sort list
L.sort((a, b) => a.id - b.id, list) //=> []

I have also noticed const L = require('list/curried') does not curry.

const sortRamdaId = R.sort((a, b) => a.id - b.id)
const sortListId = L.sort((a, b) => a.id - b.id)

sortRamdaId(array) //=> [ { id: 1 }, { id: 2 }, { id: 3 } ]
sortListId(list) //=> ERROR: sortListId is not a function

Am I using this correctly?

Reverse iteration

I can't find a way to loop over a List backwards. The only way seems to be to use reverse, but this is very inefficient for large lists.

There is reduceRight/foldr, but those don't allow for early termination.

I think we need a function

function reverseIterator<A>(l: List<A>): Iterator<A>;

(Similar to C++ rbegin/rend)

bugs: list returns wrong results (likely bug in drop function)

noticed this in uses from my prelude.ts library :-(

list appears to get confused by a series of operations, let's say its internal structures get corrupted, and it returns wrong results.

I made a reproduction script:

const L = require("list")

let f = L.list()
for (let i=0;i<1329;i++) {
    f = L.append(i, f);
}

const b = L.drop(L.length(L.takeWhile(l=>l<=200, f)), f)
const c = L.takeWhile(l=>l<=203, b)
const d = L.drop(L.length(c), b)

console.log("FIRST ISSUE first() doesn't agree with nth(0)")
console.log(L.first(d))
console.log(L.nth(0, d))

const c1 = L.append(L.nth(0, d), c)
console.log("SECOND ISSUE list of 4 drop first and last, wrong result")
console.log(L.toArray(c1))
console.log(L.toArray(L.dropLast(1, L.drop(1, c1))))

The output is:

FIRST ISSUE first() doesn't agree with nth(0)
201
204
SECOND ISSUE list of 4 drop first and last, wrong result
[ 201, 202, 203, 204 ]
[ 201, 202 ]

.random possible?

How would I go about making a .random function that would allow me to get a random value of the list? I can do it for normal arrays but I'm not sure how to do it for list.

Normal array Random code:

Array.prototype.random = function() {
			return this[Math.floor(Math.random() * this.length)];
		};

findLastIndex

Hi, first thanks for your great lib which I'm happy to use in my projects. Recently ran into an issue: needed findLastIndex() which is not implemented. If you are ok with it, I'm ready to make pull request.

Feature - Create operator that takes a function.

The idea would be to have an operator that takes a function and a count to generate a new list.

At first, I thought that was what repeat was doing.

Example

const generateDot = () => {
  const x = Math.random() * this.width;
  const y = Math.random() * this.height;
  return { x, y };
}

const dots = generate(generateDot, 50); // I couldn't find a name for the operator.

Reconsider - sideEffects: false

Im not sure about exact algo of how it works just yet, but I suspect that this field is unsafe at the moment because, while main entry has no side effects and this package.json field can be used safely for it, the other entries such as fantasy-land are actually effectful and might be dropped because of that.

I can check with webpack@4-beta later how it behaves.

Stop mutating

You mutate arguments. That is "unfunctional and bad style".

Examples:

list/src/index.ts

Lines 982 to 991 in b626bb5

function foldlSuffix<A, B>(
f: (acc: B, value: A) => B,
acc: B,
array: A[],
length: number
): B {
for (let i = 0; i < length; ++i) {
acc = f(acc, array[i]);
}
return acc;

This should be fixed and never be done again. Actually nothing should ever be mutated in the whole codebase of this library.

Can't find fromArray

Library seems to not export nor having fromArray function.
Specifically, I'm trying to import it as ES-module and bundled dist from npm doesn't have this function in exports.

head() is missing?

Is it just me or head is missing in all type definitions? and code?

documentation mentions it as an alias for first?

list version 2.0.18

thanks

question: flatMap/chain and iterables

as you know, I'm writing the prelude.ts library, and now using your list library as a backing implementation for the Vector. I'm currently considering switching the prelude's flatMap implementation away from the current prelude.ts and also the current list behavior, I was wondering if you have a particular opinion about this behavior.

Currently list has:

export function flatMap<A, B>(f: (a: A) => List<B>, l: List<A>): List<B>

The change I'm contemplating for prelude.ts would be:

export function flatMap<A, B>(f: (a: A) => Iterable<B>, l: List<A>): List<B>

And prelude.ts has the same (and had the same before it switched to a list backend for the Vector). It turns out that scala, and also immutablejs are using the looser Iterable-based signature.

list and prelude.ts however have the tighter type-signature, and for list:

> list.toArray(list.chain(x=>list.list(1,2,3), list.list(1,2,3)))
[ 1, 2, 3, 1, 2, 3, 1, 2, 3 ]
> list.toArray(list.chain(x=>[1,2,3], list.list(1,2,3)))
[]

To be clear, I'm not asking you to modify list to work in that different way, I'm asking if you had a reflection on that topic and decided that the current list signature is better. For me, in prelude.ts, I was guided by the monadic bind type-signature, and it didn't occur to me to "loosen up" the type signature, which could have advantages and inconvenients, but now I started thinking about it, and I may, or may not, make that change.

List Type

Hello, I liked to know what kind of Lists you have implemented: if your List have a math name or are
inspired to a math algorithm?

regards

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.