Skip to content
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

Support unprotected mode for specials with FullRank schemas as well #274

Merged
merged 7 commits into from
Mar 13, 2023

Conversation

kleinschmidt
Copy link
Member

This is a follow-up to #183 which extends @support_unprotect to provide support for arbitrary schema types, and uses that to generate support for specials (+, &, *, and ~) for both Schema and FullRank.

This is necessary to support cases like mixed models where we do things like (taking some liberties here with the actual method signature)

apply_schema(t::FunctionTerm{typeof(|)}, sch::FullRank, mod::Type{<:MixedModel})
    ...
    lhs, rhs = t.args
    lhs = apply_schema(lhs, sch, mod)
    ...
end

lhs may be 1, or 1 + x, or even log(x), so we can't blindly "lift" functionterms on the lhs (e.g., do something like lhs = lhs isa FunctionTerm ? lhs.f(lhs.args...) : lhs) because that would mangle log(x).

@nalimilan
Copy link
Member

Would it make sense to introduce an AbstractSchema supertype instead?

@kleinschmidt
Copy link
Member Author

Would it make sense to introduce an AbstractSchema supertype instead?

I actually first tried doing Union{Schema,FullRank}. Unfortunately, that leads to (you guessed it!) method ambiguities, because there are methods for ::FunctionTerm, ::Schema, ::Type and many more/less specific combinations. AbstractSchema would have the same problem I'm afraid :-/

@nalimilan
Copy link
Member

Too bad. Then would it make sense to have @support_unprotect define methods for both Schema and FullRank by default?

@kleinschmidt
Copy link
Member Author

Too bad. Then would it make sense to have @support_unprotect define methods for both Schema and FullRank by default?

yueah that's actually not a bad idea. it gets a bit tricky to write the macro that way though...maybe with a varargs it woudl be okay...let me play around a bit

@nalimilan
Copy link
Member

Looks good. Can you add tests?

src/schema.jl Outdated Show resolved Hide resolved
@kleinschmidt
Copy link
Member Author

okay, another thing that's turned up in doing the MixedModels upgrade is that it would be very, very handy to have methods like unprotect(t::FunctionTerm{+}) = t.f(t.args...). This macro would be a good place to define that EXCEPT that you then would get "method overwritten" errors if invoked later (to add support for another schema type for instance), soooo I dunno.

@kleinschmidt
Copy link
Member Author

(for the time being I think it's fine to vendor this in MixedModels as _unprotect or something; if it becomes necessary elsewhere we can upstream it here)

Co-authored-by: Milan Bouchet-Valat <[email protected]>
@palday
Copy link
Member

palday commented Feb 4, 2023

(for the time being I think it's fine to vendor this in MixedModels as _unprotect or something; if it becomes necessary elsewhere we can upstream it here)

I'm okay with that --- MixedModels also has the whole MultiSchema stuff.

@kleinschmidt
Copy link
Member Author

@nalimilan I've added tests (and fixed a very obvious bug that the tests caught, so thank you for that suggestion 😁 )

test/protect.jl Outdated
Comment on lines 24 to 28
function ft(f)
return function(args...)
return FunctionTerm(f, args, :($f($(args...))))
end
end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not define this simply as:

Suggested change
function ft(f)
return function(args...)
return FunctionTerm(f, args, :($f($(args...))))
end
end
ft(f, args...) = FunctionTerm(f, args, :($f($(args...))))

and call it as ft(op, a, b) instead of ft(op)(a, b)?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah that works too! I think the version here was inspired by the "lift" model of "passmissing" and friends. But for tests I'm kind of indifferent.

@kleinschmidt
Copy link
Member Author

@nalimilan I updated teh tests based on your suggestion, read for re-review.

@kleinschmidt kleinschmidt requested a review from nalimilan March 5, 2023 02:17
@kleinschmidt kleinschmidt merged commit 2bdb68f into master Mar 13, 2023
@kleinschmidt kleinschmidt deleted the dfk/support_unprotect branch March 13, 2023 14:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants