Skip to content

Commit 8118574

Browse files
committed
Vectorized @named definition
1 parent f8b1e40 commit 8118574

File tree

2 files changed

+41
-4
lines changed

2 files changed

+41
-4
lines changed

src/systems/abstractsystem.jl

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -597,13 +597,16 @@ function Base.show(io::IO, ::MIME"text/plain", sys::AbstractSystem)
597597
return nothing
598598
end
599599

600-
function _named(expr)
600+
function split_assign(expr)
601601
if !(expr isa Expr && expr.head === :(=) && expr.args[2].head === :call)
602602
throw(ArgumentError("expression should be of the form `sys = foo(a, b)`"))
603603
end
604604
name, call = expr.args
605+
end
605606

607+
function _named(name, call, runtime=false)
606608
has_kw = false
609+
call isa Expr || throw(Meta.ParseError("The rhs must be an Expr. Got $call."))
607610
if length(call.args) >= 2 && call.args[2] isa Expr
608611
# canonicalize to use `:parameters`
609612
if call.args[2].head === :kw
@@ -626,18 +629,46 @@ function _named(expr)
626629
kws = call.args[2].args
627630

628631
if !any(kw->(kw isa Symbol ? kw : kw.args[1]) == :name, kws) # don't overwrite `name` kwarg
629-
pushfirst!(kws, Expr(:kw, :name, Meta.quot(name)))
632+
pushfirst!(kws, Expr(:kw, :name, runtime ? name : Meta.quot(name)))
633+
end
634+
call
635+
end
636+
637+
function _named_idxs(name::Symbol, idxs, call)
638+
if call.head !== :->
639+
throw(ArgumentError("Not an anonymous function"))
640+
end
641+
if !isa(call.args[1], Symbol)
642+
throw(ArgumentError("not a single-argument anonymous function"))
630643
end
631-
:($name = $call)
644+
sym, ex = call.args
645+
ex = Base.Cartesian.poplinenum(ex)
646+
ex = _named(:(Symbol($(Meta.quot(name)), :_, $sym)), ex, true)
647+
ex = Base.Cartesian.poplinenum(ex)
648+
:($name = $map($sym->$ex, $idxs))
632649
end
633650

651+
check_name(name) = name isa Symbol || throw(Meta.ParseError("The lhs must be a symbol (a) or a ref (a[1:10]). Got $name."))
652+
634653
"""
635654
$(SIGNATURES)
636655
637656
Rewrite `@named y = foo(x)` to `y = foo(x; name=:y)`.
638657
"""
639658
macro named(expr)
640-
esc(_named(expr))
659+
name, call = split_assign(expr)
660+
if Meta.isexpr(name, :ref)
661+
name, idxs = name.args
662+
check_name(name)
663+
esc(_named_idxs(name, idxs, :($(gensym()) -> $call)))
664+
else
665+
check_name(name)
666+
esc(:($name = $(_named(name, call))))
667+
end
668+
end
669+
670+
macro named(name::Symbol, idxs, call)
671+
esc(_named_idxs(name, idxs, call))
641672
end
642673

643674
function _config(expr, namespace)

test/direct.jl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,3 +251,9 @@ if VERSION >= v"1.5"
251251
@named cool_name = foo(;ff)
252252
@test collect(cool_name) == [pp; :ff => ff]
253253
end
254+
255+
foo(i; name) = i, name
256+
@named goo[1:3] = foo(10)
257+
@test isequal(goo, [(10, Symbol(:goo_, i)) for i in 1:3])
258+
@named koo 1:3 i -> foo(10i)
259+
@test isequal(koo, [(10i, Symbol(:koo_, i)) for i in 1:3])

0 commit comments

Comments
 (0)