Nonempty prefixes function

Is there a function somewhere like this?

nonempty_prefixes(xs) = [@view xs[firstindex(xs):i] for i in eachindex(xs)]

julia> xs = String('a':'z')
"abcdefghijklmnopqrstuvwxyz"

julia> nonempty_prefixes(xs)
26-element Vector{SubString{String}}:
 "a"
 "ab"
 "abc"
 "abcd"
 "abcde"
 "abcdef"
 "abcdefg"
 ⋮
 "abcdefghijklmnopqrstu"
 "abcdefghijklmnopqrstuv"
 "abcdefghijklmnopqrstuvw"
 "abcdefghijklmnopqrstuvwx"
 "abcdefghijklmnopqrstuvwxy"
 "abcdefghijklmnopqrstuvwxyz"

I am probably not understanding the question but maybe first?

julia> xs = String('a':'z')
"abcdefghijklmnopqrstuvwxyz"

julia> first(xs,8)
"abcdefgh"

I’m just looking for exactly the function I wrote, but if it’s already in some package or Base.

accumulate(*,xs)
1 Like

@jar1, there is SubString, but if broadcasted as below, it is not more efficient than your code:

SubString.(xs, firstindex(xs), eachindex(xs))

If written as a comprehension it is equivalent:

[SubString(xs, firstindex(xs), i) for i in eachindex(xs)]
2 Likes
view.(xs,(:).(1,1:length(xs))
view.(fill(xs), range.(firstindex(xs), eachindex(xs)))

works on Strings and Vectors

Why fill() and not Ref()?

1 Like

Probably not, but why would you need one? Your 1-line function is pretty compact and clear and about as efficient as such a thing can get.

(Attempting to use broadcasting here will probably result in additional allocations, because broadcasting will call collect on eachindex under the hood.)

5 Likes

firstindex(xs) => begin.

1 Like

Also you might want to return a generator instead of an array:

prefixes(xs) = ((@view xs[begin:i]) for i in eachindex(xs))

(You can always collect the result when you actually need an array.)

Side question: I was surprised I had to add inner parentheses for the view in the above code. Consider this:

# This works:
julia> [@view a[1:2] for a in [[1,2]]]

# This doesn't:
julia> (@view a[1:2] for a in [[1,2]])
ERROR: syntax: unexpected ")"

Is there a reason for that or is it a bug?

2 Likes

That seems a bit inconsistent to me, too. Note also that you can use parens for macro calls. Imo, @view(a[1:2]) is nicer than (@view a[1:2]).

1 Like

In this specific case, I prefer:

view(a,1:2) 
1 Like

But in combination with begin or end, the macro form is needed.

1 Like

It turns out this is a design trade-off, due to an ambiguity between generator “for loop” and (a; b; c) block syntax. See parser bug: macro calls w/o parens in generator expressions · Issue #18650 · JuliaLang/julia · GitHub and RFC: fix #18650, parsing generator expressions containing macro calls by JeffBezanson · Pull Request #22943 · JuliaLang/julia · GitHub.

1 Like