-
-
Notifications
You must be signed in to change notification settings - Fork 80
Support function return types in longdef/shortdef #35
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
The way I use these functions, I just want to transform an expression, not code-walk over the entire tree. Would you mind if I factored out the |
Looks good, thanks! It would probably make sense to have |
I tried - still problematic. Let's leave it as is. |
Added |
src/utils.jl
Outdated
push!(positional_args, x) | ||
end | ||
end | ||
return (positional_args, kwargs) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this can be simplified a bit; :parameters
will only be in the first slot, if at all. This should probably also handle expressions of the form f(a, b = c)
correctly.
src/utils.jl
Outdated
return (positional_args, kwargs) | ||
end | ||
|
||
""" parsedef(fdef) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about splitdef
?
src/utils.jl
Outdated
end | ||
``` | ||
|
||
and returns `(fname::Symbol, args::Vector{Any}, kwargs::Vector{Any}, body_block::Expr, return_type)`. `return_type` is `:Any` if not specified. """ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This tuple is a bit long, I suggest a dict instead. It makes sense for certain keys to not be present if they're not written.
src/utils.jl
Outdated
function parsedef(fdef) | ||
@match longdef1(fdef) begin | ||
(function fname_(args__) body_ end => | ||
(fname, split_kwargs(args)..., body, :Any)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would make sense to use nothing
here to differentiate from Any
being explicitly written (or just leave out the key).
src/utils.jl
Outdated
default = Nullable(arg_expr.args[2]) | ||
arg_expr = arg_expr.args[1] | ||
else | ||
default = Nullable() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using nothing
would amount to the same here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But then we couldn't recognize f(x=nothing)
from f(x)
, no? Maybe we could return a special NoVal()
object instead? Nullables are cumbersome.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In f(x=nothing)
, :nothing
would be a symbol, so that wouldn't be an issue. You could technically write f(x=$nothing)
and break it though, so maybe nullable is the right route.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can error in the f(x=$nothing)
case. It seems fair enough for a marginal situation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That seems reasonable enough to me.
src/utils.jl
Outdated
end | ||
end | ||
if !(@capture(arg_expr, name_::typ_)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you could simplify this as something like @capture(ex, x_::T_ = default_ | x_::T_ | x_)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool, but then how can I distinguish no default
from default
being $nothing
(and trigger the error I proposed above)?
Yeah this is looking like a really useful set of functionality! Sorry for the late review but hopefully you can take a look at those couple of things and this should be good to go. |
Thank you for the comments, I'll do the necessary changes. My main use case for this functionality is to augment a function definition somehow, eg. fname, args, kwargs, body_block, return_type = parsedef(fdef)
quote
function $fname($(args...); $(kwargs...))::$return_type
$body_block
end
end
It would be annoying to have to write How about returning an object? It'll be shorter to type than a Dict. immutable FunctionDefinition
name
args
kwargs
body_block
return_type
end |
You could return |
Updated. Thank you for all the suggestions, it looks better now. |
ba86652
to
ed199a6
Compare
Any chance that we could revisit this? I've got three packages that rely on half-broken versions of this code... I added support for |
I need a permanent home for this code, so unless I get some news from you, I'll create a new package in the next few days. |
🎉 Thanks! My nemesis package, ExprTools.jl was ready to go and passed CI, but thankfully not registered yet. I've made some improvements that aren't part of this PR. I'll make a new one today-ish, then we can tag? |
👍 |
I also have a function that uses MacroTools to parse any function definition and return
(name, arg, kwargs, body, return_type)
. Would that be accepted?