Is there a way to return a function from a function factory of specific non-variadic arity, which arity is passed to the outer function?
In other words, if the outer function were called as outer(3, fx),
it would return a function object such as (v1,v2,v3)=>(somecalc + fx(v1,v2,v3)).
If it were called as outer(1, fy),
it would return (v1)=>(somecalc + fy(v1)).
Return function of specific (but variable) arity from fn factory?
Re: Return function of specific (but variable) arity from fn factory?
You’d probably have to code each length of arity? Or just accept variadic and handle the unhandled cases in fx
Re: Return function of specific (but variable) arity from fn factory?
What's the difference between (v1)=>(somecalc + fy(v1)) and (v*)=>(somecalc + fy(v*)), if fy requires exactly 1 parameter either way?
Or in other words, how do you define or observe arity?
I suppose that for r := outer(3, fx) and (v1)=>,
r(a, b) would throw an exception at the outer call (the anonymous function) instead of the inner call (fy).
r.MinParams and r.MaxParams would be 1 instead of 0.
r.IsVariadic would be false instead of true.
You cannot set the MinParams, MaxParams and IsVariadic properties, but you can redefine them for a given function or closure instance. This would only affect what value is returned when the property is queried.
For (re)implementing parameter constraints, you need only produce a function which performs some checks before calling the real function.
Or in other words, how do you define or observe arity?
I suppose that for r := outer(3, fx) and (v1)=>,
r(a, b) would throw an exception at the outer call (the anonymous function) instead of the inner call (fy).
r.MinParams and r.MaxParams would be 1 instead of 0.
r.IsVariadic would be false instead of true.
You cannot set the MinParams, MaxParams and IsVariadic properties, but you can redefine them for a given function or closure instance. This would only affect what value is returned when the property is queried.
For (re)implementing parameter constraints, you need only produce a function which performs some checks before calling the real function.
Re: Return function of specific (but variable) arity from fn factory?
i think it would be very useful if u actually could set those properties. for example, suppose the hypothetical Func::BindWithArgCount(cRequiredArgs, cOptionalArgs, bIsVariadic, ArgsToBind*) existed, his code would become:
Code: Select all
#Requires AutoHotkey v2.0-beta.2-optimisticallylol
outer(arity, someFunction) => (inner(v*) => (somecalc + someFunction(v*))).BindWithArgCount(arity, 0, false)
^^^^^ - 3
^ - no optional params
^^^^^ - not variadic
^ - and no additional args to bind
Code: Select all
#Requires AutoHotkey v2.0-beta.1
MessageBox := DllCall.Bind('MessageBox', 'Ptr', , 'Str', , 'Str', , 'UInt')
Code: Select all
MessageBox(A_ScriptHwnd, 'msgbox text', 'msgbox title', 0)
Code: Select all
; VS how it might end up being (inadvertently, too) used with no apparent errors to show
MessageBox(A_ScriptHwnd, 'msgbox text', 'msgbox title', 0, 'Str', 'a', 'Str', 'bunch', 'Str', 'of', 'Str', 'garbage')
u could write something like this instead:
Code: Select all
MessageBox(hwnd, title, caption, dwFlags) => DllCall('MessageBox', 'Ptr', hwnd, 'Str', title, 'Str', caption, 'UInt', dwFlags)
or u could stick a custom parameter-checking/enforcing function before the DllCall pretty much to the same effect
or u could write the hypothetical:
Code: Select all
MessageBox := DllCall.BindWithArgCount(4, 0, false, 'MessageBox', 'Ptr', , 'Str', , 'Str', , 'UInt')
Re: Return function of specific (but variable) arity from fn factory?
I nearly explained in my previous post how you can set those properties (via NumPut) and why doing so would be bad (because they either won't be used or will incorrectly change the behaviour of the function). Actually, I wrote about it and then deleted it before posting.
Instead, I pointed out how anyone can trivially redefine the properties and implement arbitrary parameter constraints. There is no need for a hypothetical BindWithArgCount method, because defining an actual method is trivial.
In any given set of APIs, there are generally some functions which benefit from additional wrapping, due to different string and memory allocation conventions, structs, error-reporting conventions, enum and flag parameters, etc. There are many more errors that could be prevented by adding error checking in a wrapper function, beyond just validating the number of parameters. DllCall.Bind can only take you so far (binding to user-defined functions can take you the rest of the way).and another use-case where this might be useful is for creating DllCall wrappers
It is not productive to avoid creating functions based on misplaced concern over negligible overhead.and ure also incurring a parameter passing overhead on each call, yaaay......
There are more important issues, such as the inability to identify bound functions in stack traces, or time lost while trying to trace cryptic error messages.
Re: Return function of specific (but variable) arity from fn factory?
Sorry I'm a little bit late in the discussion. In answer to @lexikos' question:
The wrapper functions are generally more complex than a single !, they are often implemented as methods rather than functions, and there are very many of them. Options I've considered:
The particular functional programming use case I'm trying to handle is, for example, a "not" function factory:What's the difference between (v1)=>(somecalc + fy(v1)) and (v*)=>(somecalc + fy(v*)), if fy requires exactly 1 parameter either way?
Code: Select all
notff(f) => x => !f(x) ;not function factory
iseven(x) => mod(x,2) == 0
isodd := notff(iseven) ;works great on a 1-arity function
eq(x,y) => x==y ;implementation in actual methods differs by object
neq := notff(eq) ;defined in a lower-level base, but needs 2-arity notff
- I could have a 1-, 2- and 3-arity (etc) version of notff or other wrappers, but there are a lot of these functions.
- I could use an if statement inside the wrapper to return the correct arity, but I'd be doing this handling in every single wrapper function factory, which seemed duplicative. This is why I was trying to find a generic way to wrap a function returning specified arity... a la my original outer(3, fx) question
- I can easily (and currently do) use notff(f) => (p*) => !f(p*) but, I Iose visibility to min/max params when calling the derived function... unless I instance-override those props. I do have functions that need to check these, so this is what I generally end up doing. To overload min/max/variadic etc. seems to be a lot of assignment for a functional approach that's supposed to make things simpler. I guess I could handle those assignments in a universal way that doesn't need to be repeated in each wrapper.
- I could try to be more true to functional programming style and make all functions single-arity. With ahk's great support for optional arguments, I was trying to use a hybrid approach in some places (since I'm already using objects, which aren't themselves pure-play functional programming constructs)... but optional arguments require wrapping multiple-arity function varieties.
- On call, I could maybe introspect "through" the wrapper functions until a non-wrapper is discovered, in order to learn the true underlying arity. I'm not sure that's even possible, nor might it be straightforward when the transform done by the wrapper isn't simple. Also, seems better to be doing the heavy lifting when defining the functions rather than when calling them.