[swift-evolution] [Pitch] Introduce user-defined dynamically "callable" types

Slava Pestov spestov at apple.com
Fri Nov 10 19:51:01 CST 2017


Hi Chris,

> On Nov 10, 2017, at 9:37 AM, Chris Lattner via swift-evolution <swift-evolution at swift.org> wrote:
> 
> Hello all,
> 
> I have a couple of proposals cooking in a quest to make Swift interoperate with dynamically typed languages like Python better.  Instead of baking in hard coded support for one language or the other, I’m preferring to add a few small but general purpose capabilities to Swift.  This is the first, which allows a Swift type to become “callable”.

I’m generally in favor of adding new features if they simplify the language model or subsume existing special cases, either moving them into the standard library or simplifying their implementation. However this proposal looks like a strictly additive feature, which introduces yet another kind of callable thing. We already have:

- Statically dispatched functions
- VTable-dispatched class methods
- Witness table dispatched protocol methods
- ObjC methods
- Dynamic method dispatch on AnyObject
- Enum case constructors
- Curried functions and various thunks, etc

I don’t see the new dynamic callable you are proposing replacing or generalizing any of the above, it will simply be a whole new code path.

This all comes at a great cost. If you look at the implementation of calls in lib/SILGen/SILGenApply.cpp you will see there is a great deal of complexity there to deal with all the different special cases. The type checker also has a lot of complexity related to method calls and member accesses.

I would be against adding yet another new type of call to the language at this point. Even if the implementation is relatively small it is yet another special case we have to maintain forever.

> Swift is well known for being exceptional at interworking with existing C and Objective-C APIs, but its support for calling APIs written in scripting langauges like Python, Perl, and Ruby is quite lacking. These languages provide an extremely dynamic programming model where almost everything is discovered at runtime.

Most other statically compiled languages don’t attempt to solve this problem of interoperating with Python and Ruby either. I’m not sure this is a feature users expect or one that should be prioritized, given all the other work that remains in the implementation that will actually improve the day to day experience of developers.

> We propose introducing this protocol to the standard library:
> 
> protocol DynamicCallable {
>   associatedtype DynamicCallableArgument
>   associatedtype DynamicCallableResult
> 
>   func dynamicCall(arguments: [(String, DynamicCallableArgument)]) throws -> DynamicCallableResult
> }
This is not really very general at all, because it assumes all arguments have the same type, along with all results. Why would arguments and results have different types if they’re type erased anyway? And why are string keyword names privileged in any way? What about varargs, inout parameters and other Swift-specific modifiers on calls?


> Before this proposal, the Swift language has two types that participate in call syntax: functions and metatypes (for initialization). Neither of those may conform to protocols at the moment, so this introduces no possible ambiguity into the language.
> 
> 

However, it rules out a possible type checker optimization — currently we can assume that if a type variable is the subject of both a conformance constraint and an apply constraint, the constraint system is invalid. With your change we could not make this assumption anymore.

> It is worth noting that this does not introduce the ability to provide dynamicly callable static/class members. We don't believe that this is important given the goal of supporting dynamic languages like Python, but if there is a usecase discovered in the future, it could be explored as future work. Such future work should keep in mind that call syntax on metatypes is already meaningful, and that ambiguity would have to be resolved somehow.
> 
> 

This is the problem with this proposal — it solves a very narrow use case, but it introduces a piece of ABI that we have to maintain forever. When future generalizations are discovered, we will have to add yet another mechanism, complicating the language model further.
>  <https://gist.github.com/lattner/a6257f425f55fe39fd6ac7a2354d693d#discussion>
> Effect on ABI stability
> 
> This is a strictly additive proposal with no ABI breaking changes.
> 
> 

However, it adds *new* ABI which we will have to maintain forever.

A strong -1 from me here.

Slava

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20171110/293df608/attachment.html>


More information about the swift-evolution mailing list