-
Notifications
You must be signed in to change notification settings - Fork 17
Description
If we treat the pipelines proposal as a separate proposal and disregard the pipelines-related examples, I'm wondering if this proposal can entirely be achieved through libraries (and if not, then what what are the key issues that prevent it)
e.g. it should be possible to write a library that allows you to write
import {_, partial} from "a-partial-application-library" // _ is a symbol, partial is like Function.call but that recognizes the symbol _ and performs partial application
const addTen = partial(add, _, 10) // instead of add(?, 10)
const another = partial(f, _, 10, "hi", _, "yo") // instead of f(?, 10, "hi", ?, "yo")
it may even be possible to support #5
// design 1
import {_0, _1, partial} from "a-partial-application-library" // _0 might be an alias for _
const another = partial(f, _1, 10, "hi", _0, "yo") // instead of f(?1, 10, "hi", ?0, "yo")
// design 2
import {_, partial} from "a-partial-application-library"
const another = partial(f, _[1], 10, "hi", _[0], "yo") // instead of f(?1, 10, "hi", ?0, "yo")
and to support #7
function add({x,y}) {
return x + y;
}
// design 1 - dumb implementation
import {_, partial} from "a-partial-application-library"
const plus2 = partial(add, {y : 2, x: _}) // instead of add({y:2, ...});
// the above is dumb because it'll cause the implementation in "partial" to do a nested object walk through all arguments to find the key that's equal to `_`
// design 2 - slightly smarter
import {_, partial} from "a-partial-application-library" // this time _ is callable
const plus2 = partial(add, _({y : 2})) // _ wraps the optional arg and marks first positional argument to add as having been partially applied
console.log(plus2({x : 3})) // and when {x: 3} is passed, partial performs Object.assign({}, {y:2}, {x: 3}) and passes that as an arg to add
// design 3 - perhaps clearer?
// we can use a different name than _ for these "args which have been supplied but incompletely" (avoiding the word "partial" because that's being used for "args which have not been supplied at all")
import {_, incomplete, partial} from "a-partial-application-library" // this time _ is callable
const plus2 = partial(add, incomplete({y : 2}))
console.log(plus2({x : 3}))
const other = partial(someFunc, _, 3, incomplete({x : 2}), _, "hi")
// we can also support fixed-length arrays by using
incomplete(_, 1) // to denote first element of array is missing, when user passes [0] this arg will resolve to [0, 1] before being sent to the function
incomplete(1, _, 3) // to denote middle element is missing, user passes [2] and this arg resolves to [1, 2, 3] before being sent to the function
incomplete(1, _, 3, _, 5) // when user passes [2, 4], function gets [1, 2, 3, 4, 5]
incomplete(1, _, 3, _, 5, _rest) // when user passes [2, 4] function gets [1,2, 3, 4, 5] and when user passes [2, 4, 6, 7] the function gets [1,2,3,4,5,6,7]
// nesting can be achieved, though you might prefer the shorter name _ over "incomplete" here
incomplete(1, _, incomplete(_, "y", _)) // user passes [2, ["x", "z"]] and function gets [1, 2, ["x", "y", "z"]
incomplete(1, _, incomplete({'key1': 'v1'})) // user passes [2, {"key2": "v2"}] and function gets [1, 2, {"key1": "v1", "key2": "v2"}
Through these examples, I'm not saying that this proposal is not needed. Indeed some of the syntax clunkiness in a userland library would go away if this were a language feature. I'm just hoping that this leads to a discussion of he core language limitations that prevent this proposal from happening as a userland library, and to discuss if this proposal addresses those limitations well.
A discussion of how this can (even partially) be achieved in a userland library may also support development of this feature in transpilers (babel, typescript) and allow it to reach users faster.