1. Re: we need official libs : Swap
Wow, this thread has seen some *good* debate from both sides! As much as I
hate to abandon Rod, who has been doing an *excellent* job of defending the
"against" position, I do find myself cautiously *for* this idea once
again...
It started when I finally discovered what some of the confusion may have
initially been concerning the {a,b} = foo() idea. From the Euphoria
reference manual:
]2.2.8 Sequence-Formation
]
] Finally, sequence-formation, using braces and commas:
]
] {a, b, c, ... }
]
] is also an operator. It takes n operands, where n is 0 or more, and
] makes an n-element sequence from their values. e.g.
]
] x = {apple, orange*2, {1,2,3}, 99/4+foobar}
]
] Sequence-formation operator is listed at the bottom of the precedence
] chart.
Here we have the source of some of the confusion on this subject.
Consciously or not, some contributors were smart enough to realize that the
sequence-formation symbols were defined as *operators* in Euphoria, so
sequences of the {a,b} variety were therefore *expressions*. As a result,
proposals for expressions on *both* sides of an assignment (e.g. x + 1 = 34)
were made -- if one could do {a,b} = foo(), went the reasoning, then one
should also be able to do x + 1 = 34.
For the sake of discussion (as well as the continued sanity of all Euphoria
programmers), let us assume that this is a false argument -- in programming,
to make life simpler for both programmers and language author(s),
expressions can *never* be used as the receiving portion of an assignment.
With this as a given, how can we then allow {a,b} = foo() to be legal, if
expressions are only allowed on the right? The solution would be to
re-define how the sequence "operators" are viewed by the interpreter, in
such a way that {a,b} is not *solely* viewed as an expression. Euphoria
already contains some precedents where symbols used in expressions can have
additional, non-expression meanings. Once again, from the Euphoria reference
manual:
]2.2.10 Precedence Chart
]
]<snip>
]
] The equals symbol '=' used in an assignment statement is not an operator,
] IT'S JUST PART OF THE SYNTAX OF THE LANGUAGE. (emphasis mine)
So, a symbol may have more than one basic functionality. True, this is the
'=' symbol we're talking about here, but as long as the usage is reasonably
clear from context, dual meanings may be permitted. {a,b} = foo() seems
pretty clear from context, don't you think?
Additionally, sequence slicing is one feature of Euphoria which *looks* like
an expression, but which also functions perfectly well at the receiving end
of an assignment:
x = s[i..j]
s[i..j] = x
s[i..j] = 0
s[1..5] = t[2..6]
To be sure, sequence slices on the left are subject to a few more
restrictions than those on the right -- receiving slices require that the
expression evaluate to either an atom or a sequence of identical length to
the slice -- yet both kinds of slices follow the same *basic* rules. Again,
it is clear from context what is going on.
So then, what must be done to allow us to code {a,b} = foo()?
First of all, we must consider the kinds of restrictions to be applied to
the receiving structure {a,b}. Just as s[i..j] = x demands scrutiny from the
interpreter, so also {a,b} = foo() requires the interpreter to look closely
at what's going on. The following are rules I have come up with which would
insure reasonably consistent integration of the {a,b} = foo() format into
the existing language:
--------
1) The receiving structure may *not* contain duplicate variables.
a) Duplicate variable names would be caught *before* execution.
Example:
{a,b} = {1,2} -- legal
{a,a} = {1,2} -- error!
b) Duplicate variable subscripts would be caught at run time.
(This would probably be the most difficult condition to verify.)
Examples:
{a[7], a[9]} = {1,2} -- legal
{a[7], a[7]} = {1,2} -- error!
{a[7][2], a[7]} = {1,2} -- NASTY error!
{a[x], a[y]} = {1,2} -- legal only if x != y
{a[x][z], a[y]} = {1,2} -- legal only if x != y
{a[7], a[9]} = {a[9], a[7]} -- legal, swaps the variables
{a[x], a[y]} = {a[y], a[x]} -- legal only if x != y
-- (if they're equal, then
-- it's redundant anyway...)
{a[x][z], a[y]} = {a[y], a[x][z]} -- legal, swaps the variables
-- but *only* if x != y
-- (my, we're *really* opening
-- a can of worms here...)
2) If the expression returns a sequence value, then its structure must
match the specified receiving structure *exactly*.
Examples:
{a,b} = {1,2} -- legal
{a,b} = {1,2,3} -- error!
{a,{b,c}} = {1,{2,3}} -- legal
{a,{b,c}} = {1,{2,3,4}} -- error!
{a,b} = {b,a} -- legal, swaps the variables
{a,b} = {b,b} -- legal, but a bit redundant
{b,b} = {a,b} -- error! (see #1 above)
3) If the expression returns an atom value, this value will be applied to
*all* receiving variables. (NOTE: I'm not 100% sure about this idea, but
it *does* fit with the s[i..j] = 0 method of slice assignment...)
Examples:
{a,b} = 2 -- legal
{a,{b,c}} = 2 -- legal, but unnecessarily complicated
{a,b,c} = 2 -- legal, identical to the above
4) Every received value *must* be assigned to its own variable, i.e.
no "placeholder" symbols, no repeated "junk" values (see #1 above).
Example:
{_, keep, _} = {1,2,3} -- error! "_" is not a variable
{junk, keep, junk} = {1,2,3} -- error! "junk" is repeated
{junk1, keep, junk2} = {1,2,3} -- legal, though not elegant
--------
The above is probably not complete, and certainly shows some of my lingering
hesitations concerning the introduction of {a,b} = foo() into Euphoria. This
was not an easy task, either, with many important details and linguistic
consequences which were not obvious at first. All of this demonstrates why
Rob has not exactly rushed to add this into the language -- this would
require some *very* significant changes to the way the interpreter currently
works.
Nevertheless, it does appear to me that this idea *can* be made into a
reasonably clear and self-consistent part of Euphoria; and, certainly, this
is the kind of thinking which *must* be done if we want to make this an
integrated part of the language.
Be seeing you,
Gabriel Boehme