# Defining custom brackets for custom objects

**URL:** <https://discourse.julialang.org/t/defining-custom-brackets-for-custom-objects/49273>\
**Category:** General Usage\
**Created:** [October 29, 2020, 11:39pm UTC](https://discourse.julialang.org/t/defining-custom-brackets-for-custom-objects/49273 "2020-10-29T23:39:43Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![giancarloantonucci](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/giancarloantonucci/32/202551_2.png) [@giancarloantonucci](https://discourse.julialang.org/u/giancarloantonucci)\
**Post date:** [October 29, 2020, 11:39pm UTC](https://discourse.julialang.org/t/defining-custom-brackets-for-custom-objects/49273/1 "2020-10-29T23:39:43Z")

</div>

Is it possible to define a method/function/macro/etc so that I can use `⟦⟧` to index a custom vector/struct? I’m looking for some kind of trick that would allow me to do something like the following:

```julia
struct MyVec
    data
    block_size
end

v = MyVec([1 2 3 4 5 6 7 8 9 10], 2)

...what I need...

i = 1
v⟦i⟧ = [5 5] # == v[(i-1)*v.block_size+1:i*v.block_size] = [5 5]

v.data == [5 5 3 4 5 6 7 8 9 10]
>> true

```

---

<div class="post-metadata">

**Author:** ![tomerarnon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tomerarnon/32/3170_2.png) [@tomerarnon](https://discourse.julialang.org/u/tomerarnon)\
**Post date:** [October 30, 2020, 12:04am UTC](https://discourse.julialang.org/t/defining-custom-brackets-for-custom-objects/49273/2 "2020-10-30T00:04:51Z")

</div>

Are you asking because you also need regular indexing to work alongside this? If not, you can simply overload `Base.getindex` and `Base.setindex!` to define whatever indexing behavior you want for your struct.  
Using custom symbols as brackets isn’t possible though, and it turns out that those particular symbols can’t be used at all…

```julia
julia> ⟧ = 1
ERROR: syntax: invalid character "⟧" near column 1

```

---

<div class="post-metadata">

**Author:** ![giancarloantonucci](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/giancarloantonucci/32/202551_2.png) [@giancarloantonucci](https://discourse.julialang.org/u/giancarloantonucci)\
**Post date:** [October 30, 2020, 12:11am UTC](https://discourse.julialang.org/t/defining-custom-brackets-for-custom-objects/49273/3 "2020-10-30T00:11:28Z")

</div>

> [@tomerarnon](#):
>
> Are you asking because you also need regular indexing to work alongside this?

Exactly.

> [@tomerarnon](#):
>
> Using custom symbols as brackets isn’t possible though

I see. I got suspicious because at [https://github.com/JuliaLang/julia/issues/8934](https://github.com/JuliaLang/julia/issues/8934) one user replied: “I’d prefer to leave them free for packages to use.”

What if I use `{}` instead of custom symbols? Would that be possible?

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [October 30, 2020, 12:42am UTC](https://discourse.julialang.org/t/defining-custom-brackets-for-custom-objects/49273/4 "2020-10-30T00:42:57Z")

</div>

Yeah, this can be done with a macro if you really want:

```julia
using MacroTools: postwalk, @capture

macro foo(expr)
    (esc ∘ postwalk)(expr) do ex
        if @capture(ex, v_{i_})
            ex = :($v.data[($i-1)*$v.block_size+1:$i*$v.block_size])
        end
        ex
    end
end

struct MyVec
    data
    block_size
end

v = MyVec([1 2 3 4 5 6 7 8 9 10], 2)

i = 1

```

Now at the repl:

```julia
julia> @foo v{i} = [5 5]
1×2 Array{Int64,2}:
 5 5

julia> v
MyVec([5 5 … 9 10], 2)

```

If you wanna use delimiters like `⟧`, you’d have to use a string macro to pre-process before building up an AST and manipulating it.

---

<div class="post-metadata">

**Author:** ![giancarloantonucci](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/giancarloantonucci/32/202551_2.png) [@giancarloantonucci](https://discourse.julialang.org/u/giancarloantonucci)\
**Post date:** [October 30, 2020, 12:46am UTC](https://discourse.julialang.org/t/defining-custom-brackets-for-custom-objects/49273/5 "2020-10-30T00:46:27Z")

</div>

Amazing!

Just out of curiosity, could it be done without macros?

---

<div class="post-metadata">

**Author:** ![CameronBieganek](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cameronbieganek/32/6915_2.png) [@CameronBieganek](https://discourse.julialang.org/u/CameronBieganek)\
**Post date:** [October 30, 2020, 12:54am UTC](https://discourse.julialang.org/t/defining-custom-brackets-for-custom-objects/49273/6 "2020-10-30T00:54:51Z")

</div>

Here’s what you can do. Make your custom vector [callable](https://docs.julialang.org/en/v1/manual/methods/#Function-like-objects). Then you effectively have two different ways to index your vector:

```julia
v[1]
v(1)

```

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [October 30, 2020, 12:55am UTC](https://discourse.julialang.org/t/defining-custom-brackets-for-custom-objects/49273/7 "2020-10-30T00:55:36Z")

</div>

No, `{}` is not a valid indexing delimiter in julia, but it parses like one specifically so they can be used in macros. We can lessen the amount of logic that’s in the macro though and offload the work to a special `mygetindex` function:

```julia
using MacroTools: prewalk, @capture
macro foo(expr)
    (esc ∘ prewalk)(expr) do ex
        if @capture(ex, (v_{i__} = x_))
            :($mysetindex!($v, $x, $(i...)))
        else
            ex
        end
    end
end

mysetindex!(v::MyVec, x, i) = v.data[(i-1)*v.block_size+1:i*v.block_size] = x

```

```julia
julia> @foo begin
           v = MyVec([1 2 3 4 5 6 7 8 9 10], 2)
           i = 1
           v{i} = [5 5]
           v.data
       end
1×10 Array{Int64,2}:
 5 5 3 4 5 6 7 8 9 10

```

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [October 30, 2020, 1:05am UTC](https://discourse.julialang.org/t/defining-custom-brackets-for-custom-objects/49273/8 "2020-10-30T01:05:52Z")

</div>

Here’s an example of the sort of pre-processing you can do in a string macro and then do regular AST manipulation:

```julia
macro foo_str(s)
    s′ = foldl(replace, ('⟦' => '{', '⟧' => '}'), init=s)
    ex = esc(Meta.parse(s′))
    :(@foo $ex)
end

```

```julia
julia> foo"""
       begin
           v = MyVec([1 2 3 4 5 6 7 8 9 10], 2)
           i = 1
           v⟦i⟧ = [5 5]
           v.data
       end
       """
1×10 Array{Int64,2}:
 5 5 3 4 5 6 7 8 9 10

```

---

<div class="post-metadata">

**Author:** ![giancarloantonucci](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/giancarloantonucci/32/202551_2.png) [@giancarloantonucci](https://discourse.julialang.org/u/giancarloantonucci)\
**Post date:** [October 30, 2020, 1:18am UTC](https://discourse.julialang.org/t/defining-custom-brackets-for-custom-objects/49273/9 "2020-10-30T01:18:26Z")

</div>

Thanks everyone. All these answers are very useful.
