Fork me on GitHub
#squint
<
2022-08-24
>
borkdude15:08:35

I ported @armed’s hn-reader from cherry to clava including macros https://github.com/borkdude/clava-hn-reader based on a branch macro-experiment

🎉 3
borkdude15:08:15

(during a train ride with really bad internet so querying the API a zillion times was fun...)

borkdude15:08:38

will clean up and continue soon (still traveling)

lilactown16:08:00

https://github.com/clavascript/clavascript/pull/124 adds the ability to extend the JS iterable protocol to Clava types 🙂

Cora (she/her)23:08:49

ugh, there's no way to get the full arity of a function

Cora (she/her)23:08:05

fn.length doesn't include rest parameters or parameters with defaults

Cora (she/her)23:08:09

so partial is super tricky

Cora (she/her)23:08:20

say you implemented it like this:

export function partial(fn, ...args) {
  return function (...moreArgs) {
    return fn(...args.concat(moreArgs));
  };
}

Cora (she/her)23:08:32

this is fine when it's a pure function

Cora (she/her)23:08:17

> a = partial((x, y) => x + y, 1)
[Function (anonymous)]
> a(2)
3

Cora (she/her)23:08:44

it breaks things when the function is attached to an object because this gets lost

Cora (she/her)23:08:44

> a = {y: 1, x: function(a, b){ return this.y + a + b}}
{ y: 1, x: [Function: x] }
> a.x(2, 3)
6
> partial(a.x, 2)(3)
NaN

Cora (she/her)23:08:16

there's no way to get at the original this of a function once it's been passed in separate from its object

Cora (she/her)23:08:42

we could keep partial for pure functions and then include a bind function to allow manipulation of this

Cora (she/her)23:08:46

function bind(thisArg, fn, ...args) {
  return fn.bind(thisArg, ...args);
}

Cora (she/her)23:08:00

> a = {y: 1, x: function(a, b){ return this.y + a + b}}
{ y: 1, x: [Function: x] }
> bind(a, a.x, 2)(3)
6

Cora (she/her)23:08:01

we could name that bind function partial but then you always have to pass in what this will be even if you don't care what it is

Cora (she/her)23:08:00

> function partial(thisArg, fn, ...args) {
...   return fn.bind(thisArg, ...args);
... }
undefined
> b = partial(null, (x, y) => x + y, 2)
[Function: bound ]
> b(3)
5

Cora (she/her)23:08:20

I think it makes sense to have separate functions for the pure function case and the object function case, so a partial function for currying pure functions and a bind function for currying object-bound functions (or applying a different thisArg to a function than it originally had)

Cora (she/her)23:08:07

so it would end up being this:

export function partial(fn, ...args) {
  return function (...moreArgs) {
    return fn(...args.concat(moreArgs));
  };
}

export function bind(thisArg, fn, ...args) {
  return fn.bind(thisArg, ...args);
}

Cora (she/her)23:08:07

or perhaps just use bind with globalThis

Cora (she/her)23:08:09

export function partial(fn, ...args) {
  return fn.bind(globalThis, ...args);
}

export function bind(thisArg, fn, ...args) {
  return fn.bind(thisArg, ...args);
}