To Chris’s use case point, I see Python -> Swift interop as a very common use case in data science / ML for speeding up certain functions/modules by embedding Swift into Python, like you can with, say, ctypes or python extensions in dynamic C libraries. This is very common practice in the Python universe, it just could be a lot better with Swift instead.
Things like this *sort of* exist with Swift (https://gist.github.com/jiaaro/e111f0f64d0cdb8aca38 <https://gist.github.com/jiaaro/e111f0f64d0cdb8aca38>), but it’s not really very mature or functional. I would LOVE to be able to speed up a lot of python code by implementing swift libraries and importing into python. - David > On Oct 30, 2017, at 13:25, Douglas Gregor via swift-evolution > <swift-evolution@swift.org> wrote: > > > >> On Oct 29, 2017, at 1:34 PM, Chris Lattner via swift-evolution >> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote: >> >>> >>> On Oct 29, 2017, at 8:23 AM, Chris Lattner via swift-evolution >>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote: >>> >>> >>>> On Oct 29, 2017, at 4:04 AM, Lukas Stabe <lu...@stabe.de >>>> <mailto:lu...@stabe.de>> wrote: >>>> >>>>> On 28. Oct 2017, at 23:10, Chris Lattner via swift-evolution >>>>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote: >>>>> >>>>> … which is to say, exactly identical to the Python version except that >>>>> new variables need to be declared with let/var. This can be done by >>>>> blessing Python.Object (which is identical to “PyObject*” at the machine >>>>> level) with some special dynamic name lookup behavior: Dot syntax turns >>>>> into a call to PyObject_GetAttrString, subscripts turn into >>>>> PyObject_GetItem, calls turn into PyObject_Call, etc. ARC would be >>>>> implemented with INCREF etc. >>>> >>>> That sounds like a very interesting prospect. Do you think it would make >>>> sense to make the language features that facilitate this (dynamic dispatch >>>> of method calls, property accesses, subscript and ARC) available to Swift >>>> classes annotated in some way, so that interop like this can be >>>> implemented as a library without special treatment by the Swift compiler? >>>> This could also enable more dynamic DSL like features. >>> >>> I haven’t explored enough of the design space to be sure, but I’d want to >>> make sure that a library version of this could be done without giving up >>> ergonomics of the result. If you were interested in being able to interop >>> with other languages that are dynamically typed and reference counted, then >>> something like this could be possible in principle: >> >> Thinking about the Perl case makes it clear to me that this should not be >> built into the compiler as a monolithic thing. Perl supports several >> different types (SV/AV/HV) which represent different concepts (scalars, >> arrays, hashes) so baking it all together into one thing would be the wrong >> way to map it. In fact, the magic we need is pretty small, and seems >> generally useful for other things. Consider a design like this: >> >> >> // not magic, things like Int, String and many other conform to this. >> protocol Pythonable { >> init?(_ : PythonObject) >> func toPython() -> PythonObject >> } > > It’s not magic unless you expect the compiler or runtime to help with > conversion between Int/String/etc. and PythonObject, as with > _ObjectiveCBridgeable. > >> >> // Not magic. >> struct PythonObject : /*protocols below*/ { >> var state : UnsafePointer<PyObject> >> >> subscript(_ : Pythonable…) -> PythonObject { >> ... >> } >> } >> >> // Magic, must be on the struct definition. >> // Could alternatively allow custom copy/move/… ctors like C++. >> protocol CustomValueWitnessTable { >> static func init(..) >> static func copy(..) >> static func move(..) >> static func destroy(..) >> } > > Swift’s implementation model supports this. As a surface-level construct it’s > going to be mired in UnsafeMutablePointers, and it’s not at all clear to me > that we want this level of control there. Presumably, binding to Python is > going to require some compiler effort—defining how it is that Python objects > are initialized/copied/moved/destroyed seems like a reasonable part of that > effort. > >> // Magic, allows anyobject-like member lookup on a type when lookup >> otherwise fails. >> protocol DynamicMemberLookupable { >> associatedtype MemberLookupResultType >> func dynamicMemberLookup(_ : String) -> MemberLookupResultType >> } > > AnyObject lookup looks for an actual declaration on any type anywhere. One > could extend that mechanism to, say, return all Python methods and assume > that you can call any Python method with any PythonObject instance. AnyObject > lookup is fairly unprincipled as a language feature, because there’s no > natural scope in which to perform name lookup, and involves hacks at many > levels that don’t always work (e.g., AnyObject lookup… sometimes… fails > across multiple source files for hard-to-explain reasons). You’re taking on > that brokenness if you expand AnyObject lookup to another ecosystem. > > Although it doesn’t really seem like AnyObject lookup is the thing you’re > asking for here. It seems more like you want dynamicMemberLookup(_:) to > capture “self” and the method name, and then be a callable thing as below... > >> >> // Magic, allows “overloaded/sugared postfix ()”. >> protocol CustomCallable { >> func call( …) >> } >> >> The only tricky thing about this is the call part of things. At least in >> the case of python, we want something like this: >> >> foo.bar(1, 2, a: x, b: y) >> >> to turn into: >> foo.dynamicMemberLookup(“bar”).call(1, 2, kwargs: [“a”:x, “b”:y]) >> >> We don’t want this to be a memberlookup of a value that has “bar” as a >> basename and “a:” and “b:” as parameter labels. > > Well, I think the MemberLookupResult is going to get the name “bar”, argument > labels “_:_:a:b:”, and arguments “1”, “2”, “x”, “y”, because that’s the Swift > model of argument labels. It can then reshuffle them however it needs to for > the underlying interaction with the Python interpreter. > > There are definite design trade-offs here. With AnyObject lookup, it’s a > known-broken feature but because it depends on synthesized Swift method > declarations, it’ll behave mostly the same way as other Swift method > declarations—static overloading, known (albeit weak) type signatures, etc. > But, it might require more of Python’s model to be grafted onto those method > declarations. With dynamic member lookup, you’re throwing away all type > safety (even for a motivated Python developer who might be willing to > annotate APIs with types) and creating a general language mechanism for doing > that. > > - Doug > >> >> -Chris >> >>> >>> protocol DynamicDispatchable { // Protocol is “magic" known by the compiler. >>> func retain() >>> func release() >>> func memberLookup(_ : String) -> Self >>> func subscript<T>(_ : T) -> Self >>> func call(_ args: [Self]) -> Self >>> } >>> >>> module Python { >>> struct Object : DynamicDispatchable { >>> var state : UnsafePointer<PyObject> >>> >>> func retain() { >>> INCREF(self) >>> } >>> >>> func memberLookup(_ : String) -> Object { >>> PyObject_GetAttrString(…) >>> } >>> etc >>> } >>> >>> module Perl5 { >>> struct Object : DynamicDispatchable { >>> var state : UnsafePointer<SV> >>> >>> func retain() { >>> SvREFCNT_inc(self) >>> } >>> …. >>> >>> >>> >>> Are there other uses for such a thing? >>> >>> -Chris >>> >>> >>> _______________________________________________ >>> swift-evolution mailing list >>> swift-evolution@swift.org <mailto:swift-evolution@swift.org> >>> https://lists.swift.org/mailman/listinfo/swift-evolution >> >> _______________________________________________ >> swift-evolution mailing list >> swift-evolution@swift.org <mailto:swift-evolution@swift.org> >> https://lists.swift.org/mailman/listinfo/swift-evolution >> <https://lists.swift.org/mailman/listinfo/swift-evolution> > _______________________________________________ > swift-evolution mailing list > swift-evolution@swift.org <mailto:swift-evolution@swift.org> > https://lists.swift.org/mailman/listinfo/swift-evolution > <https://lists.swift.org/mailman/listinfo/swift-evolution>
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution