DEV Community

Cover image for partial functions you say?
oreychandan
oreychandan

Posted on

partial functions you say?

So lets talk about functions in js/ts. Specifically the way we use them. Consider this function:

function createVertex( x: number, y: number, z: number) {
  return new Map(Object.entries({x,y,z})); 
}
console.log(createVertex(1,2,3));
//Map { "x" => 1, "y" => 2, "z" => 3 }
Enter fullscreen mode Exit fullscreen mode

So here we have a function that creates 3d vertex. We need 3 parameters to create it.

Now lets talk about partial functions a bit before I can come to the main point.
Here's how a partial function is supposed to work.
(some psuedo code below...)

f(x,y,z) -> v // our current function
f(x) -> (y) -> (z) -> v // a partial function
Enter fullscreen mode Exit fullscreen mode

This works because of function scoped data. Meaning, withing that lamba(nameless) function '(z) -> v', we have access to 'x' and 'y' which lets us create 'v' (edit: forgot to mention, this is called a closure).

This is great. We now don't need every parameter when we need to use the function. This empowers us to composition our logic in interesting ways we could not before.

Do read further, but If you have not tried partial functions yet, I suggest go experiment a bit and come back. Doing is the best way to learn (Tip: Deno is actually quite handy to do typescript scripting as you can simply run a file without having to compile all by default.)

So here's where I do my experimentations:
Disclaimer: Idk if someone else has thought of this but I have not come across anything similar yet. I don't look up stuff much. I'm just a basement mad scientist XD.

The Meal
So this "partial function" is a bit incomplete if you think about it, isn't it?
So in our above pseudo code example f(x,y,z) -> v,
what if I want to feed the function 'y' or 'z' first?
So our "partial function" is coupled with parameter order. How about we give our function some more super powers? What do you say?
And that's how I started scrubbing my beard, scratching by ever growing forehead to churn out a magical abstraction to create the function of my dreams.

Spoiler: I won't be going into the implementation details in this post. I am still working on it. The progress has been good. I just want to talk about how the final usage of this "magical abstraction" might look like.

The magic

// lets say we have a magical function
import { createMagicFunc } from "./functionGenerator2";

// our normal function
function createVertex(x: number, y: number, z: number) {
  return new Map(Object.entries({ x, y, z }));
}

// now lets sprinkle some pixie dust on it
const magicalVertexCreator = createMagicFunc(
  createVertex,
  /* Some config if any*/
);
// now 'magicalVertexCreator' is our new and
// improved partial function.
// lets see if we can use it as a normal function
console.log(magicalVertexCreator(1, 2, 3));
// Map { "x" => 1, "y" => 2, "z" => 3}
// ok lets see if we can use it as traditional partial function
console.log(magicalVertexCreator(1)(2)(3));
// similar output.
// Similar because Map and record are not ordered data,
// so they show in different order each time XD
// now for the magic. Can we feed the function which
// ever parameter we want and get back a partial function?
console.log(magicalVertexCreator({ y: 2 })({ z: 3 })({ x: 1 }));
// volla! we get the same output.
// Ok you gotto use some imagination here. ;)
// wait did you think that is all? ok wait for more treats.
console.log(magicalVertexCreator({ x: 1, z: 3 })({ y: 2 }));
// lets mix all these ways of using the function now.
// its going to get crazy now
console.log(magicalVertexCreator({ y: 2 })(1, 3));
// did you get what I just did there?
console.log(magicalVertexCreator({ z: 3, x: 1 })(2));
// at this point I am just flexing am I not?
Enter fullscreen mode Exit fullscreen mode

Conclusion:
Flexing and theory crafting aside, I have a good bit of this functionality done. I just need to see how feature rich I can do it and see how it goes really. And I really want the types to work really nice.
I dont mind if it is a bit of a heavy wrapper on a function because this is something meant to be used in application logic where the control flow benefits we get counters any performance hits we get from this.

If this seems interesting to you, do the things you do on dev.to. Is it like and follow? idk I'm new here.
Anyways, after I have a fully working code for this I will make another post.
b

Discourse: Pls be kind with each other in the comments. If you think there is an error in this post let me know. If you have suggestion on things I might have missed that fits well in this post feel free to suggest. Share your tinkerings, I want to see what you have done :)

Latest comments (0)