[Pitch] Add the DefaultConstructible protocol to the standard library


(Adam Nemecek) #1

This protocol is present in C++
http://en.cppreference.com/w/cpp/concept/DefaultConstructible as well as in
Rust https://doc.rust-lang.org/std/default/

It's the identity element/unit of a monoid or a zero.

The Swift implementation is very simple (I'm open to different names)

protocol DefaultConstructible {
    init()
}

A lot of the standard types could then be made to conform to this protocol.
These include all the numeric types, collection types (array, set, dict),
string, basically at least every type that currently has a constructor
without any arguments.

The RangeReplaceableCollection protocol would inherit from this protocol as
well.

This protocol would simplify a lot of generic algorithms where you need the
concept of a zero (which shows up a lot)

Once introduced, Sequence could define an alternative implementation of
reduce where the initial result doesn't need to be provided as it can be
default constructed.


Empty initializer protocol
(Xiaodi Wu) #2

Can you give some other examples of generic algorithms that would make use
of this DefaultConstructible? I'm having trouble coming up with any other
than reduce.

···

On Sun, Dec 25, 2016 at 14:23 Adam Nemecek via swift-evolution < swift-evolution@swift.org> wrote:

This protocol is present in C++
http://en.cppreference.com/w/cpp/concept/DefaultConstructible as well as
in Rust https://doc.rust-lang.org/std/default/

It's the identity element/unit of a monoid or a zero.

The Swift implementation is very simple (I'm open to different names)

protocol DefaultConstructible {
    init()
}

A lot of the standard types could then be made to conform to this
protocol. These include all the numeric types, collection types (array,
set, dict), string, basically at least every type that currently has a
constructor without any arguments.

The RangeReplaceableCollection protocol would inherit from this protocol
as well.

This protocol would simplify a lot of generic algorithms where you need
the concept of a zero (which shows up a lot)

Once introduced, Sequence could define an alternative implementation of
reduce where the initial result doesn't need to be provided as it can be
default constructed.

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


(Tino) #3

There is an older discussion that is somewhat linked to this topic:
"Removing the empty initialiser requirement from RangeReplaceableCollection"
https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160704/023642.html

Imho "DefaultConstructible" types can be very handy, but so far, it seems no one has presented a single use case that is important enough to justify the inclusion in the stdlib.
On the other hand, I'm quite sure that there's much functionality in the stdlib that many people consider as superfluous…

I guess adding the protocol wouldn't have a big impact on size, so for for me, the question is "Does this protocol confuse users of Swift?", which I'd answer with "yes, possibly" (unless someone comes up with a name that is more intuitive).


(Adam Nemecek) #4

There's a book that provides quite a bit of info on this

https://smile.amazon.com/Elements-Programming-Alexander-Stepanov/dp/032163537X?sa-no-redirect=1

They say that DefaultConstructible is one of the essential protocols on
which most algorithms rely in one way or another. One of the authors is the
designer of the C++ STL and basically the father of modern generics.

This protocol is important for any algebraic structure that deals with the
concept of appending or addition (as "zero" is one of the requirements of
monoid). There isn't a good short answer to your question. It's a building
block of algorithms. Think about why a RangeReplaceableCollection can
provide you with a default constructor but a Collection can't.

···

On Sun, Dec 25, 2016 at 11:37 AM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

Can you give some other examples of generic algorithms that would make use
of this DefaultConstructible? I'm having trouble coming up with any other
than reduce.
On Sun, Dec 25, 2016 at 14:23 Adam Nemecek via swift-evolution < > swift-evolution@swift.org> wrote:

This protocol is present in C++ http://en.cppreference.com/w/cpp/concept/
DefaultConstructible as well as in Rust https://doc.rust-lang.org/std/
default/

It's the identity element/unit of a monoid or a zero.

The Swift implementation is very simple (I'm open to different names)

protocol DefaultConstructible {
    init()
}

A lot of the standard types could then be made to conform to this
protocol. These include all the numeric types, collection types (array,
set, dict), string, basically at least every type that currently has a
constructor without any arguments.

The RangeReplaceableCollection protocol would inherit from this protocol
as well.

This protocol would simplify a lot of generic algorithms where you need
the concept of a zero (which shows up a lot)

Once introduced, Sequence could define an alternative implementation of
reduce where the initial result doesn't need to be provided as it can be
default constructed.

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


(Adam Nemecek) #5

Does enabling a lot of small improvements that make APIs more ergonomic
count as practical?

···

On Sun, Dec 25, 2016 at 12:19 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

On Sun, Dec 25, 2016 at 3:07 PM, Adam Nemecek <adamnemecek@gmail.com> > wrote:

There's a book that provides quite a bit of info on this

https://smile.amazon.com/Elements-Programming-Alexander-
Stepanov/dp/032163537X?sa-no-redirect=1

They say that DefaultConstructible is one of the essential protocols on
which most algorithms rely in one way or another. One of the authors is the
designer of the C++ STL and basically the father of modern generics.

This protocol is important for any algebraic structure that deals with
the concept of appending or addition (as "zero" is one of the requirements
of monoid). There isn't a good short answer to your question. It's a
building block of algorithms. Think about why a RangeReplaceableCollection
can provide you with a default constructor but a Collection can't.

It's well and fine that most algorithms rely on the concept in one way or
another. Yet the Swift standard library already implements many generic
algorithms but has no DefaultConstructible, presumably because there are
other protocols that guarantee `init()` and the algorithms being
implemented don't need to be (practically speaking) generic over all
DefaultConstructible types. My question is: what practical use cases are
there for an explicit DefaultConstructible that are impractical today?

On Sun, Dec 25, 2016 at 11:37 AM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

Can you give some other examples of generic algorithms that would make
use of this DefaultConstructible? I'm having trouble coming up with any
other than reduce.
On Sun, Dec 25, 2016 at 14:23 Adam Nemecek via swift-evolution < >>> swift-evolution@swift.org> wrote:

This protocol is present in C++ http://en.cppreference.com
/w/cpp/concept/DefaultConstructible as well as in Rust
https://doc.rust-lang.org/std/default/

It's the identity element/unit of a monoid or a zero.

The Swift implementation is very simple (I'm open to different names)

protocol DefaultConstructible {
    init()
}

A lot of the standard types could then be made to conform to this
protocol. These include all the numeric types, collection types (array,
set, dict), string, basically at least every type that currently has a
constructor without any arguments.

The RangeReplaceableCollection protocol would inherit from this
protocol as well.

This protocol would simplify a lot of generic algorithms where you need
the concept of a zero (which shows up a lot)

Once introduced, Sequence could define an alternative implementation of
reduce where the initial result doesn't need to be provided as it can be
default constructed.

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


(Chris Lattner) #6

Does enabling a lot of small improvements that make APIs more ergonomic count as practical?

Yes, that would count as practical, but Xiaodi’s question is just as important. *Which* APIs become more ergonomic?

Here are a couple of more questions:

1) How does this square with Swift’s general philosophy to not default initialize values to “zero”?

2) To your original example, it isn’t immediately clear to me that reduce should choose a default identity. Some types (e.g. integers and FP) belong to multiple different ring algebras, and therefore have different identity values that correspond to the relevant binary operations.

-Chris

···

On Dec 25, 2016, at 12:54 PM, Adam Nemecek via swift-evolution <swift-evolution@swift.org> wrote:

On Sun, Dec 25, 2016 at 12:19 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:
On Sun, Dec 25, 2016 at 3:07 PM, Adam Nemecek <adamnemecek@gmail.com <mailto:adamnemecek@gmail.com>> wrote:
There's a book that provides quite a bit of info on this

https://smile.amazon.com/Elements-Programming-Alexander-Stepanov/dp/032163537X?sa-no-redirect=1 <https://smile.amazon.com/Elements-Programming-Alexander-Stepanov/dp/032163537X?sa-no-redirect=1>

They say that DefaultConstructible is one of the essential protocols on which most algorithms rely in one way or another. One of the authors is the designer of the C++ STL and basically the father of modern generics.

This protocol is important for any algebraic structure that deals with the concept of appending or addition (as "zero" is one of the requirements of monoid). There isn't a good short answer to your question. It's a building block of algorithms. Think about why a RangeReplaceableCollection can provide you with a default constructor but a Collection can't.

It's well and fine that most algorithms rely on the concept in one way or another. Yet the Swift standard library already implements many generic algorithms but has no DefaultConstructible, presumably because there are other protocols that guarantee `init()` and the algorithms being implemented don't need to be (practically speaking) generic over all DefaultConstructible types. My question is: what practical use cases are there for an explicit DefaultConstructible that are impractical today?

On Sun, Dec 25, 2016 at 11:37 AM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:
Can you give some other examples of generic algorithms that would make use of this DefaultConstructible? I'm having trouble coming up with any other than reduce.
On Sun, Dec 25, 2016 at 14:23 Adam Nemecek via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
This protocol is present in C++ http://en.cppreference.com/w/cpp/concept/DefaultConstructible as well as in Rust https://doc.rust-lang.org/std/default/

It's the identity element/unit of a monoid or a zero.

The Swift implementation is very simple (I'm open to different names)

protocol DefaultConstructible {
    init()
}

A lot of the standard types could then be made to conform to this protocol. These include all the numeric types, collection types (array, set, dict), string, basically at least every type that currently has a constructor without any arguments.

The RangeReplaceableCollection protocol would inherit from this protocol as well.

This protocol would simplify a lot of generic algorithms where you need the concept of a zero (which shows up a lot)

Once introduced, Sequence could define an alternative implementation of reduce where the initial result doesn't need to be provided as it can be default constructed.

_______________________________________________
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
https://lists.swift.org/mailman/listinfo/swift-evolution


(Adam Nemecek) #7

*Which* APIs become more ergonomic?

I'll get back to this question in a second if I may. This would be a longer
discussion and I first want to make sure that before we get into the
details that there is a possibility of this being introduced (I'm asking if
violating the no zero defaults is more important than slightly more
ergonomic APIs). But to give a broad answer I think that the concept of a
zero is closely related to the concept of equality (and all the things that
build up on equality such as comparability and negation).

1) How does this square with Swift’s general philosophy to not default

initialize values to “zero”?

I actually wasn't aware of this philosophy. Despite this philosophy, look
at how many types actually currently implement a default constructor. Also
can I ask what's the motivation behind this philosophy?
I think that in Swift, default constructibility makes complete sense for
(most?) structs, maybe less so for classes.

2) To your original example, it isn’t immediately clear to me that reduce

should choose a default identity. Some types (e.g. integers and FP) belong
to multiple different ring algebras, and therefore have different identity
values that correspond to the relevant binary operations.

This is a good point that I've considered as well but felt that for the
most part, there is one particular identity and associated operation that
is more prominent and useful than others. Furthermore, modeling different
algebras isn't mutually exclusive with writing generic algorithms that rely
on this protocol, you can always introduce some monoidic wrapper type that
defines the more appropriate default value and operation.

···

On Sun, Dec 25, 2016 at 1:24 PM, Chris Lattner <clattner@apple.com> wrote:

On Dec 25, 2016, at 12:54 PM, Adam Nemecek via swift-evolution < > swift-evolution@swift.org> wrote:

Does enabling a lot of small improvements that make APIs more ergonomic
count as practical?

Yes, that would count as practical, but Xiaodi’s question is just as
important. *Which* APIs become more ergonomic?

Here are a couple of more questions:

1) How does this square with Swift’s general philosophy to not default
initialize values to “zero”?

