# @take macro?

**URL:** <https://discourse.julialang.org/t/take-macro/114282>\
**Category:** General Usage\
**Tags:** channel\
**Created:** [May 15, 2024, 6:34am UTC](https://discourse.julialang.org/t/take-macro/114282 "2024-05-15T06:34:37Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![yakir12](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yakir12/32/297_2.png) [@yakir12](https://discourse.julialang.org/u/yakir12)\
**Post date:** [May 15, 2024, 6:34am UTC](https://discourse.julialang.org/t/take-macro/114282/1 "2024-05-15T06:34:37Z")

</div>

I’m using a `Channel` to keep a few instances of a struct that I need to use inside a thread (following the instructions in [Thread-Safe Storage · OhMyThreads.jl](https://juliafolds2.github.io/OhMyThreads.jl/stable/literate/tls/tls/#The-safe-way:-Channel)):

```julia
 using OhMyThreads
 
 nthings = 4
 const things = Channel{MyThing}(nthings)
 foreach(1:nthings) do _
     put!(things, MyThing()) 
 end
 
 tforeach(some_iter) do _
     thing = take!(things)
     results = thing(some_data)
     put!(things, thing)
 end

```

It strikes me that the pattern of `take!`ing something, using it, and then `put!`ing it back is very similar to the `@lock`, the `do` block in `open`, etc, where I don’t need to explicitly state that I’m unlocking, closing, or putting things back.

Do other people find this pattern common, and would people find it useful if we indeed had a macro or do-block for this specific use-case?

---

<div class="post-metadata">

**Author:** ![mikmoore](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mikmoore/32/31109_2.png) [@mikmoore](https://discourse.julialang.org/u/mikmoore)\
**Post date:** [May 15, 2024, 1:16pm UTC](https://discourse.julialang.org/t/take-macro/114282/2 "2024-05-15T13:16:52Z")

</div>

This doesn’t look like a job for a macro. A function should be plenty sufficient.

Whether or not something exists, it’s very easy to write this functionality yourself. (Or so I think – I never really work with `Channel` so don’t know whether I’m neglecting something important.)

```julia
function takeput!(fun, channel)
	x = take!(channel)
	y = try
		fun(x)
	finally
		put!(channel, x) # always return the value to the channel, even with an error
	end
	return y
end

```

The `try-finally` part could be replaced with straight code if you don’t need to ensure the value goes back on the channel after an exception.

You would write your `tforeach` as

```julia
tforeach(some_iter) do _
    results = takeput!(thing, things)
end

```

_EDIT: Oops, the code I wrote here swaps the role of the function and argument relative to the original prompt. The poster below fixes my mistake._

---

<div class="post-metadata">

**Author:** ![yakir12](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yakir12/32/297_2.png) [@yakir12](https://discourse.julialang.org/u/yakir12)\
**Post date:** [May 15, 2024, 1:51pm UTC](https://discourse.julialang.org/t/take-macro/114282/3 "2024-05-15T13:51:19Z")

</div>

> Whether or not something exists, it’s very easy to write this functionality yourself.

I agree. I should have put it differently:

Do other people find this pattern common, and would people find it useful if we indeed had a macro or do-block for this specific use-case (I will edit the original post)?

Drawing inspiration from your example, and looking in Base at how the `open` do-block looks like, resulted in this:

```julia
function borrow(f::Function, c::Channel)
    v = take!(c)
    try
        return f(v)
    finally
        put!(c, v)
    end
end

```

Which allows us to do things like:

```julia
results = borrow(channel) do thing
    thing(some_data)
end

```
