Git Product home page Git Product logo

quiver-dart's People

Contributors

a14n avatar adamlofts avatar alechenninger avatar blackhc avatar cbracken avatar codelogic avatar davidmorgan avatar dependabot[bot] avatar emesx avatar feinstein avatar fniemann avatar fox32 avatar jacob314 avatar jakemac53 avatar jamesderlin avatar jtmcdole avatar justinfagnani avatar kevmoo avatar lrhn avatar lucyget avatar matanlurey avatar mfiels avatar mt40 avatar munificent avatar seaneagan avatar sethladd avatar srawlins avatar tonio-ramirez avatar vicb avatar yjbanov 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  avatar  avatar  avatar  avatar  avatar  avatar

quiver-dart's Issues

Helper to throttle async

"Yes, if you spawn all your expensive async tasks eagerly you're going to have a bad time."

Strawman:

forEachAsync(iterable, (i) => expensive(i), maxTasks: 10);

Provide collections that take custom comparators

A common use-case in applications is to use objects as keys whose equals/hashCode is different from the use-case at hand. The most common example that I keep hearing is you want to use database entities as map keys and set elements but you want to have ID-based identity, so for example {id: 1, name: "foo"} and {id: 1, name: "bar"} are considered equal.

Feature request: provide implementations of Map, Set and List that take a comparator function as a constructor parameter and use it to compare keys and elements.

SYSTEM_CLOCK should be Clock.SYSTEM or const Clock.system()

It's much more discoverable when it's in the class' namespace. And it's the style used most commonly by the dart community at large.

I prefer const Clock.system() over Clock.SYSTEM just in case arguments need to be added in the future, and a constructor makes it obvious that it returns a Clock without even needing to check the docs.

Of course there should be a deprecation period where both are available to allow people to update.

Add a periodic stream which corrects drift

Periodic timers are subject to drift as the timer is not guaranteed to be called exactly when it was scheduled for.

I filed a bug to add this to Stream.periodic (and possibly Timer.periodic):

https://code.google.com/p/dart/issues/detail?id=18642

but in the meantime, would be nice to have this in quiver. It could look like:

Stream onPeriod(Duration duration, [Function computation]);

This could be used by #130.

Implementation inspiration can be taken from:

https://gist.github.com/tanepiper/4215634

BiMap.remove does not return anything.

The Map<K, V> interface defines remove as: V remove(Object key).

The HashBiMap implementation does not return anything, but should return _map.remove(key).

Add Optional.wherePresent helper to quiver.core

Would it be possible to add a sensible way of unwrapping all the present values in an iterable of optional values? Basically the equivalent of catMaybes in Haskell's Data.Maybe

class Optional<T> {
    /**
     * Returns an iterable containing the values of all the values of the optionals 
     * which are present in the argument.
     */
    static Iterable wherePresent(Iterable optionals) =>
         optionals.expand((opt) => opt.isPresent ? [opt.value] : []);
    ...
}

Key comparator generation

Comparator is the standard way to compare items in dart. But many languages allow sorting by "key functions", for example python:

https://wiki.python.org/moin/HowTo/Sorting#Key_Functions

Since dart doesn't yet have union types, List.sort for example would have to take a dynamic sort function in order to allow Comparators and key functions, thus giving up on type safety. In the meantime, I think a good solution would be a method to easily convert key functions to Comparators, something like:

Comparable Key<T>(T item);

Comparator byKey(Key key) => (a, b) =>
    key(a).compareTo(key(b));

Usage:

['bob', 'delores', 'Cathy', 'Alan'].sort(byKey((s) => s.toLowerCase());

#114 introduces a quiver.compare that this could be added to.

json pretty printer?

I've written some code to pretty-print json, so the output doesn't all end up on one line. It's part of a larger app right now, but I'm looking for a better home for it, in order to make it available to more people. Is quiver a good place for something like a json pretty printer?

Consider simplifying forEachAsync

If forEachAsync didn't have maxTasks, leaving that use case for something like #105, then it could be:

Future forEachAsync(Future asyncAction(item), Iterable iterable) =>
    new Stream.fromIterable(iterable).asyncMap(action).drain();

upper bound on SDK constraint is not good practice

Since the SDK cannot be downgraded, it is not generally a good practice to put a cap on it. When we asked for SDK constraints we promised never to put an upper bound :)

Concretely, this caused a problem for me because I couldn't use/test quiver on 0.8.x, even though in fact the feature I wanted to use worked just fine.

Extent extent(Iterable i) in min_max.dart is wrong.

The definition of the compare function states:

  • a negative integer if [a] is smaller than [b],
  • zero if [a] is equal to [b], and
  • a positive integer if [a] is greater than [b].

The line(s) in min_max.dart:

if (compare(max, iterator.current) > 0) max = iterator.current;

a = max
b = iterator.current

So essentially the line is currently, and incorrectly read as: if(a(max) > b(current)) max = current; which causes min and max to be switched.

add binary search for lists

Not sure what's the best place to add this, but definitely something useful to have.

/// Find the first entry in a sorted [list] that matches a monotonic predicate.
/// A result `n` means that all items before `n` don't match, `n` matches,
/// and all items after `n` match as well. The result is -1 when there are no
/// items, 0 when all items match, and list.length when none does.

int binarySearch(List list, bool matches(item)) {
  if (list.length == 0) return -1;
  if (matches(list.first)) return 0;
  if (!matches(list.last)) return list.length;

  int min = 0;
  int max = list.length - 1;
  while (min < max) {
    var half = min + ((max - min) ~/ 2);
    if (matches(list[half])) {
      max = half;
    } else {
      min = half + 1;
    }
  }
  return max;
}

Proposal: Disposer

Our team found it useful to have a utility that aggregates various types of subscriptions (StreamSubscription, StreamSink (usually StreamController), as well as custom cleanup functions) and clean them up all at once at a certain moment. A popular use-case is a UI component being destroyed while still fetching things from the server. Another use-case I can see is cleaning-up when things go wrong, e.g. closing sockets/files when errors happen.

Proposed API:

class Disposer {
  Disposer();

  /// [disposable] will be "disposed of" when the [dispose] method is called. The
  /// meaning of "dispose" depends on the type of disposable, which can be one of:
  ///
  /// - [StreamSubscription], disposer calls `cancel()` when disposing
  /// - [StreamSink], disposer calls `close()` when disposing
  /// - [Function] that takes no arguments and returns either `null` or a [Future]. This
  /// function is called by the disposer as is. The implementation is defined by the user.
  void add(dynamic disposable);

  /// Disposes of all disposables [add]ed to `this` disposer.
  ///
  /// The returned future completes when all disposables are successfully disposed of.
  Future dispose();

  /// Sets a [trigger] used as a signal to dispose everything collected so far. Can be used
  /// as an alternative to calling [dispose] directly.
  set trigger(Future t);
}

Add method to combine parallel streams

#86 provided order-preserving concatenation of streams, but only listens to one stream at a time to allow for lazy creation of the streams, and to avoid buffering. This can lead to dropped events which occur before the stream is reached in the iteration.

When order is not important, it usually makes sense to create (if necessary) and listen to all the streams up front, and simply funnel all the streams' events to a new stream without the need for any buffering. Potential API:

Stream funnel(Iterable<Stream>);

I also like the name union though it may imply uniqueness of events which is not the case.

Simplify streams.concat impl

Similar to the impl of #109, should be as simple as:

Stream concat(Iterable<Stream> streams) =>
    new Stream.fromIterable(streams).asyncExpand((s) => s);

Clock has too many methods

If we had #91, then instead of:

clock.ago(days: 1)
clock.weeksAgo(2)
clock.yearsFromNow(1)

could just do:

clock.ago(day)
clock.ago(week * 2)
clock.fromNow(year)

though I'd probably be happy with just doing:

clock.now().subtract(day)
clock.now().subtract(week * 2)
clock.now().add(year)

For months, a special function would still be needed, but it ought to work for any date, not just now():

DateTime addMonths(DateTime from, int months);

why does firstNonNull return object?

This is my first try with quiver.

I use it like

var x = firstNonNull(c.maxWith, 0) + 5

