Forums

MultiArg assignment

General discussion about Cobra. Releases and general news will also be posted here.
Feel free to ask questions or just say "Hello".

MultiArg assignment

Postby hopscc » Wed Oct 08, 2008 8:34 pm

Opened a ticket for this but not a discussion (ticket:38)

1. Support multiple arg assignment ( tuple unpacking) - assignment to multiple args from a list-like-thing in a single statement
as in
Code: Select all
<multi arg commaSep list> = <List expression>

a,b = 1,2     #possible syntax
 a,b = fnReturns2Args()  #call to a method returning a list
 
x,y = [1,2]
# above approx equiv to
t = [1,2]
x=t[0]
y=t[1]
 

list=...something generating a list/array/string...
i,j,k = list # gets first 3 elements of list


2. Also support multiple assignment of Key and value pairs in a for statement
Code: Select all
for key, value in dict
...


3. Support multiple assignment from an IEnumeration expression in a for statement
Code: Select all
 for x,y in ..whatever_list_array_string
     ... do something with x and y
hopscc
 
Posts: 632
Location: New Plymouth, Taranaki, New Zealand

Re: MultiArg assignment

Postby hopscc » Wed Oct 08, 2008 8:54 pm

Item 1. is implemented.
With that 2. can be done manually relatively simply
Code: Select all
for kv in dict
    key, value = [kv.key, kv.value]
    ... rest of block...


Pythons implementation throws exception if arglist ( the x,y,z lhs variable name stream) length is not exactly same length as items in rhs expression.
My implementation does not; for shorter arglist the given args are assigned to from the start of the rhs list, longer arglist leaves additional lvalue args unchanged
from prior to the assignment expression
Code: Select all
a,b=[1,2,3]
assert a==1
assert b==2
# remaining rhs items ignored

c=9999
a,b,c = [1,2]
assert a==1
assert b==2
assert c == 9999   # c unchanged from prior to multi-arg assign


I think this silent do-what-I-mean behaviour is the most useful but I'd welcome any comments on this
( I actually think pref behaviour for the last case would be for c to be reset to its types default init value(nil, 0, '')
but theres some insurmountable opportunities I couldnt get round to implement that).
hopscc
 
Posts: 632
Location: New Plymouth, Taranaki, New Zealand

Re: MultiArg assignment

Postby hopscc » Wed Oct 08, 2008 9:06 pm

What is desired behaviour for 3. ?
I'd thought that it should obviously be
Code: Select all
for x,y in [1,2,3,4]
# iter1: [x,y] == [1,2]
# iter2: [x,y] == [3,4] .

But pythons implementation throws on this, demanding that the list be packaged as a list of 2-tuples ( in this case)
Code: Select all
# python
for x,y in [1,2],[3,4]]
#  iter1: [x,y] == [1,2]
# iter2: [x,y] == [3,4]


Which is most preferred/useful/desirable behaviour ?

What should happen here if num items in IEnumeration expression is not a multiple of number of assign-to args ??
hopscc
 
Posts: 632
Location: New Plymouth, Taranaki, New Zealand

Re: MultiArg assignment

Postby Charles » Wed Oct 08, 2008 11:23 pm

As I mentioned in direct email with you, I totally support this. It's only missing from Cobra because no one hasn't gotten around to it until now.

Regarding your questions:

-- The right hand values should number exactly the same as the left hand targets. A mismatch in count could easily indicate an error. And with slicing, the programmer can easily drop the extra values ("x, y = t[:2]").

-- In "for x, y ..." the enumerable target of the "for" should contain sequences or enumerables matching in length, just like Python.

-- Do you have type inference working?
a, b = 'foo', 3  # a is a String, b is an int


Two things that should work beyond Python are simple consequences of being on .NET:

-- The right hand values of a multi-target assignment could be a DictionaryEntry (found in System.Collections) or a KeyValuePair<of U, T> (found in System.Collections.Generic).

-- I think we could swing it so that the right hand values came from "out" parameters:
success, value = int.tryParse(s)

# currently, calling .tryParse is rather awkward, though no worse than C#:
value as int
success = int.tryParse(s, out value)


Those last two ideas are not necessary for the first patch to be applied. We can do things in stages. But matching the Python semantics is required; I think they were well thought out and fit in with Cobra.
Charles
 
Posts: 2515
Location: Los Angeles, CA

Re: MultiArg assignment

Postby hopscc » Thu Oct 09, 2008 4:48 am

Yep, remember(and found ) the mail - thats what got me to do something about this...
Which also reminds me provided syntax for simplest multiarg case is
Code: Select all
a,b,c = [1,2,3]   # rhs literal list

The patch on the ticket has a comment re what to do (uncomment and comment some code) if want exception generated for mismatch (greater) lhs args length
I'd agree that that case is possibly more likely to be an error.

