Skip to content

Commit fa31433

Browse files
author
Katharine Hyatt
committed
Split up the functiondef macro
1 parent 0e2baf8 commit fa31433

File tree

1 file changed

+64
-65
lines changed

1 file changed

+64
-65
lines changed

src/algorithms.jl

Lines changed: 64 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -157,66 +157,8 @@ macro algdef(name)
157157
end)
158158
end
159159

160-
"""
161-
@functiondef [n_args=1] f
162-
163-
Convenience macro to define the boilerplate code that dispatches between several versions of `f` and `f!`.
164-
By default, `f` accepts a single argument `A`. This enables the following signatures to be defined in terms of
165-
the final `f!(A, out, alg::Algorithm)`.
166-
167-
```julia
168-
f(A; kwargs...)
169-
f(A, alg::Algorithm)
170-
f!(A, [out]; kwargs...)
171-
f!(A, alg::Algorithm)
172-
```
173-
174-
The number of inputs can be set with the `n_args` keyword
175-
argument, so that
176-
177-
```julia
178-
@functiondef n_args=2 f
179-
```
180-
181-
would create
182-
183-
```julia
184-
f(A, B; kwargs...)
185-
f(A, B, alg::Algorithm)
186-
f!(A, B, [out]; kwargs...)
187-
f!(A, B, alg::Algorithm)
188-
```
189-
190-
See also [`copy_input`](@ref), [`select_algorithm`](@ref) and [`initialize_output`](@ref).
191-
"""
192-
macro functiondef(args...)
193-
kwargs = map(args[1:end-1]) do kwarg
194-
if kwarg isa Symbol
195-
:($kwarg = $kwarg)
196-
elseif Meta.isexpr(kwarg, :(=))
197-
kwarg
198-
else
199-
throw(ArgumentError("Invalid keyword argument '$kwarg'"))
200-
end
201-
end
202-
isempty(kwargs) || length(kwargs) == 1 || throw(ArgumentError("Only one keyword argument to `@functiondef` is supported"))
203-
f_n_args = 1 # default
204-
if length(kwargs) == 1
205-
kwarg = only(kwargs) # only one kwarg is currently supported, TODO modify if we support more
206-
key::Symbol, val = kwarg.args
207-
key === :n_args || throw(ArgumentError("Unsupported keyword argument $key to `@functiondef`"))
208-
(isa(val, Integer) && val > 0) || throw(ArgumentError("`n_args` keyword argument to `@functiondef` should be an integer > 0"))
209-
f_n_args = val
210-
end
211-
212-
f = args[end]
213-
f isa Symbol || throw(ArgumentError("Unsupported usage of `@functiondef`"))
214-
f! = Symbol(f, :!)
215-
216-
# TODO is the right way?
217-
@gensym A B
218-
ex_single_arg = quote
219-
# out of place to inplace
160+
function _arg_expr(::Val{1}, f, f!)
161+
return quote # out of place to inplace
220162
$f(A; kwargs...) = $f!(copy_input($f, A); kwargs...)
221163
$f(A, alg::AbstractAlgorithm) = $f!(copy_input($f, A), alg)
222164

@@ -257,7 +199,10 @@ macro functiondef(args...)
257199
# copy documentation to both functions
258200
Core.@__doc__ $f, $f!
259201
end
260-
ex_double_arg = quote
202+
end
203+
204+
function _arg_expr(::Val{2}, f, f!)
205+
return quote
261206
# out of place to inplace
262207
$f(A, B; kwargs...) = $f!(copy_input($f, A, B)...; kwargs...)
263208
$f(A, B, alg::AbstractAlgorithm) = $f!(copy_input($f, A, B)..., alg)
@@ -299,11 +244,65 @@ macro functiondef(args...)
299244
# copy documentation to both functions
300245
Core.@__doc__ $f, $f!
301246
end
302-
if f_n_args == 1
303-
return esc(ex_single_arg)
304-
elseif f_n_args == 2
305-
return esc(ex_double_arg)
247+
end
248+
249+
"""
250+
@functiondef [n_args=1] f
251+
252+
Convenience macro to define the boilerplate code that dispatches between several versions of `f` and `f!`.
253+
By default, `f` accepts a single argument `A`. This enables the following signatures to be defined in terms of
254+
the final `f!(A, out, alg::Algorithm)`.
255+
256+
```julia
257+
f(A; kwargs...)
258+
f(A, alg::Algorithm)
259+
f!(A, [out]; kwargs...)
260+
f!(A, alg::Algorithm)
261+
```
262+
263+
The number of inputs can be set with the `n_args` keyword
264+
argument, so that
265+
266+
```julia
267+
@functiondef n_args=2 f
268+
```
269+
270+
would create
271+
272+
```julia
273+
f(A, B; kwargs...)
274+
f(A, B, alg::Algorithm)
275+
f!(A, B, [out]; kwargs...)
276+
f!(A, B, alg::Algorithm)
277+
```
278+
279+
See also [`copy_input`](@ref), [`select_algorithm`](@ref) and [`initialize_output`](@ref).
280+
"""
281+
macro functiondef(args...)
282+
kwargs = map(args[1:end-1]) do kwarg
283+
if kwarg isa Symbol
284+
:($kwarg = $kwarg)
285+
elseif Meta.isexpr(kwarg, :(=))
286+
kwarg
287+
else
288+
throw(ArgumentError("Invalid keyword argument '$kwarg'"))
289+
end
290+
end
291+
isempty(kwargs) || length(kwargs) == 1 || throw(ArgumentError("Only one keyword argument to `@functiondef` is supported"))
292+
f_n_args = 1 # default
293+
if length(kwargs) == 1
294+
kwarg = only(kwargs) # only one kwarg is currently supported, TODO modify if we support more
295+
key::Symbol, val = kwarg.args
296+
key === :n_args || throw(ArgumentError("Unsupported keyword argument $key to `@functiondef`"))
297+
(isa(val, Integer) && val > 0) || throw(ArgumentError("`n_args` keyword argument to `@functiondef` should be an integer > 0"))
298+
f_n_args = val
306299
end
300+
301+
f = args[end]
302+
f isa Symbol || throw(ArgumentError("Unsupported usage of `@functiondef`"))
303+
f! = Symbol(f, :!)
304+
305+
return esc(_arg_expr(Val(f_n_args), f, f!))
307306
end
308307

309308
"""

0 commit comments

Comments
 (0)