Skip to content

Commit ab1372e

Browse files
committed
implement #6614, destructuring in formal arguments
1 parent 88a553a commit ab1372e

File tree

3 files changed

+59
-0
lines changed

3 files changed

+59
-0
lines changed

NEWS.md

+4
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ New language features
77
* Local variables can be tested for being defined
88
using the new `@isdefined variable` macro ([#22281]).
99

10+
* Destructuring in function arguments: when an expression such as `(x, y)` is used as
11+
a function argument name, the argument is unpacked into local variables `x` and `y`
12+
as in the assignment `(x, y) = arg` ([#6614]).
13+
1014
Language changes
1115
----------------
1216

src/julia-syntax.scm

+29
Original file line numberDiff line numberDiff line change
@@ -999,6 +999,32 @@
999999
(loop (cadr ex) (append! (reverse (cddr ex)) vars))
10001000
`(where ,ex ,.(reverse! vars)))))
10011001

1002+
(define (lower-destructuring-args argl)
1003+
(define (check-lhs a)
1004+
(if (expr-contains-p (lambda (e) (or (decl? e) (assignment? e) (kwarg? e)))
1005+
a)
1006+
(error (string "Invalid argument destructuring syntax \"" (deparse a) "\""))
1007+
a))
1008+
(define (transform-arg a)
1009+
(cond ((and (pair? a) (eq? (car a) 'tuple))
1010+
(let ((a2 (gensy)))
1011+
(cons a2 `(local (= ,(check-lhs a) ,a2)))))
1012+
((or (and (decl? a) (length= a 3)) (kwarg? a))
1013+
(let ((x (transform-arg (cadr a))))
1014+
(cons `(,(car a) ,(car x) ,(caddr a)) (cdr x))))
1015+
((vararg? a)
1016+
(let ((x (transform-arg (cadr a))))
1017+
(cons `(... ,(car x)) (cdr x))))
1018+
(else (cons a #f))))
1019+
(let loop ((argl argl)
1020+
(newa '())
1021+
(stmts '()))
1022+
(if (null? argl)
1023+
(cons (reverse newa) (reverse stmts))
1024+
(let ((a (transform-arg (car argl))))
1025+
(loop (cdr argl) (cons (car a) newa)
1026+
(if (cdr a) (cons (cdr a) stmts) stmts))))))
1027+
10021028
(define (expand-function-def- e)
10031029
(let* ((name (cadr e))
10041030
(where (if (and (pair? name) (eq? (car name) 'where))
@@ -1046,6 +1072,9 @@
10461072
(farg (if (decl? name)
10471073
(adj-decl name)
10481074
`(|::| |#self#| (call (core Typeof) ,name))))
1075+
(argl-stmts (lower-destructuring-args argl))
1076+
(argl (car argl-stmts))
1077+
(body (insert-after-meta body (cdr argl-stmts)))
10491078
(argl (fix-arglist
10501079
(arglist-unshift argl farg)
10511080
(and (not (any kwarg? argl)) (not (and (pair? argl)

test/core.jl

+26
Original file line numberDiff line numberDiff line change
@@ -5442,3 +5442,29 @@ for U in unboxedunions
54425442
end
54435443

54445444
end # module UnionOptimizations
5445+
5446+
# issue #6614, argument destructuring
5447+
f6614((x, y)) = [x, y]
5448+
@test f6614((4, 3)) == [4, 3]
5449+
g6614((x, y), (z,), (a, b)) = (x,y,z,a,b)
5450+
@test g6614((1, 2), (3,), (4, 5)) === (1,2,3,4,5)
5451+
@test_throws MethodError g6614(1, 2)
5452+
@test_throws MethodError g6614((1, 2), (3,))
5453+
@test_throws BoundsError g6614((1, 2), (3,), (1,))
5454+
h6614((x, y) = (5, 6)) = (y, x)
5455+
@test h6614() == (6, 5)
5456+
@test h6614((4, 5)) == (5, 4)
5457+
ff6614((x, y)::Tuple{Int, String}) = (x, y)
5458+
@test ff6614((1, "")) == (1, "")
5459+
@test_throws MethodError ff6614((1, 1))
5460+
gg6614((x, y)::Tuple{Int, String} = (2, " ")) = (x, y)
5461+
@test gg6614() == (2, " ")
5462+
function hh6614()
5463+
x, y = 1, 2
5464+
function g((x,y))
5465+
# make sure x and y are local
5466+
end
5467+
g((4,5))
5468+
x, y
5469+
end
5470+
@test hh6614() == (1, 2)

0 commit comments

Comments
 (0)