[Pitch] Rename Mirror

https://github.com/Anton3/swift-evolution/blob/master/proposals/NNNN-rename-mirror.md
Rename Mirror

   - Proposal: SE-NNNN <http://NNNN-filename.md>
   - Author: Anton Zhilin <https://github.com/Anton3&gt;, Adrian Zubarev
   <https://github.com/DevAndArtist&gt;
   - Status: *Awaiting review*
   - Review manager: TBD

Introduction

Rename Mirror to DebugRepresentation and CustomReflectable to
CustomDebugRepresentable.
Motivation

Name of Mirror does not reflect (no pun) what it is intended to do, i.e.
providing full featured reflection, which we want to see in Swift 4. Other
than that, it is only intended to serve for debugging purposes, e.g.
building trees for selected objects. Some evidence to that:

   - Mirror.DisplayStyle contains optional and set as special cases, but
   does not contain function
   - Mirror collects all information possible at initialization, while for
   true reflection we want laziness
   - Mirror allows customization. For example, Array<T> is represented with
   a field for each of its elements. Do we want this for “true” reflection we
   want to add in the future?

Proposed solution

   - Rename struct Mirror to DebugRepresentation
   - Rename protocol CustomReflectable to CustomDebugRepresentable
   - Rename property customMirror to customDebugRepresentation
   - Hope that one day we will get a real Mirror with full reflection
   capabilities

Impact on existing code

This is a breaking change; easy automated migration possible.

Why can't we add these features to Mirror in future?

Dmitri

···

On Thu, Jul 21, 2016 at 3:25 PM, Anton Zhilin via swift-evolution <swift-evolution@swift.org> wrote:

https://github.com/Anton3/swift-evolution/blob/master/proposals/NNNN-rename-mirror.md

Rename Mirror

Proposal: SE-NNNN
Author: Anton Zhilin, Adrian Zubarev
Status: Awaiting review
Review manager: TBD

Introduction

Rename Mirror to DebugRepresentation and CustomReflectable to
CustomDebugRepresentable.

Motivation

Name of Mirror does not reflect (no pun) what it is intended to do, i.e.
providing full featured reflection, which we want to see in Swift 4. Other
than that, it is only intended to serve for debugging purposes, e.g.
building trees for selected objects. Some evidence to that:

Mirror.DisplayStyle contains optional and set as special cases, but does not
contain function
Mirror collects all information possible at initialization, while for true
reflection we want laziness
Mirror allows customization. For example, Array<T> is represented with a
field for each of its elements. Do we want this for “true” reflection we
want to add in the future?

--
main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if
(j){printf("%d\n",i);}}} /*Dmitri Gribenko <gribozavr@gmail.com>*/

Reflection in some other languages works as follows: we have a type (let's
name it 'Reflection'). Each instance of it contains ID of one type and can,
for example, retrieve an array of its static or normal methods.
'Mirror', on the other hand, serves as a container for information about a
single instance. Moreover, types can completely customize contents of their
'Mirror's. This is incompatible with laziness and with how reflection
should work, based on experience from other languages.

···

2016-07-22 1:34 GMT+03:00 Dmitri Gribenko <gribozavr@gmail.com>:

> Mirror.DisplayStyle contains optional and set as special cases, but does
not
> contain function
> Mirror collects all information possible at initialization, while for
true
> reflection we want laziness
> Mirror allows customization. For example, Array<T> is represented with a
> field for each of its elements. Do we want this for “true” reflection we
> want to add in the future?

Why can't we add these features to Mirror in future?

> Mirror.DisplayStyle contains optional and set as special cases, but does
> not
> contain function
> Mirror collects all information possible at initialization, while for
> true
> reflection we want laziness
> Mirror allows customization. For example, Array<T> is represented with a
> field for each of its elements. Do we want this for “true” reflection we
> want to add in the future?

Why can't we add these features to Mirror in future?

Reflection in some other languages works as follows: we have a type (let's
name it 'Reflection'). Each instance of it contains ID of one type and can,
for example, retrieve an array of its static or normal methods.

I understand. But we don't know how reflection will work in Swift, we
haven't designed it yet. You are assuming it will work like it does
in other languages, which will not necessarily be the case.

Moreover, types can completely customize contents of their
'Mirror's. This is incompatible with laziness and with how reflection should
work, based on experience from other languages.

That is actually viewed as a weakness of reflection in other
languages. Allowing reflection to access other types' internal data
and APIs creates barriers for optimization, and facilitates creating
binary compatibility problems when apps include code that uses
reflection to poke at internal data of library types.

Dmitri

···

On Thu, Jul 21, 2016 at 4:06 PM, Anton Zhilin <antonyzhilin@gmail.com> wrote:

2016-07-22 1:34 GMT+03:00 Dmitri Gribenko <gribozavr@gmail.com>:

--
main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if
(j){printf("%d\n",i);}}} /*Dmitri Gribenko <gribozavr@gmail.com>*/

I agree with Dmitri. I would rather see a proper design for reflection
(similar to Completing Generics) before we start making any changes to the
existing machinery.

Best,
Austin

···

On Thu, Jul 21, 2016 at 4:39 PM, Dmitri Gribenko via swift-evolution < swift-evolution@swift.org> wrote:

On Thu, Jul 21, 2016 at 4:06 PM, Anton Zhilin <antonyzhilin@gmail.com> > wrote:
> 2016-07-22 1:34 GMT+03:00 Dmitri Gribenko <gribozavr@gmail.com>:
>>
>> > Mirror.DisplayStyle contains optional and set as special cases, but
does
>> > not
>> > contain function
>> > Mirror collects all information possible at initialization, while for
>> > true
>> > reflection we want laziness
>> > Mirror allows customization. For example, Array<T> is represented
with a
>> > field for each of its elements. Do we want this for “true” reflection
we
>> > want to add in the future?
>>
>> Why can't we add these features to Mirror in future?
>
>
> Reflection in some other languages works as follows: we have a type
(let's
> name it 'Reflection'). Each instance of it contains ID of one type and
can,
> for example, retrieve an array of its static or normal methods.

I understand. But we don't know how reflection will work in Swift, we
haven't designed it yet. You are assuming it will work like it does
in other languages, which will not necessarily be the case.

> Moreover, types can completely customize contents of their
> 'Mirror's. This is incompatible with laziness and with how reflection
should
> work, based on experience from other languages.

That is actually viewed as a weakness of reflection in other
languages. Allowing reflection to access other types' internal data
and APIs creates barriers for optimization, and facilitates creating
binary compatibility problems when apps include code that uses
reflection to poke at internal data of library types.

Dmitri

--
main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if
(j){printf("%d\n",i);}}} /*Dmitri Gribenko <gribozavr@gmail.com>*/
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

I talked about Swift here. Types can completely customize contents of their
Mirrors in Swift. A type, which pretends to be used for reflection, can't
afford that.

···

2016-07-22 2:39 GMT+03:00 Dmitri Gribenko <gribozavr@gmail.com>:

On Thu, Jul 21, 2016 at 4:06 PM, Anton Zhilin <antonyzhilin@gmail.com> > wrote:
> Moreover, types can completely customize contents of their
> 'Mirror's. This is incompatible with laziness and with how reflection
should
> work, based on experience from other languages.

That is actually viewed as a weakness of reflection in other
languages. Allowing reflection to access other types' internal data
and APIs creates barriers for optimization, and facilitates creating
binary compatibility problems when apps include code that uses
reflection to poke at internal data of library types.

> Mirror.DisplayStyle contains optional and set as special cases, but does not
> contain function
> Mirror collects all information possible at initialization, while for true
> reflection we want laziness
> Mirror allows customization. For example, Array<T> is represented with a
> field for each of its elements. Do we want this for “true” reflection we
> want to add in the future?

Why can't we add these features to Mirror in future?

