Something about your first paragraph reminded me of a question I've
had for a while. Is there a reasoning behind not being able to
restrict a protocol to value types? One way that this might be
workable is if we could overload protocols for Value vs for
reference.
I'm not totally comfortable with this, because references are a kind
of value.
We're using the word “value” in 3 different ways now. If we don't sort
them out, this is going to become impossible to resolve. So let me
propose some terms:
1. Joe's sense, i.e. the compiler-implementation-level sense, in which a
value of type T is essentially what an UnsafePointer<T> points at.
In this sense, a variable of any type T “has a value.” Even though
it's not strictly correct (since the term really applies to
expressions), I propose “rvalue” for this one.
2. The “value types vs reference types” sense, where every type falls
into one of two crisp buckets based on how it's declared. I propose
we always say “reference type” or “value type” for this one.
3. The “value semantics vs reference semantics” sense, where a type's
category depends on how it is implemented, and it's possible (though
inadvisable) to fall outside either bucket. This is the only
interesting category when you're discussing protocols and
constraints, and doesn't have any intrinsic relationship to sense #2. I propose we always say “value semantics” or “reference
semantics” for this one.
I claim that my sense is the same as #2. A reference has all the
properties of a value-type value; it has the additional ability to be
used as a handle to access independent program state. Int isn't any
less of a value because it can be used to reference values in an
array.
It's less of a value in sense #2 because
x as Any as? AnyObject
is always nil for a value in sense #2.
Rather than try to break the world down according to categories of
types, I think it's more effective to look at the semantics of
*operations*. So called "reference types" have value semantics
operations too;
Please define the term “value semantics operation.” I wager there is no
such thing.
A mutating operation with no other side effects than modifying the values of its 'inout' parameters.
reassigning a class reference, '+='-ing a pointer,
A pointer is a value type in every sense of the word.
and adding or removing elements from an Array of references are all
operations that mutate only the value being operated on, even though
none of these types are strictly "value types".
Now you're really blending meanings, or at least being very fuzzy. Your
Array of references has a sense #1 value that might not even be altered
when you change the elements in the array. It is a sense #2 value by
language rules. It almost has sense #3 value semantics but for our
inability to compare it with "==", because we don't implicitly get "=="
defined in terms of "===" for all classes.
Saying something has value semantics is meaningless without a way to
determine equivalence that respects the boundaries of the value. The
*whole point* of value semantics is that initialization, assignment,
parameter passing, and returning all create *independent* instances, with
no observable shared state, and that can be read and mutated
concurrently in different threads. To even test that, you need to nail
down what it means for a value to change, and for that, you need an
equality comparison.
What I'm trying to say is that there are "boundaries of the value" for everything in our system. For class references, that boundary happens to only include the reference itself.
-Joe
···
On May 5, 2016, at 10:03 AM, Dave Abrahams <dabrahams@apple.com> wrote:
on Thu May 05 2016, Joe Groff <jgroff-AT-apple.com> wrote:
On May 5, 2016, at 8:56 AM, Dave Abrahams <dabrahams@apple.com> wrote:
on Wed May 04 2016, Joe Groff <jgroff-AT-apple.com> wrote:
On May 4, 2016, at 5:28 AM, T.J. Usiyan via swift-evolution <swift-evolution@swift.org> wrote:
... And 30 seconds later I realized that "PureReference" could be fulfilled by something with only static or computed properties.
Any class that only had immutable value semantic members would fulfill PureReference. They would not need to be static or computed.
···
On May 4, 2016, at 4:20 PM, David Sweeris <davesweeris@mac.com> wrote:
Sent from my iPhone
On May 4, 2016, at 16:16, David Sweeris via swift-evolution <swift-evolution@swift.org> wrote:
Having given it some more thought... Does "PureReference" make sense? What would it mean? At some point a reference has to, you know, actually refer to a concrete value. Otherwise it's just turtles all the way down.
Sent from my iPhone
On May 4, 2016, at 13:32, Matthew Johnson <matthew@anandabits.com> wrote:
On May 4, 2016, at 1:21 PM, David Sweeris via swift-evolution <swift-evolution@swift.org> wrote:
On May 4, 2016, at 11:12, Joe Groff via swift-evolution <swift-evolution@swift.org> wrote:
I can see value in there being some kind of PureValue protocol, for types that represent fully self-contained values, but conforming to that protocol requires a bit more thought than just being a struct or enum, since there are structs that have reference semantics (such as UnsafePointer), and there are hybrid value types that contain references to data that isn't part of the value (an Array<Class>, for instance).
-Joe
+1
I'd think that both "PureValue" and "PureReference" would be useful. Isn't it the mixed types that make for tricky mutation rules & serialization?
I also like Joe’s idea. It fits with the direction in Swift of attaching semantics, not just syntax, to protocols.
I was thinking of something pretty similar to your PureReference idea, but slightly different. Pure / immutable references have value semantics. With that in mind I was thinking of an ImmutableObject protocol which would inherit from both AnyObject and PureValue.
Having given it some more thought... Does "PureReference" make
sense? What would it mean? At some point a reference has to, you
know, actually refer to a concrete value. Otherwise it's just
turtles all the way down.
In my thinking PureReference (or ImmutableObject) has semantics
indicating that the type is a value-semantic reference type. I think
this could be quite useful in some cases.
Like what? To a first approximation, the only thing I can see this being
useful for is Objective-C interop. Aside from being an element of an
NSArray, there's nothing a an immutable class can do that a struct
can't.
···
on Wed May 04 2016, Matthew Johnson <matthew-AT-anandabits.com> wrote:
On May 4, 2016, at 4:16 PM, David Sweeris <davesweeris@mac.com> wrote:
Sent from my iPhone
On May 4, 2016, at 13:32, Matthew Johnson <matthew@anandabits.com> wrote:
On May 4, 2016, at 1:21 PM, David Sweeris via swift-evolution <swift-evolution@swift.org> wrote:
On May 4, 2016, at 11:12, Joe Groff via swift-evolution <swift-evolution@swift.org> wrote:
I can see value in there being some kind of PureValue protocol,
for types that represent fully self-contained values, but
conforming to that protocol requires a bit more thought than just
being a struct or enum, since there are structs that have
reference semantics (such as UnsafePointer), and there are hybrid
value types that contain references to data that isn't part of
the value (an Array<Class>, for instance).
-Joe
+1
I'd think that both "PureValue" and "PureReference" would be
useful. Isn't it the mixed types that make for tricky mutation
rules & serialization?
I also like Joe’s idea. It fits with the direction in Swift of attaching semantics, not just syntax, to protocols.
I was thinking of something pretty similar to your PureReference
idea, but slightly different. Pure / immutable references have
value semantics. With that in mind I was thinking of an
ImmutableObject protocol which would inherit from both AnyObject
and PureValue.
I would agree that there are *potential* “boundaries of the value” for
everything in our system. Up to now, there has been no general
agreement that the default “boundaries of the value” for references stop
at the reference's own bits, and that mutable classes can't have an "=="
that reaches beyond those bits. Until we reach such agreement, I don't
think there's any reasonable way to argue that any of the three
categories I listed are the same. And I think we need those categories
in order to create that agreement.
···
on Thu May 05 2016, Joe Groff <jgroff-AT-apple.com> wrote:
On May 5, 2016, at 10:03 AM, Dave Abrahams <dabrahams@apple.com> wrote:
on Thu May 05 2016, Joe Groff <jgroff-AT-apple.com> wrote:
On May 5, 2016, at 8:56 AM, Dave Abrahams <dabrahams@apple.com> wrote:
on Wed May 04 2016, Joe Groff <jgroff-AT-apple.com> wrote:
On May 4, 2016, at 5:28 AM, T.J. Usiyan via swift-evolution <swift-evolution@swift.org> wrote:
Something about your first paragraph reminded me of a question I've
had for a while. Is there a reasoning behind not being able to
restrict a protocol to value types? One way that this might be
workable is if we could overload protocols for Value vs for
reference.
I'm not totally comfortable with this, because references are a kind
of value.
We're using the word “value” in 3 different ways now. If we don't sort
them out, this is going to become impossible to resolve. So let me
propose some terms:
1. Joe's sense, i.e. the compiler-implementation-level sense, in which a
value of type T is essentially what an UnsafePointer<T> points at.
In this sense, a variable of any type T “has a value.” Even though
it's not strictly correct (since the term really applies to
expressions), I propose “rvalue” for this one.
2. The “value types vs reference types” sense, where every type falls
into one of two crisp buckets based on how it's declared. I propose
we always say “reference type” or “value type” for this one.
3. The “value semantics vs reference semantics” sense, where a type's
category depends on how it is implemented, and it's possible (though
inadvisable) to fall outside either bucket. This is the only
interesting category when you're discussing protocols and
constraints, and doesn't have any intrinsic relationship to sense #2. I propose we always say “value semantics” or “reference
semantics” for this one.
I claim that my sense is the same as #2. A reference has all the
properties of a value-type value; it has the additional ability to be
used as a handle to access independent program state. Int isn't any
less of a value because it can be used to reference values in an
array.
It's less of a value in sense #2 because
x as Any as? AnyObject
is always nil for a value in sense #2.
Rather than try to break the world down according to categories of
types, I think it's more effective to look at the semantics of
*operations*. So called "reference types" have value semantics
operations too;
Please define the term “value semantics operation.” I wager there is no
such thing.
A mutating operation with no other side effects than modifying the values of its 'inout' parameters.
reassigning a class reference, '+='-ing a pointer,
A pointer is a value type in every sense of the word.
and adding or removing elements from an Array of references are all
operations that mutate only the value being operated on, even though
none of these types are strictly "value types".
Now you're really blending meanings, or at least being very fuzzy. Your
Array of references has a sense #1 value that might not even be altered
when you change the elements in the array. It is a sense #2 value by
language rules. It almost has sense #3 value semantics but for our
inability to compare it with "==", because we don't implicitly get "=="
defined in terms of "===" for all classes.
Saying something has value semantics is meaningless without a way to
determine equivalence that respects the boundaries of the value. The
*whole point* of value semantics is that initialization, assignment,
parameter passing, and returning all create *independent* instances, with
no observable shared state, and that can be read and mutated
concurrently in different threads. To even test that, you need to nail
down what it means for a value to change, and for that, you need an
equality comparison.
What I'm trying to say is that there are "boundaries of the value" for
everything in our system. For class references, that boundary happens
to only include the reference itself.
Having given it some more thought... Does "PureReference" make
sense? What would it mean? At some point a reference has to, you
know, actually refer to a concrete value. Otherwise it's just
turtles all the way down.
In my thinking PureReference (or ImmutableObject) has semantics
indicating that the type is a value-semantic reference type. I think
this could be quite useful in some cases.
Like what? To a first approximation, the only thing I can see this being
useful for is Objective-C interop. Aside from being an element of an
NSArray, there's nothing a an immutable class can do that a struct
can't.
Objective-C / cocoa interop is important enough to matter IMO.
···
Sent from my iPad
On May 5, 2016, at 10:59 AM, Dave Abrahams <dabrahams@apple.com> wrote:
on Wed May 04 2016, Matthew Johnson <matthew-AT-anandabits.com> wrote:
On May 4, 2016, at 4:16 PM, David Sweeris <davesweeris@mac.com> wrote:
Sent from my iPhone
On May 4, 2016, at 13:32, Matthew Johnson <matthew@anandabits.com> wrote:
On May 4, 2016, at 1:21 PM, David Sweeris via swift-evolution <swift-evolution@swift.org> wrote:
On May 4, 2016, at 11:12, Joe Groff via swift-evolution <swift-evolution@swift.org> wrote:
I can see value in there being some kind of PureValue protocol,
for types that represent fully self-contained values, but
conforming to that protocol requires a bit more thought than just
being a struct or enum, since there are structs that have
reference semantics (such as UnsafePointer), and there are hybrid
value types that contain references to data that isn't part of
the value (an Array<Class>, for instance).
-Joe
+1
I'd think that both "PureValue" and "PureReference" would be
useful. Isn't it the mixed types that make for tricky mutation
rules & serialization?
I also like Joe’s idea. It fits with the direction in Swift of attaching semantics, not just syntax, to protocols.
I was thinking of something pretty similar to your PureReference
idea, but slightly different. Pure / immutable references have
value semantics. With that in mind I was thinking of an
ImmutableObject protocol which would inherit from both AnyObject
and PureValue.
Generic “manager” singletons? Like maybe if you wanted to use something other than NSFileManager? I’m hazy enough on exactly what the singleton pattern means that I’m not sure it matters.
- Dave Sweeris
···
On May 5, 2016, at 10:59 AM, Dave Abrahams <dabrahams@apple.com> wrote:
on Wed May 04 2016, Matthew Johnson <matthew-AT-anandabits.com> wrote:
On May 4, 2016, at 4:16 PM, David Sweeris <davesweeris@mac.com> wrote:
Having given it some more thought... Does "PureReference" make
sense? What would it mean? At some point a reference has to, you
know, actually refer to a concrete value. Otherwise it's just
turtles all the way down.
In my thinking PureReference (or ImmutableObject) has semantics
indicating that the type is a value-semantic reference type. I think
this could be quite useful in some cases.
Like what? To a first approximation, the only thing I can see this being
useful for is Objective-C interop. Aside from being an element of an
NSArray, there's nothing a an immutable class can do that a struct
can’t.
Having given it some more thought... Does "PureReference" make
sense? What would it mean? At some point a reference has to, you
know, actually refer to a concrete value. Otherwise it's just
turtles all the way down.
In my thinking PureReference (or ImmutableObject) has semantics
indicating that the type is a value-semantic reference type. I think
this could be quite useful in some cases.
Like what? To a first approximation, the only thing I can see this being
useful for is Objective-C interop. Aside from being an element of an
NSArray, there's nothing a an immutable class can do that a struct
can't.
Objective-C / cocoa interop is important enough to matter IMO.
Sure. I don't see why we should have an ImmutableObject protocol when
we can just compose “Immutable” with “AnyObject.”
···
on Thu May 05 2016, Matthew Johnson <matthew-AT-anandabits.com> wrote:
On May 5, 2016, at 10:59 AM, Dave Abrahams <dabrahams@apple.com> wrote:
on Wed May 04 2016, Matthew Johnson <matthew-AT-anandabits.com> wrote:
On May 4, 2016, at 4:16 PM, David Sweeris <davesweeris@mac.com> wrote:
Sent from my iPhone
On May 4, 2016, at 13:32, Matthew Johnson <matthew@anandabits.com> wrote:
On May 4, 2016, at 1:21 PM, David Sweeris via swift-evolution <swift-evolution@swift.org> wrote:
On May 4, 2016, at 11:12, Joe Groff via swift-evolution <swift-evolution@swift.org> wrote:
I can see value in there being some kind of PureValue protocol,
for types that represent fully self-contained values, but
conforming to that protocol requires a bit more thought than just
being a struct or enum, since there are structs that have
reference semantics (such as UnsafePointer), and there are hybrid
value types that contain references to data that isn't part of
the value (an Array<Class>, for instance).
-Joe
+1
I'd think that both "PureValue" and "PureReference" would be
useful. Isn't it the mixed types that make for tricky mutation
rules & serialization?
I also like Joe’s idea. It fits with the direction in Swift of attaching semantics, not just syntax, to protocols.
I was thinking of something pretty similar to your PureReference
idea, but slightly different. Pure / immutable references have
value semantics. With that in mind I was thinking of an
ImmutableObject protocol which would inherit from both AnyObject
and PureValue.
Having given it some more thought... Does "PureReference" make
sense? What would it mean? At some point a reference has to, you
know, actually refer to a concrete value. Otherwise it's just
turtles all the way down.
In my thinking PureReference (or ImmutableObject) has semantics
indicating that the type is a value-semantic reference type. I think
this could be quite useful in some cases.
Like what? To a first approximation, the only thing I can see this being
useful for is Objective-C interop. Aside from being an element of an
NSArray, there's nothing a an immutable class can do that a struct
can't.
Objective-C / cocoa interop is important enough to matter IMO.
Sure. I don't see why we should have an ImmutableObject protocol when
we can just compose “Immutable” with “AnyObject.”
Yes, fair enough. A typealias is easy enough to add if it is used frequently.
I wouldn’t call it “Immutable” though as “PureValue" indicates what we care about (value semantics). “ImmutableObject” is just a good name for a value semantic reference type as immutability is the only way to achieve value semantics with a reference type.
It would be great to see “PureValue” added to the standard library and applied to its types. This would allow us to start drawing the distinction you make in your third category which is very important for many reasons, but is only latent today.
···
On May 5, 2016, at 2:51 PM, Dave Abrahams <dabrahams@apple.com> wrote:
on Thu May 05 2016, Matthew Johnson <matthew-AT-anandabits.com <http://matthew-at-anandabits.com/>> wrote:
On May 5, 2016, at 10:59 AM, Dave Abrahams <dabrahams@apple.com> wrote:
on Wed May 04 2016, Matthew Johnson <matthew-AT-anandabits.com> wrote:
On May 4, 2016, at 4:16 PM, David Sweeris <davesweeris@mac.com> wrote:
Sent from my iPhone
On May 4, 2016, at 13:32, Matthew Johnson <matthew@anandabits.com> wrote:
On May 4, 2016, at 1:21 PM, David Sweeris via swift-evolution <swift-evolution@swift.org> wrote:
On May 4, 2016, at 11:12, Joe Groff via swift-evolution <swift-evolution@swift.org> wrote:
I can see value in there being some kind of PureValue protocol,
for types that represent fully self-contained values, but
conforming to that protocol requires a bit more thought than just
being a struct or enum, since there are structs that have
reference semantics (such as UnsafePointer), and there are hybrid
value types that contain references to data that isn't part of
the value (an Array<Class>, for instance).
-Joe
+1
I'd think that both "PureValue" and "PureReference" would be
useful. Isn't it the mixed types that make for tricky mutation
rules & serialization?
I also like Joe’s idea. It fits with the direction in Swift of attaching semantics, not just syntax, to protocols.
I was thinking of something pretty similar to your PureReference
idea, but slightly different. Pure / immutable references have
value semantics. With that in mind I was thinking of an
ImmutableObject protocol which would inherit from both AnyObject
and PureValue.