For the case of a shorter arglist I'm not convinced of the utility of forcing the programmer to explicitly have to truncate the list when its unnecessary to get/provide the assignment values.
- easy to do or not its still an extra (nitpicking) step
If its a programmer error (missing arg in lhs variable name list) then a shorter set of assigned items is gonna be obvious from the missing variable later....
depends on whether you think programmer should do additional bookkeeping for being explicit to system or system should assume programmer knows what they're doing and do
with what it has


OK re 'for' and matching length of sequence objects...

Type inference works as well as assignmentExprs ( since it basically just rewrites the multi arg assignment to a stream of single assignments)

Not looked at auto unpacking KeyValuePair (it'll fall out of multiargs in 'for' on a Dict I expect )- step 2), have to look at Dictionary Entry.

Are you talking of autodetecting and rewriting the return types for (library) methods returning 'out' values or explicitly wrapping some selected candidates??
...
hopscc
 
Posts: 632
Location: New Plymouth, Taranaki, New Zealand

Re: MultiArg assignment

Postby Charles » Fri Oct 10, 2008 4:40 am

Btw this works in Python for swapping values:
a, b = b, a
So the compiler can't always do a naive series of assignments.

Regarding the "out" params, I was thinking it would be pure syntactic sugar with no wrapper methods. But I haven't thought hard about the implementation or the fact that assignment can itself be an expression.

Regarding number arg lhs targets, I still insist that it be the correct number like in Python. If it's obviously the wrong number at compile-time that would be an error. If it happens at run-time, an exception.
Charles
 
Posts: 2515
Location: Los Angeles, CA

Re: MultiArg assignment

Postby hopscc » Sat Oct 11, 2008 9:23 pm

This does the same in the current patch
Code: Select all
a,b = [b,a]

(Should have actually provided that example in one of the tests since its so common an example )


The 'out' parameter rewrite thing can be a subsequent enhancement when and if.

number lhs arg targets - and the reason(s) for this insistence would be?
hopscc
 
Posts: 632
Location: New Plymouth, Taranaki, New Zealand

Re: MultiArg assignment

Postby Charles » Sun Oct 12, 2008 9:08 am

-- Are you saying that "a, b = b, a" does swap the values? Or that you can only get the swap if you wrap the right hand side in a list?

-- I agree the "out" arg enhancement can be done later.

-- The insistence on the lhs count matching the rhs count is two fold:

One, it's in line with other aspects of Cobra, like if you say list[i] where i is out of range, the language doesn't give you nil or the last element. It gives you an error. Likewise if you say obj.foo where foo is undefined, you get an error. If you say x + y where x is 5 and y is "10", you don't get 15--you get an error. Cobra is not loosey goosey.

Two, it matches the Python semantics which are known from experience to work well and without annoyance/hindrance to the developer. It's hard to justify deviating in light of that.

-Chuck
Charles
 
Posts: 2515
Location: Los Angeles, CA

Re: MultiArg assignment

Postby hopscc » Sun Oct 12, 2008 7:35 pm

No, as is rhs has to be a list/array/string (actually anything thats compilable to a numeric indexer)

I've not looked at this stage whats required for handling an unadorned comma separated literal/identifier stream since its a niche case and
doable via a literal list/array anyway

lhs/rhs matching count:
on one: As mentioned I dont disagree (strongly enough anyway) for the greater lhs case
Code: Select all
a,b,c=[1,2]

However
Code: Select all
a,b,c = [1,2,3,4]

isnt an out of range case (compile time or runtime)
on two: python semantics works but I'd disagree about the developer annoyance (for the lesser lhs length case) and that
its not possible to do better (less hindrance) than pythons nitpicking for that case.
Anything additional come to mind?
hopscc
 
Posts: 632
Location: New Plymouth, Taranaki, New Zealand

Re: MultiArg assignment

Postby Charles » Mon Oct 13, 2008 1:40 am

-- Regarding "a, b = c, d", one possible implementation is to simply have the parser create a list out of "c, d" for now since a list rhs is working.

-- Regarding having too few targets on the lhs:

* In my own Python coding, it's rarely the case that I have four items in the list, but I only want items 1 and 2

* Cobra and Python have slicing. For those cases where you want a portion of the list, it's easy to slap a "[:n]" on the end.

* In some cases, you'll want discontiguous items anyway in which case this "shortcut" doesn't help.

-- I'm surprised that if having to slice the list is annoying, you don't find having to wrap "c, d" in brackets to also be annoying. If you forget to do it, you have to cursor back to "c".
Charles
 
Posts: 2515
Location: Los Angeles, CA

Next

Return to Discussion

Who is online

Users browsing this forum: No registered users and 109 guests