Cameron Bieganek
Cameron Bieganek

Reputation: 7674

Repeat a function call N times

What's the easiest way in Julia to call a function n times, with the same arguments, and return the result in an array? For example, I'd like to get an array of random strings, each of a certain length. The best I've been able to come up with is

julia> map(_ -> randstring(4), 1:6)
6-element Array{String,1}:
 "xBWv"
 "CxJm"
 "KsHk"
 "UUIP"
 "64o4"
 "QNgm"

Another alternative is to use broadcasting, like in either of the following:

# Broadcast over an array of 4's
randstring.(fill(4, 6))

# Broadcast over an iterator that repeats the number 4 six times
using Base.Iterators
randstring.(repeated(4, 6))

However, my preference is for a syntax like replicate(randstring(4), 6). For comparison, in R I would do the following:

> # Sample from lower-case letters only:
> random_string <- function(n) paste(sample(letters, n, replace = TRUE), collapse = '')
> replicate(6, random_string(4))
[1] "adru" "neyf" "snuo" "xvnq" "yqfv" "gept"

Upvotes: 6

Views: 2228

Answers (3)

Jesse
Jesse

Reputation: 1672

While there are ways to do this without introducing package dependencies, Lazy.jl does provide a lot of these nice, functional tools.

In particular, you said

my preference is for a syntax like replicate(randstring(4), 6)

First, note that this is no exactly "calling a function n times, because randstring(4) is not a function, it is evaluated.

So instead you want to call the anonymous function n times, to align with the equation title, in which case your preferred syntax is replicate(()->randstring(4),6)

Good news! Lazy.jl provides almost this exact syntax with the function repeatedly. The only distinction is that it takes n as its first argument: repeatedly(6,()->randstring(4))

The other distinction to notice is that this returns, for other reasons, a LazyList type, not an Array.

Now, it's likely the case that you won't notice the difference, e.g. you can index and broadcast into the List like you might an Array.

However, if you don't intend on exploiting any of the nice Lazy properties and you really do need it to be an Array then you can just directly unpack the List into Array.

Here is a full example:

using Random
using Lazy

stringlist = repeatedly(6,()->randstring(4))

stringarray = [stringlist...]

Upvotes: 1

Lufu
Lufu

Reputation: 466

I would go with

using Random
six_randstrings = [randstring(4) for _ in 1:6]

Upvotes: 12

Korsbo
Korsbo

Reputation: 724

If you're unhappy with using map or array comprehensions directly then you could create a macro for this:

macro replicate(ex, n)
    return :(map(_ -> $(esc(ex)), 1:$(esc(n))))
end

@replicate(rand(), 4)

Upvotes: 4

Related Questions