Reflection in some other languages works as follows: we have a type (let's name it 'Reflection'). Each instance of it contains ID of one type and can, for example, retrieve an array of its static or normal methods.
'Mirror', on the other hand, serves as a container for information about a single instance. Moreover, types can completely customize contents of their 'Mirror's. This is incompatible with laziness and with how reflection should work, based on experience from other languages.

Actually mirror based reflection has a couple of advantages like decoupling the reflection API from the normal API and being able to provide different mirrors for different purposes. See the paper of Gilad Bracha who used mirror based reflection in Newspeak and introduced it for Dart:

Abstract of the paper: "We identify three design principles for reflection and metaprogramming facilities in object oriented programming languages. Encapsulation: meta-level facilities must encapsulate their implementation. Stratification: meta-level facilities must be separated from base-level functionality. Ontological correspondence: the ontology of meta-level facilities should correspond to the ontology of the language they manipulate. Traditional/mainstream reflective architectures do not follow these precepts. In contrast, reflective APIs built around the concept of mirrors are characterized by adherence to these three principles."

-Thorsten

···

Am 22.07.2016 um 01:06 schrieb Anton Zhilin via swift-evolution <swift-evolution@swift.org>:
2016-07-22 1:34 GMT+03:00 Dmitri Gribenko <gribozavr@gmail.com>:

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

I think pointing a Mirror at a metatype value could be a good a mechanism for getting information about the type's stored properties and other members.

FWIW Mirrors are inspired by a feature of the same name in the Self language, which made reflection somewhat more principled than the disorganized APIs you see in Java and C#. Perhaps the latter are not a good model to follow here :-)

Slava

···

On Jul 21, 2016, at 4:06 PM, Anton Zhilin via swift-evolution <swift-evolution@swift.org> wrote:

2016-07-22 1:34 GMT+03:00 Dmitri Gribenko <gribozavr@gmail.com <mailto:gribozavr@gmail.com>>:
> Mirror.DisplayStyle contains optional and set as special cases, but does not
> contain function
> Mirror collects all information possible at initialization, while for true
> reflection we want laziness
> Mirror allows customization. For example, Array<T> is represented with a
> field for each of its elements. Do we want this for “true” reflection we
> want to add in the future?

Why can't we add these features to Mirror in future?

Reflection in some other languages works as follows: we have a type (let's name it 'Reflection'). Each instance of it contains ID of one type and can, for example, retrieve an array of its static or normal methods.
'Mirror', on the other hand, serves as a container for information about a single instance. Moreover, types can completely customize contents of their 'Mirror's. This is incompatible with laziness and with how reflection should work, based on experience from other languages.

> Moreover, types can completely customize contents of their
> 'Mirror's. This is incompatible with laziness and with how reflection
> should
> work, based on experience from other languages.

That is actually viewed as a weakness of reflection in other
languages. Allowing reflection to access other types' internal data
and APIs creates barriers for optimization, and facilitates creating
binary compatibility problems when apps include code that uses
reflection to poke at internal data of library types.

I talked about Swift here.

I am also talking about Swift. If we build a reflection mechanism
that would allow third party code to poke at Array or Dictionary
implementation details (or any other type for that matter), we would
be exposing us to the same pitfalls as other languages have now. I
would be opposed to doing that.

Types can completely customize contents of their
Mirrors in Swift.

This is desirable, for implementation hiding reasons. Nobody should
be able to observe implementation details of Array, Dictionary, or any
other library types through programmatic mechanisms.

A type, which pretends to be used for reflection, can't
afford that.

Why not?

You see, we (as a community) don't have a shared long-term vision
about what "reflection" means. Establishing that agreement would be
the prerequisite to starting any formal proposal process.
Speculatively making changes based on hypothetical designs that were
not discussed yet will not bring us to a better place.

Dmitri

···

On Thu, Jul 21, 2016 at 4:49 PM, Anton Zhilin <antonyzhilin@gmail.com> wrote:

2016-07-22 2:39 GMT+03:00 Dmitri Gribenko <gribozavr@gmail.com>:

On Thu, Jul 21, 2016 at 4:06 PM, Anton Zhilin <antonyzhilin@gmail.com> >> wrote:

--
main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if
(j){printf("%d\n",i);}}} /*Dmitri Gribenko <gribozavr@gmail.com>*/

Somehow I did not send a copy to evolution the first time:

I have to agree. Stopping the discussion on this until after Swift 3.

And response from Dmitri:

Thanks!

Just wanted to be clear -- I am not against reflection. And I am
concerned whether the current design of Mirror will work for the
long-term full-featured reflection implementation, but only because we
don't know what will be the shape of reflection in Swift. For
example, would we be able to call arbitrary public functions on a type
by name? If yes, how would that be implemented -- both in the API,
and on the low level, how would actual function call and argument
passing work? How much extra metadata and thunks would the compiler
need to emit? Would an average app or framework want that bloat?
Remember that we don't have a JIT, so we can't say "we will do what
Java (or any other mainstream language with reflection) does", because
we can't.

Swift and Self lie in different families of languages.
In Self (and Smalltalk, and ObjC), types don't really matter: one can
modify methods, which some object has, independently of all other objects.
Because of this dynamism, reflection of types has little value in these
languages.

On the other hand, in Swift (and C++, and Java) types do matter. It is
useful to get, for example, a Method, and be sure that you can call it on
all instances of matching type.
I think that Swift should favor types and not instances, as it
unfortunately does today.

This is how I imagine reflection API. We have a type ID and can request
different information about it. For example: func getMethod(name: String)
-> Method?
Most importantly, we should be able to get IDs of other related types, and
related type IDs of theirs, and so on, without collecting excessive data.

···

2016-08-11 0:40 GMT+03:00 Slava Pestov <spestov@apple.com>:

I think pointing a Mirror at a metatype value could be a good a mechanism
for getting information about the type's stored properties and other
members.

FWIW Mirrors are inspired by a feature of the same name in the Self
language, which made reflection somewhat more principled than the
disorganized APIs you see in Java and C#. Perhaps the latter are not a good
model to follow here :-)

I also don't think this is a worthy change. Mirror can be extended or
even changed in the future to become a true reflection base class. No
benefits added and breaking code are to me a reason to not go forward
with this.

L

···

On 21 July 2016 at 22:05, Anton Zhilin via swift-evolution <swift-evolution@swift.org> wrote:

Somehow I did not send a copy to evolution the first time:

I have to agree. Stopping the discussion on this until after Swift 3.

And response from Dmitri:

Thanks!

Just wanted to be clear -- I am not against reflection. And I am
concerned whether the current design of Mirror will work for the
long-term full-featured reflection implementation, but only because we
don't know what will be the shape of reflection in Swift. For
example, would we be able to call arbitrary public functions on a type
by name? If yes, how would that be implemented -- both in the API,
and on the low level, how would actual function call and argument
passing work? How much extra metadata and thunks would the compiler
need to emit? Would an average app or framework want that bloat?
Remember that we don't have a JIT, so we can't say "we will do what
Java (or any other mainstream language with reflection) does", because
we can't.

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