8000 Implementation of fold function by maraschneider · Pull Request #1 · taktile-org/coding-challenge · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Implementation of fold function #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules
87 changes: 67 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,69 @@
# Taktile Coding Challenge
# Fold

Fold is a fold function implementation in JavaScript.

## Arguments

iterable: iterable object such as String, Array, Set or Map. On each elment of the iterable the callback function is executed, while passing in the return value from the calculation on the previous element.

callback: function with two arguments: the previousValue (the value resulting from the previous call) and the currentValue

initialValue: value to which previousValue of the callback is initialized the first time the callback is called

## Examples Usage

```js
const result = fold([1, 2, 3], (a, b) => a + b, 100);
// result will be 106

const result = fold([1, 2, 3], (a, b) => a + b);
// if no inital value is given, the first value of the iterable object is used
// result will be 6

const result = fold(
new Set([1, 1, 2, 2, 3, 3]),
(a, b) => {
return a + b;
},
0
);
// result will be 6

const result = fold([], (a, b) => {
return a + b;
});
// when providing an empty array and no initial value, it
// will throw a TypeError "Reduce of empty array with no initial value"
```

## CLI Commands

Run test:
`yarn test`

## System Requirements

Support for ESM (Node.js > 12 / es module compatible browser)

## Package Goals/ Taktile Coding Challenge

Your challenge is to implement `fold` in the language of your choice.

## Description

`fold` is a higher order function that takes
* a sequence of type A
* a "starting" value of type B
* a function (A, B) -> B

- a sequence of type A
- a "starting" value of type B
- a function (A, B) -> B

and returns a B. E.g., the `sum` of an array is a special case of fold, where
* the sequence is an array of numbers
* the starting value is 0
* the function is `+`

- the sequence is an array of numbers
- the starting value is 0
- the function is `+`

You can find more information on [Wikipedia](https://en.wikipedia.org/wiki/Fold_(higher-order_function)).
You can find more information on [Wikipedia](<https://en.wikipedia.org/wiki/Fold_(higher-order_function)>).

## Instructions

Expand All @@ -31,17 +79,16 @@ Send us a link to your fork **within 1 week** of being invited to participate on
Aim to use about 1 hour of time on the solution, don't use more than 2 hours. We give roughly
equal weight to the each of the following:

* Documentation
* Packaging
* Testing
* Readability of code
* Correctness of implementation
* Performance
* Generality
* Correntness of types (if applicable)

Please don't stress if your solution isn't perfect. With a timebox of at most 2 hours,
you most likely won't be able to check all the boxes above. This challenge is intended as an
- Documentation
- Packaging
- Testing
- Readability of code
- Correctness of implementation
- Performance
- Generality
- Correntness of types (if applicable)

Please don't stress if your solution isn't perfect. With a timebox of at most 2 hours,
you most likely won't be able to check all the boxes above. This challenge is intended as an
exercise in tradeoffs. We want to understand how you view the overall value and lifecycle
of software.

46 changes: 46 additions & 0 deletions fold.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
function fold(iterable, callback, initialValue) {
validateArguments(iterable, callback, initialValue);
let result = initialValue;
let isFirstIterationWithoutInitialValue = initialValue === undefined;

for (const currentValue of iterable) {
if (isFirstIterationWithoutInitialValue) {
// if no initial value is given:
// set inital value to first value of the iterable object
result = currentValue;
isFirstIterationWithoutInitialValue = false;
continue;
}

result = callback(result, currentValue);
}
return result;
}

function validateArguments(iterable, callback, initialValue) {
if (!validateIsIterable(iterable)) {
throw new TypeError("First argument should be an iterable object");
}

if (
initialValue === undefined &&
[iterable.length, iterable.size].includes(0)
) {
throw new TypeError("Reduce of empty array with no initial value");
}

if (typeof callback !== "function") {
throw new TypeError("Second argument should be a function");
}
}

// validates if value is an iterable object (such as String, Array, Set, Map)
// see: https://stackoverflow.com/questions/18884249/checking-whether-something-is-iterable
function validateIsIterable(value) {
if (value === null || value === undefined) {
return false;
}
return typeof value[Symbol.iterator] === "function";
}

export { fold };
83 changes: 83 additions & 0 deletions fold.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import { fold } from "./fold.js";
import test from "ava";

test("returns expected result when passed numbers array and inital number", async (t) => {
const res = fold(
[1, 2, 3],
(a, b) => {
return a + b;
},
100
);
t.is(await res, 106);
});

test("returns expected result when passed numbers array with no inital value", async (t) => {
const res = fold([1, 2, 3], (a, b) => {
return a + b;
});
t.is(await res, 6);
});

test("returns expected result when passed numbers as a set and inital number", async (t) => {
const res = fold(
new Set([1, 1, 2, 2, 3, 3]),
(a, b) => {
return a + b;
},
0
);
t.is(await res, 6);
});

test("returns expected result when passed numbers as values of a map and inital number", async (t) => {
const res = fold(
new Map([
["a", 1],
["b", 2],
["c", 3],
]),
(a, b) => {
return a + b[1];
},
0
);
t.is(await res, 6);
});

test("throws error when passed empty array with no inital value", async (t) => {
const error = t.throws(
() => {
fold([], (a, b) => {
return a + b;
});
},
{ instanceOf: TypeError }
);

t.is(error.message, "Reduce of empty array with no initial value");
});

test("throws error when passed a number as first argument", async (t) => {
const error = t.throws(
() => {
fold(100, (a, b) => {
return a + b;
});
},
{ instanceOf: TypeError }
);

t.is(error.message, "First argument should be an iterable object");
});

test("throws error when passed a number as second argument", async (t) => {
const error = t.throws(
() => {
fold([100, 200], 2);
},
{ instanceOf: TypeError }
);

t.is(error.message, "Second argument should be a function");
});
19 changes: 19 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"name": "fold",
"version": "1.0.0",
"description": "implementation of a fold function in JavaScript",
"main": "fold.js",
"type": "module",
"engines": {
"node": ">12"
},
"repository": "git@github.com:maraschneider/coding-challenge.git",
"author": "Maraike Schneider <maschn93+github@gmail.com>",
"license": "MIT",
"scripts": {
"test": "ava"
},
"devDependencies": {
"ava": "^3.15.0"
}
}
Loading
0