[swift 4] static libs/modular code, fixed-size arrays, ref/pointer to structs, pointers, numeric types


(Raphael Sebbe) #1

Heard about the Swift 4 thing, so here are a few thoughts about the current
version of Swift (3). We work on a sizeable code base, with a focus on
modular code that is shared across our apps. Sorry if these things have
been discussed already, just joined, and wanted to share a snapshot of our
experience.

1. Swift is very good for lots of stuff. My favorite is code clarity and
conciseness. Math code is great in Swift too (where I typically used
Obj-C++ previously). I can feel the potential of development going faster
and code getting safer at the same time. Love it.

2. Need for static libraries (or equivalent): let me give you an example of
how we organize our code. We have an image processing library, XXX, which
currently has 2 backends : XXX+Metal XXX+OpenGL. Orthogonal to that,
another extension allows JPEG file export using a third-party encoder,
XXX+JPEG. Another feature, for when we need to process video buffer,
XXX+CoreVideo which provides handling of native pixelbuffer. All of these
are curently made as static libraries (5 libs for XXX and extensions) that
can be linked into the app depending whether they are needed or not.
Framework could technically be used too, but that is both inefficient (why
link the code at runtime? Launch delay, etc.) and it does not scale (we'd
need 20 frameworks to build a single app).

Swift, with its extension concept, is very well suited to modular
development like this. We'd like to have a better option than frameworks to
build reusable libraries. It's not an ABI thing, we really don't care about
that, we use libs just to organize code, building them as a part of the
app, and *not* to provide precompiled libraries to some other developers.
Swift package manager does not work well within Xcode either at this time,
and has a number of constraints we don't want (like having a separate git
repo for each static lib -> that's not practical at all if you just have 1
or 2 files in that lib).

I met 4 people at WWDC from both Swift and Xcode teams, but I'm not sure
this topic went through. This is a major concern: organizing reusable code
efficiently is what will bring Swift into larger projects where it could
really shine. We're currently using a hack to enable modular development in
Swift (static libs), and that should be addressed as fast as possible, all
languages have that, we shouldn't wait for Swift 5 or 6 to get it. This is
by far our number one concern with Swift.

3. Fixed-size Arrays are missing. They are useful in some contexts like:
struct Quad { CGPoint corners[4]; }
using a let array makes values immutable, using a var Array makes array
*size* mutable, which is not what is needed here.

4. Reference/pointer to structs: accessing & modifying structs deep into
the model currently requires fully qualified path to the struct instance.
Fully qualifying an inner struct in your data model can be very tedious,
depending on model complexity.

For instance, with scoped access solutions made with Swift 3, you need to
cascade blocks if you need to access multiple inner structs, which doesn't
scale well as it creates code pyramids:

scopedAccess(&varA) {
     scopedAccess(&varB) {
          // modify varA & varB
     }
}

It's easily done in C/C++ using pointers/references. To make that better,
we'd need some kind of language support IMO.

5. Memory / pointer access, including casting. It's too verbose currently
IMO when compared to C. Should be better supported for a language that is
also targeting low-level (network, disk storage). A syntax that is both
fast (like C) and safe would be great.

6. Explicit casting between numeric types (CGFloat / Double / etc.) are
cumbersome, or Int and float types. Some kind of auto promotion would be
nice.

7. I'm also fan of async/await kind of stuff, asynchronous flows, etc., but
this has already been mentioned -> cool!

Thank you for reading.

Raphael

···

--
Raphael Sebbe, @rsebbe (twitter)
creaceed.com — Apps for Mac • iPhone • iPad


(Chris Lattner) #2

Heard about the Swift 4 thing, so here are a few thoughts about the current version of Swift (3). We work on a sizeable code base, with a focus on modular code that is shared across our apps. Sorry if these things have been discussed already, just joined, and wanted to share a snapshot of our experience.

This is great, thanks! Almost all of this are out of scope for Swift 4 stage 1, but this is great feedback. Here are some comments from me, not speaking for the core team:

1. Swift is very good for lots of stuff. My favorite is code clarity and conciseness. Math code is great in Swift too (where I typically used Obj-C++ previously). I can feel the potential of development going faster and code getting safer at the same time. Love it.

Great!

2. Need for static libraries (or equivalent): let me give you an example of how we organize our code. We have an image processing library, XXX, which currently has 2 backends : XXX+Metal XXX+OpenGL. Orthogonal to that, another extension allows JPEG file export using a third-party encoder, XXX+JPEG. Another feature, for when we need to process video buffer, XXX+CoreVideo which provides handling of native pixelbuffer. All of these are curently made as static libraries (5 libs for XXX and extensions) that can be linked into the app depending whether they are needed or not. Framework could technically be used too, but that is both inefficient (why link the code at runtime? Launch delay, etc.) and it does not scale (we'd need 20 frameworks to build a single app).

Makes sense. This is something that I’d personally like SwiftPM to explore. There is no specific reason that each swift package needs to be its own dylib. I know the SwiftPM team is aware of this, and maybe there will be time to tackle it over the next year.

3. Fixed-size Arrays are missing. They are useful in some contexts like:
struct Quad { CGPoint corners[4]; }
using a let array makes values immutable, using a var Array makes array *size* mutable, which is not what is needed here.

Yep, as James mentioned, this is sort-of handled with tuples today, but not satisfactorily (for a lot of reasons). We should do better here.

4. Reference/pointer to structs: accessing & modifying structs deep into the model currently requires fully qualified path to the struct instance. Fully qualifying an inner struct in your data model can be very tedious, depending on model complexity.

The memory ownership work that is part of Swift 4 stage 1 may improve this situation, by introducing the notion of mutable references. We’ll have to see how that works out.

5. Memory / pointer access, including casting. It's too verbose currently IMO when compared to C. Should be better supported for a language that is also targeting low-level (network, disk storage). A syntax that is both fast (like C) and safe would be great.
6. Explicit casting between numeric types (CGFloat / Double / etc.) are cumbersome, or Int and float types. Some kind of auto promotion would be nice.

Both of these are similar, I personally completely agree that we should have the ability to have “small fp” promote to “bigger fp” types. This could be modeled by being able to define subtype relationships between structs.

7. I'm also fan of async/await kind of stuff, asynchronous flows, etc., but this has already been mentioned -> cool!

Me too, I can’t wait to get there, but we have to stay focused :-)

-Chris

···

On Aug 3, 2016, at 11:11 AM, Raphael Sebbe via swift-evolution <swift-evolution@swift.org> wrote:


(James Froggatt) #3

You make some interesting points. My feedback's inline.

1. Swift is very good for lots of stuff. My favorite is code clarity and conciseness. Math code is great in Swift too (where I typically used Obj-C++ previously). I can feel the potential of development going faster and code getting safer at the same time. Love it.

Same. Another one of my favourites is optionals, and non-nullable references by default.

2. Need for static libraries (or equivalent): let me give you an example of how we organize our code. We have an image processing library, XXX, which currently has 2 backends : XXX+Metal XXX+OpenGL. Orthogonal to that, another extension allows JPEG file export using a third-party encoder, XXX+JPEG. Another feature, for when we need to process video buffer, XXX+CoreVideo which provides handling of native pixelbuffer. All of these are curently made as static libraries (5 libs for XXX and extensions) that can be linked into the app depending whether they are needed or not. Framework could technically be used too, but that is both inefficient (why link the code at runtime? Launch delay, etc.) and it does not scale (we'd need 20 frameworks to build a single app).

Swift, with its extension concept, is very well suited to modular development like this. We'd like to have a better option than frameworks to build reusable libraries. It's not an ABI thing, we really don't care about that, we use libs just to organize code, building them as a part of the app, and *not* to provide precompiled libraries to some other developers. Swift package manager does not work well within Xcode either at this time, and has a number of constraints we don't want (like having a separate git repo for each static lib -> that's not practical at all if you just have 1 or 2 files in that lib).

I met 4 people at WWDC from both Swift and Xcode teams, but I'm not sure this topic went through. This is a major concern: organizing reusable code efficiently is what will bring Swift into larger projects where it could really shine. We're currently using a hack to enable modular development in Swift (static libs), and that should be addressed as fast as possible, all languages have that, we shouldn't wait for Swift 5 or 6 to get it. This is by far our number one concern with Swift.

Agreed. Frameworks really aren't enough.

3. Fixed-size Arrays are missing. They are useful in some contexts like:
struct Quad { CGPoint corners[4]; }
using a let array makes values immutable, using a var Array makes array *size* mutable, which is not what is needed here.

What are your thoughts on using tuples for this?

typealias CGPoint4 = (CGPoint, CGPoint, CGPoint, CGPoint)

struct Quad { var corners: CGPoint4 }

var fixedLength = (point1, point2, point3, point4)
print(fixedLength.0)
print(fixedLength.4) //compiler error, not an element of the tuple

With shorthand declaration syntax, this would have the benefits of a fixed-length array with added compile-time safety. A previously suggested syntax was along the lines of '(CGPoint * 4)'.

4. Reference/pointer to structs: accessing & modifying structs deep into the model currently requires fully qualified path to the struct instance. Fully qualifying an inner struct in your data model can be very tedious, depending on model complexity.

For instance, with scoped access solutions made with Swift 3, you need to cascade blocks if you need to access multiple inner structs, which doesn't scale well as it creates code pyramids:

scopedAccess(&varA) {
     scopedAccess(&varB) {
          // modify varA & varB
     }
}
  
It's easily done in C/C++ using pointers/references. To make that better, we'd need some kind of language support IMO.

Could this be generalised, maybe with a reference-semantic ‘property accessor’?

Example:

let get: () -> Bool = #get(controller.view.isVisible)
print(get())

let set: (Bool) -> () = #set(controller.view.isVisible)
set(true)

let accessor: Lens<Bool> = #lens(controller.view.isVisible)
print(accessor.value)
accessor.value = true

This would have the added bonus of also tracking the reassignment of reference-type properties - in this example, if 'view' is reassigned, the referenced value is updated.

5. Memory / pointer access, including casting. It's too verbose currently IMO when compared to C. Should be better supported for a language that is also targeting low-level (network, disk storage). A syntax that is both fast (like C) and safe would be great.

Not familiar with low-level programming in Swift, but have you considered creating domain-specific operators?
For example, I imagine something like 'UnsafeMutablePointer(v)' could be reduced to '*v'.

6. Explicit casting between numeric types (CGFloat / Double / etc.) are cumbersome, or Int and float types. Some kind of auto promotion would be nice.

I think Swift generally favours being explicit, and while implicit conversion where no data loss occurs would be nice, it could also could be easily misused. This is a tricky problem.

7. I'm also fan of async/await kind of stuff, asynchronous flows, etc., but this has already been mentioned -> cool!

I would like to see some ideas in this area.
async/await never really clicked for me until I realised it's just syntactic sugar - 'await' actually ends the function, and everything below is an implicit callback. Personally I feel like Swift's trailing closure syntax makes callbacks lightweight enough that this isn't so much of an issue. Something focusing more on the memory-management and thread-safety aspects of asynchronous code does seem useful in the context of Swift.

···

Thank you for reading.

Raphael
--
Raphael Sebbe, @rsebbe (twitter)
creaceed.com — Apps for Mac • iPhone • iPad
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Ankit Agarwal) #4

Swift, with its extension concept, is very well suited to modular
development like this. We'd like to have a better option than frameworks to
build reusable libraries. It's not an ABI thing, we really don't care about
that, we use libs just to organize code, building them as a part of the
app, and *not* to provide precompiled libraries to some other developers.
Swift package manager does not work well within Xcode either at this time,
and has a number of constraints we don't want (like having a separate git
repo for each static lib -> that's not practical at all if you just have 1
or 2 files in that lib).

You don't need to create one repo for each static library. A SwiftPM
package consists of Modules. You can create any number of products
consisting of one or more modules using the Product API in manifest file.
for eg:

products += [Product(name: "StaticLibA", type: .Library(.Static), modules:
"Foo"), Product(name: "StaticLibB", type: .Library(.Static), modules:
"Foo", "Bar")]

···

--
Ankit


(Raphael Sebbe) #5

Thank you Chris, James.

I'm answering James feedback/questions below.

What are your thoughts on using tuples for this?

typealias CGPoint4 = (CGPoint, CGPoint, CGPoint, CGPoint)

struct Quad { var corners: CGPoint4 }

var fixedLength = (point1, point2, point3, point4)
print(fixedLength.0)
print(fixedLength.4) //compiler error, not an element of the tuple

With shorthand declaration syntax, this would have the benefits of a
fixed-length array with added compile-time safety. A previously suggested
syntax was along the lines of '(CGPoint * 4)'.

I investigated tuples a bit, it's close. The one thing I'd need is being
able to index the values using a variable. The tuple.i notation apparently
doesn't work (or I did not try hard enough). Also, for low-level things
that will be mapped to GPU memory, precise/predictable/settable alignment
is needed.

4. Reference/pointer to structs: accessing & modifying structs deep into
the model currently requires fully qualified path to the struct instance.
Fully qualifying an inner struct in your data model can be very tedious,
depending on model complexity.

For instance, with scoped access solutions made with Swift 3, you need to
cascade blocks if you need to access multiple inner structs, which doesn't
scale well as it creates code pyramids:

scopedAccess(&varA) {
     scopedAccess(&varB) {
          // modify varA & varB
     }
}

It's easily done in C/C++ using pointers/references. To make that better,
we'd need some kind of language support IMO.

Could this be generalised, maybe with a reference-semantic ‘property
accessor’?

Example:

let get: () -> Bool = #get(controller.view.isVisible)
print(get())

let set: (Bool) -> () = #set(controller.view.isVisible)
set(true)

let accessor: Lens<Bool> = #lens(controller.view.isVisible)
print(accessor.value)
accessor.value = true

This would have the added bonus of also tracking the reassignment of
reference-type properties - in this example, if 'view' is reassigned, the
referenced value is updated.

Sounds good, I'm not aware of this syntax. Will investigate, thanks.

5. Memory / pointer access, including casting. It's too verbose currently
IMO when compared to C. Should be better supported for a language that is
also targeting low-level (network, disk storage). A syntax that is both
fast (like C) and safe would be great.

Not familiar with low-level programming in Swift, but have you considered
creating domain-specific operators?
For example, I imagine something like 'UnsafeMutablePointer(v)' could be
reduced to '*v'.

Do you mean operator is available only within a limited scope? That would
be interesting, because I don't want to pollute global scope with such
all-purpose operator. Sounds that I need to investigate that as well.

7. I'm also fan of async/await kind of stuff, asynchronous flows, etc.,
but this has already been mentioned -> cool!

I would like to see some ideas in this area.
async/await never really clicked for me until I realised it's just
syntactic sugar - 'await' actually ends the function, and everything below
is an implicit callback. Personally I feel like Swift's trailing closure
syntax makes callbacks lightweight enough that this isn't so much of an
issue. Something focusing more on the memory-management and thread-safety
aspects of asynchronous code does seem useful in the context of Swift.

Sure thread-safety, atomicity features would be really nice & useful.

The one problem I have with closure syntax (trailing or not, I like
trailing too), is that when you chain a few of them, which is pretty
frequent is async programming, you end up with a closure pyramid. It
doesn't scale well beyond 2 or 3 levels.

Raphael

···

On Thu, Aug 4, 2016 at 1:57 AM James Froggatt <james.froggatt@me.com> wrote:


(Raphael Sebbe) #6

thank you Ankit for that information.

Do you mean a single (SwiftPM) repository could handle the 5 static libs I
was mentioning in my first mail, with apps linking selectively with those,
as opposed to entire module/product? That'd be great.

Also, what about the state of integration in Xcode, can those setup
(SwiftPM packages) work somehow for development (including debugging, code
completion, etc), or is it something mostly distinct for now?

Thanks.

Raphael

···

On Fri, Aug 5, 2016 at 6:32 AM Ankit Agarwal <ankit@ankit.im> wrote:

Swift, with its extension concept, is very well suited to modular

development like this. We'd like to have a better option than frameworks to
build reusable libraries. It's not an ABI thing, we really don't care about
that, we use libs just to organize code, building them as a part of the
app, and *not* to provide precompiled libraries to some other developers.
Swift package manager does not work well within Xcode either at this time,
and has a number of constraints we don't want (like having a separate git
repo for each static lib -> that's not practical at all if you just have 1
or 2 files in that lib).

You don't need to create one repo for each static library. A SwiftPM
package consists of Modules. You can create any number of products
consisting of one or more modules using the Product API in manifest file.
for eg:

products += [Product(name: "StaticLibA", type: .Library(.Static), modules:
"Foo"), Product(name: "StaticLibB", type: .Library(.Static), modules:
"Foo", "Bar")]

--
Ankit


(James Froggatt) #7

Thank you Chris, James.

I'm answering James feedback/questions below.

What are your thoughts on using tuples for this?

typealias CGPoint4 = (CGPoint, CGPoint, CGPoint, CGPoint)

struct Quad { var corners: CGPoint4 }

var fixedLength = (point1, point2, point3, point4)
print(fixedLength.0)
print(fixedLength.4) //compiler error, not an element of the tuple

With shorthand declaration syntax, this would have the benefits of a fixed-length array with added compile-time safety. A previously suggested syntax was along the lines of '(CGPoint * 4)'.

I investigated tuples a bit, it's close. The one thing I'd need is being able to index the values using a variable. The tuple.i notation apparently doesn't work (or I did not try hard enough). Also, for low-level things that will be mapped to GPU memory, precise/predictable/settable alignment is needed.

Good point. A similar mechanism might be possible eventually for tuples, but right now this isn't possible.

4. Reference/pointer to structs: accessing & modifying structs deep into the model currently requires fully qualified path to the struct instance. Fully qualifying an inner struct in your data model can be very tedious, depending on model complexity.

For instance, with scoped access solutions made with Swift 3, you need to cascade blocks if you need to access multiple inner structs, which doesn't scale well as it creates code pyramids:

scopedAccess(&varA) {
     scopedAccess(&varB) {
          // modify varA & varB
     }
}
  
It's easily done in C/C++ using pointers/references. To make that better, we'd need some kind of language support IMO.

Could this be generalised, maybe with a reference-semantic ‘property accessor’?

Example:

let get: () -> Bool = #get(controller.view.isVisible)
print(get())

let set: (Bool) -> () = #set(controller.view.isVisible)
set(true)

let accessor: Lens<Bool> = #lens(controller.view.isVisible)
print(accessor.value)
accessor.value = true

This would have the added bonus of also tracking the reassignment of reference-type properties - in this example, if 'view' is reassigned, the referenced value is updated.

Sounds good, I'm not aware of this syntax. Will investigate, thanks.

Sorry, I was suggesting a *possible* syntax. No such syntax currently exists, though the functionality can be imitated with closures:

let get: () -> Bool = {controller.view.isVisible}
print(get())

let set: (Bool) -> () = {controller.view.isVisible = $0}
set(true)

struct Lens<T> {
  var get: () -> T
  var set: (T) -> ()
  var value: T { get { return get() } set { set(newValue) } }
}
let accessor: Lens<Bool> = Lens(get: {controller.view.isVisible}, set: {controller.view.visible = $0})
print(accessor.value)
accessor.value = true

It's a bit more verbose when creating the get-set accessor, and may not perform optimally, but it's actually pretty functional.

5. Memory / pointer access, including casting. It's too verbose currently IMO when compared to C. Should be better supported for a language that is also targeting low-level (network, disk storage). A syntax that is both fast (like C) and safe would be great.

Not familiar with low-level programming in Swift, but have you considered creating domain-specific operators?
For example, I imagine something like 'UnsafeMutablePointer(v)' could be reduced to '*v'.

Do you mean operator is available only within a limited scope? That would be interesting, because I don't want to pollute global scope with such all-purpose operator. Sounds that I need to investigate that as well.

If you have a specific module which performs this sort of operation a lot, you can just declare the operator as internal. If it's needed in several, making a separate module for the operators could be preferable.

7. I'm also fan of async/await kind of stuff, asynchronous flows, etc., but this has already been mentioned -> cool!

I would like to see some ideas in this area.
async/await never really clicked for me until I realised it's just syntactic sugar - 'await' actually ends the function, and everything below is an implicit callback. Personally I feel like Swift's trailing closure syntax makes callbacks lightweight enough that this isn't so much of an issue. Something focusing more on the memory-management and thread-safety aspects of asynchronous code does seem useful in the context of Swift.

Sure thread-safety, atomicity features would be really nice & useful.

The one problem I have with closure syntax (trailing or not, I like trailing too), is that when you chain a few of them, which is pretty frequent is async programming, you end up with a closure pyramid. It doesn't scale well beyond 2 or 3 levels.

Makes sense.

···

On 4 Aug 2016, at 13:00, Raphael Sebbe <raphael@creaceed.com> wrote:

On Thu, Aug 4, 2016 at 1:57 AM James Froggatt <james.froggatt@me.com> wrote:


(Manav Gabhawala) #8

> I investigated tuples a bit, it's close. The one thing I'd need is being able to index the values using a variable. The tuple.i notation apparently doesn't work (or I did not try hard enough). Also, for low-level things that will be mapped to GPU memory, precise/predictable/settable alignment is needed.

This might be a bit hacky but I just wanted to point out there exists a way to index into tuples. You can use the Mirror(reflecting: tuple).children syntax. You can loop over the values of the tuple and even though a bit awkward you can even use indices to index into the children.

Regards,
Manav Gabhawala

···

On August 4, 2016 at 5:18:13 AM, James Froggatt via swift-evolution (swift-evolution@swift.org(mailto:swift-evolution@swift.org)) wrote:

On 4 Aug 2016, at 13:00, Raphael Sebbe wrote:

> Thank you Chris, James.
>
> I'm answering James feedback/questions below.
>
> On Thu, Aug 4, 2016 at 1:57 AM James Froggatt wrote:
>
> > What are your thoughts on using tuples for this?
> >
> > typealias CGPoint4 = (CGPoint, CGPoint, CGPoint, CGPoint)
> >
> > struct Quad { var corners: CGPoint4 }
> >
> > var fixedLength = (point1, point2, point3, point4)
> > print(fixedLength.0)
> > print(fixedLength.4) //compiler error, not an element of the tuple
> >
> >
> > With shorthand declaration syntax, this would have the benefits of a fixed-length array with added compile-time safety. A previously suggested syntax was along the lines of '(CGPoint * 4)'.
> >
>
> I investigated tuples a bit, it's close. The one thing I'd need is being able to index the values using a variable. The tuple.i notation apparently doesn't work (or I did not try hard enough). Also, for low-level things that will be mapped to GPU memory, precise/predictable/settable alignment is needed.

Good point. A similar mechanism might be possible eventually for tuples, but right now this isn't possible.
> > > 4. Reference/pointer to structs: accessing & modifying structs deep into the model currently requires fully qualified path to the struct instance. Fully qualifying an inner struct in your data model can be very tedious, depending on model complexity.
> > >
> > > For instance, with scoped access solutions made with Swift 3, you need to cascade blocks if you need to access multiple inner structs, which doesn't scale well as it creates code pyramids:
> > >
> > > scopedAccess(&varA) {
> > > scopedAccess(&varB) {
> > > // modify varA & varB
> > > }
> > > }
> > >
> > > It's easily done in C/C++ using pointers/references. To make that better, we'd need some kind of language support IMO.
> > >
> > >
> >
> >
> > Could this be generalised, maybe with a reference-semantic ‘property accessor’?
> >
> > Example:
> >
> > let get: () -> Bool = #get(controller.view.isVisible)
> > print(get())
> >
> > let set: (Bool) -> () = #set(controller.view.isVisible)
> > set(true)
> >
> > let accessor: Lens = #lens(controller.view.isVisible)
> > print(accessor.value)
> > accessor.value = true
> >
> > This would have the added bonus of also tracking the reassignment of reference-type properties - in this example, if 'view' is reassigned, the referenced value is updated.
>
> Sounds good, I'm not aware of this syntax. Will investigate, thanks.

