On Dec 2, 2017, at 2:13 PM, Matthew Johnson <matt...@anandabits.com> wrote:
>> For all those reasons, we really do need something like AnyObject dispatch 
>> if we care about working with dynamically typed languages.  The design I’m 
>> suggesting carefully cordons this off into its own struct type, so it 
>> doesn’t infect the rest of the type system, and is non-invasive in the 
>> compiler.
> 
> I am quite familiar with dynamic languages and agree that this is necessary 
> if we are going to fully open up access to these languages from Swift.

Ok, then it appears you agree that something like anyobject dispatch is 
necessary for effective dynamic language interop.

>>> I strongly urge you to reconsider the decision of that dynamic members must 
>>> be made available with no indication at usage sites.  An indication of 
>>> dynamic lookup at usage sites aligns very well (IMO) with the rest of Swift 
>>> (AnyObject lookup aside) by calling attention to code that requires extra 
>>> care to get right.
>> 
>> I don’t understand this.  The proposal is fully type safe, and this approach 
>> is completely precedented by AnyObject.  Swift’s type system supports many 
>> ways to express fallibility, and keeping those decisions orthogonal to this 
>> proposal is the right thing to do, because it allows the author of the type 
>> to decide what model makes sense for them.
> 
> Allowing the author of the type to choose whether the mechanism is hidden or 
> visible is exactly what I don’t want to allow.  I think you have the right 
> design regarding types and semantics - the author chooses.  But I don’t want 
> these calls to look like ordinary member lookup when I’m reading code.  
> 
> They inherently have a much greater chance of failure than ordinary member 
> lookup.  Further, authors are likely to choose immediate traps or nil IUO as 
> failure modes as forcing users to deal with Optional on every call is likely 
> to be untenable.  I believe this behavior should be represented by some kind 
> of syntax at the usage site.  I don’t believe it is an undue burden.  It 
> would make the dynamic lookup semantic clear to all readers and would help to 
> discourage abuse.

I believe that adding explicit syntax would be counterproductive to your goals, 
and would not make dynamic lookup syntax more clear.  I assume that you would 
also want the same thing for DynamicCallable too, and operator overloads, 
subscripts, and every other operation you perform on these values, since they 
all have the exact same behavior.

If we required some syntax even as minimal as “foo.^bar” and "baz^(42)”, that 
change would turn this (which uses runtime failing or IUO return values like 
AnyObject):

        let np = Python.import("numpy")
        let x = np.array([6, 7, 8])
        let y =  np.arange(24).reshape(2, 3, 4)
        
        let a = np.ones(3, dtype: np.int32)
        let b = np.linspace(0, pi, 3)
        let c = a+b
        let d = np.exp(c)
        print(d)

into:

        let np = Python.import("numpy")
        let b = np^.array^([6, 7, 8])
        let y =  np^.arange^(24)^.reshape^(2, 3, 4)
        
        let a = np^.ones^(3, dtype: np^.int32)
        let b = np^.linspace^(0, pi, 3)
        let c = a+^b
        let d = np^.exp^(c)

This does not improve clarity of code, it merely serves to obfuscate logic.  It 
is immediately apparent from the APIs being used, the API style, and the static 
types (in Xcode or through static declarations) that this is all Python stuff.  
When you start mixing in use of native Swift types like dictionaries (something 
we want to encourage because they are typed!) you end up with an inconsistent 
mismash where people would just try adding syntax or applying fixits 
continuously until the code builds.

Beyond that, it is counterproductive to your goals, because it means that 
people are far less likely to use to use optional returns.  Doing so (which 
produces a safer result) would cause a double tax in syntax, and would be a 
confusing jumble.  I can’t bring myself to do the whole example above, one line 
- just converting member lookup syntax but not callable syntax - would end up:

        let y =  np^.arange?^(24)^.reshape^?(2, 3, 4)

If you made DynamicCallable also return optional it would be:

        let y =  np^.arange?^(24)?^.reshape^?(2, 3, 4)!

or something.  This is such madness that no one would do that.


>> Swift already has a dynamic member lookup feature, "AnyObject dispatch" 
>> which does not use additional punctuation, so this would break precedent.
> I would prefer if dynamic lookup were visible with AnyObject as well.  For 
> that reason I don’t believe it makes a good precedent to follow.  In fact, I 
> would prefer to see us go the other direction and perhaps even consider 
> revising dynamic lookup syntax for AnyObject in the future.

This is definitely not going to happen.  The change Doug mentioned is to have 
AnyObject lookup return optional instead of IUO, which forces ? on the clients. 
 Adding other syntax (like you’re suggesting) is certainly not going to happen.

The entire point of AnyObject dispatch is to improve syntactic elegance and 
clarity of code using it.  There is no other reason to exist.  Making code that 
uses it syntactically onerous completely defeats the point of having it in the 
first place, as I’ve mentioned before.


Furthermore, your premise that Swift does not have invisibly failable 
operations is plainly wrong.  Array subscript and even integer addition can 
fail.  Even the behavior of AnyObject was carefully designed and considered, 
and were really really good reasons for it returning IUO.

-Chris

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to