← Back to context

Comment by mrkaye97

2 hours ago

As a bit of a counterpoint, I help maintain SDKs for Hatchet in multiple languages (largely Python and TS, but also contribute to Go a bit too) that benefit heavily from generics. It's especially useful for things where users of the SDK provide e.g. return types from functions they register, and we want those to be strongly-typed elsewhere in the codebase. A simple Python example is:

  @hatchet.task()
  async def my_task(...) -> SomeOutputType:
    return SomeOutputType(...)

  ## imagine this is an API handler:
  @api_handler("/some/path")
  async def handle() -> ...:
    result = await my_task.run(...)

    # we now know `result` is of type `SomeOutputType` without any sort of type assertion, etc.

Admittedly, I'm not a Go expert, nor am I a programming languages expert. But I do feel that this type of behavior is really only possible (with nice ergonomics) with generics, and it's always been upsetting to me that somehow Python's type system feels more complete than Go's in this arena, or at least it has until more recently.

Maybe this falls into the 1% of cases, but I'd suspect this sort of thing is more common than that.

Edit: I should have mentioned - in the Python example above, `@hatchet.task` is generic with the output type of the task it wraps.

And I'm not a python expert, so I might be wrong here, but:

My understanding is that this decorator generates some class in the background that wraps the function into some remotely executable container thing, and handles the networking?

Since python is a dynamic language, and go is not, this would be impossible without codegen, generics or not, but go does have codegen facilities.

And the more immediate implication, that many OOP languages do (and seems to be going on in here) is that they handle asynchrony via some generic Awaitable[T] pattern.

Go does not do this, generally the way you handle asynchrony and abstract typed results is by using channels. You don't await on 'smart' objects, you read from channels (which are 'generic' in a way, but they are the few exceptions where go used to allow this behavior).