DartEditor shows the warning There is no such operator '-' in 'Object'.
I think this this would work without warning when firstNonNulls return type would be dynamic (or no return type)

Add Duration unit constants to quiver.time

Constants:

const Duration microsecond = const Duration(microseconds: 1);
const Duration millisecond = const Duration(milliseconds: 1);
const Duration second = const Duration(seconds: 1);
const Duration minute = const Duration(minutes: 1);
const Duration hour = const Duration(hours: 1);
const Duration day = const Duration(days: 1);
const Duration week = const Duration(days: 7);
const Duration year = const Duration(years: 1);

Usage:

if(stopwatch.elapsed > minute) ...

new Timer(millisecond * 500, () {...});

var inOneDay = clock.now().add(day);

Add a streams equivalent of quiver.iterables

Not all of the functions in iterables.dart make sense for streams, but the following would be useful (note: some of these are still in the unmerged pull request I opened today)

  • concatAsync- Just a shorthand for stream.expand((i) => i). The returned stream emits an event for each element when it receives an event containing an iterable.
  • zipAsync - Combine a list of streams into a stream of lists. Unlike Iterables.zip, I think the most sensible behaviour here is to perform a zipLongest on each of the streams, inserting a sentinel value in the list position corresponding to a closed stream.
  • `groupByAsync - A primitive dispatcher for streams. Create a stream of streams and emit values on different streams according to the value returned by a key function

groupJoinAsync is a tough one. I was thinking about possible use cases, the first useful one I came up with is:

Consider a game with a number of entities in the viewable area. As the entities are created, each emits an event which creates a new stream This stream can be joined with mouse events in the viewable area (with the on function testing for hit collision).

There are certainly many more possible uses, but it's certainly abstracting away from the SQL join roots and I can't really decide if it's generic enough to warrant inclusion.

Simplify doWhileAsync impl

This ought to work:

Future<bool> doWhileAsync(Future asyncAction(item), Iterable iterable) =>
    new Stream.fromIterable(iterable).asyncMap(asyncAction).every((x) => x);

Add Quantity to quiver.core

These failed dart:core feature requests:

http://dartbug.com/3176
http://dartbug.com/1492

seem like good candidates for quiver.core.

Possible API:

class Quantity<T extends Comparable<T>> extends Comparable<T> {

  final Comparable<T> _comparable;

  Quantity(this._comparable);

  int compareTo(T other) => _comparable.compareTo(other);

  bool operator < (T other) => compareTo(other) < 0;
  bool operator <= (T other) => compareTo(other) <= 0;
  bool operator > (T other) => compareTo(other) > 0;
  bool operator >= (T other) => compareTo(other) >= 0;
  bool operator == (T other) => compareTo(other) == 0;
  T min(T other) => this <= other ? _comparable : other;
  T max(T other) => this >= other ? _comparable : other;
  T clamp(T min, T max) => new Quantity(this.max(min)).min(max);
}

Replace FakeStopwatch with Clock.newStopwatch

Time-dependent units can receive Clocks as dependencies to mock the passage of time. Doing so exposes nothing about their implementation, only that they depend on the passage of time. #98 removed the need to expose the use of Timers. This issue is to remove the need to expose the use of Stopwatches. Currently quiver has FakeStopwatch for mocking stopwatches. Receiving a Stopwatch (FakeStopwatch) as a dependency, exposes even more of the implementation, specifically that you're using only a single stopwatch. A StopwatchFactory typedef would at least solve that, but it still would expose the use of Stopwatches.

If it were possible to obtain a Stopwatch from a Clock, the time-dependen unit could then just receive a Clock, and create the Stopwatch internally.

Ideally the dart:core Stopwatch impl would be backed by a Clock, see:

https://code.google.com/p/dart/issues/detail?id=18149

But until then, we will want to use the dart:core stopwatch impl in production code, and a clock-backed Stopwatch in test code. The way to handle this is polymorphism, by adding a stopwatch creation method to Clock:

Stopwatch newStopwatch();

createStopwatch could also work as a name.

It should be a method instead of a getter, since it returns a new mutable object on each invocation.

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.