proj-jasper-jasperVariadicFnsVsImplicitPartialApplication

see also [1].

maybe the thing to do is to only allow keyword default argument variadicity, and to leave fully-applied fns as 0-ary fns until an operation other than 'apply' is applied to them. If a new optional keyword supported by the fn is 'apply'd later, great. If the thing is treated as a value, great. The only uncomfortable case would seem to be when the fn actually returns a fn itself.

If we say that keyword args can only follow non-keyword args, then great: If it returns a non-0-ary fn, great, because when something is 'apply'd, we can distinguish whether to discard the 0-ary wrapper based on whether the something is a keyword arg (it must be an optional arg of the original fn) or a non-keyword arg (the original fn is now a 0-ary fn so it's used up all its non-keyword args, so execute it and get the return value). If it returns a 0-ary fn then we have a problem. But Haskell doesn't even have 0-ary fns. So maybe we can ban 0-ary fns (or, more practically, don't ban them but just point out that we're using them like this, in case people want to use them to metaprogram something).

However, what if we want to partially apply a keyword arg first? This seems like a common use case. First, we can hope that only the original, or only the returned, fn accept this keyword, in which case we're good. But we have an ambiguity in the case where both the original fn and the returned fn accept the same keyword. This maybe isnt surprising, since in Haskell the auto-partial-application goes along with currying everything. If the original fn and the new fn accepted all the same keywords, then you can think of them as just one fn with many arguments, curried in the middle somewhere (of course in our case they may not accept all the same keywords).

Can we resolve this by just choosing a convention? If we choose that the original function gets the keyword in the face of that ambiguity, we have the problem that a library passes you what it tells you is a function of type X, but actually it's a 0-ary wrapper of a function of type X, and if you pass it the magic keyword you end up hitting the wrapper parent instead of what you meant. But if we choose that the child function gets the keyword in that situation, then another function can pass you a function F that you dont know anything about, and you can pass it into some other function G that you dont know anything about, and then give G some keyword arguments, unaware that G is actually returning F to you, and then some of the keyword args that were meant for G go to F.

So, it seems that we need to (a) annouce when keyword args are given before nonkeyword args are exhaused, or we need to (b) announce when a function is done getting keyword arguments, or we need to (c) annouce when a function is NOT done getting keyword arguments despite nonkeyword args being exhaused, or (d) something else that i haven't thought of yet.

(a) seems rather strange. (b) would mean too much announcing. that leaves (c), some sort of 'i'm not done yet' operator, or (d) something else.

(c) doesn't need special support. We can simply say, 'when all the position args have been given, the fn executes. If you want to give keywords, give them before that.' If someone really wants to give keywords last to some fn f which takes two args, x and y , they can do 'g z = f x z y'. Now, to give f a final keyword, do g kwd/val. To close f, do g _/_ (all fns ignore _ keywords). So we can define 'appyXButLeaveOpenForKeyword f x = \z -> f z x'. However, this is error-prone; if someone later passes in a positional argument, it will be the last argument of f, and x will be applied to whatever f returns.

So maybe it's better to invent a special type of value, a 0-ary-waiting-for-keywords fn, which ONLY takes keywords, and which must be coerced to a value (or just closed explicitly, without any constraining of its value) in order to be closed.

Could we defer evaluation as long as possible and then apply keywords up the call chain. E.g. if f takes keyword Bob and g takes keyword Julie, and f takes 1 arg and returns g y where y = Bob's value, then f 0 Bob/3 = g y? Hmm, not sure. I think that's probably too complex for the same reason as above; if f returns a function g that was passed to it, then its client may think it can pass it a Bob later, but g might also take keyword Bob.

(only tangentially related : we want to allow one to apply different values to the same keyword, and have the last one 'take'. E.g. applying a keyword value is just equivalent to changing the default of the default argument.)

Also, the above discussion doens't cover the case of a variadic number of arguments.

Haskell can do variadic arguments by abusing the type inference system:

http://stackoverflow.com/questions/3467279/how-to-create-a-polyvariadic-haskell-function (see [2] ). But i don't want to do that.

we could either use a syntax like sum* 1 2 3 like i gave before, or we could just tell them to bite the bullet and use:

sum [1 2 3 4 5] instead of sum [1 2 3]. But this gives up partial application.. maybe go the other way, the same as 0-ary-waiting-for-keywords fns:

stopWaitingForKeywordsCloseVariadic (sum 1 2 3)

we could even use the * symbol as a synonym for stopWaitingForKeywordsCloseVariadic . So we have:

sumPlus3 = sum 1 2 sumPlus12 = sumPlus3 4 5 f = *(sumPlus12 6) f == 18

i like it better to use * to hold the fn open rather than to close it, because the reader knows how to parse it. But semantically i think it's better to explicitly close, so that you can pass a varadic function into another function which will apply some arguments with no one the wiser.

actually we should have * to open and to close for both kw and variadic. if the fn still has positional args left when you open it, nothing different happens until it runs out of positionals, at which time it stays open. This allows you to pass in a fn to a naive subroutine. e.g.:

f `x y bob/3` = x + y + bob g q = q 3 result = g (f* 1) z = result bob/5 z == 9

(but then what's the operator to turn a normal fn into a variadic fold? eg to turn + into variadic sum? mb its not so important?)

(recall that we also need a way to apply fns using data instead of arguments; and the reverse, to turn something which takes a list into a variadic. or will the Python *list and hash syntax, along with a core library fn, suffice for the latter case?)

There should also be an operator to turn a variadic fn into a function that takes a fixed number of arguments. Naw, actually, you can do that in the libs,

fix4 f = `w x y z` *(f w x y z)

(otoh how do we do fixn? maybe we do have to build that in, after all)

(or, more generally, if we have something that is 'getAndApplyNArgs n y = `x1...xn` y x1...xn' then we can implement fixn as fixn n f = *(getAndApplyNArgs n f)

(or, more generally, just have the x0..xn syntax, so we can actually say `x0..xn` in the libs. We are using x1..xn specially as implicit arguments anyhow. This can just be a macro expansion (can it? not if macros are only compile-time and we ever need to do that at runtime. hmm.. best make sure its not needed at runtime, then, e.g. n must be a numeric literal).)

(actually i bet you can do this via inductive w/o special syntax)