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

Partially apply leading arguments #2607

Closed

Conversation

dnowak
Copy link
Contributor

@dnowak dnowak commented Dec 22, 2021

It is common in FP to define dependencies of a function as leading parameters and then partially apply those dependencies to get a function that meets some function type interface.

Currently, Arrow allows partially applying a single argument. So to apply several arguments the process has to be repeated:

val sendSms: SendSms = ::sendSms
        .partially1(generateCommandId)
        .partially1(generateMessageId)
        .partially1(getNow)
        .partially1(TopicName(SMS_COMMANDS_TOPIC))

Another way is to curry the function and then apply the arguments by calling the function chain. Unfortunately, it also does not look nice if you have to keep some line length limit:

val renderSmsTemplate: RenderSmsTemplate = ::renderTemplate.curried()(
        generateCommandId
)(
        generateMessageId
)(
        getNow
)(
        TopicName(TEMPLATE_COMMANDS_TOPIC)
)(
        TemplateId(templateId)
)

To solve the problem I propose to add extension functions that will allow applying several leading arguments at once. So the examples above would change to:

val renderSmsTemplate: RenderSmsTemplate = ::renderTemplate.partially(
                generateCommandId,
                generateMessageId,
                getNow,
                TopicName(TEMPLATE_COMMANDS_TOPIC),
                TemplateId(templateId),
        )

        val sendSms: SendSms = ::sendSms.partially(
                generateCommandId,
                generateMessageId,
                getNow,
                TopicName(SMS_COMMANDS_TOPIC),
        )

The only concern I have is that it means 253 * 2 new functions :-).

@serras
Copy link
Member

serras commented Dec 23, 2021

I don't think this is a bad idea, but I think it would be better to commit both a script which generates the code, and the result of the generation.

@nomisRev
Copy link
Member

I'm wondering if this should be solved with an FIR compiler plugin, because we can really not justify adding so many methods to Arrow. The current partial application, and function composition are already adding 1-2k methods and I would estimate it's one of the least used features in Arrow Core.

We originally even wanted to remove partial application for 1.x.x

A plugin could solve this problem completely without affecting the binary in any way, since it could just create anonymous lambdas for the partially applied functions, no?

@dnowak
Copy link
Contributor Author

dnowak commented Dec 23, 2021

A more generic solution is needed that does not introduce hundreds of methods.

@dnowak dnowak closed this Dec 23, 2021
@raulraja
Copy link
Member

A plugin similar to match types in Scala3 would allow us to write a single function that supports n arity if we can also have tuple <-> args auto conversions in the plugin.

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.

None yet

4 participants