Skip to content

Commit

Permalink
Merge dea5105 into 61707d9
Browse files Browse the repository at this point in the history
  • Loading branch information
joelnet committed Sep 25, 2018
2 parents 61707d9 + dea5105 commit c4de207
Show file tree
Hide file tree
Showing 11 changed files with 132 additions and 45 deletions.
10 changes: 4 additions & 6 deletions examples/fizz-buzz/main.mjs
@@ -1,8 +1,7 @@
import after from 'mojiscript/core/after'
import cond from 'mojiscript/core/cond'
import pipe from 'mojiscript/core/pipe'
import pipeR from 'mojiscript/core/pipeR'
import when from 'mojiscript/core/when'
import map from 'mojiscript/list/map'
import range from 'mojiscript/list/range'
import S from 'sanctuary'

// getFizzInfo :: Number -> FizzInfo
Expand Down Expand Up @@ -33,9 +32,8 @@ const fizzBuzz = log => pipe ([
log
])

const main = ({ last, log }) => pipeR (next => [
when (n => n <= last)
(after (fizzBuzz (log)) (x => next (x + 1)))
const main = ({ last, log }) => pipe ([
map (fizzBuzz (log)) (range (1) (last + 1))
])

export default main
16 changes: 16 additions & 0 deletions internal/iterableSerialReduce.js
@@ -0,0 +1,16 @@
/* eslint-disable */
const iterableSerialReduce = (func, initial, iterable, promise = Promise.resolve(initial)) => {
const iterator = iterable[Symbol.iterator]()
const { value, done } = iterator.next()
return done
? promise
: promise.then(() =>
iterableSerialReduce(
func,
initial,
iterator,
promise.then(acc => func(acc, value))
))
}

module.exports = iterableSerialReduce
13 changes: 0 additions & 13 deletions internal/serialReduce.js

This file was deleted.

22 changes: 20 additions & 2 deletions list/__tests__/filter.test.js
Expand Up @@ -3,17 +3,35 @@ const filter = require("../filter")
describe("list/filter", () => {
const isOdd = num => num % 2 !== 0
const asyncIsOdd = num => Promise.resolve(num).then(isOdd)
function* iterator() {
yield 1
yield 2
yield 3
}

test("sync filters", () => {
test("sync array", () => {
const expected = [1, 3]
const actual = filter(isOdd)([1, 2, 3])
expect(actual).toMatchObject(expected)
})

test("async filters", () => {
test("async array", () => {
expect.assertions(1)
const expected = [1, 3]
const actual = filter(asyncIsOdd)([1, 2, 3])
return expect(actual).resolves.toMatchObject(expected)
})

test("sync iterator", () => {
const expected = [1, 3]
const actual = filter(isOdd)(iterator())
expect(actual).toMatchObject(expected)
})

test("async iterator", () => {
expect.assertions(1)
const expected = [1, 3]
const actual = filter(asyncIsOdd)(iterator())
return expect(actual).resolves.toMatchObject(expected)
})
})
23 changes: 21 additions & 2 deletions list/__tests__/map.test.js
Expand Up @@ -3,18 +3,37 @@ const map = require("../map")
describe("list/map", () => {
const double = num => num * 2
const asyncDouble = num => Promise.resolve(num).then(double)
function* iterator() {
yield 1
yield 2
yield 3
}

test("sync map", () => {
test("sync array", () => {
expect.assertions(1)
const expected = [2, 4, 6]
const actual = map(double)([1, 2, 3])
expect(actual).toMatchObject(expected)
})

test("async maps", () => {
test("async array", () => {
expect.assertions(1)
const expected = [2, 4, 6]
const actual = map(asyncDouble)([1, 2, 3])
return expect(actual).resolves.toMatchObject(expected)
})

test("sync iterable", () => {
expect.assertions(1)
const expected = [2, 4, 6]
const actual = map(double)(iterator())
expect(actual).toMatchObject(expected)
})

test("async iterable", () => {
expect.assertions(1)
const expected = [2, 4, 6]
const actual = map(asyncDouble)(iterator())
return expect(actual).resolves.toMatchObject(expected)
})
})
9 changes: 9 additions & 0 deletions list/__tests__/range.test.js
@@ -0,0 +1,9 @@
const range = require('../range')

describe('list/range', () => {
test('creates range', () => {
const expected = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
const actual = [...range(0)(10)]
expect(actual).toMatchObject(expected)
})
})
22 changes: 20 additions & 2 deletions list/__tests__/reduce.test.js
Expand Up @@ -3,17 +3,35 @@ const reduce = require("../reduce")
describe("list/reduce", () => {
const add = x => y => x + y
const asyncAdd = x => y => Promise.resolve(x).then(add(y))
function* iterator() {
yield 1
yield 2
yield 3
}

test("sync reduces", () => {
test("sync array", () => {
const expected = 6
const actual = reduce(add)(0)([1, 2, 3])
expect(actual).toBe(expected)
})

test("async reduces", () => {
test("async array", () => {
expect.assertions(1)
const expected = 6
const actual = reduce(asyncAdd)(0)([1, 2, 3])
return expect(actual).resolves.toBe(expected)
})

test("sync iterable", () => {
const expected = 6
const actual = reduce(add)(0)(iterator())
expect(actual).toBe(expected)
})

test("async iterable", () => {
expect.assertions(1)
const expected = 6
const actual = reduce(asyncAdd)(0)(iterator())
return expect(actual).resolves.toBe(expected)
})
})
19 changes: 12 additions & 7 deletions list/filter.js
@@ -1,6 +1,6 @@
/* eslint-disable */
const isThenable = require('../internal/isThenable')
const serialReduce = require('../internal/serialReduce')
const iterableSerialReduce = require('../internal/iterableSerialReduce')

const asyncFilterReducer = func => (acc, x) => {
const result = func(x)
Expand All @@ -11,15 +11,20 @@ const asyncFilterReducer = func => (acc, x) => {

const filter = func => iterable => {
const values = []
for (let i = 0; i < iterable.length; i++) {
const x = iterable[i]
const result = func(x)
const iterator = iterable[Symbol.iterator]()
var { value, done } = iterator.next()

while (!done) {
const result = func(value)
if (isThenable(result)) {
return serialReduce(asyncFilterReducer(func), [], values.concat(iterable), i + 1, result.then(() => [ x ]))
} else if (result) {
values.push(x)
return iterableSerialReduce(asyncFilterReducer(func), null, iterator, result.then(() => [ value ]))
}
if (result) {
values.push(value)
}
var { value, done } = iterator.next()
}

return values
}

Expand Down
20 changes: 13 additions & 7 deletions list/map.js
@@ -1,6 +1,6 @@
/* eslint-disable */
const isThenable = require('../internal/isThenable')
const serialReduce = require('../internal/serialReduce')
const iterableSerialReduce = require('../internal/iterableSerialReduce')

const asyncMapReducer = func => (acc, x) => {
const result = func(x)
Expand All @@ -9,16 +9,22 @@ const asyncMapReducer = func => (acc, x) => {
: (acc.push(result), acc)
}

const map = func => xs => {
const map = func => iterable => {
const values = []
for (let i = 0; i < xs.length; i++) {
const result = func(xs[i])
const iterator = iterable[Symbol.iterator]()
var { value, done } = iterator.next()

while (!done) {
const result = func(value)

if (isThenable(result)) {
return serialReduce(asyncMapReducer(func), [], values.concat(xs), i + 1, result.then(v => [ v ]))
} else {
values.push(result)
return iterableSerialReduce(asyncMapReducer(func), null, iterator, result.then(v => [ v ]))
}

values.push(result)
var { value, done } = iterator.next()
}

return values
}

Expand Down
7 changes: 7 additions & 0 deletions list/range.js
@@ -0,0 +1,7 @@
/* eslint-disable */
const range = (start) => function* (end) {
let current = start
while (current < end) yield current++
}

module.exports = range
16 changes: 10 additions & 6 deletions list/reduce.js
@@ -1,16 +1,20 @@
/* eslint-disable */
const isThenable = require('../internal/isThenable')
const serialReduce = require('../internal/serialReduce')
const iterableSerialReduce = require('../internal/iterableSerialReduce')

const reduce = func => initial => list => {
const reduce = func => initial => iterable => {
let acc = initial
for (let i = 0; i < list.length; i++) {
acc = func(acc)(list[i])
const iterator = iterable[Symbol.iterator]()
var { value, done } = iterator.next()

while (!done) {
acc = func(acc)(value)
if (isThenable(acc)) {
return serialReduce((a, b) => func(a)(b), acc, list, i + 1, acc)
return iterableSerialReduce((a, b) => func(a)(b), null, iterator, acc)
}
var { value, done } = iterator.next()
}
// Array.prototype.reduce.call (list, (acc, val) => func (acc) (val), initial)

return acc
}

Expand Down

0 comments on commit c4de207

Please sign in to comment.