2) To your original example, it isn’t immediately clear to me that reduce
should choose a default identity. Some types (e.g. integers and FP) belong
to multiple different ring algebras, and therefore have different identity
values that correspond to the relevant binary operations.

-Chris

On Sun, Dec 25, 2016 at 12:19 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

On Sun, Dec 25, 2016 at 3:07 PM, Adam Nemecek <adamnemecek@gmail.com> >> wrote:

There's a book that provides quite a bit of info on this

https://smile.amazon.com/Elements-Programming-Alexander-Step
anov/dp/032163537X?sa-no-redirect=1

They say that DefaultConstructible is one of the essential protocols on
which most algorithms rely in one way or another. One of the authors is the
designer of the C++ STL and basically the father of modern generics.

This protocol is important for any algebraic structure that deals with
the concept of appending or addition (as "zero" is one of the requirements
of monoid). There isn't a good short answer to your question. It's a
building block of algorithms. Think about why a RangeReplaceableCollection
can provide you with a default constructor but a Collection can't.

It's well and fine that most algorithms rely on the concept in one way or
another. Yet the Swift standard library already implements many generic
algorithms but has no DefaultConstructible, presumably because there are
other protocols that guarantee `init()` and the algorithms being
implemented don't need to be (practically speaking) generic over all
DefaultConstructible types. My question is: what practical use cases are
there for an explicit DefaultConstructible that are impractical today?

On Sun, Dec 25, 2016 at 11:37 AM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

Can you give some other examples of generic algorithms that would make
use of this DefaultConstructible? I'm having trouble coming up with any
other than reduce.
On Sun, Dec 25, 2016 at 14:23 Adam Nemecek via swift-evolution < >>>> swift-evolution@swift.org> wrote:

This protocol is present in C++ http://en.cppreference.com
/w/cpp/concept/DefaultConstructible as well as in Rust
https://doc.rust-lang.org/std/default/

It's the identity element/unit of a monoid or a zero.

