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 for default values in Request #31

Open
PangMo5 opened this issue Nov 10, 2023 · 2 comments
Open

Support for default values in Request #31

PangMo5 opened this issue Nov 10, 2023 · 2 comments
Labels
currently not possible Not possible because of Swift / macro limitations enhancement New feature or request

Comments

@PangMo5
Copy link

PangMo5 commented Nov 10, 2023

Hi, first of all, thanks for writing such a nice macros.

There was one thing that I found disappointing.
The Swift syntax does not allow you to set default values for parameters in protocol functions.
If it's a normal protocol function, you can set the default value of the function parameter through an extension, but since it's a macro, it doesn't seem possible.

I don't know much about macros, but here's what I can think of.

@API
protocol Users {
  @GET("/users")
  func getList(size: Int = 20, cursor: String?) async throws -> [User]

  @POST("/user")
  func createUser(email: String, password: String, nickname: String? = nil) async throws
}

If it is possible to have an implementation that violates Swift syntax like the one above with just a macros, then the above seems to be the most convenient and reasonable.

@API
protocol Users {
  @GET("/users")
  func getList(@Default(20) size: Int, cursor: String?) async throws -> [User]

  @POST("/user")
  func createUser(email: String, password: String, @Default(nil) nickname: String?) async throws
}

Looking at the comments in the code and the post at, it seems that this is probably not possible at the moment, as there is no macros specification. If a spec is added in the future, this would be fine.

In addition to this, if there is a way to do this in the current implementation without a new one, I'd to hear about it!

@joshuawright11
Copy link
Owner

joshuawright11 commented Nov 11, 2023

Thanks for suggestion @PangMo5 - I'd definitely love if we could support this!

At one point I actually had the @Default functionality as you suggested but unfortunately we lost the ability to do that in the Xcode 15 Beta update that post you linked is about.

Also unfortunately, Swift doesn't support either default arguments (your first example) or property wrappers (potential other implementation) in protocol definitions yet. I don't believe there is another way to do it, otherwise I'd be very open to it. If you have any ideas of how this could be accomplished let me know!

For now, however, you can achieve the desired effect using (albeit verbose) extensions.

@API
protocol Users {
  @GET("/users")
  func getList(size: Int, cursor: String?) async throws -> [User]

  @POST("/user")
  func createUser(email: String, password: String, nickname: String?) async throws
}

// note that the @GET / other macros aren't needed in the extension.
extension Users {
    func getList(size: Int = 20, cursor: String?) async throws -> [User] {
        try await getList(size: size, cursor: cursor)
    }

    func createUser(email: String, password: String, nickname: String? = nil) async throws {
        try await createUser(email: email, password: password, nickname: nickname)
    }
}

Again - this is pretty verbose and I think your first example is the ideal solution, but default arguments aren't currently allowed in protocols.

@joshuawright11 joshuawright11 added enhancement New feature or request currently not possible Not possible because of Swift / macro limitations labels Dec 14, 2023
@ypotsiah
Copy link

@joshuawright11 ,
Is it possible to generate such Users extension by something like that?

@API
protocol Users {
  @GET("/users", defaults: ["size": 20])
  func getList(size: Int, cursor: String?) async throws -> [User]

  @POST("/user", defaults: ["nickname": nil])
  func createUser(email: String, password: String, nickname: String?) async throws
}

Looks not very type safe but probably we can match keys from defaults with endpoint's ages and verify values with appropriate types as well (and throw error if needed).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
currently not possible Not possible because of Swift / macro limitations enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants