My bad. I'm so used to have as
everywhere in my code to bridge types that I forgot it didn't work for numeric types.
Iām not sure what you mean by this. When you bridge an NSString
to String
, its representation in memory is unchanged, and all operations are handled through resilient function calls. When bridging in the other direction, String
storage is an NSString
subclass, as Iāve already cited previously. That there are optimizations possible to improve string performance in no way changes the semantics or syntax of the language, where as
is a coercion operator that does not convert between types.
I mean that this is not real toll-free
as in Obj-C where the casting required zero instruction as it was just a casting.
In Swift, you still have to execute code to create a String value, populate it with the NSString and set the right flags to tell Swift to handle it specially.
This proposition is about letting custom type support that kind of bridging / conversion, where the compiler generate a function call to convert a type into an other type.
You may argue that in case of NSString<->String, this is more a wrapping that a conversion, but the principle is the same. You still need to call a special function that convert a representation into an other one (either by wrapping it or converting it).
And String is not the only bridges types. When you use as
on an NSNumber to convert it to a base type, there is a real type conversion, not just a wrapping of the underlying value.
I'm not native English, so maybe my understanding of coercion
is not right, but from Wikipedia, coercion is just an implicit conversion.
No, you canāt use as
for NSNumber bridging. You must use as?
or as!
: these are distinct operators with semantics even more complicated than those of as
. Critically, those are not coercion operators like as
is.
Absolutely can.
import Foundation
print(true as NSNumber)
Compiles, runs, prints "1".
That is not bridging. That is telling Swift that you want the literal true
to be of type NSNumber
. There is no other type involved. See the examples given above for literals.
import Foundation
let b: Bool = true
print(b as NSNumber)
Same result.
Ah, right. This is to imitate a subtyping relationship between Bool
and NSNumber
. Confusing, though, as you can see. Full of subtleties as well.
Thereās been talk about whether this feature is a good idea at all, and as you can guess I would be in favor of eventually removing it.
Very confusing. Especially as you are right telling that you can't bridge from NSNumber to a numerical type, but only from a numerical/boolean type to NSNumber.
Sorry for the confusion. When I said bridging I didn't mean as in toll-free bridging. I meant bridging simply in as a way to bridge together two different APIs like the Swift Standard Library and Foundation as in the String
and NSString
example. Talking about this specific example; The toll-free bridging between String
and NSString
is just an implementation detail. An important one, sure, but a detail nevertheless. The important aspect here is the semantics of the as
operator in someString as NSString
, which it pretty straightforward, "treat this type as this type". It doesn't matter if it's toll-free bridging, coercion, conversion, etc. This shouldn't make a difference and certainly, I don't think we should add yet another keyword for conversion.
I disagree, I don't think using as
to convert between Bool
and NSNumber
is confusing. From an API perspective, it makes a lot of sense. Again, that's super straightforward, as would HTTPRequest as URLRequest
be. I don't think it really matters "how" the as
operator is working beneath the cover. On the other hand, I think the language would benefit a lot in having an idiomatic and consistent way to express "treat this type as this type" for our custom types as well.
Swift has standardized on OneType(instanceOfAnotherType)
as the idiomatic way of converting between two types. It is not the role of as
.
Those are not the semantics of the as
operator. Bridging between Foundation and standard library types has been engineered carefully to maximize interoperability between Swift and Objective-C APIs. That characteristic is not an āimplementation detailā but rather a tentpole feature of Swift. In other words, it would not have been acceptable to change the implementation of Swift String
so that bridging from NSString
involved eagerly converting from UTF-16 to UTF-8.
Now, if you want to discuss the possibility of value subtyping relationships...
This.
Right, this is why I'm proposing the overload of the as
operator. Initializing a type with another type with no label is not always used to convey conversion. One example using SwitUI:
Text("Hello world!")
We're not converting a String
to Text
here, we're initializing Text
with a String
(using the StringProtocol
, but with a String
nonetheless). Text
here is a View
used for UI, not a container for characters as String
is.
Now let's compare:
URLRequest(httpRequest)
// vs
httpRequest as URLRequest
The version with the as
operator is much more clearer.
I honestly don't understand why you're insisting on the topic of toll-free bridging. The as
operator is used as a way to perform toll-free bridging, but it's not the only use of the as
operator. Right now I think we've seen three different uses just in this conversation:
Toll-free bridging as in:
let string: String = "Hello world!"
let nsstring = string as NSString
Conversion to imitate a subtyping relationship (If I understood correctly) as in:
let bool: Bool = true
let nsnumber = bool as NSNumber
Subtyping relationship as in:
class Parent {}
class Child : Parent {}
let child: Child = Child()
let parent = child as Parent
or
protocol Protocol {}
struct Child : Protocol {}
let child: Child = Child()
let protocol = child as Protocol
From the type system perspective, the underlying method which is used by the as
operator is irrelevant. All I want to be able to do is to state that one type can be expressed as another. Now my question is; If we already have toll-free bridging and conversion for Foundation
types using the as
operator, why can't we have them for our custom types?
As youāve shown, āasā has a variety of meanings.
Do you mean a subtyping relationship? Value subtyping is certainly a large topic.
Do you mean you want custom toll-free bridging? Thatās also an interesting topic, but is probably best tackled after Swift gets more facilities to control type layout.
But as
is not equivalent to or an alternative to the standard syntax for converting between types, which is expressed as an initializer.
Yes, that's why I'm proposing this, so it becomes.
Can you tell me any disadvantage of having the as
operator as the standard syntax for converting between types?
There is a way and it's standardized :
To reiterate, as
does not do Type conversion. It's used to:
- Cast from one Type to an underlying type that the variable already is.
- Clarify Type inference from literal values
- Specialized bridging between Swift and Obj-C.
The last of which is more/less a compromise to make interop easy.
There is currently zero usage that converts one Swift Type to another Swift Type
Thatās a very different topic from custom bridging.
Do I understand that your position is that you do not like the established syntax for converting between types, and therefore you want to reuse an existing syntax which is not for converting between types for this purpose?