# Makie/Observable: \`@lift\` and type

**URL:** <https://discourse.julialang.org/t/makie-observable-lift-and-type/136597>\
**Category:** Visualization\
**Tags:** question\
**Created:** [April 7, 2026, 5:23am UTC](https://discourse.julialang.org/t/makie-observable-lift-and-type/136597 "2026-04-07T05:23:17Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![ryofurue](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ryofurue/32/24531_2.png) [@ryofurue](https://discourse.julialang.org/u/ryofurue)\
**Post date:** [April 7, 2026, 5:23am UTC](https://discourse.julialang.org/t/makie-observable-lift-and-type/136597/1 "2026-04-07T05:23:18Z")

</div>

Basically, I want to write my plotting functions in such a way that they work whether the arrays to be plotted are `Observable`s or not. This enables me to use my snapshot-producing functions in creating movies.

For this purpose, I currently use `@lift` when some operations are necessary on the array before plotting, but then I’ve noticed that the array returned by `@lift` doesn’t necessarily have the right types. To illustrate what I mean, I’ve created the following toy program:

```julia-auto
using Makie # Observables
using OffsetArrays
const nooffs = OffsetArrays.no_offset_view

oa = zeros(-1:2, 0:4)
oa_obs = Observable(oa)
@show typeof(oa), typeof(oa_obs)

b = nooffs(oa) # -> Array
@show typeof(b)
bb = @lift(nooffs($oa)) # -> OffsetArray. Why?
@show typeof(bb)
b_obs = @lift(nooffs($oa_obs))
@show typeof(b_obs)

```

The strange thing is that `no_offset_view` doesn’t work under `@lift`: `bb` is still an `OffsetArray`.

In the above example, I apply `@lift` to an array that is not an `Observable` to use the same code whether the array is an `Observable` or not.

Of course, the simplest workaround is to call my plotting function always with an `Observable` array even when producing a snapshot.

So, why does `@lift` work like that? Is there another function that I should use in place of `@lift` ?

---

<div class="post-metadata">

**Author:** ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)\
**Post date:** [April 7, 2026, 12:47pm UTC](https://discourse.julialang.org/t/makie-observable-lift-and-type/136597/2 "2026-04-07T12:47:01Z")

</div>

Yes, if passed a non-observable, `@lift` falls back to calling `map` (!!). I was also surprised by this, and made a Makie PR two years ago that was’t accepted.  
The `@lift` macro with the semantics you want is available in [MakieExtra.jl](https://discourse.julialang.org/t/ann-makieextra-jl-more-recipes-and-tools-for-makie-plots/118618):

```julia-auto
using MakieExtra

@lift ...

```

---

<div class="post-metadata">

**Author:** ![ryofurue](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ryofurue/32/24531_2.png) [@ryofurue](https://discourse.julialang.org/u/ryofurue)\
**Post date:** [April 7, 2026, 1:58pm UTC](https://discourse.julialang.org/t/makie-observable-lift-and-type/136597/3 "2026-04-07T13:58:35Z")

</div>

> [@aplavin](#):
>
> `@lift` falls back to calling `map`

!!! Is that right!

```julia-auto
bb = map(nooffs, oa)

```

So, I’m applying the `no_offset_view` function to each element of the `OffsetArray`!

This made me wonder, what about `lift` ? Then, I realized that `lift` is an alias to `map` . . .

I may be wrong but I guess this may be viewed as a missed opportunity because `lift` could be defined as

```julia-auto
lift(f, x::Observable) = map(f, x)
lift(f, x) = f(x) # non-Observable

```

---

<div class="post-metadata">

**Author:** ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)\
**Post date:** [April 7, 2026, 4:20pm UTC](https://discourse.julialang.org/t/makie-observable-lift-and-type/136597/4 "2026-04-07T16:20:01Z")

</div>

Yes, totally that!  
Handling non-observables consistently (as discussed above), and also supporting output type specification (like `@lift (...)::Int`) are the two key differences in MakieExtra’s `@lift` compared to Makie itself. Otherwise, the exact same semantics, drop-in replacement.  
See [generalize lift() and @lift() by aplavin · Pull Request #3915 · MakieOrg/Makie.jl · GitHub](https://github.com/MakieOrg/Makie.jl/pull/3915) PR for discussion history.
