首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Julia splat算子解包装

Julia splat算子解包装
EN

Stack Overflow用户
提问于 2017-02-20 02:45:06
回答 2查看 2K关注 0票数 3

在Python中,可以使用*运算符来解压可迭代。

代码语言:javascript
复制
In [1]: head, *tail = [1, 2, 3, 4, 5]

In [2]: head
Out[2]: 1

In [3]: tail
Out[3]: [2, 3, 4, 5]

我想在朱莉娅身上产生同样的行为。我认为等效的...操作符可以工作,但在这种情况下似乎只会产生一个错误。

代码语言:javascript
复制
julia> head, tail... = [1, 2, 3, 4, 5]
ERROR: syntax: invalid assignment location "tail..."

我能够使用以下方法生成我想要的结果,但这是一个丑陋的解决方案。

代码语言:javascript
复制
julia> head, tail = A[1], A[2:end]
(1,[2,3,4,5])

我是否可以对数组进行解压缩,以便tail将在head之后使用splat (...)运算符包含其余的项?如果没有,最清洁的选择是什么?

编辑:这个特性是在#2626中提出的。看起来它将是1.0版本的一部分。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-02-20 13:13:31

这听起来确实像是宏的任务:

代码语言:javascript
复制
function unpack(lhs, rhs) 
    len = length(lhs.args)
    if len == 1
        # just remove the splatting
        l, is_splat = remove_splat(lhs.args[1])
        return :($l = $(esc(rhs)))
    else
        new_lhs = :()
        new_rhs = quote 
            tmp = $(esc(rhs))
            $(Expr(:tuple)) 
        end
        splatted = false
        for (i, e) in enumerate(lhs.args)
            l, is_splat = remove_splat(e)
            if is_splat
                splatted && error("Only one splatting operation allowed on lhs")
                splatted = true
                r = :(tmp[$i:end-$(len-i)])
            elseif splatted
                r = :(tmp[end-$(len-i)])
            else
                r = :(tmp[$i])
            end
            push!(new_lhs.args, l)
            push!(new_rhs.args[4].args, r)
        end
        return :($new_lhs =  $new_rhs)
    end
end

remove_splat(e::Symbol) = esc(e),  false

function remove_splat(e::Expr)
    if e.head == :(...)
        return esc(e.args[1]), true
    else
        return esc(e), false
    end
end

macro unpack(expr)
    if Meta.isexpr(expr, :(=))
        if Meta.isexpr(expr.args[1], :tuple)
            return unpack(expr.args[1], expr.args[2])
        else
            return unpack(:(($(expr.args[1]),)), expr.args[2])
        end
    else
        error("Cannot parse expression")
    end
end

它没有经过很好的测试,但是基本的东西起作用了:

代码语言:javascript
复制
julia> @unpack head, tail... = [1,2,3,4]
(1,[2,3,4])

julia> @unpack head, middle..., tail = [1,2,3,4,5]
(1,[2,3,4],5)

几个朱莉娅·戈查斯:

代码语言:javascript
复制
x,y = [1,2,3] #=> x = 1, y = 2

a = rand(3)
a[1:3], y = [1,2,3] #=> a = [1.0,1.0,1.0], y = 2

宏遵循此行为

代码语言:javascript
复制
@unpack a[1:3], y... = [1,2,3]
#=> a=[1.0,1.0,1.0], y=[2,3]
票数 2
EN

Stack Overflow用户

发布于 2021-10-31 19:55:32

朱莉娅1.6

现在可以在非结构化赋值的左侧使用...从可迭代集合的前面提取任意数量的项,同时也可以收集其余的项。

在分配前两项同时消耗其余部分的示例:

代码语言:javascript
复制
julia> a, b, c... = [4, 8, 15, 16, 23, 42]
# 6-element Vector{Int64}:
#   4
#   8
#  15
#  16
#  23
#  42

julia> a
# 4

julia> b
# 8

julia> c
# 4-element Vector{Int64}:
#  15
#  16
#  23
#  42

此语法是使用Base.rest实现的,可以重载该语法以自定义其行为。

重载Base.rest(s::Union{String, SubString{String}}, i::Int)以关闭Vector{Char}而不是默认SubString的示例

代码语言:javascript
复制
julia> a, b... = "hello"
julia> b
# "ello"

julia> Base.rest(s::Union{String, SubString{String}}, i=1) = collect(SubString(s, i))
julia> a, b... = "hello"
julia> b
# 4-element Vector{Char}:
#  'e': ASCII/Unicode U+0065 (category Ll: Letter, lowercase)
#  'l': ASCII/Unicode U+006C (category Ll: Letter, lowercase)
#  'l': ASCII/Unicode U+006C (category Ll: Letter, lowercase)
#  'o': ASCII/Unicode U+006F (category Ll: Letter, lowercase)
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42335661

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档