gohypergiant / standard-toolkit

The web "standard library" for the Accelint family of systems.
Apache License 2.0
0 stars 0 forks source link

Swap functions to data last #27

Open brandonjpierce opened 4 weeks ago

brandonjpierce commented 4 weeks ago

e.g. instead of

function toDigits(value, precision) {}

do

function toDigits(precision, value) {}

this way we can either auto curry this function or have it curried by default e.g.

const toDigit = (precision) => (value) => ...
// or
const curriedToDigit = autoCurry(toDigit);

and then in userland:

const toTenths = toDigit(2);
const value = toTenths(1.1234);
brandonjpierce commented 1 week ago

Swapped math functions over in https://github.com/gohypergiant/standard-toolkit/pull/23

brandonjpierce commented 2 days ago

If you have questions on the ethos behind this change, please reach out to @belsrc

kalisjoshua commented 1 day ago

Is there an easy list of modules that need this treatment?

brandonjpierce commented 1 day ago

I can get that list assembled, yes

belsrc commented 1 day ago

For this, as you mentioned, there is two possible future use approaches. Which might be nice/easier to do in tandem. Which probably want to have a larger discussion on them (another issue? rfc-ish thing? 🤷 ). That being "do we want to auto curry them or just curry them or do nothing." They all have benefits and drawbacks.

kalisjoshua commented 1 day ago

When possible consistency is my highest priority; only challenge is when performance contradicts consistency. As I understand things (so far) we are rather concerned with performance - out of necessity - so have we run into any consistency challenges for performance reasons? If not, I tend to prefer to do less over doing more; i.e. don't curry till it is needed.

belsrc commented 1 day ago

Yea, thats part of the convo. Using Brandon's examples above:

const toDigit = (precision, value) => {} - Which requires downstream effort in order to curry it. Stuff like precision usual isnt something that changes and is prime for partial application.

const toDigit = (precision) => (value) => {} - Requires it to always be used in its curried form. Personally not an issue for me as () and ()() aren't that difficult. Though I can see how some would look at it weirdly.

const toDigit = autocurry((precision, value) => {}) - Best of both worlds as it can be used as () and ()() out of the box. Downside of another call on the stack.

kalisjoshua commented 1 day ago

There are two independent issues:

Argument Ordering

Ordering the arguments list to place the most variable values at the end to support curry-ing/partial application.

Function Definition

Writing a function such that it is curry-ied or not.


Are we consistently creating library/reusable code in: a "curry"-ied style, an idiomatic style, or a mix of both?

belsrc commented 1 day ago

Are we consistently creating library/reusable code in: a "curry"-ied style, an idiomatic style, or a mix of both?

This could also be part of the discussion, I suppose. Most of the things that are currently in curry format (() => () => {}) are things that Brandon ripped from one of my private repos 😆 . In which I tend to go with the traditional approach.

Aside: @brandonjpierce , could also use a ticket for possibly cleaning up some calls. Things like the below don't need to be spelled out and can instead simply be point-free.

export function toBoolean(val: unknown) {
  return isTrue(val);
}

// ↓

export const toBoolean =  isTrue;

(This one is literally just an alias)