On Sat, 20 Jun 2015, Sven Schreiber wrote:
Am 20.06.2015 um 09:50 schrieb Riccardo (Jack) Lucchetti:
> On Fri, 19 Jun 2015, Allin Cottrell wrote:
>
>> 2) If and when a contributed function package returns a list, it
>> should be just as explicit as the built-in functions with regard to
>> the character and naming of the series members of the returned list.
>> Again, there should be no surprises for anyone who has read the doc. I
>> would regard violation of this principle as sufficient reason to
>> reject a function package.
>
> This. This is, IMO, the heart of the matter.
I don't think this is the heart of the current discussion, because there
is no disagreement with respect to "mean" functions that secretly aim to
overwrite your data.
We agree that in principle there should be encapsulation -- but we also
agree/know that gretl's design purposefully doesn't really do this when
it comes to lists.
My main point (and I will formulate it a little bluntly, to get the
point across): Your "safeguard" does not ensure encapsulation, either.
As we know, the assigned name of the returned list has nothing to do
with the names of the member series. So when a user ignores the
function's documentation, dataloss can occur in any case, with explicit
assignment or without. Therefore the "safeguard" argument is not valid
to justify your change. Instead your Feb 2015 change is an ad-hoc
special-casing that makes it harder to program in hansl.
Sven, you're misunderstanding how "returning a list" works in hansl.
Qualification: what I have to say here in the first instance relates
to user-defined functions; I'll come back to built-in functions at the
end.
Just to be clear, a function that returns a list doesn't necessarily
create or return any new series. We could imagine a function that
takes a list argument and returns a list holding (say) all and only
those series in the input list that are strictly positive. However,
we're talking here about the (presumably more common) case where a
function returns a list that contains one or more newly created
series.
Now, note that a function can create any series the author likes, but
in general such series will not "make it" back to the caller level.
Rather, they will be destroyed when the function exits. The exceptions
are (a) if the function returns a series or (b) if it returns a list
containing newly defined series and the caller assigns the return
value. If a function offers a list return and it is _not_ assigned by
the caller, then all series defined within the function are discarded
on exit, so there can be no series-name collision.
This is the effect of the change I made in February. Before then, the
series included in a list return were shifted to caller level even if
the list was not assigned to anything. Under the new scheme, the list
(array of integer series IDs) created at function level cannot itself
be passed back to the caller as an anonymous object (when not
assigned) because it will be broken: the series it references will in
general not exist any more since they haven't been "accepted" by the
caller.
At present our built-in data-transformation functions are not subject
to the same constraint. If you do, for example,
<hansl>
list X = <whatever>
log(X)
</hansl>
then despite the non-assignment of the return value of log(), the logs
of the members of X will be added to the dataset. Obviously there's a
case for saying this is inconsistent behavior, but I think it's
defensible. I won't get into that right now; I want to think about it
some more first.
Allin