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

improved function partial application design #56518

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

nsajko
Copy link
Contributor

@nsajko nsajko commented Nov 10, 2024

This replaces Fix (xref #54653) with fix. The usage is similar: use fix(i)(f, x) instead of Fix{i}(f, x).

Benefits:

  • Improved type safety: creating an invalid type such as Fix{:some_symbol} or Fix{-7} is not possible.
  • The design should be friendlier to future extensions. E.g., suppose that publicly-facing functionality for fixing a keyword (instead of positional) argument was desired, it could be achieved by adding a new method to fix taking a Symbol, instead of adding new public names.

Lots of changes are shared with PR #56425, if one of them gets merged the other will be greatly simplified.

@nsajko nsajko added design Design of APIs or of the language itself feature Indicates new feature / enhancement requests labels Nov 10, 2024
@nsajko nsajko force-pushed the partial_application branch 3 times, most recently from 3549ca3 to 0ea9693 Compare November 10, 2024 19:46
@adienes
Copy link
Contributor

adienes commented Nov 10, 2024

look, I'm not trying to be the bad guy on all your PRs. but I feel like you are misrepresenting the status quo

Improved type safety: creating an invalid type such as Fix{:some_symbol} or Fix{-7} is not possible.

this is already not possible with Fix. the constructor will throw an error as implemented in this block

        if !(N isa Int)
            throw(ArgumentError(LazyString("expected type parameter in `Fix` to be `Int`, but got `", N, "::", typeof(N), "`")))
        elseif N < 1
            throw(ArgumentError(LazyString("expected `N` in `Fix{N}` to be integer greater than 0, but got ", N)))
        end

@nsajko
Copy link
Contributor Author

nsajko commented Nov 10, 2024

I'm not misrepresenting anything, this is the (embarrassing) behavior on master:

julia> Base.Fix{-1}
Base.Fix{-1}

@adienes
Copy link
Contributor

adienes commented Nov 10, 2024

try constructing it?

@nsajko
Copy link
Contributor Author

nsajko commented Nov 10, 2024

Could you please take your off-topic chatting to Discourse or wherever?

@adienes
Copy link
Contributor

adienes commented Nov 10, 2024

it was a direct and objective refute to one of the primary motivations you provided in the commit message. it feels pretty on topic to me.

that being said, you clearly don't want my input, so I'll stop providing it (as, I suspect, will everyone else)

This replaces `Fix` (xref JuliaLang#54653) with `fix`. The usage is similar: use
`fix(i)(f, x)` instead of `Fix{i}(f, x)`.

Benefits:
* Improved type safety: creating an invalid type such as
  `Fix{:some_symbol}` or `Fix{-7}` is not possible.
* The design should be friendlier to future extensions. E.g., suppose
  that publicly-facing functionality for fixing a keyword (instead of
  positional) argument was desired, it could be achieved by adding a
  new method to `fix` taking a `Symbol`, instead of adding new public
  names.

Lots of changes are shared with PR JuliaLang#56425, if one of them gets merged
the other will be greatly simplified.
@KristofferC
Copy link
Member

Why does every PR now try to push in this "typed domain numbers" package into Base..?

As has been said regarding

Improved type safety: creating an invalid type such as Fix{:some_symbol} or Fix{-7} is not possible.

julia> Base.Fix{1}(*, "1")
(::Base.Fix1{typeof(*), String}) (generic function with 2 methods)

julia> Base.Fix{-1}(*, "1")
ERROR: ArgumentError: expected `N` in `Fix{N}` to be integer greater than 0, but got -1
Stacktrace:
 [1] (Base.Fix{-1})(f::typeof(*), x::String)
   @ Base ./operators.jl:1181
 [2] top-level scope
   @ REPL[10]:1

julia> Base.Fix{:some_symbol}(*, "1")
ERROR: ArgumentError: expected type parameter in `Fix` to be `Int`, but got `some_symbol::Symbol`
Stacktrace:
 [1] (Base.Fix{:some_symbol})(f::typeof(*), x::String)
   @ Base ./operators.jl:1179
 [2] top-level scope
   @ REPL[11]:1

so it is unclear what is being improved here.

I don't really understand what the other benefit means.

@martinholters
Copy link
Member

From what I can tell, this PR comprises three changes that are related, but could be considered independently:

  1. Introduce a function fix that creates the required type to wrap the function and fixed argument.
  2. Rename that type from Fix to PartiallyAppliedFunction.
  3. Change the N type parameter from an integer to a type-domain integer.

I agree that 1. might make future extensions to e.g. fixing keyword arguments more seamless, but could just be introduced when the time is ripe. If we expect the type to change in the future, this function might give the needed indirection to make that less breaking, but that is quite speculative.
I like 2., but it's clearly a matter of taste, and I'm not sure it's worth the trouble renaming now.
I see no benefit in 3.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
design Design of APIs or of the language itself feature Indicates new feature / enhancement requests
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants