Re: [swift-evolution] [pitch] Substring performance affordances

2017-07-02 Thread Dave Abrahams via swift-evolution

on Wed Jun 28 2017, Ben Cohen  wrote:

> Hi swift-evolution,
>
> Below is a short pitch for some performance improvements to be made to String 
> to accommodate
> Substrings.
>
> As outlined in SE-0163, the more general question of implicit conversion from 
> Substring to String
> was deferred pending feedback on the initial implementation. To date, the 
> feedback we’ve received
> hasn’t suggested that such an implicit conversion is necessary – that 
> migrations from 3.2 to 4.0
> haven’t led to an extensive need to perform Substring->String conversion. Any 
> further input, either
> on or off list, about this particular aspect of migration would be very 
> gratefully received.
>
> # Substring performance affordances
>
> * Proposal: [SE-](-substring-affordances.md)
> * Authors: [Ben Cohen](https://github.com/airspeedswift 
> )
> * Review Manager: TBD
> * Status: **Awaiting review**
>
> ## Introduction
>
> This proposal modifies a small number of methods in the standard library that
> are commonly used with the `Substring` type:
>
> - Modify the `init` on floating point and integer types, to construct them
>   from `StringProtocol` rather than `String`. 

+1.  This just makes good sense.

> 
> - Change `join` to be an extension `where Element: StringProtocol` 

I don't see how this is implementable unless we ignore the May 10
core team resolution that RangeReplaceableCollection conformance be
removed from StringProtocol, or we add RangeReplaceableCollection to the
constraints on Element.  We had good reasons for the resolution, so I
think we'd need to do the latter.

That said, I presume this is being called "joined()" per
https://github.com/apple/swift/pull/10734... I'm concerned that we
haven't sufficiently considered the forest of joined() overloads we're
expanding.  For all other sequences, joined() produces a lazy result.  I
realize that joining strings to produce a string is a really important
operation, but

   String(myStrings.joined())

is not so onerous as to make it an obvious choice to add this overload
to StringProtocol, especially since the other ones will still appear on
String thanks to its Sequence conformance.  String's conformance to
Collection gets confusing when these kinds of things happen.  Instead,
we should be considering dropping the eager overload from String for
Swift 4.  Or, if we think it's important enough to avoid the explicit
conversion to string, maybe we should be thinking about making the other
joined()s eager.

> - Add extensions to `Dictionary where Key == String` and `Set where
> Element == String` to test for presence of a `Substring`.

Here's why I don't think we should do this:

* As noted in your introduction, we deliberately avoided taking steps
  that would make Substrings transparently work where Strings are now
  accepted so that we'd find out whether the impedance mismatch was
  going to be an issue.  We've had very little time to get information
  about String/Substring interop issues that people might face and
  doing this now would mute the signal.

* The proposal's stated motivation is to work around a performance
  problem, and it does so by adding a very specific, special-purpose
  piece of API.  But the performance issues are actually more general:

  - Sets and dictionaries offer no way to look up a key and, when the
key isn't found, use the bucket information computed by the lookup
for a subsequent insertion.

  extension Set {
func toggle(_ k: Element) {
  let p = s.lookup(k) // < for example
  if p.found {
s.remove(at: p.index)
  }
  else {
s.insert(k, at: p)
  }
}
  }

  - Substring offers no way to create a corresponding String that avoids
a copy when necessary for performance reasons:

  for w: Substring in words {
result += transform(
  String(maintainingExcessStorageBySharing: w)) // <== for example
  }

If transform is an API that—as we recommend by default—operates on
String rather than Substring or StringProtocol, and is known not to
make long-term copies of its argument, users currently have no way
to avoid the performance cost of a copy.  It's not something people
should use every day, but when you need it, you need it.

  Together these APIs can be used to solve the Substring performance
  problem with Set/Dictionary insertion, and a whole
  raft of others besides.

let p = s.lookup(String(maintainingExcessStorageBySharing: w))
if !p.found { s.insert(String(w), at: p)

* The proposed API adds overloads, which harms usability, and having
  these particular overloads is IMO not clearly the right answer in the
  long term.  Removing APIs later is expensive in labor, harmful to
  users, and sometimes difficult technically.  

* Handling these cases transparently sets up an expectation that other
  such cases 

Re: [swift-evolution] [Pitch] Contextual variables

2017-07-02 Thread rintaro ishizaki via swift-evolution
Ughh, my bad, let me withdraw this idea:

func saveAndRestore(_ variable: inout T, _ tmpVal: T, body: ()
-> R) -> R {
let savedVal = variable
variable = tmpVal
defer { variable = savedVal }
return body()
}
var contextVal: Int = 0saveAndRestore(, 1) {
print(contextVal)
}


I don't think this is guaranteed to work.




2017-07-03 11:48 GMT+09:00 rintaro ishizaki via swift-evolution <
swift-evolution@swift.org>:

>
>
> 2017-07-03 11:23 GMT+09:00 rintaro ishizaki via swift-evolution <
> swift-evolution@swift.org>:
>
>>
>>
>> 2017-06-28 21:33 GMT+09:00 Dimitri Racordon via swift-evolution <
>> swift-evolution@swift.org>:
>>
>>> Hello community!
>>>
>>> I’d like to pitch an idea for a user-friendly way for functions to pull
>>> values from an arbitrary environment. Let me introduce the concept with a
>>> motivational example before I dig into dirty syntax and semantics. Note
>>> that I intentionally removed many pieces of code from my examples, but I
>>> guess everybody will be able to understand the context.
>>>
>>> Say you are writing a visitor (with the pattern of the same name) for an
>>> AST to implement an interpreter:
>>>
>>> class Interpreter: Visitor {
>>> func visit(_ node: BinExpr){ /* ... */ }
>>> func visit(_ node: Literal){ /* ... */ }
>>> func visit(_ node: Scope)  { /* ... */ }
>>> func visit(_ node: Identifier) { /* ... */ }
>>> }
>>>
>>> Although this design pattern is often recommended for AST processing,
>>> managing data as we go down the tree can be cumbersome. The problem is that
>>> we need to store all intermediate results as we climb up the tree in some
>>> instance member, because we can’t use the return type of the visit(_:) 
>>> method,
>>> as we would do with a recursive function:
>>>
>>
>>
>> Why you can't use the return type? associatedtype doesn't solve the
>> problem?
>>
>> protocol Visitor {
>> associatedtype VisitResult
>> func visit(_ node: BinExpr) throws -> VisitResult
>> func visit(_ node: Literal) throws -> VisitResult
>> func visit(_ node: Scope) throws -> VisitResult
>> func visit(_ node: Identifier) throws -> VisitResult
>> }
>> extension BinExpr {
>> func accept(_ visitor: V) throws -> V.VisitResult { return 
>> visitor.visit(self) }
>> }extension Literal {
>> func accept(_ visitor: V) throws -> V.VisitResult { return 
>> visitor.visit(self) }
>> }extension Scope {
>> func accept(_ visitor: V) throws -> V.VisitResult { return 
>> visitor.visit(self) }
>> }extension Identifier {
>> func accept(_ visitor: V) throws -> V.VisitResult { return 
>> visitor.visit(self) }
>> }
>> class Interpreter : Visitor {
>> func visit(_ node: BinExpr) -> Int {
>> let lhsResult = node.lhs.accept(self)
>> let rhsResult = node.rhs.accept(self)
>> /* ... */
>> return result
>> }
>>
>> /* ... */
>> }
>>
>>
>>
>>
>>
>>
>>> class Interpreter: Visitor {
>>> func visit(_ node: BinExpr) {
>>> node.lhs.accept(self)
>>> let lhs = accumulator!
>>> node.rhs.accept(self)
>>> let rhs = accumulator!
>>> /* ... */
>>> }
>>>
>>> func visit(_ node: Literal){ /* ... */ }
>>> func visit(_ node: Scope)  { /* ... */ }
>>> func visit(_ node: Identifier) { /* ... */ }
>>>
>>> var accumulator: Int? = nil
>>>
>>> /* ... */
>>> }
>>>
>>> As our interpreter will grow and need more visitors to “return” a value,
>>> we’ll be forced to add more and more stored properties to its definition.
>>> Besides, the state of those properties is difficult to debug, as it can
>>> quickly become unclear what depth of the tree they should be associated to.
>>> In fact, it is as if all these properties acted as global variables.
>>>
>>> The problem gets even bigger when we need to *pass* variables to a
>>> particular execution of a visit(_:). Not only do we need to add a
>>> stored property to represent each “argument”, but we also have to store
>>> them in stacks so that a nested calls to a particular visit can get their
>>> own “evaluation context”. Consider for instance the implementation of the
>>> visit(_ node: Identifier), assuming that the language our AST
>>> represents would support lexical scoping.
>>>
>>
>>
>> How about returning curried function from visitor?
>>
>>
>> class Interpreter : Visitor {
>>
>> typealias VisitResult = ([String:Int]) throws -> Int
>>
>> func visit(_ node: Identifier) throws -> VisitResult {
>> return { symbols in
>> guard let result = symbols[node.name] {
>> throws UndefinedIdentifierError(node.name)
>> }
>> return result
>> }
>> }
>>
>> /* ... */
>> }
>>
>>
>>
>>
>>> class Interpreter: Visitor {
>>> /* ... */
>>>
>>> func visit(_ node: Scope) {
>>> symbols.append([:])
>>> for child in node.children {
>>> child.accept(self)
>>> }
>>> symbols.removeLast()
>>> }

Re: [swift-evolution] [Pitch] Contextual variables

2017-07-02 Thread rintaro ishizaki via swift-evolution
2017-07-03 11:23 GMT+09:00 rintaro ishizaki via swift-evolution <
swift-evolution@swift.org>:

>
>
> 2017-06-28 21:33 GMT+09:00 Dimitri Racordon via swift-evolution <
> swift-evolution@swift.org>:
>
>> Hello community!
>>
>> I’d like to pitch an idea for a user-friendly way for functions to pull
>> values from an arbitrary environment. Let me introduce the concept with a
>> motivational example before I dig into dirty syntax and semantics. Note
>> that I intentionally removed many pieces of code from my examples, but I
>> guess everybody will be able to understand the context.
>>
>> Say you are writing a visitor (with the pattern of the same name) for an
>> AST to implement an interpreter:
>>
>> class Interpreter: Visitor {
>> func visit(_ node: BinExpr){ /* ... */ }
>> func visit(_ node: Literal){ /* ... */ }
>> func visit(_ node: Scope)  { /* ... */ }
>> func visit(_ node: Identifier) { /* ... */ }
>> }
>>
>> Although this design pattern is often recommended for AST processing,
>> managing data as we go down the tree can be cumbersome. The problem is that
>> we need to store all intermediate results as we climb up the tree in some
>> instance member, because we can’t use the return type of the visit(_:) 
>> method,
>> as we would do with a recursive function:
>>
>
>
> Why you can't use the return type? associatedtype doesn't solve the
> problem?
>
> protocol Visitor {
> associatedtype VisitResult
> func visit(_ node: BinExpr) throws -> VisitResult
> func visit(_ node: Literal) throws -> VisitResult
> func visit(_ node: Scope) throws -> VisitResult
> func visit(_ node: Identifier) throws -> VisitResult
> }
> extension BinExpr {
> func accept(_ visitor: V) throws -> V.VisitResult { return 
> visitor.visit(self) }
> }extension Literal {
> func accept(_ visitor: V) throws -> V.VisitResult { return 
> visitor.visit(self) }
> }extension Scope {
> func accept(_ visitor: V) throws -> V.VisitResult { return 
> visitor.visit(self) }
> }extension Identifier {
> func accept(_ visitor: V) throws -> V.VisitResult { return 
> visitor.visit(self) }
> }
> class Interpreter : Visitor {
> func visit(_ node: BinExpr) -> Int {
> let lhsResult = node.lhs.accept(self)
> let rhsResult = node.rhs.accept(self)
> /* ... */
> return result
> }
>
> /* ... */
> }
>
>
>
>
>
>
>> class Interpreter: Visitor {
>> func visit(_ node: BinExpr) {
>> node.lhs.accept(self)
>> let lhs = accumulator!
>> node.rhs.accept(self)
>> let rhs = accumulator!
>> /* ... */
>> }
>>
>> func visit(_ node: Literal){ /* ... */ }
>> func visit(_ node: Scope)  { /* ... */ }
>> func visit(_ node: Identifier) { /* ... */ }
>>
>> var accumulator: Int? = nil
>>
>> /* ... */
>> }
>>
>> As our interpreter will grow and need more visitors to “return” a value,
>> we’ll be forced to add more and more stored properties to its definition.
>> Besides, the state of those properties is difficult to debug, as it can
>> quickly become unclear what depth of the tree they should be associated to.
>> In fact, it is as if all these properties acted as global variables.
>>
>> The problem gets even bigger when we need to *pass* variables to a
>> particular execution of a visit(_:). Not only do we need to add a stored
>> property to represent each “argument”, but we also have to store them in
>> stacks so that a nested calls to a particular visit can get their own
>> “evaluation context”. Consider for instance the implementation of the
>> visit(_ node: Identifier), assuming that the language our AST represents
>> would support lexical scoping.
>>
>
>
> How about returning curried function from visitor?
>
>
> class Interpreter : Visitor {
>
> typealias VisitResult = ([String:Int]) throws -> Int
>
> func visit(_ node: Identifier) throws -> VisitResult {
> return { symbols in
> guard let result = symbols[node.name] {
> throws UndefinedIdentifierError(node.name)
> }
> return result
> }
> }
>
> /* ... */
> }
>
>
>
>
>> class Interpreter: Visitor {
>> /* ... */
>>
>> func visit(_ node: Scope) {
>> symbols.append([:])
>> for child in node.children {
>> child.accept(self)
>> }
>> symbols.removeLast()
>> }
>>
>> func visit(_ node: Identifier) {
>> accumulator = symbols.last![node.name]!
>> }
>>
>> var symbols = [[String: Int]]()
>> }
>>
>> We could instead create another instance of our visitor to set manage
>> those evaluation contexts. But that would require us to explicitly copy all
>> the variables associated to those contexts, which could potentially be
>> inefficient and error prone.
>>
>> In fact, this last point is also true when dealing with recursive
>> functions. For instance, our visit(_ node: Identifier) method could be
>> rewritten as:
>>
>> func 

Re: [swift-evolution] [swift-evolution-announce] [Revised and review extended] SE-0180 - String Index Overhaul

2017-07-02 Thread Dave Abrahams via swift-evolution

Hi Karl,

It was pointed out to me that I never answered this thoughtful post of
yours...

on Mon Jun 26 2017, Karl Wagner  wrote:

>> On 23. Jun 2017, at 02:59, Kevin Ballard via swift-evolution
>>  wrote:
>> 
>> https://github.com/apple/swift-evolution/blob/master/proposals/0180-string-index-overhaul.md
>> 
>> 
>> Given the discussion in the original thread about potentially having
>> Strings backed by something other than utf16 code units, I'm
>> somewhat concerned about having this kind of vague `encodedOffset`
>> that happens to be UTF16 code units. If this is supposed to
>> represent an offset into whatever code units the String is backed
>> by, then it's going to be a problem because the user isn't supposed
>> to know or care what the underlying storage for the String is.
>
> Is that true? The String manifesto shows a design where the underlying
> Encoding and code-units are exposed.

That is the eventual goal.  Note that with this proposal we are making
progress towards that goal, but getting all the way there is out of
scope for this release.

> From the talk about String’s being backed by something that isn’t
> UTF-16, I took that to mean that String might one-day become
> generic. Defaults for generic parameters have been mentioned on the
> list before, so “String” could still refer to “String”
> on OSX and maybe “String” on Linux.

I think you may have misunderstood.  String currently supports a few
different underlying representations (ASCII, UTF-16, NSString), all of
which happen to use a UTF-16-compatible encoding.  The eventual goal is
to expand the possible underlying representations of String to
accomodate other encodings.

That said, the underlying representation of String is *not* part of
String's type, and we don't intend to change that.  When String APIs
access the underlying representation, that access is dynamically
dispatched.  If the encoding were a generic parameter, then it would be
statically dispatched (at least in part), but it would also become part
of String's type, and, for example, you would get an error when trying
to pass a String where a String was
expected.  It's important that code passing Strings around remain
smoothly interoperable, so we don't want to introduce this sort of type
mismatch.

Instead, the intention is that someone could make a UTF8String type that
conformed to StringProtocol, and that String itself could be constructed
from any instance of StringProtocol to be used as its underlying
representation.  That way, if you need the performance that comes with
knowing and manipulating the underlying encoding, you can use UTF8String
directly, and if you need to interoperate with code that uses the
lingua-franca String type, you can wrap String around your UTF8String
and pass that.

> I would support a definition of encodedOffset that removed mention of
> UTF-16 and phrased things in terms of String.Encoding and
> code-units. 

Well, a few points about this:

I support removing the text “(UTF-16)” from the initial documentation
comments on these APIs, which is, AFAICT, the only source of the concern
you and others have expressed. That said, Strings are in fact currently
encoded as UTF-16 and as long as Cocoa interop is important, that too is
important and useful information, so it should be documented somewhere.

I don't support describing anything in terms of String.Encoding at this
time.  That enum was added to String by the Foundation overlay, and is not
part of the plan for String except insofar as it is required for source
compatibility and Cocoa interop.  A more appropriate way to describe the
encoding in terms of the language would be as something like
Unicode.UTF16 (at compile-time) or an instance of Unicode.Encoding.Type
(at runtime).  But I see no need to describe it in language terms until
we are ready to add APIs to String that can support multiple encodings
and/or report the underlying encoding, and we are not ready to do that
yet.

> For example, I would like to be able to construct new String indices
> from a known index plus a quantity of code-units known to represent a
> sequence of characters:
>
> var stringOne = “Hello,“
> let stringTwo = “ world"
>
> var idx = stringOne.endIndex
> stringOne.append(contentsOf: stringTwo)
> idx = String.Index(encodedOffset: idx.encodedOffset + 
> stringTwo.codeUnits.count)
> assert(idx == stringOne.endIndex)

I'm not sure what you mean by “represent a sequence of characters” in
this context.  Don't a sequence of code units always represent a
sequence of characters?

The code you wrote above would (almost) work as written under this
proposal, given that Strings always have an encoding that's compatible
with some default.  In other words, making it work *depends* on the fact
that the encoding of stringTwo is compatible with (has a non-strict
sub/superset relation 

Re: [swift-evolution] [Pitch] Contextual variables

2017-07-02 Thread rintaro ishizaki via swift-evolution
2017-06-28 21:33 GMT+09:00 Dimitri Racordon via swift-evolution <
swift-evolution@swift.org>:

> Hello community!
>
> I’d like to pitch an idea for a user-friendly way for functions to pull
> values from an arbitrary environment. Let me introduce the concept with a
> motivational example before I dig into dirty syntax and semantics. Note
> that I intentionally removed many pieces of code from my examples, but I
> guess everybody will be able to understand the context.
>
> Say you are writing a visitor (with the pattern of the same name) for an
> AST to implement an interpreter:
>
> class Interpreter: Visitor {
> func visit(_ node: BinExpr){ /* ... */ }
> func visit(_ node: Literal){ /* ... */ }
> func visit(_ node: Scope)  { /* ... */ }
> func visit(_ node: Identifier) { /* ... */ }
> }
>
> Although this design pattern is often recommended for AST processing,
> managing data as we go down the tree can be cumbersome. The problem is that
> we need to store all intermediate results as we climb up the tree in some
> instance member, because we can’t use the return type of the visit(_:) method,
> as we would do with a recursive function:
>


Why you can't use the return type? associatedtype doesn't solve the problem?

protocol Visitor {
associatedtype VisitResult
func visit(_ node: BinExpr) throws -> VisitResult
func visit(_ node: Literal) throws -> VisitResult
func visit(_ node: Scope) throws -> VisitResult
func visit(_ node: Identifier) throws -> VisitResult
}
extension BinExpr {
func accept(_ visitor: V) throws -> V.VisitResult {
return visitor.visit(self) }
}extension Literal {
func accept(_ visitor: V) throws -> V.VisitResult {
return visitor.visit(self) }
}extension Scope {
func accept(_ visitor: V) throws -> V.VisitResult {
return visitor.visit(self) }
}extension Identifier {
func accept(_ visitor: V) throws -> V.VisitResult {
return visitor.visit(self) }
}
class Interpreter : Visitor {
func visit(_ node: BinExpr) -> Int {
let lhsResult = node.lhs.accept(self)
let rhsResult = node.rhs.accept(self)
/* ... */
return result
}

/* ... */
}






> class Interpreter: Visitor {
> func visit(_ node: BinExpr) {
> node.lhs.accept(self)
> let lhs = accumulator!
> node.rhs.accept(self)
> let rhs = accumulator!
> /* ... */
> }
>
> func visit(_ node: Literal){ /* ... */ }
> func visit(_ node: Scope)  { /* ... */ }
> func visit(_ node: Identifier) { /* ... */ }
>
> var accumulator: Int? = nil
>
> /* ... */
> }
>
> As our interpreter will grow and need more visitors to “return” a value,
> we’ll be forced to add more and more stored properties to its definition.
> Besides, the state of those properties is difficult to debug, as it can
> quickly become unclear what depth of the tree they should be associated to.
> In fact, it is as if all these properties acted as global variables.
>
> The problem gets even bigger when we need to *pass* variables to a
> particular execution of a visit(_:). Not only do we need to add a stored
> property to represent each “argument”, but we also have to store them in
> stacks so that a nested calls to a particular visit can get their own
> “evaluation context”. Consider for instance the implementation of the
> visit(_ node: Identifier), assuming that the language our AST represents
> would support lexical scoping.
>


How about returning curried function from visitor?


class Interpreter : Visitor {

typealias VisitResult = ([String:Int]) throws -> Int

func visit(_ node: Identifier) throws -> VisitResult {
return { symbols in
guard let result = symbols[node.name] {
throws UndefinedIdentifierError(node.name)
}
return result
}
}

/* ... */
}




> class Interpreter: Visitor {
> /* ... */
>
> func visit(_ node: Scope) {
> symbols.append([:])
> for child in node.children {
> child.accept(self)
> }
> symbols.removeLast()
> }
>
> func visit(_ node: Identifier) {
> accumulator = symbols.last![node.name]!
> }
>
> var symbols = [[String: Int]]()
> }
>
> We could instead create another instance of our visitor to set manage
> those evaluation contexts. But that would require us to explicitly copy all
> the variables associated to those contexts, which could potentially be
> inefficient and error prone.
>
> In fact, this last point is also true when dealing with recursive
> functions. For instance, our visit(_ node: Identifier) method could be
> rewritten as:
>
> func interpret(_ identifier: Identifier, symbols: [String: Value]) -> Int
>  { /* ... */ }
>
> so that its evaluation context is passed as a parameter. But this also
> requires all other functions to also pass this argument, even if their
> execution does not require the parameter.
>
> func interpret(_ binExpr: 

Re: [swift-evolution] Would having "MyType.Protocol" to indicate a type's protocols mess anything up?

2017-07-02 Thread Christopher Kornher via swift-evolution
A full-fledged introspection system should provide this information, which I 
suppose could be useful for creating proxies through code generation or dynamic 
Objective-C like features, should they ever be added to the language. Would 
that be sufficient for your needs? It is not clear to me what problem you are 
trying to solve.

Hopefully I won't stir up too much trouble by saying that this kind of 
capability is very useful in Objective-C for mocking, for example.


> On Jul 2, 2017, at 7:55 PM, Daryle Walker via swift-evolution 
>  wrote:
> 
> 
>> On Jul 1, 2017, at 2:07 AM, Brent Royal-Gordon > > wrote:
>> 
>>> On Jun 30, 2017, at 6:17 PM, Daryle Walker via swift-evolution 
>>> > wrote:
>>> 
>>> Given a type MyType, how can I get a type-alias to the type’s protocols? If 
>>> MyType conforms to Protocol1 and Protocol2, I would want something like
>>> 
>>> typealias MyProtocol = Protocol1 & Protocol2
>>> 
>>> (and Any if MyType doesn’t conform to any protocols). Does this facility 
>>> already exist in Swift? I don’t think it does, so I proposed the hybrid 
>>> “MyType.Protocol” syntax to express the idea.
>> 
>> Leave the syntax aside. What are you planning to do with this feature? I 
>> understand that you want to have some way of saying "composition of all 
>> protocols this type conforms to"; I don't understand *why* you want it or 
>> what kind of code you would need it for.
> 
> 
> It wasn’t until I started this thread that I realized that Swift didn’t have 
> a way to get a bulk list of a type’s protocols. A little later, I came up 
> with a reason why this never came up before (or at least not often): knowing 
> this isn’t really useful.
> 
> You could use this to make MyTypeB conform to all protocols of MyTypeA. But 
> then you’re stuck. The list of protocols for a type is a closed from the 
> linker’s perspective, but open from the user’s perspective. The user couldn’t 
> write all the methods needed unless the unknown ones all have default 
> implementations. The proposal I’m coming up with has a facility to copy all 
> the members of one type to another. You can specify by exact member name, or 
> you can specify a protocol to get copies of all applicable members at once. 
> This is where an all-protocols alias can help. With manual copying, the 
> user’s cardinality of members copied is usually less than what’s available, 
> with an automatic list the cardinalities are always equal.
> 
> — 
> Daryle Walker
> Mac, Internet, and Video Game Junkie
> darylew AT mac DOT com 
> 
> ___
> 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


Re: [swift-evolution] Would having "MyType.Protocol" to indicate a type's protocols mess anything up?

2017-07-02 Thread Daryle Walker via swift-evolution

> On Jul 1, 2017, at 2:07 AM, Brent Royal-Gordon  wrote:
> 
>> On Jun 30, 2017, at 6:17 PM, Daryle Walker via swift-evolution 
>> > wrote:
>> 
>> Given a type MyType, how can I get a type-alias to the type’s protocols? If 
>> MyType conforms to Protocol1 and Protocol2, I would want something like
>> 
>>  typealias MyProtocol = Protocol1 & Protocol2
>> 
>> (and Any if MyType doesn’t conform to any protocols). Does this facility 
>> already exist in Swift? I don’t think it does, so I proposed the hybrid 
>> “MyType.Protocol” syntax to express the idea.
> 
> Leave the syntax aside. What are you planning to do with this feature? I 
> understand that you want to have some way of saying "composition of all 
> protocols this type conforms to"; I don't understand *why* you want it or 
> what kind of code you would need it for.


It wasn’t until I started this thread that I realized that Swift didn’t have a 
way to get a bulk list of a type’s protocols. A little later, I came up with a 
reason why this never came up before (or at least not often): knowing this 
isn’t really useful.

You could use this to make MyTypeB conform to all protocols of MyTypeA. But 
then you’re stuck. The list of protocols for a type is a closed from the 
linker’s perspective, but open from the user’s perspective. The user couldn’t 
write all the methods needed unless the unknown ones all have default 
implementations. The proposal I’m coming up with has a facility to copy all the 
members of one type to another. You can specify by exact member name, or you 
can specify a protocol to get copies of all applicable members at once. This is 
where an all-protocols alias can help. With manual copying, the user’s 
cardinality of members copied is usually less than what’s available, with an 
automatic list the cardinalities are always equal.

— 
Daryle Walker
Mac, Internet, and Video Game Junkie
darylew AT mac DOT com 

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


Re: [swift-evolution] [Pitch] Contextual variables

2017-07-02 Thread Brent Royal-Gordon via swift-evolution

> On Jun 28, 2017, at 5:33 AM, Dimitri Racordon via swift-evolution 
>  wrote:
> 
> Using our contextual variables, one could rewrite our motivational example as 
> follows:
> 
> class Interpreter: Visitor {
> func visit(_ node: BinExpr) {
> let lhs, rhs : Int
> set accumulator = nil in {
> node.lhs.accept(self)
> lhs = accumulator!
> }
> set accumulator = nil in {
> node.lhs.accept(self)
> rhs = accumulator!
> }
> 
> switch node.op {
> case "+":
> accumulator = lhs + rhs
> case "-":
> accumulator = lhs - rhs
> default:
> fatalError("unexpected operator \(node.op)")
> }
> }
> 
> func visit(_ node: Literal) {
> accumulator = node.val
> }
> 
> func visit(_ node: Scope) {
> set symbols = [:] in {
> for child in node.children {
> child.accept(self)
> }
> }
> }
> 
> func visit(_ node: Identifier) {
> guard let val = symbols?[node.name] else {
> fatalError("undefined symbol: \(node.name)")
> }
> accumulator = val
> }
> 
> context var accumulator: Int?
> context var symbols: [String: Int]?
> }
> 
> It is no longer unclear what depth of the tree the accumulator variable 
> should be associated with. The mechanism is handled automatically, preventing 
> the programmer from incorrectly reading a value that was previously set for 
> another descent. It is no longer needed to manually handle the stack 
> management of the symbols variable, which was error prone in our previous 
> implementation.

As far as I can see, you can do this with existing features:

struct Contextual {
 private var values: [Value]
 
 var value: Value {
  get { return values.last! }
  set { values[values.index(before: values.endIndex)] = 
newValue }
 }
 
 mutating func with(_ value: Value, do body: () throws -> R) 
rethrows -> R {
  values.append(value)
  defer { values.removeLast() }
  return try body()
}
}

 class Interpreter: Visitor {
var accumulator: Contextual
var symbols: Contextual<[String: Int]>

func visit(_ node: BinExpr) {
let lhs, rhs : Int
accumulator.with(nil) {
node.lhs.accept(self)
lhs = accumulator.value!
}
accumulator.with(nil) {
node.lhs.accept(self)
rhs = accumulator.value!
}

switch node.op {
case "+":
accumulator.value = lhs + rhs
case "-":
accumulator.value = lhs - rhs
default:
fatalError("unexpected operator \(node.op)")
}
}

func visit(_ node: Literal) {
accumulator.value = node.val
}

func visit(_ node: Scope) {
symbols.with([:]) {
for child in node.children {
child.accept(self)
}
}
}

func visit(_ node: Identifier) {
guard let val = symbols.value[node.name] else {
fatalError("undefined symbol: \(node.name)")
}
accumulator.value = val
}
}

(There is actually a minor problem with this: the closures passed to 
`with(_:do:)` can't initialize `lhs` and `rhs` because DI can't prove they're 
run exactly once. I'd like an `@once` annotation on closure parameters to 
address this, but in the mean time, you can use `var` for those parameters 
instead of `let`.)

Obviously, your `context` keyword is slightly prettier to use. But is that 
enough? Is this use case *so* common, or the syntax of `with(_:do:)` and 
`value` *so* cumbersome, that it's worth adding language features to avoid it?

And if the existing syntax *is* too cumbersome, could the Property Behaviors 
proposal (with some of the extensions described at the end) allow you to 
implement this yourself with an acceptable syntax? 


Basically, what about this problem *requires* a solution built in to the 
language? Language-level solutions are difficult to design and have to be 
maintained forever, so it's going to take a lot to convince us this is a good 
addition to the language.

-- 
Brent Royal-Gordon
Architechies

___
swift-evolution mailing list
swift-evolution@swift.org

[swift-evolution] How many kinds of declarations can a named type hold?

2017-07-02 Thread Daryle Walker via swift-evolution
I think I got most of this, but it’s hard to completely figure out because the 
information is scattered across the grammar.

So, I’m coming up with a statement to copy over a member from one type to 
another:

publish MEMBER-FROM-OTHER-TYPE

and I’m trying to encapsulate this into a grammar. This requires me to figure 
out how to name every single declaration in a type. I got so far:

published-member → decimal-digits
published-member → type-identifier
published-member → identifier | identifier ( argument-names_opt )
published-member → operator | operator (argument-names_opt )
published-member → init | init (argument-names_opt )
published-member → init ? | init ? (argument-names_opt )
published-member → init ! | init ! (argument-names_opt )
published-member → subscript | subscript ( argument-names_opt )

The first line is for tuples, and the rest are for struct/enum/class. The 
second line covers some generics, but I don’t mention generics anywhere else. 
The third line covers properties and functions, while all the following lines 
over functions. There are two branches for those lines to cover all overloads 
sharing a name and to cover a specific overload.

Do I have to mention generic stuff in any of the lines past the second? Are 
there declaration kinds I’m straight-up missing? (Remember that identifier 
covers constants; variables; type-aliases; enumeration cases; inner structure, 
enumeration, class, and extensions; and operator precedence groups.)

— 
Daryle Walker
Mac, Internet, and Video Game Junkie
darylew AT mac DOT com 

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


Re: [swift-evolution] [Pitch] Introducing the "Unwrap or Die" operator to the standard library

2017-07-02 Thread Georgios Moschovitis via swift-evolution
> let last = array.last ?? fatalError(“array must not be empty”)

I prefer, the above, explicit version.

-g.

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