The Swift implementation is very simple (I'm open to different names)

protocol DefaultConstructible {
    init()
}

A lot of the standard types could then be made to conform to this
protocol. These include all the numeric types, collection types (array,
set, dict), string, basically at least every type that currently has a
constructor without any arguments.

The RangeReplaceableCollection protocol would inherit from this
protocol as well.

This protocol would simplify a lot of generic algorithms where you
need the concept of a zero (which shows up a lot)

Once introduced, Sequence could define an alternative implementation
of reduce where the initial result doesn't need to be provided as it can be
default constructed.

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

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


(David Sweeris) #8

Would generic protocols solve #2? "func addStuff<T: Addable&HasIdentity<Addable>> (...) -> T {...}"? If so, does that affect the reasoning behind #1?

- Dave Sweeris

···

On Dec 25, 2016, at 13:24, Chris Lattner via swift-evolution <swift-evolution@swift.org> wrote:

On Dec 25, 2016, at 12:54 PM, Adam Nemecek via swift-evolution <swift-evolution@swift.org> wrote:
Does enabling a lot of small improvements that make APIs more ergonomic count as practical?

Yes, that would count as practical, but Xiaodi’s question is just as important. *Which* APIs become more ergonomic?

Here are a couple of more questions:

1) How does this square with Swift’s general philosophy to not default initialize values to “zero”?

2) To your original example, it isn’t immediately clear to me that reduce should choose a default identity. Some types (e.g. integers and FP) belong to multiple different ring algebras, and therefore have different identity values that correspond to the relevant binary operations.


(Dave Abrahams) #9

There's a book that provides quite a bit of info on this

https://smile.amazon.com/Elements-Programming-Alexander-Stepanov/dp/
032163537X?sa-no-redirect=1

They say that DefaultConstructible is one of the essential protocols on
which most algorithms rely in one way or another. One of the authors is the
designer of the C++ STL and basically the father of modern generics.

This protocol is important for any algebraic structure that deals with the
concept of appending or addition (as "zero" is one of the requirements of
monoid). There isn't a good short answer to your question. It's a building
block of algorithms. Think about why a RangeReplaceableCollection can
provide you with a default constructor but a Collection can't.

It's well and fine that most algorithms rely on the concept in one way or
another. Yet the Swift standard library already implements many generic
algorithms but has no DefaultConstructible, presumably because there are
other protocols that guarantee `init()` and the algorithms being
implemented don't need to be (practically speaking) generic over all
DefaultConstructible types. My question is: what practical use cases are
there for an explicit DefaultConstructible that are impractical today?

Actually we have included it in RangeReplaceableCollection because
init() + replaceSubrange() is a really powerful combination that lets
you implement things like initialization from any other collection of
the same element type.

However, though I hate to disagree with Alex, I don't really think
default constructibility is as fundamental as he says it is. It almost
never shows up as a requirement in most algorithms I've seen, and I
don't like the idea of folding it into a standard base grouping of
requirements such as “Regular” because it effectively weakens the
invariants of the things that have to conform. How do you
default-construct a CollectionOfOne, for example? You can't; you'd have
to add an “invalid” state that is otherwise unnecessary. Also, outside
of a protocol like Monoid, where it has a relationship to the operator,
there's no obvious semantics to attach to default construction.
Protocols (a.k.a. concepts) are not just bags of syntax; unless you can
attach semantics to the operations, you can't write useful generic
algorithms against them. So we shouldn't have DefaultConstructible for
the same reason we shouldn't have “Plusable” to represent something that
lets you write x + x.

Can you give some other examples of generic algorithms that would make
use of this DefaultConstructible? I'm having trouble coming up with any
other than reduce.

This protocol is present in C++ http://en.cppreference.com
/w/cpp/concept/DefaultConstructible as well as in Rust
https://doc.rust-lang.org/std/default/

It's the identity element/unit of a monoid or a zero.

The Swift implementation is very simple (I'm open to different names)

protocol DefaultConstructible {
    init()
}

A lot of the standard types could then be made to conform to this
protocol. These include all the numeric types, collection types (array,
set, dict), string, basically at least every type that currently has a
constructor without any arguments.

The RangeReplaceableCollection protocol would inherit from this protocol
as well.

This protocol would simplify a lot of generic algorithms where you need
the concept of a zero (which shows up a lot)

Once introduced, Sequence could define an alternative implementation of
reduce where the initial result doesn't need to be provided as it can be
default constructed.

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

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

Cheers,

···

on Sun Dec 25 2016, Xiaodi Wu <swift-evolution@swift.org> wrote:

On Sun, Dec 25, 2016 at 3:07 PM, Adam Nemecek > <adamnemecek@gmail.com> wrote:
On Sun, Dec 25, 2016 at 11:37 AM, Xiaodi Wu <xiaodi.wu@gmail.com> > wrote:

On Sun, Dec 25, 2016 at 14:23 Adam Nemecek via swift-evolution < >>> swift-evolution@swift.org> wrote:

--
-Dave


(Dave Abrahams) #10

There's a book that provides quite a bit of info on this

https://smile.amazon.com/Elements-Programming-Alexander-Stepanov/dp/
032163537X?sa-no-redirect=1

They say that DefaultConstructible is one of the essential protocols on
which most algorithms rely in one way or another. One of the authors is the
designer of the C++ STL and basically the father of modern generics.

This protocol is important for any algebraic structure that deals with the
concept of appending or addition (as "zero" is one of the requirements of
monoid). There isn't a good short answer to your question. It's a building
block of algorithms. Think about why a RangeReplaceableCollection can
provide you with a default constructor but a Collection can't.

It's well and fine that most algorithms rely on the concept in one way or
another.

Well, I challenge that premise. There are actually very few that depend
on it AFAICT, and for those that do, there's often no obvious semantics.
For example, for numbers, should default construction produce the
additive identity (0) or multiplicative identity (1), and why?

···

on Sun Dec 25 2016, Xiaodi Wu <swift-evolution@swift.org> wrote:

On Sun, Dec 25, 2016 at 3:07 PM, Adam Nemecek > <adamnemecek@gmail.com> wrote:

Yet the Swift standard library already implements many generic
algorithms but has no DefaultConstructible, presumably because there
are other protocols that guarantee `init()` and the algorithms being
implemented don't need to be (practically speaking) generic over all
DefaultConstructible types. My question is: what practical use cases
are there for an explicit DefaultConstructible that are impractical
today?

On Sun, Dec 25, 2016 at 11:37 AM, Xiaodi Wu <xiaodi.wu@gmail.com> > wrote:

Can you give some other examples of generic algorithms that would make
use of this DefaultConstructible? I'm having trouble coming up with any
other than reduce.
On Sun, Dec 25, 2016 at 14:23 Adam Nemecek via swift-evolution < >>> swift-evolution@swift.org> wrote:

This protocol is present in C++ http://en.cppreference.com
/w/cpp/concept/DefaultConstructible as well as in Rust
https://doc.rust-lang.org/std/default/

It's the identity element/unit of a monoid or a zero.

The Swift implementation is very simple (I'm open to different names)

protocol DefaultConstructible {
    init()
}

A lot of the standard types could then be made to conform to this
protocol. These include all the numeric types, collection types (array,
set, dict), string, basically at least every type that currently has a
constructor without any arguments.

The RangeReplaceableCollection protocol would inherit from this protocol
as well.

This protocol would simplify a lot of generic algorithms where you need
the concept of a zero (which shows up a lot)

Once introduced, Sequence could define an alternative implementation of
reduce where the initial result doesn't need to be provided as it can be
default constructed.

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

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

--
-Dave


(Xiaodi Wu) #11

There's a book that provides quite a bit of info on this

https://smile.amazon.com/Elements-Programming-Alexander-Stepanov/dp/
032163537X?sa-no-redirect=1

They say that DefaultConstructible is one of the essential protocols on
which most algorithms rely in one way or another. One of the authors is the
designer of the C++ STL and basically the father of modern generics.

This protocol is important for any algebraic structure that deals with the
concept of appending or addition (as "zero" is one of the requirements of
monoid). There isn't a good short answer to your question. It's a building
block of algorithms. Think about why a RangeReplaceableCollection can
provide you with a default constructor but a Collection can't.

It's well and fine that most algorithms rely on the concept in one way or
another. Yet the Swift standard library already implements many generic
algorithms but has no DefaultConstructible, presumably because there are
other protocols that guarantee `init()` and the algorithms being
implemented don't need to be (practically speaking) generic over all
DefaultConstructible types. My question is: what practical use cases are
there for an explicit DefaultConstructible that are impractical today?

···

On Sun, Dec 25, 2016 at 3:07 PM, Adam Nemecek <adamnemecek@gmail.com> wrote:

On Sun, Dec 25, 2016 at 11:37 AM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

Can you give some other examples of generic algorithms that would make
use of this DefaultConstructible? I'm having trouble coming up with any
other than reduce.
On Sun, Dec 25, 2016 at 14:23 Adam Nemecek via swift-evolution < >> swift-evolution@swift.org> wrote:

This protocol is present in C++ http://en.cppreference.com
/w/cpp/concept/DefaultConstructible as well as in Rust
https://doc.rust-lang.org/std/default/

It's the identity element/unit of a monoid or a zero.

The Swift implementation is very simple (I'm open to different names)

protocol DefaultConstructible {
    init()
}

A lot of the standard types could then be made to conform to this
protocol. These include all the numeric types, collection types (array,
set, dict), string, basically at least every type that currently has a
constructor without any arguments.

The RangeReplaceableCollection protocol would inherit from this protocol
as well.

This protocol would simplify a lot of generic algorithms where you need
the concept of a zero (which shows up a lot)

Once introduced, Sequence could define an alternative implementation of
reduce where the initial result doesn't need to be provided as it can be
default constructed.

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


(Adam Nemecek) #12

Is it well settled, either in Swift or in C++/Rust/etc., that the value

returned by a default initializer/constructor is regarded as an identity
element or zero?

Int() == 0, String() == "" so to some extent by convention, a lot of types
have a default value as is.

Is the thread that I get by writing `let t = Thread()` some kind of zero

in any reasonable sense of the word?

DefaultConstructibility makes less sense for types that represent some sort
of resource but make sense for things that are values. But even in this
case, Thread() gives you a default value for example if you are working
with a resizable collection of threads. A better question is why does
thread currently implement a default constructor?

Do you mean to argue that for an integer the additive identity should be

considered "more prominent and useful" than the multiplicative identity?
I'm not aware of any mathematical justification for such a conclusion.

I do. The justification is that if I call the default constructor of Int
currently, I get the value of 0. Which means that the binary operation must
be addition. If I call String() I get "" which is the identity of the +
String operation.

Going to your original example, I should add: other languages provide a

version of `reduce` that doesn't require an initial result (for instance,
JavaScript). In JavaScript, `[1, 2, 3].reduce((a, b) => a + b)` uses the
element at array index 0 as the initial result, and the accumulator
function is invoked starting with the element at array index 1. This is
precisely equivalent to having `reduce` use the additive identity as the
default initial result when + is the accumulator function and the
multiplicative identity when * is the accumulator function (with the
accumulator function being invoked starting with the element at array index
0). It does not require a DefaultConstructible protocol. What more
ergonomic solution could be implemented using a monoidic wrapper type?

These two will have different signatures. The reduce you describe returns
an optional, the other one would returns the default value. Fundamentally
the default constructibles are useful in numerical computations e..g.
dealing with tensors.

···

On Sun, Dec 25, 2016 at 3:30 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

On Sun, Dec 25, 2016 at 5:27 PM, Adam Nemecek <adamnemecek@gmail.com> > wrote:

> *Which* APIs become more ergonomic?

I'll get back to this question in a second if I may. This would be a
longer discussion and I first want to make sure that before we get into the
details that there is a possibility of this being introduced (I'm asking if
violating the no zero defaults is more important than slightly more
ergonomic APIs). But to give a broad answer I think that the concept of a
zero is closely related to the concept of equality (and all the things that
build up on equality such as comparability and negation).

> 1) How does this square with Swift’s general philosophy to not default
initialize values to “zero”?

I actually wasn't aware of this philosophy. Despite this philosophy, look
at how many types actually currently implement a default constructor.

(Not a rhetorical question:) Is it well settled, either in Swift or in
C++/Rust/etc., that the value returned by a default initializer/constructor
is regarded as an identity element or zero? Is the thread that I get by
writing `let t = Thread()` some kind of zero in any reasonable sense of the
word?

Also can I ask what's the motivation behind this philosophy?
I think that in Swift, default constructibility makes complete sense for
(most?) structs, maybe less so for classes.

> 2) To your original example, it isn’t immediately clear to me that
reduce should choose a default identity. Some types (e.g. integers and FP)
belong to multiple different ring algebras, and therefore have different
identity values that correspond to the relevant binary operations.

This is a good point that I've considered as well but felt that for the
most part, there is one particular identity and associated operation that
is more prominent and useful than others. Furthermore, modeling different
algebras isn't mutually exclusive with writing generic algorithms that rely
on this protocol, you can always introduce some monoidic wrapper type that
defines the more appropriate default value and operation.

Do you mean to argue that for an integer the additive identity should be
considered "more prominent and useful" than the multiplicative identity?
I'm not aware of any mathematical justification for such a conclusion.

Going to your original example, I should add: other languages provide a
version of `reduce` that doesn't require an initial result (for instance,
JavaScript). In JavaScript, `[1, 2, 3].reduce((a, b) => a + b)` uses the
element at array index 0 as the initial result, and the accumulator
function is invoked starting with the element at array index 1. This is
precisely equivalent to having `reduce` use the additive identity as the
default initial result when + is the accumulator function and the
multiplicative identity when * is the accumulator function (with the
accumulator function being invoked starting with the element at array index
0). It does not require a DefaultConstructible protocol. What more
ergonomic solution could be implemented using a monoidic wrapper type?

On Sun, Dec 25, 2016 at 1:24 PM, Chris Lattner <clattner@apple.com> wrote:

On Dec 25, 2016, at 12:54 PM, Adam Nemecek via swift-evolution < >>> swift-evolution@swift.org> wrote:

Does enabling a lot of small improvements that make APIs more ergonomic
count as practical?

Yes, that would count as practical, but Xiaodi’s question is just as
important. *Which* APIs become more ergonomic?

Here are a couple of more questions:

1) How does this square with Swift’s general philosophy to not default
initialize values to “zero”?

2) To your original example, it isn’t immediately clear to me that
reduce should choose a default identity. Some types (e.g. integers and FP)
belong to multiple different ring algebras, and therefore have different
identity values that correspond to the relevant binary operations.

-Chris

On Sun, Dec 25, 2016 at 12:19 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

On Sun, Dec 25, 2016 at 3:07 PM, Adam Nemecek <adamnemecek@gmail.com> >>>> wrote:

There's a book that provides quite a bit of info on this

https://smile.amazon.com/Elements-Programming-Alexander-Step
anov/dp/032163537X?sa-no-redirect=1

They say that DefaultConstructible is one of the essential protocols
on which most algorithms rely in one way or another. One of the authors is
the designer of the C++ STL and basically the father of modern generics.

This protocol is important for any algebraic structure that deals with
the concept of appending or addition (as "zero" is one of the requirements
of monoid). There isn't a good short answer to your question. It's a
building block of algorithms. Think about why a RangeReplaceableCollection
can provide you with a default constructor but a Collection can't.

It's well and fine that most algorithms rely on the concept in one way
or another. Yet the Swift standard library already implements many generic
algorithms but has no DefaultConstructible, presumably because there are
other protocols that guarantee `init()` and the algorithms being
implemented don't need to be (practically speaking) generic over all
DefaultConstructible types. My question is: what practical use cases are
there for an explicit DefaultConstructible that are impractical today?

On Sun, Dec 25, 2016 at 11:37 AM, Xiaodi Wu <xiaodi.wu@gmail.com> >>>>> wrote:

Can you give some other examples of generic algorithms that would
make use of this DefaultConstructible? I'm having trouble coming up with
any other than reduce.
On Sun, Dec 25, 2016 at 14:23 Adam Nemecek via swift-evolution < >>>>>> swift-evolution@swift.org> wrote:

This protocol is present in C++ http://en.cppreference.com
/w/cpp/concept/DefaultConstructible as well as in Rust
https://doc.rust-lang.org/std/default/

It's the identity element/unit of a monoid or a zero.

The Swift implementation is very simple (I'm open to different names)

protocol DefaultConstructible {
    init()
}

A lot of the standard types could then be made to conform to this
protocol. These include all the numeric types, collection types (array,
set, dict), string, basically at least every type that currently has a
constructor without any arguments.

The RangeReplaceableCollection protocol would inherit from this
protocol as well.

This protocol would simplify a lot of generic algorithms where you
need the concept of a zero (which shows up a lot)

Once introduced, Sequence could define an alternative implementation
of reduce where the initial result doesn't need to be provided as it can be
default constructed.

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

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


(Xiaodi Wu) #13

> *Which* APIs become more ergonomic?

I'll get back to this question in a second if I may. This would be a
longer discussion and I first want to make sure that before we get into the
details that there is a possibility of this being introduced (I'm asking if
violating the no zero defaults is more important than slightly more
ergonomic APIs). But to give a broad answer I think that the concept of a
zero is closely related to the concept of equality (and all the things that
build up on equality such as comparability and negation).

> 1) How does this square with Swift’s general philosophy to not default
initialize values to “zero”?

I actually wasn't aware of this philosophy. Despite this philosophy, look
at how many types actually currently implement a default constructor.

(Not a rhetorical question:) Is it well settled, either in Swift or in
C++/Rust/etc., that the value returned by a default initializer/constructor
is regarded as an identity element or zero? Is the thread that I get by
writing `let t = Thread()` some kind of zero in any reasonable sense of the
word?

Also can I ask what's the motivation behind this philosophy?
I think that in Swift, default constructibility makes complete sense for
(most?) structs, maybe less so for classes.

> 2) To your original example, it isn’t immediately clear to me that
reduce should choose a default identity. Some types (e.g. integers and FP)
belong to multiple different ring algebras, and therefore have different
identity values that correspond to the relevant binary operations.

This is a good point that I've considered as well but felt that for the
most part, there is one particular identity and associated operation that
is more prominent and useful than others. Furthermore, modeling different
algebras isn't mutually exclusive with writing generic algorithms that rely
on this protocol, you can always introduce some monoidic wrapper type that
defines the more appropriate default value and operation.

Do you mean to argue that for an integer the additive identity should be
considered "more prominent and useful" than the multiplicative identity?
I'm not aware of any mathematical justification for such a conclusion.

Going to your original example, I should add: other languages provide a
version of `reduce` that doesn't require an initial result (for instance,
JavaScript). In JavaScript, `[1, 2, 3].reduce((a, b) => a + b)` uses the
element at array index 0 as the initial result, and the accumulator
function is invoked starting with the element at array index 1. This is
precisely equivalent to having `reduce` use the additive identity as the
default initial result when + is the accumulator function and the
multiplicative identity when * is the accumulator function (with the
accumulator function being invoked starting with the element at array index
0). It does not require a DefaultConstructible protocol. What more
ergonomic solution could be implemented using a monoidic wrapper type?

···

On Sun, Dec 25, 2016 at 5:27 PM, Adam Nemecek <adamnemecek@gmail.com> wrote:

On Sun, Dec 25, 2016 at 1:24 PM, Chris Lattner <clattner@apple.com> wrote:

On Dec 25, 2016, at 12:54 PM, Adam Nemecek via swift-evolution < >> swift-evolution@swift.org> wrote:

Does enabling a lot of small improvements that make APIs more ergonomic
count as practical?

Yes, that would count as practical, but Xiaodi’s question is just as
important. *Which* APIs become more ergonomic?

Here are a couple of more questions:

1) How does this square with Swift’s general philosophy to not default
initialize values to “zero”?

2) To your original example, it isn’t immediately clear to me that reduce
should choose a default identity. Some types (e.g. integers and FP) belong
to multiple different ring algebras, and therefore have different identity
values that correspond to the relevant binary operations.

-Chris

On Sun, Dec 25, 2016 at 12:19 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

On Sun, Dec 25, 2016 at 3:07 PM, Adam Nemecek <adamnemecek@gmail.com> >>> wrote:

There's a book that provides quite a bit of info on this

https://smile.amazon.com/Elements-Programming-Alexander-Step
anov/dp/032163537X?sa-no-redirect=1

They say that DefaultConstructible is one of the essential protocols on
which most algorithms rely in one way or another. One of the authors is the
designer of the C++ STL and basically the father of modern generics.

This protocol is important for any algebraic structure that deals with
the concept of appending or addition (as "zero" is one of the requirements
of monoid). There isn't a good short answer to your question. It's a
building block of algorithms. Think about why a RangeReplaceableCollection
can provide you with a default constructor but a Collection can't.

