On 1/30/19 1:59 PM, Richard Hipp wrote:
It seems that you distinguish between the xStep and xFinal methods by the number of argments. xStep [has] 1+N argument (where N is the number of function parameters) and xFinal has just 1.
Yes. I was explicit about that in my first email.
Dan suggests (and I agree) that this will not extend well to window functions.
I agree too. Trouble is, I designed around aggregate functions while disregarding window functions because of my total lack of experience with window functions.
It might be better to have an initial argument that is the "method" name.
I did initially consider this but decided it was not necessary for aggregate functions because final will always have zero arguments whereas step will never usefully have zero arguments.
xStep would 2+N arguments where the first argument is the string "step" and xFinal has 2 arguments where the first argument is "final". Then when you go to add the xValue and xInverse routines for window functions, you will have a convenient way to distinguish those calls from xStep and xFinal.
Adding an extra initial argument to the aggregate functions is not a difficult thing to do. I can certainly add that. I just didn't see it as useful because it conveys information redundantly provided by another path guaranteed to be there. Again, I agree it leaves room for future expansion, but (1) it's highly unlikely that the fundamental definition of an aggregate function will change, and (2) I don't think it's strictly necessary that the same calling convention be used for aggregate functions and window functions. My preference would be that all functions, regardless of kind, have the same convention, but this is not possible because the interface to scalar functions is set in stone, and it would be useless to insert a first argument that's always "function". Therefore, since aggregate functions must be defined differently than scalar functions, I thought it would be fine for window functions to be defined differently than aggregate functions. The next chance I get (probably tomorrow morning), I'll go ahead and add "step" or "final" as the initial argument to aggregate functions. I'll also lift the prohibition on aggregate functions with no arguments. All my above reasoning notwithstanding (I just wanted to document why I took the approach I did), this change does benefit aggregate functions by making it easier to tie into TclOO and similar Tcl object systems which use initial arguments as method names. As for procedures that don't need this, they are free to ignore the argument. Old example, works with current code, here for baseline comparison: db function list -deterministic -aggregate { apply {{state args} { concat $state $args }} } New example: db function list -deterministic -aggregate { apply {{method state args} { concat $state $args }} } Alternately: db function list -deterministic -aggregate { apply {{method state args} { switch $method { step {concat $state $args} final {set state} } }} } Or: namespace eval ListAggregate { namespace export step final namespace ensemble create proc step {state args} { concat $state $args } proc final {state} { return $state } } db function list -deterministic -aggregate ListAggregate Or: oo::class create ListAggregate oo::objdefine ListAggregate { method step {state args} { concat $state $args } method final {state} { return $state } } db function list -deterministic -aggregate ListAggregate Or: oo::class create ListAggregate { method step {state args} { concat $state $args } method final {state} { my destroy return $state } } db function list -deterministic -aggregate [ListAggregate new] Though I do not prefer that final example since it creates heavyweight infrastructure to hold per-instance internal state, yet doesn't actually make use of it. However, this could be useful as an alternative to storing state data in the return value, making it possible to modify it in-place without incurring copy-on-write, as documented in the tclSqlFuncStep() comments. Overall, my preference is to avoid creating global named objects when anonymous values will do the job, hence my use of [apply]. -- Andy Goth | <andrew.m.goth/at/gmail/dot/com> _______________________________________________ sqlite-users mailing list sqlite-users@mailinglists.sqlite.org http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users