Sorry, I was suggesting a *possible* syntax. No such syntax currently exists, though the functionality can be imitated with closures:

let get: () -> Bool = {controller.view.isVisible}
print(get())

let set: (Bool) -> () = {controller.view.isVisible = $0}
set(true)

struct Lens {
var get: () -> T
var set: (T) -> ()
var value: T { get { return get() } set { set(newValue) } }
}
let accessor: Lens = Lens(get: {controller.view.isVisible}, set: {controller.view.visible = $0})
print(accessor.value)
accessor.value = true

It's a bit more verbose when creating the get-set accessor, and may not perform optimally, but it's actually pretty functional.
>
> >
> > > 5. Memory / pointer access, including casting. It's too verbose currently IMO when compared to C. Should be better supported for a language that is also targeting low-level (network, disk storage). A syntax that is both fast (like C) and safe would be great.
> >
> > Not familiar with low-level programming in Swift, but have you considered creating domain-specific operators?
> > For example, I imagine something like 'UnsafeMutablePointer(v)' could be reduced to '*v'.
> >
> >
>
> Do you mean operator is available only within a limited scope? That would be interesting, because I don't want to pollute global scope with such all-purpose operator. Sounds that I need to investigate that as well.

If you have a specific module which performs this sort of operation a lot, you can just declare the operator as internal. If it's needed in several, making a separate module for the operators could be preferable.
> >
> > > 7. I'm also fan of async/await kind of stuff, asynchronous flows, etc., but this has already been mentioned -> cool!
> >
> > I would like to see some ideas in this area.
> > async/await never really clicked for me until I realised it's just syntactic sugar - 'await' actually ends the function, and everything below is an implicit callback. Personally I feel like Swift's trailing closure syntax makes callbacks lightweight enough that this isn't so much of an issue. Something focusing more on the memory-management and thread-safety aspects of asynchronous code does seem useful in the context of Swift.
> >
> >
> > >
> Sure thread-safety, atomicity features would be really nice & useful.
>
> The one problem I have with closure syntax (trailing or not, I like trailing too), is that when you chain a few of them, which is pretty frequent is async programming, you end up with a closure pyramid. It doesn't scale well beyond 2 or 3 levels.

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


(Dave Abrahams) #9

> I investigated tuples a bit, it's close. The one thing I'd need is
> being able to index the values using a variable. The tuple.i
> notation apparently doesn't work (or I did not try hard
> enough). Also, for low-level things that will be mapped to GPU
> memory, precise/predictable/settable alignment is needed.

This might be a bit hacky but I just wanted to point out there exists
a way to index into tuples. You can use the Mirror(reflecting:
tuple).children syntax. You can loop over the values of the tuple and
even though a bit awkward you can even use indices to index into the
children.

True, but the inefficiency of that approach pretty much defeats the
purpose of having a fixed-sized array.

···

on Thu Aug 04 2016, Manav Gabhawala <swift-evolution@swift.org> wrote:

Regards,
Manav Gabhawala

On August 4, 2016 at 5:18:13 AM, James Froggatt via swift-evolution > (swift-evolution@swift.org(mailto:swift-evolution@swift.org)) wrote:

On 4 Aug 2016, at 13:00, Raphael Sebbe wrote:

> Thank you Chris, James.
>
> I'm answering James feedback/questions below.
>
> On Thu, Aug 4, 2016 at 1:57 AM James Froggatt wrote:
>
> > What are your thoughts on using tuples for this?
> >
> > typealias CGPoint4 = (CGPoint, CGPoint, CGPoint, CGPoint)
> >
> > struct Quad { var corners: CGPoint4 }
> >
> > var fixedLength = (point1, point2, point3, point4)
> > print(fixedLength.0)
> > print(fixedLength.4) //compiler error, not an element of the tuple
> >
> >
> > With shorthand declaration syntax, this would have the benefits
> > of a fixed-length array with added compile-time safety. A
> > previously suggested syntax was along the lines of '(CGPoint *
> > 4)'.
> >
>
> I investigated tuples a bit, it's close. The one thing I'd need is
> being able to index the values using a variable. The tuple.i
> notation apparently doesn't work (or I did not try hard
> enough). Also, for low-level things that will be mapped to GPU
> memory, precise/predictable/settable alignment is needed.