It's well and fine that most algorithms rely on the concept in one way
or another. Yet the Swift standard library already implements many generic
algorithms but has no DefaultConstructible, presumably because there are
other protocols that guarantee `init()` and the algorithms being
implemented don't need to be (practically speaking) generic over all
DefaultConstructible types. My question is: what practical use cases are
there for an explicit DefaultConstructible that are impractical today?

On Sun, Dec 25, 2016 at 11:37 AM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

Can you give some other examples of generic algorithms that would make
use of this DefaultConstructible? I'm having trouble coming up with any
other than reduce.
On Sun, Dec 25, 2016 at 14:23 Adam Nemecek via swift-evolution < >>>>> swift-evolution@swift.org> wrote:

This protocol is present in C++ http://en.cppreference.com
/w/cpp/concept/DefaultConstructible as well as in Rust
https://doc.rust-lang.org/std/default/

It's the identity element/unit of a monoid or a zero.

The Swift implementation is very simple (I'm open to different names)

protocol DefaultConstructible {
    init()
}

A lot of the standard types could then be made to conform to this
protocol. These include all the numeric types, collection types (array,
set, dict), string, basically at least every type that currently has a
constructor without any arguments.

The RangeReplaceableCollection protocol would inherit from this
protocol as well.

This protocol would simplify a lot of generic algorithms where you
need the concept of a zero (which shows up a lot)

Once introduced, Sequence could define an alternative implementation
of reduce where the initial result doesn't need to be provided as it can be
default constructed.

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

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


(Xiaodi Wu) #14

> Is it well settled, either in Swift or in C++/Rust/etc., that the value
returned by a default initializer/constructor is regarded as an identity
element or zero?

Int() == 0, String() == "" so to some extent by convention, a lot of types
have a default value as is.

Yes, those particular types have initializers that take no arguments. That
does not address my question. You merely restated your initial observation
that many types in Swift have implemented `init()`.

I didn't think the value returned by `init()` was regarded as any sort of
zero--or even any sort of "default." In fact, some types in Foundation have
a static property called `default` distinct from `init()`. In Rust, the
Default trait requires a function called `default()`, which is documented
as being useful when you want "some kind of default value, and don't
particularly care what it is."

I was asking whether there's some understanding, of which I've been
unaware, that the result of `init()` (or the equivalent in other languages)
is expected to be some sort of zero or an identity element. I'm not aware
of any evidence to that effect. Are you?

Is the thread that I get by writing `let t = Thread()` some kind of zero
in any reasonable sense of the word?

DefaultConstructibility makes less sense for types that represent some
sort of resource but make sense for things that are values. But even in
this case, Thread() gives you a default value for example if you are
working with a resizable collection of threads.

It gives you something different every time. How can this be squared with
your stated motivation regarding concepts of zero and concepts of equality?

A better question is why does thread currently implement a default

constructor?

It's an initializer that takes no arguments, because none are needed for a
new thread. How else would you write it?

Do you mean to argue that for an integer the additive identity should be
considered "more prominent and useful" than the multiplicative identity?
I'm not aware of any mathematical justification for such a conclusion.

I do. The justification is that if I call the default constructor of Int
currently, I get the value of 0.

This is backwards. Why do you believe that the value you obtain from
`init()` is intended to be an identity element at all, let alone the most
important one? (It's also circular reasoning. Since `init()` only ever
gives you one value at a time, by your reasoning it demonstrates that every
type must have one "more prominent and useful" identity, which is begging
the question.)

Which means that the binary operation must be addition.

Based on the value of `Int.init()`, you conclude that addition of integers
is a "more prominent and useful" operation than multiplication? Again, this
is backwards. Rather, we know that each numerical type belongs to multiple
ring algebras; there is no basis for reckoning any as "more useful." Since
`init()` can only ever give us one value at a time, we know that `init()`
cannot give a value that is a meaningful default with respect to any
particular operation.

If I call String() I get "" which is the identity of the + String operation.

Or, it's what you get because that's the most trivial possible string.
Quite simply, I do not think the designer of most types that implement
`init()` have paused to wonder whether the value that you get is the
identity element associated with the most useful and prominent operation
that can be performed on that type. I certainly never have.

Going to your original example, I should add: other languages provide a
version of `reduce` that doesn't require an initial result (for instance,
JavaScript). In JavaScript, `[1, 2, 3].reduce((a, b) => a + b)` uses the
element at array index 0 as the initial result, and the accumulator
function is invoked starting with the element at array index 1. This is
precisely equivalent to having `reduce` use the additive identity as the
default initial result when + is the accumulator function and the
multiplicative identity when * is the accumulator function (with the
accumulator function being invoked starting with the element at array index
0). It does not require a DefaultConstructible protocol. What more
ergonomic solution could be implemented using a monoidic wrapper type?

These two will have different signatures. The reduce you describe returns
an optional,

The statement I wrote was in JavaScript, so I'm not sure what you mean by
returning an optional. `[].reduce((a, b) => a + b)` results in an error in
JavaScript. In Swift, such a function may also be implemented with a
precondition that the array is not empty and would not return an optional.

the other one would returns the default value.

In what scenario would you prefer to propagate a default after reducing a
potential empty collection _without supplying an explicit default_ for that
operation? This would certainly violate the Swift convention of not
defaulting to zero and, I suspect, most users of Swift would not regard
that as ergonomic at all.

Fundamentally the default constructibles are useful in numerical
computations e..g. dealing with tensors.

Can you give an example of an algorithm dealing with tensors where you
would use a `DefaultConstructible` generic over all types that have
`init()`, as opposed to working with the existing `Integer`,
`FloatingPoint`, and other numerical protocols? (I should also add, FWIW, I
have never seen a generic algorithm written for integers or FP types that
has preferred the use of `T()` over `0`.)

···

On Sun, Dec 25, 2016 at 7:30 PM, Adam Nemecek <adamnemecek@gmail.com> wrote:

On Sun, Dec 25, 2016 at 3:30 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

On Sun, Dec 25, 2016 at 5:27 PM, Adam Nemecek <adamnemecek@gmail.com> >> wrote:

> *Which* APIs become more ergonomic?

I'll get back to this question in a second if I may. This would be a
longer discussion and I first want to make sure that before we get into the
details that there is a possibility of this being introduced (I'm asking if
violating the no zero defaults is more important than slightly more
ergonomic APIs). But to give a broad answer I think that the concept of a
zero is closely related to the concept of equality (and all the things that
build up on equality such as comparability and negation).

> 1) How does this square with Swift’s general philosophy to not
default initialize values to “zero”?

I actually wasn't aware of this philosophy. Despite this philosophy,
look at how many types actually currently implement a default constructor.

(Not a rhetorical question:) Is it well settled, either in Swift or in
C++/Rust/etc., that the value returned by a default initializer/constructor
is regarded as an identity element or zero? Is the thread that I get by
writing `let t = Thread()` some kind of zero in any reasonable sense of the
word?

