# \`rand(::MyType, N)\` allocates a lot, how to define return type properly?

**URL:** https://discourse.julialang.org/t/rand-mytype-n-allocates-a-lot-how-to-define-return-type-properly/133807
**Category:** Performance
**Created:** [November 11, 2025, 11:43pm UTC](https://discourse.julialang.org/t/rand-mytype-n-allocates-a-lot-how-to-define-return-type-properly/133807 "2025-11-11T23:43:58Z")
**Posts on this page:** 5
**Page:** 1

<div class="post-metadata">

### Author: ![tamasgal](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamasgal/32/27946_2.png) [@tamasgal](https://discourse.julialang.org/u/tamasgal)
#### Post date: [November 11, 2025, 11:43pm UTC](https://discourse.julialang.org/t/rand-mytype-n-allocates-a-lot-how-to-define-return-type-properly/133807/1 "2025-11-11T23:43:58Z")

</div>

Apologies if this has been discussed before but I am a bit lost in the docs and examples out there regarding a type-safe implementation of a proper rand interface. I guess it’s OK to have yet another another topic on this 😉

We are

```julia-auto
using Random

```

I simplified my use-case a lot. Let’s say we have a parametric type which can act as a random number generator by implementing (for the sake of simplicity, let’s have these two methods)

```julia-auto
struct Foo{T<:AbstractFloat}
   x::T
end

(foo::Foo)() = rand() * foo.x
(foo::Foo)(rng::AbstractRNG) = rand(rng) * foo.x

```

It works nicely:

```julia-auto
julia> foo = Foo(23.5)
Foo{Float64}(23.5)

julia> foo()
14.45342364543

```

But still does not work within the rand universe:

```julia-auto
julia> rand(foo)
ERROR: MethodError: no method matching Random.Sampler(::Type{TaskLocalRNG}, ::Random.SamplerTrivial{Foo{Float64}, Any}, ::Val{1})
This error has been manually thrown, explicitly, so the method may exist but be intentionally marked as unimplemented.

```

To get this working, the simplest possible way is probably this method:

```julia-auto
Random.rand(rng::AbstractRNG, foo::Random.SamplerTrivial{Foo{T}}) where {T} = foo[](rng)

```

which now allows

```julia-auto
julia> rand(foo)
4.275336808366797

julia> rand(foo, 5)
5-element Vector{Any}:
 20.016527280057733
 23.000581372857162
 12.988361756507565
  2.0685534186007852
  2.333543063789338

```

Long story short, it allocates a lot because rand cannot figure out the `eltype` of my sampler, therefore we get a `Vector{Any}` although `foo()` always returns a `Float64`. In my use case, it’s of a parametric type btw.

Benchmarking, just for the numbers:

```julia-auto
julia> @benchmark rand(foo, 1_000_000)
BenchmarkTools.Trial: 781 samples with 1 evaluation per sample.
 Range (min … max): 4.475 ms … 64.231 ms ┊ GC (min … max): 0.00% … 92.56%
 Time (median): 4.977 ms ┊ GC (median): 0.00%
 Time (mean ± σ): 6.378 ms ± 3.206 ms ┊ GC (mean ± σ): 22.94% ± 21.63%

  ▁█▇▂▁▂▄▂ ▂▃                                              
  █████████▆▅▆████▅▇██▇▇▆▇▅▇▅▇▆▆▇▇█▆▆▇█▇▅▆▅▅▆▇▅▆▁▇▁▄▆▆▁▆▆▄▅▄ ▇
  4.48 ms Histogram: log(frequency) by time 14.3 ms <

 Memory estimate: 22.92 MiB, allocs estimate: 1000003.

```

I went through [Random Numbers · The Julia Language](https://docs.julialang.org/en/v1/stdlib/Random/) and tons of trials and errors (even managed to crash Julia a few times) but could not get it right.

At some point I thought I understood everything and this should work, but it does not 😆 It still gives me `Vector{Any}`

```julia-auto
julia> Random.Sampler(::Type{<:AbstractRNG}, foo::Foo, ::Val{1}) =
           Random.SamplerTrivial(foo, Float64)

julia> Random.rand(rng::AbstractRNG, s::Random.SamplerTrivial{Foo,Float64}) = s[]().x

julia> rand(foo, 5)
5-element Vector{Any}:
  9.614490452513847
 13.571465906535863
  8.647284173324959
 14.56590026126972
 15.010035608615501

```

I even tried with `Val{Inf}` but no success

```julia-auto
julia> Random.Sampler(::Type{<:AbstractRNG}, foo::Foo, ::Val{Inf}) =
           Random.SamplerTrivial(foo, Float64)

julia> rand(foo, 5)
ERROR: MethodError: no method matching Random.SamplerTrivial(::Foo{Float64}, ::Type{Float64})
The type `Random.SamplerTrivial` exists, but no method is defined for this combination of argument types when trying to construct it.

```

What is the currently recommended way to define this correctly? The Random-docs mention here and there that some interfaces are not stable so I don’t want to mess around too much. Btw. my sampler return type is a parametric one, but once I am on the right track, it should be easy I think 😉

Here is a workaround (3 allocs for 1000000 samples) but of course it’s not as nice as being embedded into the rand universe with all the nice features:

```julia-auto
julia> function (foo::Foo{T})(n::Integer) where T
          out = Vector{T}(undef, n)
          for idx in eachindex(out)
              out[idx] = rand(foo)
          end
          out
      end

julia> foo(5)
5-element Vector{Float64}:
 8.170854883533778
17.33952422420556
 4.586268393336077
16.44952665515737
20.909410249922733

julia> @benchmark foo(1_000_000)
BenchmarkTools.Trial: 2981 samples with 1 evaluation per sample.
Range (min … max): 1.404 ms … 3.581 ms ┊ GC (min … max): 0.00% … 53.10%
Time (median): 1.494 ms ┊ GC (median): 0.00%
Time (mean ± σ): 1.676 ms ± 326.646 μs ┊ GC (mean ± σ): 11.49% ± 13.59%

 ▅▇██▇▅▃▂▁ ▄▅▅▄▂▁▁▁ ▁ ▂▂▁▁ ▁▁▃▂▁▁ ▁ ▂
 █████████▇▇▇▆▆▆▄▆▄▇████████▇█▆▇▆█████▇███████▆▅▁▅███▆▆▆▄▄▁▆ █
 1.4 ms Histogram: log(frequency) by time 2.69 ms <

Memory estimate: 7.66 MiB, allocs estimate: 3.

```

---

<div class="post-metadata">

### Author: ![xinady](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/xinady/32/33502_2.png) [@xinady](https://discourse.julialang.org/u/xinady)
#### Post date: [November 12, 2025, 4:14am UTC](https://discourse.julialang.org/t/rand-mytype-n-allocates-a-lot-how-to-define-return-type-properly/133807/2 "2025-11-12T04:14:16Z")

</div>

HI  
About why `Vector{Any}` is returned described in [Random Numbers · The Julia Language](https://docs.julialang.org/en/v1/stdlib/Random/#A-simple-sampler-without-pre-computed-data). To return `Vector{Float64}` needs additionally to define:

```julia-auto
 Base.eltype(::Type{Foo}) = Float64

```

or maybe Foo’s `T` parameter type if not only `Float64` required.  
I’m not a big expert on the random samplers interface, so maybe someone can suggest a better option for cumstom number generator overall.

Also, it is better interpolate values inside benchmarks macros something like:

```julia-auto
@benchmark rand($foo, $1_000_000)

```

to avoid false times and allocations not caused by the function.

---

<div class="post-metadata">

### Author: ![rfourquet](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rfourquet/32/3610_2.png) [@rfourquet](https://discourse.julialang.org/u/rfourquet)
#### Post date: [November 12, 2025, 9:28am UTC](https://discourse.julialang.org/t/rand-mytype-n-allocates-a-lot-how-to-define-return-type-properly/133807/3 "2025-11-12T09:28:44Z")

</div>

Yes @xinady’s answer is correct, see [Random Numbers · The Julia Language](https://docs.julialang.org/en/v1/stdlib/Random/#A-simple-sampler-without-pre-computed-data). I’m just adding a tiny precision: as calling your `Foo` object returns a float which is the result of multiplying `T` with `Float64`, perhaps you can use `promote_type`, like in

```julia
Base.eltype(::Type{Foo{T}}) where {T} = promote_type(T, Float64)

```

---

<div class="post-metadata">

### Author: ![tamasgal](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamasgal/32/27946_2.png) [@tamasgal](https://discourse.julialang.org/u/tamasgal)
#### Post date: [November 12, 2025, 1:08pm UTC](https://discourse.julialang.org/t/rand-mytype-n-allocates-a-lot-how-to-define-return-type-properly/133807/4 "2025-11-12T13:08:13Z")

</div>

Damn, I overlooked the `eltype` line. Thanks! I will check that out. My case is a bit more complicated (multiple parameters).

---

<div class="post-metadata">

### Author: ![tamasgal](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamasgal/32/27946_2.png) [@tamasgal](https://discourse.julialang.org/u/tamasgal)
#### Post date: [November 12, 2025, 1:19pm UTC](https://discourse.julialang.org/t/rand-mytype-n-allocates-a-lot-how-to-define-return-type-properly/133807/5 "2025-11-12T13:19:48Z")

</div>

Yes, `eltype` does the trick, very naturally 😉
