On Wed, 23 May 2001, Stas Bekman wrote:
> I don't think that poping the first list's element for list.scalar is the
> intuitive thing to do. 'scalar @list' (== list.scalar) should be the same
> as list.size and in case of function func.scalar it should let the
> function know that the context it scalar so wantarray() will do the right
> thing, but this seems to be not impossible to do with the suggested patch,
> since the alteration of the data structure happens after the function was
> called in the list context (always).
On Wed, 23 May 2001, Randal L. Schwartz wrote:
> No, there's at least half a dozen different relationships between what
> a function does in a list context and what it does in a scalar
> context. "size", "first element", "last element", "third element" (getpwnam),
> "string-representation" (localtime/gmtime), "one of many, leaving rest"
> (each, readline, readdir), "joined value" (``), and so on.
>
> I think "first element" actually makes sense here, since it applies
> equally well to both a one-element array and a scalar, which is what
> we're trying to unify.
I agree with Stas and Randall. There are already plenty of ways to convert
arrays to scalars, so we don't need a new "scalar" op. It's a hack.
Moreover, I do agree it creates confusion with the perl scalar function.
I propose the following features:
1. allow array operations on scalars. The semantics are that the
scalar is promoted to a 1 element array before the array op is
called. This means my "array" op (scalar -> array promotion) is
mostly redundant, since you could now just write foo.join(",")
without worrying if foo was a scalar or array (instead of
foo.array.join(",")). It's probably worth adding the array op
to LIST_OPS since there are cases where it is still useful.
Similarly, in place of my scalar op, you could just write foo.0,
foo.size or whatever, without worrying if foo was a scalar or array.
We should keep the array op since there could be places where you
really want to make sure you have an array.
2. allow scalar ops on arrays and hashes (for symmetry). The semantics
are that we loop over the array or hash values. The result is a
same-sized array or hash. Not relevent to the current discussion,
but probably quite useful.
3. provide some syntax for calling plugin functions in scalar context.
Array context remains the default. The syntax needs to be coupled
closely with the function call itself since one expression could
contain several calls; for example, in
foo.func1().func2().func3()
how would you specify that func1 and func2 are called in scalar context
and func3 in array context?
Here are some possibilities:
foo.$func1().$func2().func3() -> no good, $func1 already means
value of func1.
foo.func1$().func2$().func3() -> not pleasing, but doable.
foo.func1().scalar.func2().scalar.func3() -> more pleasing, but harder
This last example is quite different from my scalar op (which is
applied after the function is called). Using "scalar" as a postfix
operator to force scalar context would be harder to implement, but
not impossible. Perhaps the loop in Stash::get() can peek ahead
and pass a flag to _dotop? Maybe this isn't so hard afterall.
(1) and (2) should be easy to implement. (3) is a bit harder:
some aesthetically pleasing syntax needs to be chosen and the
parser and stash need to understand the new syntax.
Craig