Also can I ask what's the motivation behind this philosophy?
I think that in Swift, default constructibility makes complete sense for
(most?) structs, maybe less so for classes.

> 2) To your original example, it isn’t immediately clear to me that
reduce should choose a default identity. Some types (e.g. integers and FP)
belong to multiple different ring algebras, and therefore have different
identity values that correspond to the relevant binary operations.

This is a good point that I've considered as well but felt that for the
most part, there is one particular identity and associated operation that
is more prominent and useful than others. Furthermore, modeling different
algebras isn't mutually exclusive with writing generic algorithms that rely
on this protocol, you can always introduce some monoidic wrapper type that
defines the more appropriate default value and operation.

Do you mean to argue that for an integer the additive identity should be
considered "more prominent and useful" than the multiplicative identity?
I'm not aware of any mathematical justification for such a conclusion.

Going to your original example, I should add: other languages provide a
version of `reduce` that doesn't require an initial result (for instance,
JavaScript). In JavaScript, `[1, 2, 3].reduce((a, b) => a + b)` uses the
element at array index 0 as the initial result, and the accumulator
function is invoked starting with the element at array index 1. This is
precisely equivalent to having `reduce` use the additive identity as the
default initial result when + is the accumulator function and the
multiplicative identity when * is the accumulator function (with the
accumulator function being invoked starting with the element at array index
0). It does not require a DefaultConstructible protocol. What more
ergonomic solution could be implemented using a monoidic wrapper type?

On Sun, Dec 25, 2016 at 1:24 PM, Chris Lattner <clattner@apple.com> >>> wrote:

On Dec 25, 2016, at 12:54 PM, Adam Nemecek via swift-evolution < >>>> swift-evolution@swift.org> wrote:

Does enabling a lot of small improvements that make APIs more ergonomic
count as practical?

Yes, that would count as practical, but Xiaodi’s question is just as
important. *Which* APIs become more ergonomic?

Here are a couple of more questions:

1) How does this square with Swift’s general philosophy to not default
initialize values to “zero”?

2) To your original example, it isn’t immediately clear to me that
reduce should choose a default identity. Some types (e.g. integers and FP)
belong to multiple different ring algebras, and therefore have different
identity values that correspond to the relevant binary operations.

-Chris

On Sun, Dec 25, 2016 at 12:19 PM, Xiaodi Wu <xiaodi.wu@gmail.com> >>>> wrote:

On Sun, Dec 25, 2016 at 3:07 PM, Adam Nemecek <adamnemecek@gmail.com> >>>>> wrote:

There's a book that provides quite a bit of info on this

https://smile.amazon.com/Elements-Programming-Alexander-Step
anov/dp/032163537X?sa-no-redirect=1

They say that DefaultConstructible is one of the essential protocols
on which most algorithms rely in one way or another. One of the authors is
the designer of the C++ STL and basically the father of modern generics.

This protocol is important for any algebraic structure that deals
with the concept of appending or addition (as "zero" is one of the
requirements of monoid). There isn't a good short answer to your question.
It's a building block of algorithms. Think about why a
RangeReplaceableCollection can provide you with a default constructor but a
Collection can't.

It's well and fine that most algorithms rely on the concept in one way
or another. Yet the Swift standard library already implements many generic
algorithms but has no DefaultConstructible, presumably because there are
other protocols that guarantee `init()` and the algorithms being
implemented don't need to be (practically speaking) generic over all
DefaultConstructible types. My question is: what practical use cases are
there for an explicit DefaultConstructible that are impractical today?

On Sun, Dec 25, 2016 at 11:37 AM, Xiaodi Wu <xiaodi.wu@gmail.com> >>>>>> wrote:

Can you give some other examples of generic algorithms that would
make use of this DefaultConstructible? I'm having trouble coming up with
any other than reduce.
On Sun, Dec 25, 2016 at 14:23 Adam Nemecek via swift-evolution < >>>>>>> swift-evolution@swift.org> wrote:

This protocol is present in C++ http://en.cppreference.com
/w/cpp/concept/DefaultConstructible as well as in Rust
https://doc.rust-lang.org/std/default/

It's the identity element/unit of a monoid or a zero.

The Swift implementation is very simple (I'm open to different
names)

protocol DefaultConstructible {
    init()
}

A lot of the standard types could then be made to conform to this
protocol. These include all the numeric types, collection types (array,
set, dict), string, basically at least every type that currently has a
constructor without any arguments.

The RangeReplaceableCollection protocol would inherit from this
protocol as well.

This protocol would simplify a lot of generic algorithms where you
need the concept of a zero (which shows up a lot)

Once introduced, Sequence could define an alternative
implementation of reduce where the initial result doesn't need to be
provided as it can be default constructed.

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

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


(David Sweeris) #15

"Identity", but, at least for many numeric types, you'd need a mechanism for specifying which one you mean.

- Dave Sweeris

···

On Dec 26, 2016, at 11:12, Tino Heth via swift-evolution <swift-evolution@swift.org> wrote:

There is an older discussion that is somewhat linked to this topic:
"Removing the empty initialiser requirement from RangeReplaceableCollection"
https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160704/023642.html

Imho "DefaultConstructible" types can be very handy, but so far, it seems no one has presented a single use case that is important enough to justify the inclusion in the stdlib.
On the other hand, I'm quite sure that there's much functionality in the stdlib that many people consider as superfluous…

I guess adding the protocol wouldn't have a big impact on size, so for for me, the question is "Does this protocol confuse users of Swift?", which I'd answer with "yes, possibly" (unless someone comes up with a name that is more intuitive).


(Adam Nemecek) #16

The elements already have an Identity, the one that you get when you invoke
the default constructor. It's 0 for Int, "" for String.

···

On Mon, Dec 26, 2016 at 11:24 AM, David Sweeris <davesweeris@mac.com> wrote:

On Dec 26, 2016, at 11:12, Tino Heth via swift-evolution < > swift-evolution@swift.org> wrote:

There is an older discussion that is somewhat linked to this topic:
"Removing the empty initialiser requirement from
RangeReplaceableCollection"
https://lists.swift.org/pipermail/swift-evolution/
Week-of-Mon-20160704/023642.html

Imho "DefaultConstructible" types can be very handy, but so far, it seems
no one has presented a single use case that is important enough to justify
the inclusion in the stdlib.
On the other hand, I'm quite sure that there's much functionality in the
stdlib that many people consider as superfluous…

I guess adding the protocol wouldn't have a big impact on size, so for for
me, the question is "Does this protocol confuse users of Swift?", which I'd
answer with "yes, possibly" (unless someone comes up with a name that is
more intuitive).

"Identity", but, at least for many numeric types, you'd need a mechanism
for specifying which one you mean.

- Dave Sweeris


(Adam Nemecek) #17

For integers, 0 is an additive identity. Is there a reason it should be

given special treatment over 1, the multiplicative identity?

E.g. for statistical reasons. When I have a collection of users with age
etc it makes sense to ask what is the combined age of the collection? What
is the semantic meaning of multiplying their ages?