Good point. A similar mechanism might be possible eventually for
tuples, but right now this isn't possible.
> > > 4. Reference/pointer to structs: accessing & modifying structs
> > > deep into the model currently requires fully qualified path to
> > > the struct instance. Fully qualifying an inner struct in your
> > > data model can be very tedious, depending on model complexity.
> > >
> > > For instance, with scoped access solutions made with Swift 3,
> > > you need to cascade blocks if you need to access multiple
> > > inner structs, which doesn't scale well as it creates code
> > > pyramids:
> > >
> > > scopedAccess(&varA) {
> > > scopedAccess(&varB) {
> > > // modify varA & varB
> > > }
> > > }
> > >
> > > It's easily done in C/C++ using pointers/references. To make
> > > that better, we'd need some kind of language support IMO.
> > >
> > >
> >
> >
> > Could this be generalised, maybe with a reference-semantic ‘property accessor’?
> >
> > Example:
> >
> > let get: () -> Bool = #get(controller.view.isVisible)
> > print(get())
> >
> > let set: (Bool) -> () = #set(controller.view.isVisible)
> > set(true)
> >
> > let accessor: Lens = #lens(controller.view.isVisible)
> > print(accessor.value)
> > accessor.value = true
> >
> > This would have the added bonus of also tracking the
> > reassignment of reference-type properties - in this example, if
> > 'view' is reassigned, the referenced value is updated.
>
> Sounds good, I'm not aware of this syntax. Will investigate, thanks.

Sorry, I was suggesting a *possible* syntax. No such syntax
currently exists, though the functionality can be imitated with
closures:

let get: () -> Bool = {controller.view.isVisible}
print(get())

let set: (Bool) -> () = {controller.view.isVisible = $0}
set(true)

struct Lens {
var get: () -> T
var set: (T) -> ()
var value: T { get { return get() } set { set(newValue) } }
}
let accessor: Lens = Lens(get: {controller.view.isVisible}, set:
{controller.view.visible = $0})
print(accessor.value)
accessor.value = true

It's a bit more verbose when creating the get-set accessor, and may
not perform optimally, but it's actually pretty functional.
>
> >
> > > 5. Memory / pointer access, including casting. It's too
> > > verbose currently IMO when compared to C. Should be better
> > > supported for a language that is also targeting low-level
> > > (network, disk storage). A syntax that is both fast (like C)
> > > and safe would be great.
> >
> > Not familiar with low-level programming in Swift, but have you
> > considered creating domain-specific operators?
> > For example, I imagine something like 'UnsafeMutablePointer(v)'
> > could be reduced to '*v'.
> >
> >
>
> Do you mean operator is available only within a limited scope?
> That would be interesting, because I don't want to pollute global
> scope with such all-purpose operator. Sounds that I need to
> investigate that as well.

If you have a specific module which performs this sort of operation
a lot, you can just declare the operator as internal. If it's needed
in several, making a separate module for the operators could be
preferable.
> >
> > > 7. I'm also fan of async/await kind of stuff, asynchronous
> > > flows, etc., but this has already been mentioned -> cool!
> >
> > I would like to see some ideas in this area.
> > async/await never really clicked for me until I realised it's
> > just syntactic sugar - 'await' actually ends the function, and
> > everything below is an implicit callback. Personally I feel like
> > Swift's trailing closure syntax makes callbacks lightweight
> > enough that this isn't so much of an issue. Something focusing
> > more on the memory-management and thread-safety aspects of
> > asynchronous code does seem useful in the context of Swift.
> >
> >
> > >
> Sure thread-safety, atomicity features would be really nice & useful.
>
> The one problem I have with closure syntax (trailing or not, I
> like trailing too), is that when you chain a few of them, which is
> pretty frequent is async programming, you end up with a closure
> pyramid. It doesn't scale well beyond 2 or 3 levels.

Makes sense. _______________________________________________
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