@@ -157,66 +157,8 @@ macro algdef(name)
157157 end )
158158end
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!))
307306end
308307
309308"""
0 commit comments