Mathematically, identities are associated with (type, operation) pairs,

not types alone.

Correct, however we aren't talking about mathematics, we are talking about
the implementation of a language that runs on very concrete architectures
where very concrete bit patterns mean very concrete things that are
unlikely to change any time soon.

···

On Mon, Dec 26, 2016 at 11:35 AM, Tony Allevato <allevato@google.com> wrote:

For integers, 0 is an additive identity. Is there a reason it should be
given special treatment over 1, the multiplicative identity? Historically
the only reason is because it has the all-clear bit pattern.

Mathematically, identities are associated with (type, operation) pairs,
not types alone.

This conversation has put me in the column of "numeric types shouldn't
have default initializers at all", personally.
On Mon, Dec 26, 2016 at 11:27 AM Adam Nemecek via swift-evolution < > swift-evolution@swift.org> wrote:

The elements already have an Identity, the one that you get when you
invoke the default constructor. It's 0 for Int, "" for String.

On Mon, Dec 26, 2016 at 11:24 AM, David Sweeris <davesweeris@mac.com> >> wrote:

On Dec 26, 2016, at 11:12, Tino Heth via swift-evolution < >> swift-evolution@swift.org> wrote:

There is an older discussion that is somewhat linked to this topic:
"Removing the empty initialiser requirement from
RangeReplaceableCollection"
https://lists.swift.org/pipermail/swift-evolution/
Week-of-Mon-20160704/023642.html

Imho "DefaultConstructible" types can be very handy, but so far, it seems
no one has presented a single use case that is important enough to justify
the inclusion in the stdlib.
On the other hand, I'm quite sure that there's much functionality in the
stdlib that many people consider as superfluous…

I guess adding the protocol wouldn't have a big impact on size, so for
for me, the question is "Does this protocol confuse users of Swift?", which
I'd answer with "yes, possibly" (unless someone comes up with a name that
is more intuitive).

"Identity", but, at least for many numeric types, you'd need a mechanism
for specifying which one you mean.

- Dave Sweeris

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


(David Sweeris) #18

I'd agree, except sometimes you need a T, any T, for when you want to create a "pre-sized" array for stuffing results into by index:
for i in ... {
    a[i] = ...
}
Simply saying "var a =[T](); a.reserveCapacity()" doesn't cut it because it'll still crash if you try to store anything in a[i] without somehow putting at least i+1 elements in the array first.

- Dave Sweeris

···

On Dec 26, 2016, at 11:35, Tony Allevato <allevato@google.com> wrote:

Mathematically, identities are associated with (type, operation) pairs, not types alone.

This conversation has put me in the column of "numeric types shouldn't have default initializers at all", personally.


(David Sweeris) #19

"Age" is an additional layer of semantics beyond just "a numerical value".

- Dave Sweeris

···

On Dec 26, 2016, at 11:42, Adam Nemecek <adamnemecek@gmail.com> wrote:

> For integers, 0 is an additive identity. Is there a reason it should be given special treatment over 1, the multiplicative identity?

E.g. for statistical reasons. When I have a collection of users with age etc it makes sense to ask what is the combined age of the collection? What is the semantic meaning of multiplying their ages?


(Adam Nemecek) #20

The all-zero bit pattern represents the integer zero—that's not the same

as whether it represents the best "default" value for an integer as a
higher-level concept, or whether such a default should exist in the first
place.

It represents a sensible value to initialize an int to when I want to
initialize an array of ints to a certain size. There is a reason why you
zero out memory but you don't "one out" memory.

That doesn't explain why the additive identity is more special than the

multiplicative one. It just argues that it's more convenient for a
particular use case.

Because the identity associated with the default initializer as is is the
additive identity which means the default operation is addition.

···

On Mon, Dec 26, 2016 at 11:57 AM, Tony Allevato <tony.allevato@gmail.com> wrote:

On Mon, Dec 26, 2016 at 11:43 AM Adam Nemecek via swift-evolution < > swift-evolution@swift.org> wrote:

> For integers, 0 is an additive identity. Is there a reason it should
be given special treatment over 1, the multiplicative identity?

E.g. for statistical reasons. When I have a collection of users with age
etc it makes sense to ask what is the combined age of the collection? What
is the semantic meaning of multiplying their ages?

That doesn't explain why the additive identity is more special than the
multiplicative one. It just argues that it's more convenient for a
particular use case.

I would turn your example around—if you're interested enough in thorough
type design that you feel that a DefaultConstructible protocol would be
useful here, then I offer that a better and safer design would be to create
an "Age" value type (or, more generally, measurement types with concepts of
units) if you want compile-time safety and limiting the supported
operations to only those that are sensical. "Int" is arguably too wide a
type to represent an age in a public API because it would allow two ages to
be multiplied together, as you said.

> Mathematically, identities are associated with (type, operation) pairs,
not types alone.

Correct, however we aren't talking about mathematics, we are talking
about the implementation of a language that runs on very concrete
architectures where very concrete bit patterns mean very concrete things
that are unlikely to change any time soon.

The all-zero bit pattern represents the integer zero—that's not the same
as whether it represents the best "default" value for an integer as a
higher-level concept, or whether such a default should exist in the first
place.

On Mon, Dec 26, 2016 at 11:35 AM, Tony Allevato <allevato@google.com> >> wrote:

For integers, 0 is an additive identity. Is there a reason it should be
given special treatment over 1, the multiplicative identity? Historically
the only reason is because it has the all-clear bit pattern.

Mathematically, identities are associated with (type, operation) pairs,
not types alone.

This conversation has put me in the column of "numeric types shouldn't
have default initializers at all", personally.
On Mon, Dec 26, 2016 at 11:27 AM Adam Nemecek via swift-evolution < >> swift-evolution@swift.org> wrote:

The elements already have an Identity, the one that you get when you
invoke the default constructor. It's 0 for Int, "" for String.

On Mon, Dec 26, 2016 at 11:24 AM, David Sweeris <davesweeris@mac.com> >> wrote:

On Dec 26, 2016, at 11:12, Tino Heth via swift-evolution < >> swift-evolution@swift.org> wrote:

There is an older discussion that is somewhat linked to this topic:
"Removing the empty initialiser requirement from
RangeReplaceableCollection"
https://lists.swift.org/pipermail/swift-evolution/Week-of-
Mon-20160704/023642.html

Imho "DefaultConstructible" types can be very handy, but so far, it seems
no one has presented a single use case that is important enough to justify
the inclusion in the stdlib.
On the other hand, I'm quite sure that there's much functionality in the
stdlib that many people consider as superfluous…

I guess adding the protocol wouldn't have a big impact on size, so for
for me, the question is "Does this protocol confuse users of Swift?", which
I'd answer with "yes, possibly" (unless someone comes up with a name that
is more intuitive).

"Identity", but, at least for many numeric types, you'd need a mechanism
for specifying which one you mean.

- Dave Sweeris

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

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