Re: [swift-evolution] [Accepted] SE-0168: Multi-Line String Literals

2017-04-23 Thread Pyry Jahkola via swift-evolution
Hmm, I can see that Wux already replied to this question but let me give 
another more or less obvious answer which I believe has come up in a shape or 
another already:

Brent Royal-Gordon via swift-evolution  wrote:

>> No, I am suggesting that whatever design is used for escaped newlines, if at 
>> all possible it should be equally apt for "strings" and """strings""" such 
>> that it will not require indentation stripping.
> 
> Could you share an example of such a design?

One way to achieve the criteria below for both singly and triply quoted strings 
would be to borrow the repeated opening quote syntax (from earlier discussions) 
for singly quoted strings:

let s1 = "abc\
  "def\n\
  "ghi \
  "xyz"
assert(s1 == "abcdef\nghi xyz")

let s2 = "abc\
 "def\n\
/* Leading white space, */ "ghi \
// as well as comments

// and empty lines in between are
// insignificant when it comes to singly
// quoted literals.
"xyz"
assert(s2 == s1)

let s3 = """
abc\
def
ghi \
xyz
"""
assert(s3 == s1)

The criteria:

> * Permits non-significant hard-wrapping in a string literal.

✅ The string continues from the position of the backslash, with no extra space 
or line break inserted.

> * Works equally well with single and triple string literals.

✅ In both cases, a trailing `\` has the same meaning. In singly quoted strings, 
the only way to insert a newline is by quoting (`\n`), as it always was.

> * Preserves code indentation, but does not require single string literals to 
> do indentation stripping.

✅ The indentation is just more explicit with singly quoted string literals.

> * Is not horribly inconvenient.

路‍♂️ Depends who you ask, I guess, but I think not horrible. And, after all, 
the programmer is free to choose between two quoting styles with different 
trade offs.

* * *

One thing that remains to be defined is whether trailing space is allowed (and 
ignored) after the backslash or not (and thus an error). I initially thought 
it's best to make into a compiler error, just like the indenting white space of 
the triple quoted string literals.

OTOH, we could also allow inline comments after the backslash:

let whyNot = "this, \
"that, \ // <- Oxford comma
"and stuff"
assert(whyNot == "this, that, and stuff")

let list = """
- this,
- that,\n\// comment using "Adrian's \n\"
- and stuff
"""
assert(list == "- this,\n- that,\n- and stuff")

[Nit: If comments after the backslash were allowed, we'd need to either require 
a space after the backslash (e.g. `\ //`), or else accept as string 
continuation / comment start markers both `\//` (until newline) and `\/*` 
(until `*/`), as seen in the latter example above.]

I find this design — with or without comments — would naturally allow the 
programmer to choose between precision (singly quoted) and 
convenience/legibility (triply quoted). And of course it would allow breaking 
long string literals to multiple lines in a consistent way, which, for triply 
quoted strings, is also lighter than just concatenating with `+`.

— Pyry

PS. I also slightly regret that SE-0168 ended up stripping the trailing 
newline, because multiline strings seem to compose (concatenate) better with a 
trailing newline there by default. But I understand if the inconvenience of 
`print(str, terminator: "")` weighed more than the other option.___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Discussion] Simplifying case syntax

2017-03-01 Thread Pyry Jahkola via swift-evolution
I guess I should also include the example where the user actually wanted the 
oldValue to be "x":

if case let .two(newValue, value) = example, value == oldValue { ... }

No surprises there, even if another conditional is required.

— Pyry

> On 1 Mar 2017, at 22.53, Pyry Jahkola via swift-evolution 
> <swift-evolution@swift.org> wrote:
> 
> Erica,
> 
> Instead of going into all these lengths introducing new syntax, why not 
> simply turn it into a warning when a `case let` binding shadows an existing 
> variable with the exact same type (which supposedly also conforms to 
> Equatable)?
> 
> Examples, including how to silence the said warning:
> 
> enum Value { case one(T), two(T, T), three(T, T, T) }
> 
> let example: Value = .two("a", "b")
> let oldValue = "x"
> // (Besides, you probably intended `oldValue` to be a `Character` in your
> // example. Well, it's a `String` in mine.)
> 
> if case let .two(newValue, oldValue) = example { ... }
> // 
> // warning: 'oldValue' shadows an existing variable of same type 'String'
> 
> if case let .two(newValue, (oldValue)) = example { assert(oldValue == 
> "b") }
> // Ok, adding extra parentheses silences the warning.
> 
> if case let .one(example) = example { ... }
> // Ok, because there's no way the author would equate the `example: 
> String`
> // in the LHS to the `example: Value` of the RHS.
> 
> let maybe: Optional = "perhaps"
> if case let maybe? = maybe { ... }
> if case let .some(maybe) = maybe { ... }
> // Again, none of these examples would be affected by the warning, because
> // the `maybe: String` bound in the `case let` has a different type than
> // the `maybe: String?` in the outer scope.
> 
> Personally, I do like the convenience that I can bind several variables with 
> one `let` keyword in a case expression. And I can't see the appeal to making 
> `~=`, let alone a completely new special-syntax assignment operator, more 
> prominent in Swift.
> 
> — Pyry
> 
>> On 28 Feb 2017, at 21.01, Erica Sadun via swift-evolution 
>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>> 
>> The following draft proposal addresses one matter of substance (eliminating 
>> edge case errors by adopting at-site conditional binding) and one of style 
>> (using the pattern match operator consistently). Its discussion was deferred 
>> from Phase 1 and remains in a fairly early stage. Your feedback will help me 
>> decide whether this is a proposal I want to keep developing or one that I 
>> should set aside and focus on other matters. Thank you. -- E
>> 
>> The work-in-progress gist is here:  
>> https://gist.github.com/erica/06dad9bbe1a70290fe6b89a64f73bc0c 
>> <https://gist.github.com/erica/06dad9bbe1a70290fe6b89a64f73bc0c> 
>> 
>> Simplifying case syntax
>> 
>> Proposal: TBD
>> Author: Erica Sadun <https://github.com/erica>
>> Status: TBD
>> Review manager: TBD
>>  
>> <https://gist.github.com/erica/06dad9bbe1a70290fe6b89a64f73bc0c#introduction>Introduction
>> 
>> This proposal re-architects case syntax grammar to reduce potential errors 
>> and simplify unwrapping enumerations. 
>> 
>> Swift-evolution thread: [Pitch] Reimagining guard case/if case 
>> <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20161024/tbd.html>
>>  
>> <https://gist.github.com/erica/06dad9bbe1a70290fe6b89a64f73bc0c#motivation>Motivation
>> 
>> In its current design, Swift case binding suffers from two weaknesses.
>> 
>> Mixed external and internal let/var binding may introduce errors from 
>> uncommon edge cases.
>> Real-world users may not consider the parallel construction between if 
>> case/guard case with switchstatements or naturally connect the two layouts.
>>  
>> <https://gist.github.com/erica/06dad9bbe1a70290fe6b89a64f73bc0c#internal-case-binding>Internal
>>  Case Binding
>> 
>> When pattern matching, it's common to bind a variable or constant. It's 
>> uncommon but legal to use a bound value as an argument. Adopting an "always 
>> explicit, always within the parentheses" rule adds consistency and safety to 
>> Swift. 
>> 
>> Consider the following enumeration and values:
>> 
>> // An enum with one, two, or three associated values
>> enum Value { case one(T), two(T, T), three(T, T, T) }
>> 
>> // An example with two associated values
>> let examp

Re: [swift-evolution] [Discussion] Simplifying case syntax

2017-03-01 Thread Pyry Jahkola via swift-evolution
Erica,

Instead of going into all these lengths introducing new syntax, why not simply 
turn it into a warning when a `case let` binding shadows an existing variable 
with the exact same type (which supposedly also conforms to Equatable)?

Examples, including how to silence the said warning:

enum Value { case one(T), two(T, T), three(T, T, T) }

let example: Value = .two("a", "b")
let oldValue = "x"
// (Besides, you probably intended `oldValue` to be a `Character` in your
// example. Well, it's a `String` in mine.)

if case let .two(newValue, oldValue) = example { ... }
// 
// warning: 'oldValue' shadows an existing variable of same type 'String'

if case let .two(newValue, (oldValue)) = example { assert(oldValue == "b") }
// Ok, adding extra parentheses silences the warning.

if case let .one(example) = example { ... }
// Ok, because there's no way the author would equate the `example: String`
// in the LHS to the `example: Value` of the RHS.

let maybe: Optional = "perhaps"
if case let maybe? = maybe { ... }
if case let .some(maybe) = maybe { ... }
// Again, none of these examples would be affected by the warning, because
// the `maybe: String` bound in the `case let` has a different type than
// the `maybe: String?` in the outer scope.

Personally, I do like the convenience that I can bind several variables with 
one `let` keyword in a case expression. And I can't see the appeal to making 
`~=`, let alone a completely new special-syntax assignment operator, more 
prominent in Swift.

— Pyry

> On 28 Feb 2017, at 21.01, Erica Sadun via swift-evolution 
>  wrote:
> 
> The following draft proposal addresses one matter of substance (eliminating 
> edge case errors by adopting at-site conditional binding) and one of style 
> (using the pattern match operator consistently). Its discussion was deferred 
> from Phase 1 and remains in a fairly early stage. Your feedback will help me 
> decide whether this is a proposal I want to keep developing or one that I 
> should set aside and focus on other matters. Thank you. -- E
> 
> The work-in-progress gist is here:  
> https://gist.github.com/erica/06dad9bbe1a70290fe6b89a64f73bc0c 
>  
> 
> Simplifying case syntax
> 
> Proposal: TBD
> Author: Erica Sadun 
> Status: TBD
> Review manager: TBD
>  
> Introduction
> 
> This proposal re-architects case syntax grammar to reduce potential errors 
> and simplify unwrapping enumerations. 
> 
> Swift-evolution thread: [Pitch] Reimagining guard case/if case 
> 
>  
> Motivation
> 
> In its current design, Swift case binding suffers from two weaknesses.
> 
> Mixed external and internal let/var binding may introduce errors from 
> uncommon edge cases.
> Real-world users may not consider the parallel construction between if 
> case/guard case with switchstatements or naturally connect the two layouts.
>  
> Internal
>  Case Binding
> 
> When pattern matching, it's common to bind a variable or constant. It's 
> uncommon but legal to use a bound value as an argument. Adopting an "always 
> explicit, always within the parentheses" rule adds consistency and safety to 
> Swift. 
> 
> Consider the following enumeration and values:
> 
> // An enum with one, two, or three associated values
> enum Value { case one(T), two(T, T), three(T, T, T) }
> 
> // An example with two associated values
> let example2: Value = .two("a", "b")
> 
> // A bound symbol
> let oldValue = "x"
> This code's goal is to conditionally bind newValue and pattern match the 
> value stored in the oldValue symbol. The first example succeeds. The second 
> example compiles and runs but does not match the coder's intent. Using an 
> external letcreates a new oldValue shadow instead of pattern matching 
> oldValue's stored value.
> 
> // Safe
> if case .two(let newValue, oldValue) = example2 { 
> ... 
> }
> 
> // Syntactically legal but incorrect
> if case let .two(newValue, oldValue) = example2 { 
> ... 
> }
(…)

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


Re: [swift-evolution] Reduce with inout

2017-01-24 Thread Pyry Jahkola via swift-evolution

> Freak Show wrote:
> 
> Am I the only one who finds this incredibly ugly and hard to read?
> 
> This is more or less solved by inject:into: idiom.  There is no reason for 
> inout for this particular problem.

Yeah, the original signature seems more useful. If you go all `inout` like 
Gwendal suggested, you might as well just iterate over the sequence with `for x 
in xs`, updating the state as you go.

But your comment brought another idea to mind: if `mutating:` is considered a 
bad name for a non-`inout` argument, how about `reduce(into:combine:)`, similar 
to what Karl suggested earlier in this thread?

I think it reads very well at the call site, does not suggest `inout`ness of 
the argument too much (of course there's no `&` at the call site either), and 
it's still easily found with auto-completion:

let counts = words.reduce(into: [:]) {
  $0[$1] = ($0[$1] ?? 0) + 1
}

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


Re: [swift-evolution] [Pitch] Nil struct

2016-11-08 Thread Pyry Jahkola via swift-evolution
If we start from this thought…

> Adrian Zubarev wrote:
> Shouldn’t it be just like this:
> public protocol ExpressibleByNilLiteral {
> 
>   init(nilLiteral: Nil)
> }

Then why not just:

public protocol ExpressibleByIntLiteral {
  static var `nil`: Self
}

…such that Foo.nil creates your nil value of type Foo?

— Pyry

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


Re: [swift-evolution] guard let x = x

2016-11-03 Thread Pyry Jahkola via swift-evolution
As pleasing as it sounds*), the idea of type narrowing breaks down badly if:

– the binding is implicit (without explicit extra syntax involved) and
– what is bound happens to be mutable.

An example being:

// var message: String?
if message != nil { // magic turns 'message' into a non-optional 'String' 
here
  handleMessage(message)
  message = nil // 'String' is not 'ExpressibleByNilLiteral'
}

What magic would we require to still allow access to the Optional interface of 
'message' in that block? In other words, I'm afraid type narrowing for Swift's 
enums (including Optional) isn't quite as simple as that.

— Pyry

*) OTOH, I could see much benefit from being able to narrow down enums of all 
kinds, e.g. `Result` such that in the `else` branch of a failing `guard case 
let .success(value) = result`, the `error` value of `case failure(error)` were 
guaranteed by the compiler to be readily available, something like:

enum Result { case success(T); case failure(Error) }
// ...
// let result: Result
guard case let .success(string) = result
else case let .failure(error) = result {
  // ^
  // Guaranteed to succeed because 'result' was proven to be of 'case 
failure(Error)'
  throw error
}
print(string)

> On 3 Nov 2016, at 6.37, Hooman Mehr via swift-evolution 
>  wrote:
> 
> 
>> On Nov 2, 2016, at 2:02 PM, Matthew Johnson via swift-evolution 
>> > wrote:
>>> On Nov 2, 2016, at 3:47 PM, Sean Heber via swift-evolution 
>>> > wrote:
>>> 
>>> For what it’s worth, I concur. I think type narrowing makes it feel more 
>>> like the language is actually doing some work *for* me rather than me 
>>> having to babysit the language with some new syntax or keyword.
>> 
>> I’ve been staying out of the discussion because it doesn’t seem particularly 
>> relevant to Swift 4 phase 1, but +1.  Type narrowing is by far the most 
>> general and scalable solution which could be applied in other ways in the 
>> future.
>> 
> 
> Same as me, I was staying out as well. 
> +1 for type narrowing instead of the original proposal. Thank you Haravikk 
> for bringing this up.
> 
>>> 
>>> l8r
>>> Sean
>>> 
 On Nov 2, 2016, at 3:25 PM, Haravikk via swift-evolution 
 > wrote:
 
 I still think that type narrowing is the right way to handle this like so:
 
if x != nil {
// x is definitely not nil inside this block (implicitly 
 unwrapped)
} // x remains optional outside of it
 
if (x != nil) || (x == y) {
// if y's type is non-optional, then x is definitely not nil 
 inside this block also
// i.e- if all conditions narrow to the same result, the type 
 is narrowed inside the block
}
 
if x is Foo {
x.someMethodSpecificToFoo()
}
 
 Personally I'm very much against the use of shadowing in the first place, 
 and never use it myself. I tend to precede unwrapped value with "this" 
 like so:
 
if let thisFoo = foo {
// Do something with thisFoo
}
 
 I know it's maybe down to personal preference but I'd prefer to discourage 
 shadowing entirely, and focus on type-narrowing, as it's a much more 
 natural, and more generally useful, way to handle this "problem", as it 
 doesn't actually require a specific syntax at all; if your condition 
 narrows the type, then you can use the variable as whatever it is known to 
 be.
> ___
> 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] guard let x = x

2016-10-31 Thread Pyry Jahkola via swift-evolution

> On 31 Oct 2016, Xiaodi Wu wrote:
> 
> Don't we currently have "for x in y" and "for var x in y"? So, we could have 
> "unwrap x" and "unwrap var x".
> 
> And since unwrap wouldn't allow arbitrary Boolean expressions at the front 
> like if and guard statements do, it could use the where clause like for loops 
> do.

You're right. I'd forgotten about that. I found out you can even place the 
`var` keyword inside a tuple pattern where only one variable is going to be 
modified locally:

for (var i, c) in "foobar".characters.enumerated() {
  i += 1  // pretty contrived example
  print(i, c)
}

— Pyry

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


Re: [swift-evolution] guard let x = x

2016-10-31 Thread Pyry Jahkola via swift-evolution

> On 31 Oct 2016, Xiaodi Wu wrote:
> 
> An alternative that would seem to satisfy some objections is to have a 
> distinct "unwrap" statement--as in: "unwrap x else { ... }".

True. The `let`, on the other hand, has the minor upside that it's naturally 
substituted with `var` where in-place mutation is needed:

guard let value, var collection else { ... }
collection.append(value)
// ...

Disclaimer: I don't know if this is a realistic usage scenario but it seems 
more natural to Swift, in my view.

— Pyry

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


Re: [swift-evolution] guard let x = x

2016-10-31 Thread Pyry Jahkola via swift-evolution
Going back to the originating message of this thread. This idea (or a variant 
thereof) has been mentioned in the list of Commonly Rejected Proposals (2nd 
last bullet under Control Flow, Closures, Optional Binding, and Error Handling 
):

> Syntactic sugar for if let self-assignment 
> :
>  An alternative syntax (such as if let foo? { ... } or if let foo=? { ... }) 
> to serve as a shorthand for if let foo = foo { ... } is often proposed and 
> rejected because it is favoring terseness over clarity by introducing new 
> magic syntactic sugar.

So any discussion on this topic would have to target these concerns first.

> On 26 Oct 2016, David Goodine wrote:
> 
> I was typing the above (for the hundredth time) the other day and I was 
> wondering whether it might be worth considering offering a shorter syntax:
> 
> guard let x, y, z else {…}


That said, while I don't mind having to repeat the variable name myself, I 
think David Goodine's syntax would have to repeat the `let` to align with 
SE-0099 
,
 like so:

guard let x, let y, let z else { ... }

Personally, I wouldn't mind if this syntax existed. I think it explains itself 
rather well. And today, unlike when it was first discussed a long time before 
SE-0099, it's no longer confusable with Boolean conditions.

But it's certainly out of scope for Swift 4 phase 1.

— Pyry

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


Re: [swift-evolution] [Pitch] Simpler interpretation of a reference to a generic type with no arguments

2016-10-11 Thread Pyry Jahkola via swift-evolution
I was reminded of this proposal which seems like an obvious win in clarity. 
Still planning to submit it, Slava?

— Pyry

> On 28 Jun 2016, at 21:13, Dave Abrahams via swift-evolution 
>  wrote:
> 
> on Thu Jun 23 2016, Slava Pestov  wrote:
> 
>> Simpler interpretation of a reference to a generic type with no
>> arguments
>> 
>> Proposal: SE-
>> 
>> Author: Slava Pestov 
>> Status: Awaiting review
>> Review manager: TBD
>> Introduction
>> 
>> This proposal cleans up the semantics of a reference to a generic type
>> when no generic arguments are applied.
>> 
>> Swift-evolution thread: Discussion thread topic for that proposal
>> 
>> Motivation
>> 
>> Right now, we allow a generic type to be referenced with no generic
>> arguments applied in a handful of special cases. The two primary rules
>> here are the following:
>> 
>> If the scope from which the reference is made is nested inside the
>> definition of the type or an extension thereof, omitting generic
>> arguments just means to implicitly apply the arguments from context.
>> 
>> For example,
>> 
>> struct GenericBox {
>>  let contents: Contents
>> 
>>  // Equivalent to: func clone() -> GenericBox
>>  func clone() -> GenericBox {
>>return GenericBox(contents: contents)
>>  }
>> }
>> 
>> extension GenericBox {
>>  func print() {
>>// Equivalent to: let cloned: GenericBox
>>let cloned: GenericBox = clone()
>>print(cloned.contents)
>>  }
>> }
>> If the type is referenced from an unrelated scope, we attempt to infer
>> the generic parameters.
>> 
>> For example,
>> 
>> func makeABox() -> GenericBox {
>>  // Equivalent to: GenericBox(contents: 123)
>>  return GenericBox(contents: 123)
>> }
>> The problem appears when the user expects the second behavior, but
>> instead encounters the first. For example, the following does not type
>> check:
>> 
>> extension GenericBox {
>> 
>>  func transform(f: Contents -> T) -> GenericBox {
>>// We resolve 'GenericBox' as 'GenericBox', rather than
>>// inferring the type parameter
>>return GenericBox(contents: f(contents))
>>  }
>> }
>> Proposed
>> solution
>> 
>> The proposed solution is to remove the first rule altogether. If the
>> generic parameters cannot be inferred from context, they must be
>> specified explicitly with the usual Type syntax.
> 
> SGTM.  I've always found this shorthand to be somewhat surprising,
> including in C++ where (IIUC) it originated.
> 
> 
> -- 
> Dave

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


Re: [swift-evolution] [Pitch] Refactor Metatypes

2016-10-02 Thread Pyry Jahkola via swift-evolution
That sounds very good to me, and AnyType aligns well with the proposed 
Any<...> syntax.

— Pyry

> Adrian Zubarev wrote:
> 
> That’s right. I was about to say something similar about the Of.
> 
> Actually Type would be the correct name for the static/concrete metatype.
> 
> We already have this notation but not in a generic way T.Type
> If we add of only in our mind to Type, we’ll get “Type of a type T” which 
> is shortly referred as a “metatype of T”. (Array - Array of Element 
> type)
> Since Subtype in reality is some *existential metatype* and the whole talk 
> about existential types now tend to have the Any prefix, lets follow that 
> trend here too.
> 
> Type - (static/concrete/exact) metatype.
> AnyType - existential metatype.
> It might be even easier to memorise this name than Subtype.
> 
> The example from the proposal rewritten:
> 
> // Types:
> protocol Foo {}
> protocol Boo : Foo {}
> class A : Foo {}
> class B : A, Boo {}
> struct S : Foo {}
> 
> // Metatypes:
> let a1: Type = A.self   //=> Okay
> let p1: Type = Foo.self   //=> Okay
> let p2: Type = C.self //=> Error -- `C` is not the same as `Foo`
> 
> let any_1: AnyType = A.self   //=> Okay
> let any_2: AnyType = Foo.self //=> Okay
> 
> let a_1: AnyType = A.self   //=> Okay
> let p_1: AnyType = A.self //=> Okay
> let p_2: AnyType = Foo.self   //=> Error -- `Type` is not a subtype 
> of `AnyType`
> 
> // Generic functions:
> func dynamic(type: AnyType, `is` _: Type) -> Bool {
>   return type is AnyType
> }
> 
> func dynamic(type: AnyType, `as` _: Type) -> AnyType? {
>   return type as? AnyType
> }
> 
> let s1: Type = S.self
> 
> dynamic(type: s1, is: Foo.self)//=> true
> dynamic(type: s1, as: Foo.self)//=> an `Optional<AnyType>`
> The type(of:) function could now stay, because now we’d only need to change 
> the return type.
> 
> func type(of instance: T) -> AnyType
> Isn’t this a good compromise?
> 
> 
> 
> -- 
> Adrian Zubarev
> Sent with Airmail
> 
> Am 2. Oktober 2016 um 09:01:45, Pyry Jahkola via swift-evolution 
> (swift-evolution@swift.org) schrieb:
> 
>> OTOH, we don't have ArrayOf or DictionaryOfKeyAndValue<Key, Value>, 
>> while we still pronounce them that way. I don't think prepositions belong in 
>> the name of types but in exceptional cases, and this doesn't sound 
>> exceptional enough to me.
> 
> ___
> 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] [Pitch] Refactor Metatypes

2016-10-02 Thread Pyry Jahkola via swift-evolution

> Goffredo Marocchi wrote:
> 
> I think the names should be bikeshedded more still. From your examples they 
> seem to make sense when I mentally add Of like TypeOf<> and SubTypeOf<>, but 
> since you are not commenting on why that is wrong or right or misleading, or 
> at least I have missed your reply on that, I am still a bit at loss. Maybe we 
> need other words altogether?

OTOH, we don't have ArrayOf or DictionaryOfKeyAndValue, 
while we still pronounce them that way. I don't think prepositions belong in 
the name of types but in exceptional cases, and this doesn't sound exceptional 
enough to me.

— Pyry

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


Re: [swift-evolution] [Last second] Precedence of nil-coalescing operator seems too low

2016-09-08 Thread Pyry Jahkola via swift-evolution
Vladimir,

I don't disagree with you about bitwise operations (please read my email 
again). I'm saying when it comes to `??`, we don't have the evidence necessary 
for proposing a breaking change.

> On 08 Sep 2016, at 14:21, Vladimir.S  wrote:
> 
> Why do you need to see some precedence (…) while this construction is so 
> simple and obviously would be used often and *will* cause bugs. (…)

Let me put it differently: I still haven't seen, nor was I able to conceive 
myself, a realistic example where `??` would cause problems.

>> The original motivation by Erica simply failed to compile (…)
> 
> Sorry, but you are just not right.

Let me remind you that the original motivation from Erica wasn't about which 
way `foundIndex ?? lastIndex + 1` goes but about whether `let y = 5 + x ?? 2` 
compiles at all.

> The code compiles without even warning:
> 
> let foundIndex : Int? = 1
> let lastIndex = 2
> 
> let nextIndex = foundIndex ?? lastIndex + 1

It certainly does compile. But is it realistic? Look at the variable names: 
does this code make any sense at all? What is `lastIndex`? What is `lastIndex + 
1`? Why not `things.endIndex`? Indeed, why not:

let foundIndex: Int? = things.index(of: something)
let nextIndex = foundIndex.map { $0 + 1 } ?? things.endIndex

That said, I give you the benefit of the doubt – I still believe there can be 
examples where `??` may be confusing. But without seeing any such examples from 
the real world, I don't think we have a case for changing `??`.

> After I showed the code compiles, would you change your opinion?

No, not with these examples.

* * *

Finally:

> IMO the best solution (…) would be to require (…) parenthesis when operators 
> from different groups are mixed in the same expression. IMO no need in 
> complex rules to make Swift safer. I.e. when you have a = 10 + 5 * 10 - you 
> don't need parenthesis, when you have a = b << 4  - also all is ok, but if 
> you have a = b << 4 + 5 * 10 - you'll have a warning until add parenthesis to 
> make your intention clear. (…)

Look, changing how `b << 4 + 5 * 10` is compiled is exactly what I was 
proposing. With my changes, it would become a compiler error. IMO, it ought to 
be parenthesised explicitly as either

(b << 4) + 5 * 10

or

b << (4 + 5 * 10)

depending on which one was intended.

— Pyry

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


Re: [swift-evolution] [Review] SE-0140: Bridge Optional As Its Payload Or NSNull

2016-09-03 Thread Pyry Jahkola via swift-evolution
I don't feel confident enough about the Swift–Obj-C interop to cast my own vote 
but I'd like to question this sentiment:

> On 03 Sep 2016, at 03:17, Charles Srstka via swift-evolution 
>  wrote:
> 
> With the existing behavior, such mistakes are immediately obvious as 
> Objective-C receives an opaque object that it cannot use (and probably soon 
> crashes), so they are unlikely to make it past QA testing.

How is this different with NSNull though? If the callee expects an array of 
NSNumbers for example and uses them (for anything more specific than NSObject), 
the first NSNull instance will throw an NSInvalidArgumentException basically 
crashing the program as well:

$ cat example.m
@import Foundation;

int main() {
id number = NSNull.null;
NSLog(@"%ld", [number integerValue]);
}

$ clang -fmodules example.m -o example && ./example
2016-09-03 10:47:21.822 example[31488:151700] -[NSNull integerValue]: 
unrecognized selector sent to instance 0x7fff78561780
(snip...)
libc++abi.dylib: terminating with uncaught exception of type NSException
Abort trap: 6

OTOH, if the only thing the Obj-C code planned to do was immediately convert 
the NSArray into JSON, then a previously crashing example would now start 
producing a JSON array with mixed numbers and nulls. But is that kind of code 
likely in practice?

It would be different though if NSNull just swallowed any messages it receives 
like `nil` does. There are 3rd party examples 
 of 
that behaviour, and that would be detrimental to code quality in the case of 
Swift interop.

— Pyry

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


Re: [swift-evolution] Keyword for protocol conformance

2016-08-26 Thread Pyry Jahkola via swift-evolution
Hi Xiaodi and Charles,

> As I said, this discussion has already happened several times. I'm literally 
> just repeating what people said eight months ago, six months ago, and four 
> months ago. There's not a good answer to this and perhaps several other 
> issues, which is why I don't see a way forward for the proposal. After all, I 
> was the one proposing the same idea last winter, so I've had a few months to 
> think about it.


I've been following the discussion from the side both now and before. Without 
being able to cover everything that's been said, I hope this message brings at 
least a bit of new air into the discussion.

— — —

Here's one more approach that, AFAICT, would enable both retroactive modelling 
and fairly good error diagnostics: bring the full protocol conformance together 
with a dedicated definition block which can both define implementations and 
refer to implementations defined elsewhere.

Details:

1. Allow marking the conformance to a given protocol with a block of code. This 
could be nested inside a struct/enum/class body or its extension:

struct Vector {
  conformance Hashable { /* TBD, read on… */ }
}
extension Vector {
  conformance CustomStringConvertible { /* … */ }
}

or at the top level, as a clearly marked single-conformance extension:

conformance Vector : CustomDebugStringConvertible { /* … */ }

2. Inside the body of that block, all protocol (non-extension) methods must be 
marked with `override`. That includes both the required interface and the 
customisable interface with library-provided default implementations:

struct Vector {
  conformance Hashable {
override static func ==(lhs: Self, rhs: Self) -> Bool { /* … */ }
// Ok.

var hashValue: Int { /* … */ }
// error: property 'hashValue' is required by Hashable.
// (Fixit: mark with 'override')

override static func < (lhs: Self, rhs: Self) -> Bool { /* … */ }
// error: protocol Hashable does not require 'static func <'.
// (Fixit #1: remove override. Etc.)
  }
}

3. When conformance is made explicit as described above, no other part of code 
is allowed to interfere with that type's conformance to the protocol under 
question:

conformance Vector : Collection {
  override var startIndex: Int { return 0 }
  override var endIndex: Int { return _count }
  override subscript(index: Int) -> Double { return _elements[index] }
  override func index(after i: Int) -> Int { return i + 1 }
}
extension Vector {
  var count: Int { return _count }
  // error: property 'count' was introduced by explicit conformance to 
Collection.
  // (Fixit: Add explicit override to the conformance block.)
}

4a. When using a `conformance` block for retroactive modelling, or to 
explicitly include methods, properties etc. defined elsewhere, it is enough to 
list those in the body of the `conformance` block:

protocol CountHaving {
  associatedtype Count : Integer
  var count: Count
}
conformance Array : HasCount {
  override var count: Int // Ok, explicit retroactive modelling.
}

4b. Any override declarations without a body within an explicit `conformance` 
block are requirements for the definitions to exist elsewhere. That includes 
overridden properties without getters and setters. For example, here's an 
alternative way of fixing the error in #4:

conformance Vector : Collection {
  override var startIndex: Int { return 0 }
  override var endIndex: Int { return _count }
  override subscript(index: Int) -> Double { return _elements[index] }
  override func index(after i: Int) -> Int { return i + 1 }
  override var count: Int // No body; defined elsewhere.
}
extension Vector {
  var count: Int { return _count } // Ok.
}

5. Just like any other extensions, `conformance` blocks could introduce other 
non-`override` methods etc. to its needs, but they probably should keep it at 
minimum.

— — —

Downsides. Now, there are obvious reasons not to introduce this complexity to 
the language:

− It adds quite a bit of boilerplate to the conformance definition. (OTOH, 
programmers in a hurry would still be able to use the existing implicit 
conformance syntax, thereby avoiding the boilerplate on the one hand, and the 
better diagnostics on the other.)

− It would make it harder to add new required methods with default 
implementations without breaking code elsewhere. Because explicitly conforming 
types which already happened to have a matching function, property, or 
subscript would need to include it in the explicit conformance block. (OTOH, 
maybe that's what they indeed asked for by making the conformance explicit!)

− It would add yet another keyword to the language, context-specific but 
regardless. And the amount of `override` noise isn't looking very pretty.

− It possibly complicates some other convenient use of 

Re: [swift-evolution] [Idea] Add `bounds` function to standard library

2016-08-25 Thread Pyry Jahkola via swift-evolution
> On 25 Aug 2016, at 12:05, Nicholas Maccharoli wrote:
> 
> I personally see merit in adding a function to bound the value of a variable 
> within a range and think it would be simple to write with the existing 
> implementations of `min` and `max` with something like:
> 
> public func bounds(value: T, _ lower: T, _ upper: T) -> T 
> {
> return max(lower, min(value, upper))
> }
> 
> Does this sound like something the community thinks would be worthwhile to 
> add?

I'd welcome that addition. In terms of function interface, I think we can do 
better than the 3-argument `clamp(x, min, max)` function that is seen in 
several math libraries.

Our ***Range types already have a `clamped(to:)` member function, e.g. here's 
one for ClosedRange 
. It 
creates a new range constraining the receiver's bounds within the new bounds 
given as argument.

I think the sensible thing would be to add a similar, and equally named, method 
to the Comparable protocol, taking in the ClosedRange to limit the value 
to:

extension Comparable {
  public func clamped(to limits: ClosedRange) -> Self {
return self < limits.lowerBound ? limits.lowerBound
 : self > limits.upperBound ? limits.upperBound
 : self
  }
}

(-0.1).clamped(to: 0 ... 1)   // 0.0
3.14.clamped(to: 0 ... .infinity) // 3.14
"foo".clamped(to: "a" ... "f")// "f"
"foo".clamped(to: "a" ... "g")// "foo"

>From my experience, I'd say it'd be most useful for clamping floating-point 
>numbers and collection indices.

— Pyry

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


Re: [swift-evolution] [Idea] Use optionals for non-optional parameters

2016-08-16 Thread Pyry Jahkola via swift-evolution

> On 16 Aug 2016, at 20:24, Justin Jia via swift-evolution 
>  wrote:
> 
> Thank you for the sharing how you solve this problem! It seems like the best 
> workaround so far. 
> 
> I wish $0 can be replaced by the actual name. (Maybe tuples?)
> 
> let a = (x: x, y: y)
> let result = a.my_map { foo(x: $0.x, y: $0.y }
> 
> In my_map unwrap all variables inside tuple?
> 
> I agree that short-circuiting is an issue. But personally I still think the 
> imperfect solution is good enough. But I'll try to find other possible 
> solutions. 

One technique around this is to introduce a set of generic library functions 
that try to unwrap all of their arguments and construct a tuple thereof if 
every argument evaluated to `.some(_)`. The evaluation of expressions can also 
be delayed with @autoclosure:

func unwrap(_ a: A?, _ b: @autoclosure () throws -> B?) rethrows -> 
(A, B)? {
guard let a = a, let b = try b() else { return nil }
return (a, b)
}

func unwrap(_ a: A?,
 _ b: @autoclosure () throws -> B?,
 _ c: @autoclosure () throws -> C?) rethrows -> (A, B, 
C)?
{
guard let a = a, let b = try b(), let c = try c() else { return nil }
return (a, b, c)
}

// ...etc, for higher arities than 3.

Repetitive library code? Yes. But can be easily generated with a code generator 
such as swift.gyb, and you hardly need it for arities higher than a few.

You can use `unwrap()` together with `if let` or `guard let`:

if let (a, b, c) = unwrap(Int("1"), Double("12"), Bool("true")) {
print(a, b, c) //=> 1 12.0 true
}

Or even `.map()` if you like. This use is similar to Dave Sweeris' suggestion 
of `optionally()`:

struct User { var username, language: String }
let data = ["u": "chris", "l": "swift"]
let user = unwrap(data["u"], data["l"]).map {u, l in
User(username: u, language: l)
}
print(user) //=> Optional(User(username: "chris", language: "swift"))

I guess that reads better than this equivalent with `.flatMap()` and `.map()`:

let user = data["u"].flatMap { u in
data["l"].map { l in
User(username: u, language: l)
}
}

OTOH, it isn't much better than either delayed `let` initialisation:

let user: User?
if let u = data["u"], let l = data["l"] {
user = User(username: u, language: l)
} else {
user = nil
}

Or the use of a one-off closure like so:

let user: User? = {
guard let u = data["u"], let l = data["l"] else { return nil }
return User(username: u, language: l)
}()

— Pyry

(Sorry for the sparing use of newlines in the examples above. Tried to keep it 
tight.)

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


Re: [swift-evolution] [Review] SE-0131: Add AnyHashable to the standard library

2016-07-25 Thread Pyry Jahkola via swift-evolution
Dmitri Gribenko wrote:

>> There's one very obscure gotcha with AnyHashable that subclass instances of
>> a Hashable base class should be cast to the base type before wrapping into
>> AnyHashable, otherwise such wrapped values may break the equivalence law of
>> symmetry (`a == b` iff `b == a`).
> 
> The implementation that I have does not suffer from this issue.  (The
> initializer of AnyHashable walks the superclass chain and upcasts the
> value to the correct type.)

Brilliant! Glad that you found a resolution!

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


Re: [swift-evolution] [SHORT Review] SE-0132: Rationalizing Sequence end-operation names

2016-07-25 Thread Pyry Jahkola via swift-evolution

> On 25 Jul 2016, at 09:10, Chris Lattner via swift-evolution 
>  wrote:
> 
> Hello Swift community,
> 
> The review of "SE-0132: Rationalizing Sequence end-operation names" begins 
> now and runs through July 26.  Apologies for the short review cycle, but 
> we’re right up against the end of source breaking changes for Swift 3.  The 
> proposal is available here:
> 
>   
> https://github.com/apple/swift-evolution/blob/master/proposals/0132-sequence-end-ops.md
> 
>   * What is your evaluation of the proposal?

+1 to the method renames.
-1 to the slice syntax proposed.

I find the introduction of unary operators confusing. I don't think it's good 
design that you need to remove a space when moving from the old syntax to the 
new one:

array[array.startIndex ..< someIndex] // before
array[..   * Is the problem being addressed significant enough to warrant a change 
> to Swift?

Yes.

>   * Does this proposal fit well with the feel and direction of Swift?

Yes.

>   * If you have used other languages or libraries with a similar feature, 
> how do you feel that this proposal compares to those?

N/A

>   * How much effort did you put into your review? A glance, a quick 
> reading, or an in-depth study?


Quick reading.

Thanks to Brent for the effort!

— Pyry

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


Re: [swift-evolution] [Review] SE-0131: Add AnyHashable to the standard library

2016-07-25 Thread Pyry Jahkola via swift-evolution

> On 24 Jul 2016, at 01:26, Chris Lattner via swift-evolution 
>  wrote:
> 
> Hello Swift community,
> 
> The review of "SE-0131: Add AnyHashable to the standard library" begins now 
> and runs through July 25.  This proposal is a bit unusual, since it is a late 
> additive proposal.  The reason we need to do something here is as a critical 
> part of "SE-0116: Import Objective-C id as Swift Any type”, enabling 
> importing untyped NSDictionary's and NSSet’s properly.  The core team 
> considers this already conceptually approved for Swift 3 as part of SE-0116, 
> but would greatly appreciate feedback on the details of the proposed design.
> 
> The proposal is available here:
> 
>   
> https://github.com/apple/swift-evolution/blob/master/proposals/0131-anyhashable.md
> 
>   * What is your evaluation of the proposal?

+1, this is a nice addition, and useful at times.

There's one very obscure gotcha 

 with AnyHashable that subclass instances of a Hashable base class should be 
cast to the base type before wrapping into AnyHashable, otherwise such wrapped 
values may break the equivalence law of symmetry (`a == b` iff `b == a`).

But now that most of Foundation's class clusters are bridged into value types, 
that problem is unlikely to occur to anyone anymore.

>   * Is the problem being addressed significant enough to warrant a change 
> to Swift?

So and so.

>   * Does this proposal fit well with the feel and direction of Swift?

Yes. Maybe it will also help us gain more experience when designing real 
existential types.

>   * If you have used other languages or libraries with a similar feature, 
> how do you feel that this proposal compares to those?

A bit of a hack compared to real existentials. But a good one.

>   * How much effort did you put into your review? A glance, a quick 
> reading, or an in-depth study?

Quick reading.

— Pyry

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


Re: [swift-evolution] [Proposal] Formalized Ordering, take 2

2016-07-25 Thread Pyry Jahkola via swift-evolution

> On 25 Jul 2016, at 21:23, Nevin Brackett-Rozinsky 
>  wrote:
> 
> My one question is, will I be able to write `someCollection.sort(.ascending)` 
> and get the expected result? (This could be an additive future direction.)


To sort to ascending order, you'd still just call `.sort()` with no arguments.

To limit the scope of this proposal somewhat, I moved the introduction of new 
sorting functions into the Future directions section. All of those changes are 
additive in a way or another:

1. The default .sort() function would use `<=>` instead of `<`.

(a) On the one hand, we'd get improved performance in cases like 
Array.sort() where doing another `<` comparison would be more costly.
(b) On the other hand, we'd get well-defined behaviour when sorting Double 
arrays containing NaNs, because all non-NaN values would be sorted into one 
contiguous subrange of the result.

That's an additive change because (a) types implementing total order will still 
sort according to the same spec as `.sort(by: <)`.

2. If I had it my way, the default .sort() would also become stable, and the 
programmer could opt in to using a faster unstable sort variant. There are 
cases where an unstable sort performs better, but a stable sort is a better 
default, not least because it's usually what people want when sorting a table 
by a given column.

3. Several functions (e.g. `.sort(by:)`) would be paired with a 
`frobnicate(ordering:)` variant where the block returns `Ordering` instead of 
`Bool`. For sorting to descending order, you'd call something like 
`someCollection.sort(ordering: Ordering.reversing(<=>))`. Or whatever naming 
we'll end up with.

— Pyry

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


Re: [swift-evolution] [Proposal] Formalized Ordering, take 2

2016-07-25 Thread Pyry Jahkola via swift-evolution

> On 25 Jul 2016, at 18:51, Björn Forster  wrote:
> 
> Could you please explain for someone as simple minded as me why there is (or 
> has to be) a difference in the implementation of <, <= and >, >=?
> Sorry, but I don't get into my head why there is/has to be a preference for 
> one side. Could you or someone else point out (in the proposal) why there is 
> a need/what is the reason for this?
> I assume that this might not be obvious to some other people on the first 
> look, too.

The reason is two-fold:

Firstly, and most importantly, because we want the law of antisymmetry (that `a 
< b` iff `b > a`, and likewise for ≤ and ≥) to hold even in the presence of 
strange types. Turning only one operator of every such pair into customisation 
points makes it essentially impossible to break that law.

Secondly, because we want to minimise the surface area of Comparable to keep 
the API as simple as possible. The drawback of my design is that while it 
manages to alleviate many subtleties of IEEE-754, it also contains many member 
functions (essentially all but `<=>`) which should not be customised for most 
types in practice.

— Pyry

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


Re: [swift-evolution] [SHORT Review] SE-0133: Rename `flatten()` to `joined()`

2016-07-25 Thread Pyry Jahkola via swift-evolution

> On 25 Jul 2016, at 09:10, Chris Lattner via swift-evolution 
>  wrote:
> 
> The review of "SE-0133: Rename `flatten()` to `joined()`" begins now and runs 
> through July 26.  Apologies for the short review cycle, but we’re right up 
> against the end of source breaking changes for Swift 3.  The proposal is 
> available here:
> 
>   
> https://github.com/apple/swift-evolution/blob/master/proposals/0133-rename-flatten-to-joined.md
> 
>   * What is your evaluation of the proposal?

+1, this makes sense. The functions are very closely related, and while we have 
"flatten" in `flatMap`, is isn't unprecedented to call the joining operation 
`join` instead of `flatten`.

Flatten also somewhat suffers from the expectation that it would flatten 
arbitrary depths of nestings down to just one. (That would be absurd in Swift's 
type system, but is precedented in e.g. Clojure 
.) 
The word "join" instead sounds like a more 1-dimensional operation, and thus 
decreases the minor surprise factor.

It's also nice that `.joined(separator:)` can be simplified down to `.joined()` 
when the default separator is wanted. And I'd say the empty collection is an 
obvious choice for default in here.

>   * Is the problem being addressed significant enough to warrant a change 
> to Swift?

Yes, it makes the function easier to find.

>   * Does this proposal fit well with the feel and direction of Swift?

Yes.

>   * If you have used other languages or libraries with a similar feature, 
> how do you feel that this proposal compares to those?

Yes. E.g. Haskell calls it `join` 
.

>   * How much effort did you put into your review? A glance, a quick 
> reading, or an in-depth study?

Quick reading.

— Pyry

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


Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-24 Thread Pyry Jahkola via swift-evolution

> Dave Abrahams wrote:
> 
> Asking whether zero appears in a sequence that happened to contain a NaN 
> would equally be a precondition violation.

No, it wouldn't because Double would implement Equatable + Comparable by 
providing custom implementations of ==, <, >, <=, and >=, in addition to 
Double.<=> which may trap.

My point in 
https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160718/025375.html
 is that by keeping all those operators within the required interface of 
protocol Comparable, such customisation remains possible. The original proposal 
only suggested == in Equatable and <=> in Comparable. If that were the case, 
then generic algorithms would necessarily end up calling <=>.

It is key that not only <=> is a customisation point of Comparable. Only those 
generic algorithms which used <=> directly (e.g. sort, partition, binary 
search) would see precondition violations if the sequence contained one or more 
NaNs.

***

Another possible choice would be to return .descending whenever either of the 
comparands were NaN, while also making <, >, <=, and >= return false in such 
cases. Then we wouldn't see preconditionFailures but instead produced bogus 
results from sort, partition etc. That's the tradeoff Haskell has chosen for 
its `compare` function over Double, FWIW.

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


Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-24 Thread Pyry Jahkola via swift-evolution
Pyry Jahkola wrote:

>> or even to ask whether
>> someSequence.contains(.nan).  IMO that's not really acceptable.
> 
> Not correct. Algorithms like contains(_:) or firstIndex(of:) would use the == 
> operator which is part of the protocol and thus wouldn't call <=> on 
> FloatingPoint types which override the default implementation.

Oops, spoke too soon. Well, I think it's easy enough to require people to write 
numbers.contains(where: { $0.isNaN }) in this use case.

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


Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-24 Thread Pyry Jahkola via swift-evolution
Dave Abrahams wrote:

>> Given all this, I propose a simpler model that makes `a <=> b` follow
>> the expected behaviour of < and ==, with the tradeoff that `a <=>
>> .nan` and `.nan <=> b` will abort with a precondition failure:
> 
> This effectively makes it a precondition violation to default-sort
> a sequence of floats that contains a NaN

Correct. I'm still pondering if that could be alleviated in this model with 
minor modifications. Note however, that the proposed IEEE 754 total order would 
put negative NaNs at front and positive NaNs at the end. I can't say that's too 
useful either.

> or even to ask whether
> someSequence.contains(.nan).  IMO that's not really acceptable.

Not correct. Algorithms like contains(_:) or firstIndex(of:) would use the == 
operator which is part of the protocol and thus wouldn't call <=> on 
FloatingPoint types which override the default implementation.

— Pyry

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


Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-23 Thread Pyry Jahkola via swift-evolution
Given all this, I propose a simpler model that makes `a <=> b` follow the 
expected behaviour of < and ==, with the tradeoff that `a <=> .nan` and `.nan 
<=> b` will abort with a precondition failure:

1) We keep the current Interface of Equatable  unchanged, with != defined in 
terms of ==.

2) Comparable would still refine Equatable, and include all the comparison 
operators, adding the new <=>:

protocol Comparable : Equatable {
  static func <=>(lhs: Self, rhs: Self) -> Ordering
  static func <(lhs: Self, rhs: Self) -> Bool
  static func >(lhs: Self, rhs: Self) -> Bool
  static func <=(lhs: Self, rhs: Self) -> Bool
  static func >=(lhs: Self, rhs: Self) -> Bool
}

The comparison operators are kept in the interface so that partially ordered 
types such as Double can be supported in generic code. However, the 
documentation should recommend against defining `<` manually.

3) Default implementations for  are provided for the 
following operators: ==, <, >, <=, and >=.

4) User-defined types will need to define just <=> to conform to Comparable. 
(Even == can be omitted!)

5) FloatingPoint types implement custom versions of ==, <, >, <=, and >= using 
the standard IEEE 754 definition (i.e. comparisons involving NaN return false). 
Zero is zero; `0.0 == -0.0 && !(-0.0 < 0.0)` holds.

6) FloatingPoint types implement <=> as:

func <=> (lhs: T, rhs: T) -> Ordering {
  if lhs < rhs { return .ascending }
  if rhs < lhs { return .descending }
  precondition(lhs == rhs)
  return .same
}

7) Algorithms using <=> directly should mention so in their documentation as a 
precondition that they require total order between elements. Many generic 
algorithms can be defined in terms of == or <, and should.

If we took the oroginally planned route that distinguished between identities 
such as -0.0 vs. +0.0, or between the 2⁴⁹ - 2 ≈ 5.6 × 10¹⁴ possible NaN values 
that Double has, we'd also need to consider other oddballs like the difference 
and ordering between the Strings "ä" and "a\u{308}", which are considered equal 
but produce a different Unicode representation. I think it's best to hide those 
identities behind another interface than Equatable and Comparable, and let the 
protocols serve more mundane application logic.

— Pyry

> Dave Abrahams wrote:
> 
> 
>> on Sat Jul 23 2016, Xiaodi Wu  wrote:
>> 
>> On Fri, Jul 22, 2016 at 11:34 PM, Stephen Canon  wrote:
>> 
 The point of this design is that `===` means identity and that `.same `
 also means identity.
 
 Since this is new territory I suppose we get to decide what identity
 means for floating point.  Should +0 and -0 have the same identity or
 not?  I’ll leave the answer to folks more knowledgable about numerics
 than I.
>>> 
>>> Boy, I take my wife out for a movie and come back to 50 new messages on SE.
>>> 
>>> I need to read the entire thread more carefully, but off the top of my
>>> head, I think that `-0 === +0` is False.  If we’re going to have an
>>> `isSame` / `isIdentical` / whatever it's called, I would expect it to imply
>>> substitutability.  Although -0 == +0, they are not equivalent when
>>> substituted:
>>> 
>>> - 1/(-0) != 1/0
>>> - Float(-0).sign != Float(+0).sign
>>> - etc
>>> 
>>> This probably then implies that `<=>` is not `.same` either.  I’ll read
>>> the rest of this and respond more completely tomorrow.
>> 
>> Eagerly await your evaluation of the discussion. In the meantime:
>> 
>> I think Dave's view that `===` defines identity in terms of "essential"
>> qualities implies that two identical values can be
>> different/non-substitutable in "inessential" qualities. For generic
>> purposes, the sign of zero could be one such inessential quality.
> 
> Yes, and I think our view of how people work with numbers in swift (and
> their protocol conformances) reflect this approach.  
> 
> http://article.gmane.org/gmane.comp.lang.swift.evolution/16321
> 
> My sense is that we want to choose the default notions of identity and
> ordering so as to support the way people think about these numeric
> types, inexact though it may be.  Therefore, finding 0.0 in a sequence
> of floats should succeed when the sequence contains -0.0, and a stable
> sort on floating point keys should preserve the relative order of all
> elements having +0.0 and -0.0 keys.  
> 
> People that want to work with inessential qualities such as the sign of
> zero can always pass Float.totalOrdering (or whatever) to their
> closure-accepting algorithms.
> 
> [In order to support the user model, we still need to fix the semantics
> of the default identity and ordering operations so that things like
> sorting and searching work, which is why == and < won't cut it for these
> purposes]
> 
>> On the other hand, the stdlib stride algorithm is going to be borked if -0
>> < +0. Of course, as we already started to do there, we could specialize for
>> floating point and then adjust accordingly. 

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Pyry Jahkola via swift-evolution
Xiaodi Wu wrote:

> I just assumed that the core team's vision was that this would be addressed 
> by a domain-specific floating point `areSame(a: Self, b: Self) -> Bool { 
> return (a == 0 && b == 0) || (a <=> b) == .same }`. This is a valid 
> equivalence relation afaik.

I guess so, but it's a different from what Dmitri gave here:

>> 7. What, in fact, is the proposed total order for the stdlib's 
>> floating-point types?
> 
> The IEEE 754 definition.
> 
> https://github.com/apple/swift/blob/f318fe853d7898246db24d501f1ddc03c9eb8651/stdlib/public/core/FloatingPoint.swift.gyb#L855

— Pyry

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


Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Pyry Jahkola via swift-evolution
Dmitri Gribenko wrote:

>> 7. What, in fact, is the proposed total order for the stdlib's 
>> floating-point types?
> 
> The IEEE 754 definition.
> 
> https://github.com/apple/swift/blob/f318fe853d7898246db24d501f1ddc03c9eb8651/stdlib/public/core/FloatingPoint.swift.gyb#L855

Cool. So if I'm reading it correctly, that's exactly the same order as what I 
defined here, using bitPattern: 
http://swiftlang.ng.bluemix.net/#/repl/5791db33719d5d045b4d430c. I suppose your 
implementation is better in the usual case where most values are in the range 
of -Double.infinity ... Double.infinity.

— Pyry

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


Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Pyry Jahkola via swift-evolution

> On 22 Jul 2016, at 04:11, Robert Widmann via swift-evolution 
>  wrote:
> 
> Harlan Haskins, Jaden Geller, and I have been working on a proposal to clean 
> up the semantics of ordering relations in the standard library.  We have a 
> draft that you can get as a gist.  Any feedback you might have about this 
> proposal helps - though please keeps your comments on Swift-Evolution and not 
> on the gist.

Bravo! It would be great to have Comparable defined in terms of a full 
comparison. I'd specifically call out String as a concrete example in the 
Motivation section, as this proposal is likely to give a performance boost on 
sorting String arrays, which is a pretty common thing to do.



I think the Detailed design section should explicitly show as source code:

1. What is the updated Equatable protocol?

2. What are all the updated operators? (I.e. show the new default 
implementations of `==` and `!=` too.)

3. In code comments, what are the updated rules or laws that should hold for 
Equatable and Comparable (and FloatingPoint, if any)?

4. What are the new "by: (Self, Self) -> Ordering" functions that the proposal 
is about to introduce to the stdlib?



On the topic of partial orderings (e.g. floating-point types), starting with 
the more important questions first:

5. Will it be considered "ok" to define a type for which `T.areSame(a, b) == 
true` but `a != b`? An obvious example would be Double.nan, so I assume the 
answer is a resounding yes.

6. Similarly, will it be "ok" to define a type for which `T.areSame(a, b) == 
false` but `a == b`? One possible example could be the comparison of `-0.0 <=> 
+0.0`. Should those be `.same` or not?

7. What, in fact, is the proposed total order for the stdlib's floating-point 
types?

(For an example, here is one possible way of defining `<=>` for Double, using 
`Double.bitPattern`. It distinguishes between +0.0 and -0.0, and even the 
various patterns of NaN! But do we want this for our `<=>` or something else?

func <=> (lhs: Double, rhs: Double) -> Ordering {
  func f(_ x: UInt64) -> UInt64 {
return x < 0x8000_ ? x + 0x8000_ : ~x
  }
  return f(lhs.bitPattern) <=> f(rhs.bitPattern)
}
print(-0.0 <=> 0.0) // ascending
print( 1.0 <=> 0.0) // descending
print( Double.infinity <=> Double.nan)  // ascending
print(-Double.infinity <=> -Double.nan) // descending
print(  Double.nan <=> Double.nan)  // same

See http://swiftlang.ng.bluemix.net/#/repl/5791db33719d5d045b4d430c for a 
running example.)



A general idea:

8. I wouldn't mind if the proposal also covered including generated definitions 
for `tuple1 <=> tuple2` of tuples from zero arity through to 6 or whatever the 
gyb's upper limit may be.

That would simplify the example implementation of Date down to:

func <=> (lhs: Date, rhs: Date) -> Ordering {
  return (lhs.year, lhs.month, lhs.day)
 <=> (rhs.year, rhs.month, rhs.day)
}

9. Some of us were not satisfied with the name of `.areSame(_:_:)`. Let me just 
point out that it would be nice if the name aligned with whatever 
`Ordering.same` will be called.

-- Pyry

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


Re: [swift-evolution] [Proposal][Discussion] Qualified Imports

2016-07-21 Thread Pyry Jahkola via swift-evolution
I think we're getting somewhere.

> On 21 Jul 2016, at 12:01, Robert Widmann  wrote:
> 
>>> (An excerpt about the hiding directive 
>>> )
>> 
>> 4. Hmm, the above design detail is easily missed when reading the proposal. 
>> So what you're proposing is that the hiding of Date essentially turns Date 
>> into a type that the code will know almost nothing about, except it's 
>> something we can pass to other types' methods that expect a Date, am I right?
>> 
>> What's the benefit in that? Do you anticipate it will make importing lighter 
>> somehow, possibly improving compilation or library loading speed? You 
>> mentioned something along those lines in the Motivation, but I'm not sure if 
>> I got it right here.
> 
> It is so that use of an API in a framework like Foundation does not 
> necessitate polluting your Swift files with a million using imports - thus 
> defeating the purpose of this proposal.

You explained further below what else `hiding` imports can be used for. But my 
comment was motivated by your example of `import Foundation hiding (Date)`. 

I fail to see how the lack of `hiding` imports would imply Swift files with a 
lot using imports. In my counting, they amount to at most one extra using 
import. (And I propose ~10 lines below what would get that to zero.)

The simple reason I could see someone write `import Foundation hiding (Date)` 
is because another imported module "Julian" she uses happens to export another 
Date type which she wants to use instead. And if we could just as well solve 
that use case by making it so that

import Foundation
import Julian, Julian using (Date)
assert(Date.self == Julian.Date.self)

brings in both modules but makes Julian.Date the one that Date is shorthand of.

Besides, Joe and friends offered the use of `*` to mean "and everything else", 
which is problematic because `*` also happens to be an operator function name. 
But we could make it so that the underscore imports everything else (without 
explicit qualification), making the above example exactly equivalent to:

import Foundation using (_)   // same as `import Foundation`
import Julian using (_, Date) // bring in Date explicitly and all else 
implicitly
assert(Date.self == Julian.Date.self)


> DateFormatter alone needs to know about Date, String, TimeInterval, Calendar, 
> Locale, and TimeZone.  Each of those needs to know about additional 
> components.  To require an import decl to use these types explicitly would be 
> madness.  You'd just wind up importing Foundation anyway.

"You'd just wind up importing Foundation anyway" is an argument that doesn't 
seem imply from the given Motivation section AFAICT.

I can see three kinds of problems here (objective or subjective), caused by 
importing the whole Foundation:
Identifier name conflicts, which we could solve with just the `import Module 
using (name, Name, _)` syntax, essentially indicating which Module should be 
preferred.

Identifier names shadowing module names, where e.g. a `private enum Foundation 
{}` disables the fully qualified access to the Foundation module's API). This 
remains an unsolved problem, but the introduction of qualified module imports 
`import Foundation as Foundation` or `import Foundation as F` (or, heh, `import 
Foundation as is`) would be one way of going about it.

Auto-completer "hygiene", or being explicit which part of a large imported API 
is not considered appropriate to use by the author.
Point 3 is the only problem that `hiding` imports could be uniquely used for, 
especially if they can be narrowed down to members of imported types and 
extensions (e.g. Swift.String.UTF8View, as given in the proposal). But is that 
worth having?


>> 5. These chaining rules do fit on the back of a napkin, but I'm not sure if 
>> we need them at all. I'm not convinced we need `hiding` imports, and without 
>> hiding imports, we need no rules for the order of imports.
> 
> How else are we to allow you to import a using type but not any of its member 
> types?

I don't know. I'm asking "why?" not "how?"


> How could we support removing APIs related to NSCell in AppKit apps? How 
> about NSStream everywhere else? How else can we allow, in the future, the 
> ability to import NSObject but none of its KVO-related members?

I'm saying you should explain this in the Motivation. Or consider moving the 
`hiding` import syntax into a further proposal.


> A hiding import is an invariant: It says a particular API should never be 
> considered for use in this file.  The very act of 'using' an identifier means 
> you are hiding all others.  The very act of 'hiding' an identifier means you 
> are using all others.

That is very logical. But it would be better if there was a real-world example 
use case given where the use of `hiding` was a clear win over 

Re: [swift-evolution] [Proposal][Discussion] Qualified Imports

2016-07-21 Thread Pyry Jahkola via swift-evolution
Back to the pre-proposal itself,

I support taking it forward and it being accepted in some form. However, I 
remain unconvinced that we'd ever want `hiding` imports in Swift.

Here are a few specific comments on the text (8 in total):
> Motivation
> 
> The existing syntax for qualified imports from modules is needlessly 
> explicit, does not compose, and has a default semantics that dilutes the 
> intended meaning of the very operation itself. Today, a qualified import 
> looks something like this
> 
> import class Foundation.Date
> This means that clients of Foundation that wish to see only Date must know 
> the exact kind of declaration that identifier is.
> 
> 

1. Given this motivation, isn't it sufficient being able to import without 
knowing the exact kind of declaration? In other words, I agree we want `using` 
imports, but what motivates `hiding` imports really?

As it was pointed out by Félix, the use of `hiding` imports moves away the 
focus of what is imported into what is not imported, and while name conflict 
problems usually arise when importing another module on top of already working 
code, I think it's better to fix them at the import statement which brings in 
the winning name declaration, i.e. the `using` import.


>  
> Proposed
>  solution
> 
> The grammar and semantics of qualified imports will change completely with 
> the addition of import qualifiers and import directives. We also introduce 
> two new contextual keywords: using and hiding, to facilitate fine-grained 
> usage of module contents.
> 
> 

2. Is there a typo above? The proposal does not mention import qualifiers 
anywhere else. I guess those are part of what got postponed into later 
proposals.


> Detailed design
> 
> 1) using: The using directive is followed by a list of identifiers for 
> non-member nominal declarations within the imported module that should be 
> exposed to this file. 
> 
> // The only visible parts of Foundation in this file are 
> // Foundation.Date, Foundation.DateFormatter, and Foundation.DateComponents
> //
> // Previously, this was
> // import class Foundation.Date
> // import class Foundation.DateFormatter
> // import class Foundation.DateComponents
> import Foundation using (Date, DateFormatter, DateComponents)
> 
3. I support the idea of `using` imports. That's something we do need, and its 
introduction is sufficient to cover the existing use cases of the old selective 
import syntax about to be deprecated here.



> 2) hiding: The hiding directive is followed by a list of identifiers for 
> non-member nominal declarations within the imported module that should be 
> hidden from this file.
> 
> // Imports all of Foundation except `Date`
> import Foundation hiding (Date)
> As today, all hidden identifiers do not hide the type, they merely hide that 
> type’s members and its declaration. For example, this means values of hidden 
> types are still allowed. Unlike the existing implementation, using their 
> members is forbidden.
> 
> 
4. Hmm, the above design detail is easily missed when reading the proposal. So 
what you're proposing is that the hiding of Date essentially turns Date into a 
type that the code will know almost nothing about, except it's something we can 
pass to other types' methods that expect a Date, am I right?

What's the benefit in that? Do you anticipate it will make importing lighter 
somehow, possibly improving compilation or library loading speed? You mentioned 
something along those lines in the Motivation, but I'm not sure if I got it 
right here.



> Import directives chain to one another and can be used to create a 
> fine-grained module import:
> 
> // This imports Swift.Int, Swift.Double, and Swift.String but hides 
> Swift.String.UTF8View
> import Swift using (String, Int, Double) 
>  hiding (String.UTF8View)
> Directive chaining occurs left-to-right:
> 
> // This says to 1) Use Int 2) Hide String 3) rename Double to Triple.  It is 
> invalid
> // because 1) Int is available 2) String is not, error.
> import Swift using (Int) hiding (String)
> // Valid.  This will be merged as `using (Int)`
> import Swift using () using (Int)
> // Valid.  This will be merged as `hiding (String, Double)`
> import Swift hiding (String) hiding (Double) hiding ()
> // Valid (if redundant). This will be merged as `using ()`
> import Swift using (String) hiding (String)
> 
5. These chaining rules do fit on the back of a napkin, but I'm not sure if we 
need them at all. I'm not convinced we need `hiding` imports, and without 
hiding imports, we need no rules for the order of imports.



> Because import directives are file-local, they will never be exported along 
> with the module that declares them.
> 
> 
6. +1 on imports being file-local, that's essentially what we have today.

What I will keep suggesting is that `using` imports actually take up the name 
in the file-local scope such 

Re: [swift-evolution] [Proposal][Discussion] Qualified Imports

2016-07-21 Thread Pyry Jahkola via swift-evolution

> On 21 Jul 2016, at 10:29, Robert Widmann  wrote:
> 
> This proposal is specifically source breaking because we're only trying to 
> deprecate and remove
> 
> import {class|func|struct|...} Module.Entity
> 
> -style imports (which not too many people seem to know actually exist).

That's a worthy goal. But do we need to offer and implement the alternative? 
Could we not live without that syntax while we nail down the better import 
syntax?

I've used the explicit import syntax a few times to make it clear what I'm 
importing, but I wouldn't really miss it if it got removed in Swift 3, and an 
alternative was added back in Swift 3.1.

— Pyry

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


Re: [swift-evolution] [Proposal][Discussion] Qualified Imports

2016-07-21 Thread Pyry Jahkola via swift-evolution

> On 21 Jul 2016, at 10:20, Robert Widmann  wrote:
> 
>> Simple! You don't need to hide the others if we enforce a rule that 
>> explicitly mentioning one in the current file imports that name as a 
>> fileprivate identifier which shadows the ones not explicitly mentioned:
> 
> What you're describing is making a distinction between an open module and an 
> imported module and is both additive and out of scope for this particular 
> proposal.  We didn't want to touch module re-exports until that proposal came 
> up later.  This is a fantastic idea that we have plans to incorporate in 
> there nonetheless.  This distinction is far more powerful than our current 
> approach of just opening every module that gets imported into the top level 
> namespace.

Cool, thanks for the feedback. Now, is there a reason to consider any of this 
before Swift 3's timeframe? Isn't this all additive?

In any case then, I'll hold that proposal back until Swift 3's scope has been 
fixed.

— Pyry

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


Re: [swift-evolution] [Proposal][Discussion] Qualified Imports

2016-07-21 Thread Pyry Jahkola via swift-evolution
Oops, hit Send too soon…

> Pyry Jahkola wrote:
> 
> import A  // ok, unqualified import keeps A as a second-class 
> identifier
> import B as B // ok, qualified import makes B a first-class identifier in 
> file scope
> 
> typealias A = Int // ok, shadows the module name A
> 
> typealias B = Int
> // error: invalid redeclaration of 'Bar'
> // note: previously declared here: 'import Bar as Bar'

Of course that last error message was meant to read:

// error: invalid redeclaration of 'B'
// note: previously declared here: 'import B as B'

— Pyry

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


Re: [swift-evolution] [Proposal] Qualified Imports and Modules

2016-07-20 Thread Pyry Jahkola via swift-evolution
> On 19 Jul 2016, at 00:09, Robert Widmann via swift-evolution 
>  wrote:
> 
> TJ Usiyan, Harlan Haskins, and I have been working on a proposal to rework 
> qualified imports and introduce an explicit module system to Swift that we’d 
> like to publish for your viewing pleasure.
> 
> The initial impetus was set out in a radar (rdar://17630570 
> ) I sent fairly early on that didn’t receive a response, so 
> I started a swift-evolution 
>  thread 
> discussing the basics of this proposal.  It has been refined and expanded a 
> bit to include an effort to make Swift modules explicit and updated with the 
> feedback of that first thread.  Contents of the proposal are inline and can 
> also be had as a gist 
>  or on 
> Github. 

Firstly, thank you Robert, TJ, and Harlan for the proposal and especially for 
considering the introduction of submodules too! Those would be very useful when 
Swift libraries start growing. But maybe we can delay that discussion past 
Swift 3.

* * *

Secondly, I used to be in the selective import camp before, but I think it's 
somewhat counter to Swift's feel and direction where most of the API is wrapped 
inside types, and function names consist of not just the base name but argument 
labels too (even if we now have the "Gregorian" naming SE-0021 available). So 
while I don't see a big problem introducing something like

import Foo.(fooConstant, bar(a:b) as bar1(a:b:), IrrelevantType as _)

to pick identifiers à la carte, I don't think it would be useful very often. 
And the alternative of accessing `bar` through the module name as `Foo.bar` 
does work just as well already.

…Well, that is except for the problem when the module name `Foo` happens to be 
shadowed by a non-module name `Foo`. I'd rather tackle that problem, and I do 
so as follows:

* * *

My usual pain points with imported (micro-)frameworks have been:

A) …when two modules (e.g. `Foo` and `Bar`) export the same identifier (`baz`) 
for different meanings.
B) …when a local or imported identifier (e.g. `class Tree`) has the same name 
as a module `Tree`.

In case A, I can just disambiguate by prefixing with the module name: `Foo.baz` 
vs. `Bar.baz`.

In case B, there is really no way around that I'm aware of. Anyway you write 
`Tree.foo` Swift will try to look up under the type `Tree` and never the module 
`Tree`.

Those two issues could be addressed by simply introducing qualified imports as 
follows:

import Darwin as Darwin // qualified import (there could be a shorthand but 
what?)
import UIKit as UI  // qualified import with renaming
import Tree // unqualified import brings in struct Tree.Tree, 
among others.
import Tree as T// qualified import

let out = Darwin.stdout  // ok
var vc: UI.UIViewController? // ok
let tree: Tree = T.emptyTree // ok; `struct Tree.Tree` was imported 
unqualified

let err = stderr
// error: Use of unresolved identifier 'stderr'
// note: did you mean 'Darwin.stderr'?

var view: UIView?
// error: Use of unresolved type 'UIView'
// note: did you mean 'UI.UIView'?

enum UI {}
// error: invalid redeclaration of 'UI'
// note: 'UI' previously declared (line 2)

The qualified import syntax, `import MODULE as NAME`, imports the module MODULE 
such that its contents can be accessed through the prefix of `NAME.` – but not 
without it, unless also imported without qualification.

The given NAME uses up that identifier in the current scope (as if it was a 
private type) such that there can be no locally visible type or value with the 
same name in that scope. For example, if the current module defined NAME 
publicly or internally in another file, then that identifier would be shadowed 
in this file by the qualified module name NAME.

Side note: It is still possible to chain multiple module imports, qualified or 
not, on the same line (albeit not a particularly good coding style if they're 
unrelated). The order of imports does not matter. So the above example could've 
been written as:

import Darwin as Darwin, UIKit as UI, Tree as T, Tree

* * *

I think that's the small change we need most urgently. The rest can wait.

— Pyry

PS: Another thing I'd see useful, especially when migrating code from the 
`MyPlayground_Sources` module to a real project would be a syntax something 
like `_.foo` to access the `foo` that is visible in the current file top-level, 
so to escape any local shadowing.

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


Re: [swift-evolution] [Review] SE-0122: Use colons for subscript declarations

2016-07-20 Thread Pyry Jahkola via swift-evolution

> On 20 Jul 2016, Chris Lattner wrote:
> 
> The review of "SE-0122: Use colons for subscript declarations " begins now 
> and runs through July 24. The proposal is available here:
> 
>   
> https://github.com/apple/swift-evolution/blob/master/proposals/0122-use-colons-for-subscript-type-declarations.md
> 
>   * What is your evaluation of the proposal?

I'm mildly in favour because I think (settable) subscripts are more similar to 
properties than functions. But is this change worth having in Swift 3? I'm a 
bit surprised it's discussed this late in the cycle.

Here are some considerations on the topic:

1. If we bring colons in, why not change the parentheses into brackets too? 
Like so:

public subscript[index: Int]: Element

2. If we change the arrows into colons but then later choose to make throwing 
subscripts possible, how could that be still done? Probable answer: by adding 
the `throws` specifier to the getter or setter as needed.

3. Do we want to address the fact that – unlike functions – subscript arguments 
currently have implicitly blank external names, i.e. that `subscript(at: Int)` 
and `subscript(_ at: Int)` are equivalent? I don't think we do; but if that's 
the case then it's probably a good idea to also make the declaration syntax 
less alike with functions. So that would be a small argument in favour of 
SE-0122.

>   * Is the problem being addressed significant enough to warrant a change 
> to Swift?

Probably not at this stage. I think this change could be introduced even 
post-Swift 3, although that would then require maintaining both syntaxes for an 
extended period of time.

>   * Does this proposal fit well with the feel and direction of Swift?

I think so.

>   * If you have used other languages or libraries with a similar feature, 
> how do you feel that this proposal compares to those?

N/A

>   * How much effort did you put into your review? A glance, a quick 
> reading, or an in-depth study?

A quick reading.

— Pyry

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


Re: [swift-evolution] [Review] SE-0117: Default classes to be non-subclassable publicly

2016-07-08 Thread Pyry Jahkola via swift-evolution

> Chris Lattner wrote:
> 
> The review of "SE-0117: Default classes to be non-subclassable publicly" 
> begins now and runs through July 11. The proposal is available here:
> 
>
> https://github.com/apple/swift-evolution/blob/master/proposals/0117-non-public-subclassable-by-default.md
> 
>* What is your evaluation of the proposal?

+0.9. I'm positive with making the subclassability of exported classes 
explicit, but I'd reconsider the keywords proposed.

Given how the ecosystem has shaped up so far, there are very few cases where 
Swift classes could be realistically patched by subclassing and overriding. 
Instead, forking and recontributing open-source code is the better way to go. 
From my OOP in any programming languages, almost all unplanned (by library 
author) uses of subclassing have become terrible hacks that were hard to 
maintain in application code. And I don't want to imagine having to maintain a 
library that multiple users have patched by subclassing without a documentation 
of the contract between the superclass and its subclasses.

In Swift, classes seem to be most essentially about reference semantics and not 
so much about inheritance. With that, I think it's better that unlimited 
subclassing becomes a conscious choice by the library author, so that we also 
increase the probability of remembering to document what can be overridden and 
how. Originally, I would've even supported making `final` the default, but 
adding the new "sealed" inheritance mode is a very good compromise that makes 
life easier when writing application code.

Sealed classes also open a new language design opportunity where `switch` cases 
can be proven total given a sealed class type as argument.

However, I also think we shouldn't merge the the `public` modifier with the 
newly proposed keywords. From the alternatives mentioned so far, I'd give my +1 
to `public open class/func` or the spelling `public(open) class`. In this 
position, I think it'll be unambiguous given context whether `open` acts as a 
keyword or not.

Alternatively, we could reuse the `super` keyword in this context; the only 
minor issue I can see in `public super class` (besides that "superclass" should 
be written without a space) is that public unsealed classes aren't the only 
publicly visible superclasses (sealed classes are also publicly superclasses of 
their public subclasses). Well, and that the "superfunc" in `public super func` 
would be an unfamiliar term, even if it's easily taught as the kind of function 
which you should consider calling as `super.foo(...)` somewhere in an override.

The proposal also left open whether the subclassability is inherited in 
subclasses. I think it's clear that the answer is "no", and thus every subclass 
of a publicly subclassable superclass is only publicly subclassable if 
explicitly marked so.

>* Is the problem being addressed significant enough to warrant a change to 
> Swift?

Yes, Swift should use language design opportunities like this to statically 
encourage thoughtful library design.

>* Does this proposal fit well with the feel and direction of Swift?

Yes. It also doesn't take away the option yo make well-thought use of OOP 
better in the future, such as abstract classes.

>* If you have used other languages or libraries with a similar feature, 
> how do you feel that this proposal compares to those?

N/A.

>* How much effort did you put into your review? A glance, a quick reading, 
> or an in-depth study?

Quick reading or a bit more.

— Pyry

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


Re: [swift-evolution] [Proposal] Variadics as Attribute

2016-07-08 Thread Pyry Jahkola via swift-evolution
I agree that we should have a way to call a variadic function with an Array at 
hand, without needing to take its elements apart (`foo(x[0], x[1], x[2])`) — 
which indeed is only practical when we statically know its length.

But I fear there's a shortcoming in this proposal that hasn't been addressed: 
How would the compiler clear the ambiguity in single-argument calls between 
existentials such as `Any` or `CustomStringConvertible` and sequences thereof 
(e.g. `[Any]` or `[CustomStringConvertible]`, which both can be treated as 
`Any` and `CustomStringConvertible` as well?

If you take this function for example,

func printThem(@variadic _ values: [Any])

then what would `values` be in the following calls, and why?

printThem() // clearly []
printThem(1) // clearly [1]
printThem(1, 2) // clearly [1, 2]
printThem([1], [2]) // clearly [[1], [2]]
printThem([]) // [] or [[]], which one?
printThem([1]) // [1] or [[1]]?
printThem([1, 2]) // [1, 2] or [[1, 2]]?

I think it would be less painful a change (i.e. can be delayed past Swift 3) if 
we just augment what we have (the `...` argument declaration syntax) with a way 
to expand an Array in place of a variadic argument:

func printThem(_ values: Any...)

printThem(1) // values == [1]
printThem([1]) // values == [[1]]
// Possible expansion postfix syntax:
printThem([1]...) // values == [1]
// Expanding a non-array sequence:
let things: Set = [1, 2, 3]
printThem(Array(things)...)

I think variadic functions are intended for human convenience and rarely used 
in performance-critical code, and it's probably more convenient that they're 
always passed as an Array, and not as a generic sequence.

— Pyry

Haravikk wrote:

> For example, consider the following variadic function:
> 
> func someMethod(_ values:Int...) { … }
> Under this proposal the above can be rewritten as one of the following:
> 
> func someMethod(@variadic _ values:[Int]) { … } // Basic Array solution
> func someMethod(@variadic _ values:Foo) { … }   // Foo is a custom 
> ArrayLiteralConvertible type
> func someMethod(@variadic _ 
> values:I) { … } // Flexible, single-pass, generic solution
> func someMethod(@variadic _ 
> values:S) { … } // Flexible, (probably) multi-pass, generic solution
> func someMethod(@variadic _ 
> values:C) { … } // Flexible, definitely multi-pass, indexed, generic solution
> In this case the Iterator variation is preferred for greatest flexibility, 
> but it will depend upon the actual requirements of the method. Any of these 
> can be called as follows:
> 
> someMethod([1, 2, 3, 4, 5, 6])  // normal array-literal call for any of the 
> above
> someMethod(1, 2, 3, 4, 5, 6)// variadic call, synonymous with 
> array-literal call
> someMethod(foo) // foo is an existing Array, Foo, Iterator, 
> Sequence or Collection variable as appropriate
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Accepted] SE-0111: Remove type system significance of function argument labels

2016-07-08 Thread Pyry Jahkola via swift-evolution

> Charlie Monroe wrote:
> 
> This hasn't occurred to me until now, but this will also elminate the 
> following (right?):
> 
> public typealias XUURLRequestModifier = (request: NSMutableURLRequest) -> Void
> 
> Which is really nice since when expanded by Xcode, this automatically offers 
> you the "request" label for the variable so you don't have to name it.

As far as I understood, no it won't eliminate that use case, and quite the 
contrary this is exactly the cosmetic change to the original proposal that the 
core team wanted to add. So your code above will work, but with the change that 
a closure `modifier` of type `XUURLRequestModifier` is called like 
`modifier(req)` from now on and not `modifier(request: req)`.

I think it's often missed in this discussion that there are not one but *two* 
cases where argument labels (or the lack of them) matter in Swift, and both of 
cases also affect auto-completion:

1) The first case is when calling a closure (which most often was passed to the 
current function as an argument). What the accepted proposal SE-0111 did was 
remove argument labels from those calls in all circumstances:

func modifyRequest(modifier: XUURLRequestModifier) {
  // This autocompletes without labels as something like:
  modifier(<#request#>)
  // I.e. the cosmetic labels still appear as placeholders, AFAICT.
}

Most of the time, the code that calls a closure is written once and run 
multiple times with various blocks, so simple mistakes that argument types 
won't catch get easily catched in unit tests or when testing the application.

2) The second, and much more common case in application-level code IMO is when 
passing a closure argument to a library function:

// This, I think, would autocomplete as:
frob.modifyRequest { (request: NSMutableURLRequest) -> Void in
  // I.e. now the cosmetic label becomes the default argument name.
}

So this is where cosmetic labels matter most and nothing changed in this regard 
in the outcome of SE-0111.

* * *

For people longing to pass labels when *calling* closures, I think you should 
consider proposing the extended naming syntax idea (or some variant) where an 
N-argument closure can alternatively be bound to a name with N labels (see 
https://github.com/apple/swift-evolution/blob/master/proposals/0021-generalized-naming.md):

// This closure is named `modify(request:)`
let modify(request:): XUURLModifierRequest = { request in
  ...
}
modify(request: req)

// The argument with label `modifier` is *locally* named `mod(req:)`.
func example(modifier mod(req:): XUURLModifierRequest) {
  mod(req: someRequest)
}

example { request in ... }
example(modifier: modify(request:))

Note that the local name `req(mod:)` wouldn't need to match the call site 
(except in type), and they really shouldn't either.

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


Re: [swift-evolution] [Accepted] SE-0113: Add integral rounding functions to FloatingPoint

2016-07-06 Thread Pyry Jahkola via swift-evolution
I think one more thing needs clarification. Shouldn't the "defaulted" 
`rounded()` and `round()` be defined as protocol extension methods *without* 
the possibility to override the default rounding mode in a conforming type? 
Like so:

public protocol FloatingPoint {
  ...
  func rounded(_ rule: RoundingRule) -> Self
  mutating func round(_ rule: RoundingRule)
}

public extension FloatingPoint {
  public func rounded() -> Self {
return rounded(.toNearestOrAwayFromZero)
  }
  public mutating func round() {
round(.toNearestOrAwayFromZero)
  }
}

I would find it quite surprising if some type conforming to FloatingPoint 
rounded differently by default than the others.

— Pyry

> Chris Lattner wrote:
> 
> Since protocol requirements cannot currently have default arguments, the 
> desired behavior should be achieved with two overloads of each operation:
> 
> protocol FloatingPoint {
>  ...
>  /// Returns a rounded representation of `self`, according to the specified 
> rounding rule.
>  func rounded() -> Self
>  func rounded(_ rule: RoundingRule) -> Self
> 
>  /// Mutating form of `rounded`.
>  mutating func round()
>  mutating func round(_ rule: RoundingRule)
> }
> 
> Where the no argument cases can be implemented with a protocol extension that 
> forwards to the single-argument versions.
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Fix or remove Swift.min and Swift.max?

2016-07-03 Thread Pyry Jahkola via swift-evolution
+1, and bumping this topic.

The background — which I'm sure Jens is aware of — is that IEEE-754 floating 
point numbers can't truly conform to Comparable. (The problematic case being 
that neither of `x < .nan`, `x == .nan`, or `x > .nan` can be `true`.)

But given that the NaN-abolishing semantics of `fmin` is quite useful, and 
since we also want that Double and Float remain conforming to Comparable 
(albeit brokenly), could we consider fixing this issue by moving `min(_:_:)` 
and `max(_:_:)` into Comparable?

The Comparable protocol would become:

public protocol Comparable : Equatable {
  func < (lhs: Self, rhs: Self) -> Bool
  func <= (lhs: Self, rhs: Self) -> Bool
  func >= (lhs: Self, rhs: Self) -> Bool
  func > (lhs: Self, rhs: Self) -> Bool
  static func minimum(lhs: Self, rhs: Self) -> Self
  static func maximum(lhs: Self, rhs: Self) -> Self
}

with default implementations added for the new static functions, and custom 
implementations for FloatingPoint types. The `Swift.min` and `Swift.max` 
functions would then forward their logic to `Comparable.minimum` and 
`Comparable.maximum`.

— Pyry

> On 29 Jun 2016, Jens Persson wrote:
> 
> Hi all!
> 
> Swift.min (and Swift.max) propagates nan or not depending on the order of its 
> args:
> 
> Swift.min(1.0, .nan) // 1.0
> Swift.min(.nan, 1.0) // nan (!)
> 
> Double.minimum(1.0, .nan) // 1.0
> Double.minimum(.nan, 1.0) // 1.0
> 
> fmin(1.0, .nan) // 1.0
> fmin(.nan, 1.0) // 1.0
> 
> The new static minimum and maximum funcs on FloatingPoint in Swift 3 shows 
> the expected behaviour (ie the same as fmin, fmax and IEEE-754), so what 
> should happen with Swift.min and Swift.max?
> 
> Fix, remove or perhaps something else?
> 
> https://bugs.swift.org/browse/SR-1011 

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


Re: [swift-evolution] [Review] SE-0111: Remove type system significance of function argument labels

2016-07-03 Thread Pyry Jahkola via swift-evolution
> On 30 Jun 2016, Chris Lattner wrote:
> 
> The review of "SE-0111: Remove type system significance of function argument 
> labels" begins now and runs through July 4. The proposal is available here:
> 
>   
> https://github.com/apple/swift-evolution/blob/master/proposals/0111-remove-arg-label-type-significance.md
>  
> 
> What is your evaluation of the proposal?

+1. With the way the community has settled using argument labels, it seems 
clear to me that argument labels are part of a function's name and should not 
affect its type.

What we currently have technically works because the compiler is quite lenient 
in type conversions between different argument labels. But since there are 
corner cases lurking where labels in the function type matter (as demonstrated 
in the proposal), it's best we get rid of them entirely for clarity. As it has 
been pointed out, the status quo also complicates the overload resolution 
process and causes confusing error messages when the compiler can't tell if 
your argument labels are wrong or argument types. We're better without that 
complexity.

Further, I think removing this oddity could make function application with 
tuples feasible again (a.k.a the simple form of "tuple splatting" with all 
arguments in the tuple) by requiring to fully name the function before passing 
the arguments tuple:

func doSomething(x: Int, y: Int) -> Bool { return true }
func doSomething(any: Any) -> Bool { return false } // This can't possibly 
be considered below.

let args = (1, 2)
let named = (x: 1, y: 2)
let f = doSomething(x:y:)
f(args) // Unambiguous call, if the syntax is made legal 
(again).
doSomething(x:y:)(args) // So is this.
doSomething(args)   // This would still be an error as per SE-0029 
.
let tuples = [(1, 2), (3, 4), (5, 6)]
print(tuples.map(f)) // This would be allowed. (Confusingly it already 
works despite SE-0029!)

In particular, you couldn't apply a `func` function with a tuple (which was 
what SE-0029 removed) but you could apply a qualified function reference 
(SE-0021 
)
 as well as a function value (i.e. a named closure) with a tuple, because both 
of them have set in stone their argument list length before the tuple 
application and thus suffer from none of the disadvantages listed in the 
motivation for SE-0029 
.
 That would of course need a separate proposal and can be delayed until Swift 3 
has been released.

> Is the problem being addressed significant enough to warrant a change to 
> Swift?

Yes.

> Does this proposal fit well with the feel and direction of Swift?

I think so.

> If you have used other languages or libraries with a similar feature, how do 
> you feel that this proposal compares to those?

Well, we've had argument labels in Objective-C but since it's not a strongly 
typed language I don't think it applies for comparison. However, I naturally 
feel argument labels in Objective-C as well are part of the function's name 
rather than its type.

> How much effort did you put into your review? A glance, a quick reading, or 
> an in-depth study?

More than a quick reading. I've suggested a similar idea before but didn't 
motivate it well enough to gain interest back then. Big thanks to Austin for 
driving it forward this time!

— Pyry

PS. Can anybody explain why the last example in my code above turned out to be 
allowed even though SE-0029 seems to prohibit it? Here's a more comprehensive 
test which made me positively surprised that it still worked after SE-0029:

let f: (Int, Int) -> Int = (+)
let x = (1, 2)
let x, y = (3, 4)
f(1, 2) //=> 3
// f((1, 2))  // Does not compile, as expected 
(SE-0029).
// f(x)   // Does not compile, as expected.
[x, y].map(f) //=> [3, 7] // Surprisingly compiles, but why?
let g: ((Int, Int)) -> Int = f// Huh? So `f` can coerce to a 
`(tuple) -> Int`?
g(x) //=> 3   // So this is what made `map` work 
above.
(f as ((Int, Int)) -> Int)(x) //=> 3  // This works too, didn't expect it 
to.
[x, y].map(+)  //=> [3, 7]// Finally, why is this allowed 
despite SE-0029?

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


Re: [swift-evolution] [Proposal] Add floor() and ceiling() functions to FloatingPoint

2016-06-27 Thread Pyry Jahkola via swift-evolution

> David Sweeris wrote:
> 
> I'm starting to come down from me earlier +1... Floor and ceiling are more 
> functions than properties of a number, aren't they?

I agree with that. Having used various math libraries for decades now, I'd find 
it odd to find these as members of a floating-point type, especially so for the 
suggested in-place mutating variants. These tend to be function-like constructs 
(or various kinds of brackets) in mathematics too, just like trigonometric 
functions.

But since do we need these in the FloatingPoint protocol for generic 
algorithms, I'd suggest defining them as static members, and keeping 
state-of-art names (or close) where possible:

protocol FloatingPoint {
  static func floor(_ value: Self) -> Self
  static func ceiling(_ value: Self) -> Self
  static func truncate(_ value: Self) -> Self
  static func round(_ value: Self) -> Self
}

The top-level functions can them simply delegate to these counterparts:

func floor(_ value: T) -> T {
  return .floor(value)
}

— Pyry

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


Re: [swift-evolution] [Pitch] Remove type inference for associated types

2016-06-25 Thread Pyry Jahkola via swift-evolution
Hi Austin,

I also think it's better to make associated types explicit in protocol 
conformance. But I'm not sure the requirement to use the `associatedtype` 
keyword on the conformance site is the right way to do so, especially since you 
haven't addressed how nested types could fulfill associated type requirements 
in the new design:

extension Foo : P {
struct A { ... }
}

— Pyry

> Austin Zheng wrote:
> 
> Hello all,
> 
> Per Chris Lattner's list of open Swift 3 design topics 
> (http://article.gmane.org/gmane.comp.lang.swift.evolution/21369), I've put 
> together a proposal for removing type inference for associated types.
> 
> It can be found here: 
> https://github.com/austinzheng/swift-evolution/blob/az-assoctypeinf/proposals/-remove-assoctype-inference.md
> 
> Thoughts, criticism, and feedback welcome. There are at least two slightly 
> different designs in the proposal, and I'm sure people will have ideas for 
> even more.
> 
> Best,
> Austin
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Review] SE-0102: Remove @noreturn attribute and introduce an empty NoReturn type

2016-06-22 Thread Pyry Jahkola via swift-evolution

> On 22 Jun 2016, at 14:47, Charlie Monroe via swift-evolution 
>  wrote:
> 
> I can live with Never. But the proposed NoReturn is a single-case solution 
> and would eventually require a code-breaking change anyway were the bottom 
> type implemented under a different name.

Excuse me, but it seems to me you might be missing one important point about 
the proposal: there's going to be no “the” bottom type — any enum with no cases 
would act as one if the proposal is accepted. The standard library would just 
happen name one to stand as the preferred default.

In other words (unless I'm mistaken), no compiler magic proposed about a 
specific (`NoReturn` or `Never`) empty enum. All the proposed “magic” would be 
about uninhabited types 

 (link to specific section in the proposal) as return types.

— Pyry

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


Re: [swift-evolution] [Draft] Tuple-Based Compound Optional Binding

2016-06-12 Thread Pyry Jahkola via swift-evolution

> On 12 Jun 2016, at 14:46, Brent Royal-Gordon via swift-evolution 
>  wrote:
> 
> guard let (a, b, c) = (opt1, opt2, opt3) else { ... }

You mention `guard case` in the motivation, but I think for the uninitiated 
reader it would be fair to point out that the following example already works 
equivalently, with only a few extra characters:

guard case let (a?, b?, c?) = (opt1, opt2, opt3) else { ... }

Aside of that, it's yet more magic to our `if let` syntax but I don't mind, it 
would be useful at times.

— Pyry

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


Re: [swift-evolution] Remove nil and NilLiteralConvertible

2016-06-08 Thread Pyry Jahkola via swift-evolution
I don't see a reason to rename or remove the `nil` literal.

But I can come up with a concrete reason to deprecate NilLiteralConvertible: 
The language has made Optional a very specific thing with `if let` syntax, 
implicit wrapping, and optional chaining to name a few. But the second most 
common way (I guess) to create an Optional—by using the `nil` literal—isn't 
actually guaranteed to create an Optional.

let condition: Bool
let x = condition ? 1 : nil
// error: result values in '? :' expression have mismatching types 'Int' 
and '_'

An expression like the above doesn't compile because the compiler can't tell 
what type `nil` should initialise. (Currently, at least Optional and 
ImplicitlyUnwrappedOptional seem possible, but with NilLiteralConvertible, 
something like a conforming MyJSON could be as well!) This, I think, can be 
confusing to new users. And life would be simpler if `nil` always stood for 
`Optional.none`, which would then infer the associated Wrapped type 
respectfully.

So no, I don't support this idea but I think we should sunset 
NilLiteralConvertible.

— Pyry

PS. Besides, the above statement will compile with any of the following edits:

let x = condition ? 1 : Optional.none
let x = condition ? 1 : nil as Optional
let x = condition ? 1 : Optional()
let x = condition ? 1 as Optional : nil
let x = condition ? 1 as Int? : nil
let x = condition ? Optional(1) : nil
let x: Int? = condition ? 1 : nil

> On 08 Jun 2016, at 23:41, Антон Жилин via swift-evolution 
>  wrote:
> 
> (No joking)
> Points:
> 
> 1. When nil was added to the language, we could not infer enumeration type:
> if x != Optional.none { ... }
> 
> Now it looks like this:
> if x != .none { ... }
> 
> If at this point we had a proposal to add nil as a replacement for .none, 
> would we accept it?
> 
> 2. nil is very generic, it only approximately allows to express the 
> intentions.
> In case of Optional, .none is clearer. In case of JSON processing, .null is 
> clearer. In case of a semantically nullable struct, NilLiteralConvertible 
> usually goes to default constructor.
> 
> 3. Too many "empty" things: .none, nil; NSNull, Void, NoReturn types.
> 
> 4. There should be a single consistent terminology: no value in Swift equals 
> none.
> 
> - Anton
> ___
> 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] [proposal] Allow function argument type to be omitted when passing a default value from which it can be inferred

2016-06-07 Thread Pyry Jahkola via swift-evolution

> On 07 Jun 2016, at 22:08, Sam Dods via swift-evolution 
>  wrote:
> 
> yes, exactly Doug... the properties at type level are part of the interface 
> and their types can be inferred, so i don't see the difference with function 
> argument types.
> 
> i just find it really bulky when writing something like this:
> 
> func doSomething(thing, withManager: SomethingManager = SomethingManager()) {
>   // prepare the thing
> }

You can get rid of the repetition here by using the implicit member expression 
syntax (i.e. dot-prefixing the initialiser):

func doSomething(thing, withManager: SomethingManager = .init()) { ... }

— Pyry

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


Re: [swift-evolution] [Draft] Change @noreturn to unconstructible return type

2016-06-06 Thread Pyry Jahkola via swift-evolution

> On 06 Jun 2016, at 22:40, Michael Peternell via swift-evolution 
>  wrote:
> 
> E.g. with the proposal, the following function:
> 
> @noreturn func error(msg: String = "") -> T {
>fatalError("bottom: \(msg)")
> }
> 
> has to be written as
> 
> func error(msg: String = "") -> T {
>fatalError("bottom: \(msg)")
> }
> 
> It still returns bottom, but there is no way to say so in the declaration. 
> The proposal just made the language less expressive!

This isn't my understanding of the idea. My understanding is that instead of a 
generic function, you'd write `error` as:

func error(_ msg: String = "") -> Never {
fatalError("bottom: \(msg)")
// or equivalently, since fatalError() also returns Never:
//return fatalError("bottom: \(msg)")
}

And because `Never` is a real bottom type (this is probably the extra compiler 
support needed that Chris Lattner referred to), you can use this function in 
any type context, meaning that it behaves as if it's of type `∀x. String → x`:

// Example 1:
func someImplementationDetail(input: Int) -> [String] {
// ...
return error("unimplemented for now")
}

// Example 2:
var ints: [Int] = []
ints.append(error("FIXME"))

// Example 3:
let e: Either = ...
let s: String = e.left ?? e.right ?? error("impossible")

I would even consider specifying that every empty enum type behaves like this, 
and that `Never` was just the default you should probably use, defined in the 
stdlib as:

/// The bottom type, or return type of functions that do not return.
/// This enum is intentionally empty.
enum Never {}

In other words in my imagination, there would be no magic in the type `Never` 
per se, but in the treatment of empty enums in general.

— Pyry

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


Re: [swift-evolution] [Draft] Change @noreturn to unconstructible return type

2016-06-05 Thread Pyry Jahkola via swift-evolution
>>> I would prefer the type to be simple, and be implemented as a case-less 
>>> enum (not a bottom value, as in Haskell).
>>> 
>>> None should be a usual enum, with no compiler magic except that functions 
>>> returning None are equivalent to current @noreturn.
>> 
>> I think it would be more useful if the compiler allowed `Never` in every 
>> type context (i.e. whatever type `T` was expected, an expression of type 
>> `Never` would be allowed), making expressions like the following compile:
>> 
>> let unwrapped: Int = optional ?? fatalError("explanation why this must 
>> not happen")
>> 
>> — Pyry
> 
> I dunno, I think @noreturn is clearer than any of these. It tells you that 
> the function… won’t return. None, Never, etc. could be mistaken as a synonym 
> for Void, whereas @noreturn is pretty hard to miss.

FWIW, in the rejection of SE-0097 
,
 this was what the core team had to say about it:

1) For noreturn, the core team prefers to explore a solution where a function 
can be declared as returning an non-constructable “bottom” type (e.g. an enum 
with zero cases).  This would lead to something like:

func abort() -> NoReturn { … }

This will require some new support in the compiler, but should flow better 
through the type system than @noreturn in function composition and other 
applications.  Joe Groff offered to write a proposal for this.

— Pyry

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


Re: [swift-evolution] [Draft] Change @noreturn to unconstructible return type

2016-06-05 Thread Pyry Jahkola via swift-evolution

> On 05 Jun 2016, at 21:26, Антон Жилин via swift-evolution 
>  wrote:
> 
> The following names were suggested: NoReturn, Bottom, None, Never.
> I would pick None, because it looks like opposite to Any and fits nicely in 
> generic types.

I would pick `Never` because `None` would overload the notion of a returnable 
nothingness with its antonym!

OTOH, "never" is quite unlikely to be a type name in user code, likely pretty 
googleable, and explains itself quite well in examples like `Result`.

> I would prefer the type to be simple, and be implemented as a case-less enum 
> (not a bottom value, as in Haskell).
> 
> None should be a usual enum, with no compiler magic except that functions 
> returning None are equivalent to current @noreturn.

I think it would be more useful if the compiler allowed `Never` in every type 
context (i.e. whatever type `T` was expected, an expression of type `Never` 
would be allowed), making expressions like the following compile:

let unwrapped: Int = optional ?? fatalError("explanation why this must not 
happen")

— Pyry

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


Re: [swift-evolution] [Pitch] Renaming sizeof, sizeofValue, strideof, strideofValue

2016-06-04 Thread Pyry Jahkola via swift-evolution
> On 04 Jun 2016, Erica Sadun wrote:
> 
> Discussion has more or less drawn down. Are there any further significant 
> requests / issues that need addressing? Both standalone functions (my 
> recommended approach)  and the MemoryLayout struct approach (alternative, 
> with reasons why I think it's not as ideal) are discussed in-proposal.
> 
> Pull Request: https://github.com/apple/swift-evolution/pull/350

Good proposal, Erica!

Regardless of the little input I've given to this discussion, I actually prefer 
the set of `memory*` prefixed top-level functions to a `MemoryLayout` struct or 
tuple.

However, I think it's most common to call these functions with a type argument, 
and we should thus stick to the practice of keeping that use case short, and 
the call-with-value case explicit. In particular, I'd avoid the label for a 
type argument, and say `ofValue:` when passing a value:

memorySize(ofType:)  → memorySize(_:)
memorySize(of:)  → memorySize(ofValue:)
memoryInterval(ofType:)  → memoryInterval(_:)
memoryInterval(of:)  → memoryInterval(ofValue:)
memoryAlignment(ofType:) → memoryAlignment(_:)
memoryAlignment(of:) → memoryAlignment(ofValue:)

Secondly, (this might be over-engineering but) would it still make sense to use 
`@autoclosure` in the `ofValue:` functions because they don't really need their 
arguments evaluated?

public func memorySize(ofValue _: @autoclosure T -> ()) -> Int
public func memoryInterval(ofValue _: @autoclosure T -> ()) -> Int
public func memoryAlignment(ofValue _: @autoclosure T -> ()) -> Int

— Pyry, whose name gets autocoerced in various ways apparently.

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


Re: [swift-evolution] [Proposal] Protected Access Level

2016-05-30 Thread Pyry Jahkola via swift-evolution
That's a cool hack! For a lighter way to distinguish overridable methods that 
one shouldn't ordinarily call, did anyone consider approximating "protected" 
(or as called in Objective-C speak, "private extension") methods with public 
class methods?

public class UIView {
public class func _layoutSubviews(_ view: UIView)
}

This way, they become overridable, won't show up in the editor auto completion 
list for a given instance, and can be called… but definitely make you think 
twice before you do!

— Pyry

> Callionica (Swift) via swift-evolution  kirjoitti 
> 30.5.2016 kello 7.49:
> 
> I've written up how to provide protected access control for Swift code today 
> here:
> 
> http://www.callionica.com/developer/#swift-protected
> 
> No compiler changes necessary for this technique and it distinguishes between 
> methods that can only be overridden and methods that can be both called and 
> overridden.
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Review] SE-0091: Improving operator requirements in protocols

2016-05-25 Thread Pyry Jahkola via swift-evolution

> On 25 May 2016, at 12:21, Brent Royal-Gordon  wrote:
> 
>> Brent, I think it's even slightly more complicated than that. Think e.g. how 
>> two subclass instances of NSArray should compare equal even if they've got 
>> different types. (I really dislike class inheritance for these reasons, but 
>> below is my take on how we could better live with the issue in Swift.)
> 
> If you're referring to this:
> 
>>> guard let other = other as? Self else {
>>> return super == other
>>> }
> 
> I probably should have said `#Self`, meaning e.g. `NSArray` if you're 
> implementing `NSArray.==`. What you really want to test for there is the 
> *static* type of `self`, not the dynamic type.
> 
> If you're referring to the multiple dispatch thing, I actually think that 
> will handle subclassing perfectly well. If you have a class hierarchy like 
> this, with each class implementing its own `(Self, Self)` equality operation:
> 
>   NSObject
>   NSArray
>   MyArray
>   MyOtherArray
> 
> Then using `==` on `MyArray` and `MyOtherArray` should use `(NSArray, 
> NSArray).==()`, which presumably would compare the length and elements to 
> test for equality.

It's kind of hard to explain without working code so here's a sample to play 
with: 
http://swiftlang.ng.bluemix.net/#/repl/c1ddd24113169ab82df118660c8e0de6ea24e48d32997c327638a88dc686e91f
 
.
 Use the `#if true` line to toggle between the implementations. The core of the 
issue—which I think will also happen if we ever gain the ability to "open" 
existentials—is at the point where we cast the right-hand side to Self:

struct AnyEquatable : Equatable {
let value: Any
let isEqual: (AnyEquatable) -> Bool
init(_ value: T) {
self.value = value
self.isEqual = {r in
guard let other = r.value as? T.EqualSelf else { return false }
return value == other
}
}
}

func == (l: AnyEquatable, r: AnyEquatable) -> Bool {
return l.isEqual(r)
}

See the cast `r.value as? T.EqualSelf`, or `r.value as? T` like it would go for 
the stdlib Equatable. When `T` is MyArray or MyOtherArray and the erased type 
of `r.value` is not, the cast will fail.

>> For the very example of Equatable and Foundation classes, we would get the 
>> right behaviour for NSObject's `isEqual` by changing the definition of 
>> Equatable into:
>> 
>>protocol Equatable {
>>associatedtype EqualSelf = Self // the default is ok pretty much 
>> always
>>func == (lhs: Self, rhs: EqualSelf) -> Bool
>>func != (lhs: Self, rhs: EqualSelf) -> Bool
>>}
>> 
>> This way, the compiler would always be looking for the `(Self, NSObject) -> 
>> Bool` shape of operation, which actually picks up statically the correct 
>> overload for `lhs.isEqual(rhs)`.
> 
> But you would need to do this for all operators. A protocol that requires `<` 
> or `+` would need to de-privilege the right-hand side in exactly the same way.


That's true. Maybe if we want to take this issue into account we should name 
`EqualSelf` more generally. Or then we can just shrug away the problem and 
document it. It's not something I tend to face in real work, partly because I 
try to avoid inheritance as much as possible, but I know it's there.

— Pyry

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


Re: [swift-evolution] [Review] SE-0091: Improving operator requirements in protocols

2016-05-25 Thread Pyry Jahkola via swift-evolution
Brent, I think it's even slightly more complicated than that. Think e.g. how 
two subclass instances of NSArray should compare equal even if they've got 
different types. (I really dislike class inheritance for these reasons, but 
below is my take on how we could better live with the issue in Swift.)

> On 25 May 2016, at 11:15, Brent Royal-Gordon via swift-evolution 
>  wrote:
> 
>>> As Brent pointed out in his reply, without multiple dispatch, you don't 
>>> really benefit from privileging the lhs argument, and in fact you can end 
>>> up in situations where the behavior is surprising if you don't implement 
>>> both orders. For example, in your (NSString, NSURL) example, each class 
>>> would have to be extended to explicitly support comparison with the other 
>>> in order to support commutativity if equality was an instance method. I'm 
>>> not sure that's any better for those particular types than just having the 
>>> operators global in the first place.
>> 
>> I assume you’d still have to implement it with NSObject as the “other” type, 
>> like you do in Objective-C. You’d just return false in that case.
> 
> It is rather unfortunate, though, that your `(Self, Self)` operator 
> essentially becomes `(Self, NSObject)` once `NSObject` conforms. I mean, 
> Swift will at least *tell* you this is happening and force you to write an 
> `other as? Self` test, but the way the type of the right-hand side gets 
> pinned down while the left-hand side stays unspecified is just strange.
> 
> (Incidentally, I think rather than returning `false` here, you probably ought 
> to say:
> 
>   guard let other = other as? Self else {
>   return super == other
>   }
> 
> Would you be able to use `super` in that way? You probably ought to, if we're 
> planning to use left-side dispatch.)
> 
> Meanwhile, a multi dispatch solution would send two otherwise unrelated types 
> to `NSObject`'s implementation, which would `===` the two instances, discover 
> they were not identical, and return `nil`. More specific implementations 
> would not even have to think about this case; the method dispatch would just 
> do it for them. I don't know if that solution is feasible, but if it is, it 
> seems clearly correct—it simply gives you the right behavior every single 
> time with no hand-wringing about type mismatches.
> 
> (On the other hand, if we *do* use left-side dispatch, we might be able to 
> solve the `isEqual` interop problems complained about upthread: if `==` is 
> implicitly given an `@objc(isEqual:)` attribute, and `isEqual` definitions or 
> calls are fix-it-ed to `==`, the problem essentially solves itself.)

For the very example of Equatable and Foundation classes, we would get the 
right behaviour for NSObject's `isEqual` by changing the definition of 
Equatable into:

protocol Equatable {
associatedtype EqualSelf = Self // the default is ok pretty much always
func == (lhs: Self, rhs: EqualSelf) -> Bool
func != (lhs: Self, rhs: EqualSelf) -> Bool
}

This way, the compiler would always be looking for the `(Self, NSObject) -> 
Bool` shape of operation, which actually picks up statically the correct 
overload for `lhs.isEqual(rhs)`.

When it comes to existentials, the usual case is like you said above; you want 
to check if you can cast the `rhs` to `Self`. But that usual case excludes the 
complication of class clusters where the instances of two different subclasses 
of a common superclass may compare equal.

— Pyry

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


Re: [swift-evolution] Proposal SE-0009 Reconsideration

2016-05-22 Thread Pyry Jahkola via swift-evolution

> On 22 May 2016, David Hart wrote:
> 
> If the design team is very serious about not integrating optional warnings, 
> then I don’t think it is a huge bother to implement think in linters like 
> SwiftLint is doing.

I'm fine with the way SE-0009 was decided but I think the review left one 
consideration for linters unexplored: How to be explicit about what's captured 
by a closure if the coding style enforced by a linter involves using `self.` 
everywhere?

There were (are) basically two reasons for keeping `self.` implicit the way it 
is:

Reason 1. It keeps noise level down. E.g. computed properties often read better 
this way:

var area: Double {
  return width * height
  // rather than: 'self.width * self.height'
}

Reason 2. It makes the capturing of `self` explicit, because `self.` is only 
required in escaping closures and thus the capturing expressions require 
thinking when writing code and also stand out when reading code.

I think those are good reasons. But then, the language rules don't really 
favour the other coding style where the `self.` prefix is used throughout, even 
if it *can* be enforced by a linter:

Example 1. There's no other way (but using the `self.` prefix) to indicate that 
`self` should be retained by a closure:

self.prepareWork()
queue.async { [self] in
// ^
// error: Expected 'weak', 'unowned', or no
// specifier in capture list
  self.doTheWork()
}

Example 2. There's currently no way to mark when an escaping closure is 
intended to **not** capture any other references but those explicitly listed:

queue.async { [bar] in
  if bar.isAdjustable {
baz.adjust()
  }
}
// Meant 'bar', but compiler didn't alert!

So I think it would be a good idea to adjust the capture list syntax a bit:

Suggestion 1. Allow capture lists to explicitly state that they capture `self` 
strongly by spelling it out with no weak/unowned specifier, i.e. `[self]`.

Suggestion 2. Add a succinct way to indicate that the capture list is 
*comprehensive*, i.e. that implicitly capturing other variables from the local 
scope is an error. (Capturing variables from the file scope should be allowed 
though, I reckon.) The syntax for this could be e.g. postfixing the capture 
list brackets with the exclamation mark `!`:

queue.async { [service]! in
  service.handleTask(self.task)
//   ^
// error: Implicit capture of 'self' in closure
}
queue.async { [service, self]! in
  service.execute(self.task) // ok
}
queue.async { [service, task = self.task]! in
  service.execute(task) // also ok; didn't capture 'self'
}
queue.async { [bar]! in
  if bar.isAdjustable {
baz.adjust()
//  ^
// error: Implicit capture of 'baz' in closure
  }
}

With these two changes, the coding style choice of what to use the `self.` 
prefix for would be better supported both ways, and no optional warnings would 
be needed. A linter could then require capturing `self` explicitly where it's 
used inside an escaping block. Myself, I wouldn't use comprehensive capture 
lists all the time but there have been a few cases where it would've been 
useful to prevent mistakenly capturing anything that could create a retain 
cycle.

Any thoughts? Would an idea like this help any of the people who started this 
mailing list thread—that is, with the aid of a respectively configured linter 
of course?

— Pyry

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


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0041: Updating Protocol Naming Conventions for Conversions

2016-05-18 Thread Pyry Jahkola via swift-evolution

> On 18 May 2016, Brent Royal-Gordon wrote:
> 
> I don't think `Convertible` is clearer than `Initializable`, but I think it 
> rolls off the tongue better, is easier to spell, is more compatible with 
> non-initializer implementations, and in general wins on a lot of squishy, 
> subjective, hard-to-define axes.
> 
> Subjectively, I've noticed that a lot of people *don't* think of things like 
> `Double(myFloat)` as being initializers; they think of them as conversions. 
> To those people, `Convertible` is probably the right name.

Isn't it odd that we use four different terms for both kinds of String 
conversions that we have?

A1: extension Foo : CustomStringConvertible // proposed: 
CustomStringRepresentable
A2: foo.description
A3: String(foo) // or `String(printing: foo)` if SE-0089 gets accepted
A4: print(foo)

B1: extension Foo : CustomDebugStringConvertible // proposed: 
CustomDebugStringRepresentable
B2: foo.debugDescription
B3: String(reflecting: foo)
B4: debugPrint(foo)

I don't have great suggestions but wouldn't it be better to move the naming of 
cases 1 & 2 towards the words used in cases 3 & 4?

— Pyry

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


Re: [swift-evolution] [Review] SE-0081: Move where clause to end of declaration

2016-05-16 Thread Pyry Jahkola via swift-evolution
> On 16 May 2016, Thorsten Seitz wrote:
> 
> Funny, for me reading a function is quite the other way around:
> I prefer to first look at the function name and parameter list to give me an 
> idea of what the function will do (the parameter names help a lot).
> Having instead first to memorize a list of types with all their constraints 
> just builds up the cognitive load without helping much, because their usage 
> is yet unknown.

This is also my biggest motivation for the proposal: keeping the function name 
and arguments close to each other.

> So, for me reading the signature would look like (with the proposal in place):
> 
>>> internal func _arrayOutOfPlaceReplace(_ source: inout B, _ bounds: 
>>> Range, _ newValues: C, _ insertCount: Int)


^ Agreed! That's essentially what I'm trying to find too when skimming through 
code.

An alternative approach with the same desired outcome would be moving the 
parameter list before the function name, either `func<...> someFunction(...)`, 
or even before the `func` keyword. But since we already use `where`, it seems 
more natural to me for Swift to place the constraints list to the end.

— Pyry

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


Re: [swift-evolution] [Review] SE-0081: Move where clause to end of declaration

2016-05-16 Thread Pyry Jahkola via swift-evolution

> On 16 May 2016, at 01:45, Brent Royal-Gordon via swift-evolution 
>  wrote:
> 
> I'm actually tempted to suggest that a conformance should be *mandatory* and 
> you should have to specify `Any` if you don't have anything more specific to 
> say about the generic parameter:
> 
>   func map(@noescape transform: (Element) throws -> T) rethrows 
> -> [T]

That's a good idea indeed if we ever intend to have other kinds of generic 
arguments (in particular, constant values like `length: Int`).

Even so, I wouldn't want to prohibit adding more protocol constraints in the 
where clause even if you can introduce all constaints of `T` at once as `T: 
protocol`.

— Pyry

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


Re: [swift-evolution] [Review] SE-0081: Move where clause to end of declaration

2016-05-14 Thread Pyry Jahkola via swift-evolution
Tony & Haravikk,

(Reformatting your quoted examples just a bit…)

>> It enables things like:
>> func someMethod(value: S) -> AnySequence
>> where S.Generator.Element == T { ... }
> 
> I'm not assuming that. Under the current syntax, I would format your example 
> as:
> 
> func someMethod<
> S : SequenceType, T
> where S.Generator.Element == T
> >(value: S) -> AnySequence {
> ...
> }

You are both right here, but please note that the proposal still also allows 
moving all constraints to the `where` clause:

func someMethod(value: S) -> AnySequence
where S : SequenceType,
  S.Generator.Element == T
{
...
}

just like Swift 2 allows doing so within the `<...>` brackets:

func someMethod(value: S) -> AnySequence {
...
}

The reason I'd recommend that style for anything but simple constraints is 
because:

1) It makes the call site `let items = someMethod(value: things)` lightest to 
visually match to the declaration, because the only thing between the function 
name and its argument list is the `<...>` bracketed list of introduced generic 
types which you'll expect to see in the function signature and constraints.

2) In general, the `where` constraints really apply to the whole function/type 
declaration, not just a single generic parameter.

3) It was claimed that all constraints should go right next to the introduction 
of the generic parameters. But that isn't the whole case because Swift also 
applies implicit constraints onto any generic parameters that are used in 
constrained positions. If that wasn't clearly said, take the following example 
in Swift 2.x:

func aMethod(value: S) 
-> Set {
return Set(value)
}

That declaration actually makes you wait all the way until the return type 
`Set` until you learn that `T` must also necessarily be `Hashable`. So I 
don't see how it's that different if the `where` clause isn't right next to the 
generic type arguments' introduction:

func aMethod(value: S) -> Set // FWIW, this line contains what I 
usually have in mind when browsing code.
where // T : Hashable, // (implicit)
  S : SequenceType,
  S.Generator.Element == T
{
return Set(value)
}

— Pyry

PS. Besides, neither the original example nor mine was really fair; you don't 
need `where` for these. Instead, you'd just write:

func someMethod(value: S) -> 
AnySequence {
...
}

which SE-0081 has nothing to argue for or against.

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


Re: [swift-evolution] [Review] SE-0075: Adding a Build Configuration Import Test

2016-05-13 Thread Pyry Jahkola via swift-evolution
> On 13 May 2016, Erica Sadun wrote:
> 
>> As per Pyry’s feedback, you could add a version:
>> 
>> #if import Frobnication(<1.7.3) // <- Only added version constraint here.
>> extension Knob : Frobnicatable { ... }
>> #endif
> 
> I have no problem with this but would need to defer to the build and language 
> people to determine whether that's practical in today's Swift. Right now, 
> there's a major-version mention in build packages but I'm not sure whether 
> that information then propagates in a usable way. If it's possible, then yes, 
> I'd rather add it in the initial design than as a later addition and I can 
> extend Pyry's suggestion in "Future Directions".

I already gave my +1 on the original proposal and if `canImport` is indeed 
easiest to implement we should get it going now.

The `#if import Foo` blocks and conditional imports with version checks can 
easily be added at a later time without much complication or breakage, AFAICT. 
Good if you can include those in the "Future Directions" section.

> p.s. Also on my Swift Bucket list: "import as".

Splendid! I'd already forgotten about qualified imports and renaming! Those 
would be welcome additions too.

— Pyry

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


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0041: Updating Protocol Naming Conventions for Conversions

2016-05-13 Thread Pyry Jahkola via swift-evolution
Taking the suggested changes into account, here's my review.

1) +1, I think this is a reasonable way for naming this family of protocols.

2) The problem isn't huge, but I think it's worth fixing. So far, the naming of 
stdlib protocols has been somewhat inconsistent in this regard.

3) I've used other languages & stdlibs with similar naming schemes, although 
none of them used the words "initializable" and "representable". Common 
alternatives have been word compositions involving expressions such as 
"convertible", "from", "to", "bi(jective)", "can build". However, I think 
"init" is so central in Swift that the use of "Initializable" is well 
justified. "Representable" is slightly less so but self-explanatory IMO, and 
more so than "convertible" which could be understood either or both ways.

4) Quick reading.

— Pyry

> On 13 May 2016, Matthew Johnson wrote:
> 
> While the community feedback on our SE-0041 proposal "Updating Protocol 
> Naming Conventions for Conversions" 
> (https://github.com/apple/swift-evolution/blob/master/proposals/0041-conversion-protocol-conventions.md
>  
> )
>  has been positive about the need to establish conventions, feedback has been 
> mixed to negative with regard to the specific conventions suggested in the 
> proposal.
> 
> With that in mind, Erica and I have been working on refactoring those 
> recommendations. We put together the following update and invite the 
> community to bikeshed further with us. We hope this offers the Swift core 
> team the flexibility to accept our proposal "with revision" if an alternative 
> garners more support. With luck, we'll reach a naming consensus during the 
> review period.
> 
> UPDATED APPROACH
> 
> Our updated approach focuses on the two most important conventions: one for 
> initialization and one for representation.
> 
> 1. `Initializable`
> 
> `Initializable` designates protocols that convert *from* a type or from an 
> associated type mentioned in the protocol name, such as the current 
> `LiteralConvertible` protocols.  This convention would include member 
> requirements for initializers, factory methods, and any other way an instance 
> can be imported to establish a new instance of the conforming type.
> 
> For example, conforming to `ArrayLiteralInitializable` would allow a set to 
> be created with `Set(arrayLiteral: )` and `var set: Set = []`.
> 
> This phrase replaces the `Creatable` form from our original proposal.
> 
> 2. `Representable`
> 
> `Representable` designates protocols whose primary purpose is to project *to* 
> a type or associated type mentioned in the protocol name.  Items in the 
> standard library that would be subsumed into this naming include 
> `CustomStringConvertible`, `CustomDebugStringConvertible`, and 
> `RawRepresentable`, which we imagine would become 
> `CustomStringRepresentable`, `CustomDebugStringRepresentable`, and (as 
> current) `RawRepresentable`.
> 
> This second category groups together the `Convertible` and `Representable` 
> categories from our original proposal and is predicated on the feedback from 
> the design team review. The `Representable` designation does not promise 
> bidirectional conversion although some `Representable` protocols may include 
> requirements to allow attempted initialization *from* the type of the 
> representation. Doing so falls outside the naming contract we are proposing. 
> 
> FUTURE DIRECTIONS
> 
> We did not include a third category for bidirectional conversion in this 
> update. We recognize that style of contract is rare in Swift. Lossless 
> conversion does not appear in the standard library outside of 
> `RawRepresentable`, which we agreed was better covered by `Representable`. If 
> such a convention is needed or adopted, we reserve the `Isomorphic` 
> designation for future use.
> 
> Sent from my iPad

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


Re: [swift-evolution] [Review] SE-0075: Adding a Build Configuration Import Test

2016-05-13 Thread Pyry Jahkola via swift-evolution
> Gwendal Roué wrote:
> 
> `#if import Foo` can not deal with the fact that a single source file may 
> have to perform the importability test several times.

This would be less of a problem if conditional imports like that worked locally 
in all scopes of code, so you could write just

func foo() {
#if import UIKit
// Actually use UIKit...
#endif
// UIKit no longer visible.
}

— Pyry

> For example:
> 
>   #if canImport(UIKit)
>   import UIKit
>   // Some UIKit-related declarations
>   #endif
>   // Later in the same file
>   func f() {
>   #if canImport(UIKit)
>   // Use UIKit-only declarations
>   #endif
>   }
> 
> I know, I know, some will tell me to refactor my code. So let's just say I'm 
> prototyping and that the code doesn't have its final shape, OK?
> 
> Still, testing for module importability is not the same as importing it.
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Review] SE-0075: Adding a Build Configuration Import Test

2016-05-13 Thread Pyry Jahkola via swift-evolution
Patrick,

I think you're making valuable points here. I also can't think of cases where 
you wouldn't also import a module in case it was found to be importable. So the 
use cases I can think of could as well be tackled by allowing expressions such 
as `import Foo.Bar` as compile-time checks within the conditions of `#if` like 
you suggested. That would bring those libraries only visible within the scope 
of that block.

However, there can be cases where you're considering importing more than one 
module, so something like:

#if import Foo, import Bar
  ...
#elseif import Baz
  ...
#endif

should be considered in that design too. And I don't like the fact that it 
would import many modules in one line of code.

However, I don't get your concerns of "whether already imported or not". Isn't 
`import` strictly about bringing identifiers of linked libraries visible in the 
current file and not about linking to libraries in code.

— Pyry

> I guess one issue I can see is it’s used in two different ways:
> - The first use of canImport is used to check whether it can import a module, 
> and then does so, but there’s no requirement for it to do so. Is this the 
> right this to do?
> - The second use of canImport makes no guarantee that the module has been 
> imported, only that it can.
> 
> What if instead `import` could return whether it imported or not, when used 
> with #if? Instead of ‘can import’, you get ‘did just import’ and ‘has 
> imported’.
> 
> 
> import Required // Error if not present, current behaviour
> 
> #if import CoolThing // Skips code block if not present, imports otherwise
>  // Do something with CoolThing module
> #else
>  import AlmostAsCoolThing
> #endif
> 
> and you test at the use-site
> 
> #if module(X) // Does not import, only checks if it has been imported
>  // use things that are available in X
> #else
> 
> 
> As per Pyry’s feedback, you could add a version:
> 
> #if import Frobnication(<1.7.3) // <- Only added version constraint here.
> extension Knob : Frobnicatable { ... }
> #endif
> 
> 
> 
> Just a way to make it less low level.
> 
> ___
> 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] [Review] SE-0075: Adding a Build Configuration Import Test

2016-05-13 Thread Pyry Jahkola via swift-evolution
> The review of "SE-0075: Adding a Build Configuration Import Test" begins now 
> and runs through May 16. The proposal is available here:
> 
>   
> https://github.com/apple/swift-evolution/blob/master/proposals/0075-import-test.md
> 
>   * What is your evaluation of the proposal?

+1, I think it's a welcome change that improves modularity between libraries.

>   * Is the problem being addressed significant enough to warrant a change 
> to Swift?

Yes.

There's another real problem that this feature solves which I couldn't see 
mentioned in the proposal: adding protocol conformances to optional 
dependencies. Suppose a library named Frobnication defined a protocol 
`Frobnicatable`, with some known conformances:

// module Frobnication
public protocol Frobnicatable {
mutating func frobnicate()
}
extension String : Frobnicatable { ... }
extension Frob : Frobnicatable { ... }

Now, suppose something in a 3rd party library called Knobs was also clearly 
`Frobnicatable` but `canImport` didn't exist. The community would have to pick 
from the following poorly scaling alternatives:

#1) Either Frobnication would require and import Knobs as its dependency and 
add the conformances,
#2) or vice versa, Knobs would pull Frobnication as its dependency,
#3) or everybody using both libraries would need to define the conformances 
theirselves,
#4) or someone would need to maintain a "KnobsFrobnication" library for the 
sole purpose of defining the said protocol conformances.

* * *

With `canImport`, on the other hand, we get two good options:

#5) Either Frobnication checks `#if canImport(Knobs)` and conditionally adds 
the conformances,
#6) or Knobs checks if it `canImport(Frobnication)` and conditionally adds the 
conformances to any suitable types it defines (which is what any new libraries 
that the author of Frobnication wasn't aware of could do in the future).

* * *

But there remains one issue that there's no clear path for moving conformance 
definitions from one library into the other one day. This proposal could be 
improved by allowing to check for library versions too! If similarly to `#if 
swift(>=2.2)`, we could check `#if canImport(Knobs >= @2.10.0)`, then the 
authors of Knobs and Frobnication could organise an orchestrated move of 
conformance definitions from one library into another. Before the move, Knobs 
2.9.x would have defined:

// module Knobs 2.9.x
#if canImport(Frobnication)
import Frobnication
extension Knob : Frobnicatable { ... }
#endif

Preparing for the move, a new version of Frobnication could introduce the 
conformance thusly:

// module Frobnication 1.7.3
#if canImport(Knobs >= @2.10.0) // *) see note below
import Knobs
extension Knob : Frobnicatable { ... }
#endif

Then, Knobs could gracefully sunset its conformance definitions beginning from 
the 2.10.0 release:

// module Knobs 2.10.0
#if canImport(Frobnication < @1.7.3) // <- Only added version constraint 
here.
import Frobnication
extension Knob : Frobnicatable { ... }
#endif

*) I'm not sold to any specific syntax, but we could e.g. use the `@` prefix to 
distinguish version number literals like `@1`, `@0.10` and `@0.10.0` from 
similar but differently behaving numeric literals.

In any case, even with just `canImport(module)`, we can do a lot better than 
currently.

>   * Does this proposal fit well with the feel and direction of Swift?

Yes.

>   * If you have used other languages or libraries with a similar feature, 
> how do you feel that this proposal compares to those?

Yes, like mentioned in the proposal, it's very similar to the 
`__has_import()` macro in Clang. I'm not fully familiar with 
the design space in Haskell, but it seems to me instead of using something 
similar to `canImport` Haskellers tend to favour the approach I listed above as 
alternative #4 (e.g. https://github.com/lens/lens-aeson/ 
 brings the lens and aeson libraries 
together).

>   * How much effort did you put into your review? A glance, a quick 
> reading, or an in-depth study?

Quick reading.

— Pyry

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


Re: [swift-evolution] Making `.self` After `Type` Optional

2016-05-06 Thread Pyry Jahkola via swift-evolution

> On 06 May 2016, at 10:19, Adrian Zubarev via swift-evolution 
>  wrote:
> 
> Wouldn’t this enforce enum cases and some static struct variables to be 
> lowercase?
> 
> Is this really a welcome change? I mean I’d love to see the drop of `.self` 
> magic from types, but not sure about the UppercaseTypes, lowercaseValue 
> convention here.

Lowercase enum cases and static struct variables is already the case in Swift 
3. Look up “Lowercase enum cases and static properties” in the accepted SE-0006 

 proposal.

— Pyry

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


Re: [swift-evolution] Making `.self` After `Type` Optional

2016-05-06 Thread Pyry Jahkola via swift-evolution
> I understand why the alternative of changing the generic type parameter list 
> symbols was rejected, to be consistent with other C based languages, but I 
> don't understand why the following was rejected:
> 
> making the UppercaseTypes, lowercaseValues convention a syntactic 
> requirement, as is done in ML and Haskell.
> I see that as a good viable alternative.

+1, enforcing the initial character case of type and value identifiers would 
clear up the language IMO.

It would also mean we'd need to bridge all C APIs in correct case.

Also, in general +1 to getting rid of `.self`.

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


Re: [swift-evolution] [Review] SE-0073: Marking closures as executing exactly once

2016-05-04 Thread Pyry Jahkola via swift-evolution
Hi Gwendal,

Nice writeup. So I see that you recognise how this extra specification will 
complicate (while also facilitate) things. And I also see that you're a 
co-author of the proposal. So I'm more than happy if you can squeeze this extra 
into it.

However reading your example code, I had to squint to see—without the 
compiler's squiggly red aid—what all the problematic cases are.

1) Is it obvious to everybody why you can't always use `x` in the end of Cases 
2 and 4? For example, with `if—else` you MUST initialise the variable or escape 
its scope in all branches; you can't just write the following to complete the 
initialisation later:

let x: Int
if cond { x = 1 }
// ...
if !cond { x = 2 } // too late!

2) Should Cases 2 and 4 be made illegal? The requirement could then be that all 
`catch` blocks either:
2.a) initialise another value for `x`, or
2.b) escape the scope using `throw`, `return`, `fatalError`, whatnot…

3) If you consider including this addition to the proposal, it might also help 
other reviewers if you explained how the compiler will be able to help the 
programmer write a valid program. E.g. what would the error messages about 
partially initialised variables look like? And where and when would they 
appear? Could the compiler suggest certain fixits? Etc.

So, I'm all +1 and very glad if you can make it! (But also somewhat sceptical 
whether it could get accepted.)

— Pyry

> On 04 May 2016, at 12:24, Gwendal Roué  wrote:
> 
> I quite expect being able to throw out of a @noescape(once) block. Maybe the 
> sentence "it must not be executed on any path that throws" should be removed 
> from the proposal, should it have the implications you describe.
> 
> Here is below what I expect this proposal to allow. So you see one 
> problematic case?
> 
>   // Function which rethrows closure errors:
>   func f1(closure: @noescape(once) () throws -> ()) rethrows {
>   try closure()
>   }
> 
>   // Function which may throw before, inside, or after the closure:
>   func f2(closure: @noescape(once) () throws -> ()) throws {
>   try mayFailBefore()
>   try closure()
>   try mayFailAfter()
>   }
>   
>   // Support function
>   func getX() throws -> Int { return 1 }
>   
> Case 1:
> 
>   let x: Int
>   f1 {
>   x = 1
>   // use x
>   }
>   // use x
>   
> Case 2:
> 
>   let x: Int
>   do {
>   try f1 {
>   x = try getX()
>   // use x
>   }
>   // use x
>   } catch {
>   // can't use x
>   }
>   // can't use x
>   
> Case 3:
> 
>   let x: Int
>   do {
>   try f1 {
>   x = try getX()
>   // use x
>   }
>   // use x
>   } catch {
>   x = 1
>   }
>   // use x
>   
> Case 4:
> 
>   let x: Int
>   do {
>   try f2 {
>   x = try getX()
>   // use x
>   }
>   // use x
>   } catch {
>   // can't use x
>   }
>   // can't use x
> 
> Case 5:
> 
>   let x: Int
>   do {
>   try f2 {
>   x = try getX()
>   // use x
>   }
>   // use x
>   } catch {
>   x = 1
>   }
>   // use x
> 
> Gwendal Roué
> 


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


Re: [swift-evolution] [Review] SE-0073: Marking closures as executing exactly once

2016-05-04 Thread Pyry Jahkola via swift-evolution
Here's my review of "SE-0073 
:
 Marking closures as executing exactly once".

> What is your evaluation of the proposal?

+1. I think this is a good idea and should be accepted (without extending the 
proposed scope).

However, I think the proposal should be more explicit about the case when (and 
whether) the block itself throws. Specifically, I think we should highlight 
that the criterion that

> it must not be executed on any path that throws


implies that a @noescape(once) parameter itself cannot throw (until another 
language change allows otherwise). Consider this use case:

final class Database {
  final class Transaction { ... }
  // Not allowed by SE-0073:
  func transact(_ apply: @noescape(once) (Transaction) throws -> ()) 
rethrows
}

func incrementScore(db: Database, game: String) throws -> Int {
  let oldScore: Int
  // This use of "@noescape(once) ... throws" *could* be ok if the error was
  // unconditionally propagated out of the scope of uninitialised variables:
  try db.transact { tx in
oldScore = try tx.read(key: "\(game).score")
try tx.update(key: "\(game).score", value: oldScore + 1)
try tx.update(key: "\(game).updatedAt", value: NSDate())
  }
  return oldScore
}

Being able to throw out of a @noescape(once) block would be useful in cases 
like this, as it would naturally allow rolling back a transaction. But it would 
complicate the language by requiring that no one catches the error in the scope 
where uninitialised variables are defined. I suggest adding this remark to the 
Future directions.

> Is the problem being addressed significant enough to warrant a change to 
> Swift?

Yes. I'm looking forward to being able to initialise immutable variables in 
dispatch_sync blocks and such without needing to resort to defining them as 
`var`.

> Does this proposal fit well with the feel and direction of Swift?

Yes it does, it aligns nicely with the trailing closure syntax that allows for 
the emulation of control flow constructs with library code. And as we know, the 
control flow constructs already allow the delayed initialisation of local 
variables.

> If you have used other languages or libraries with a similar feature, how do 
> you feel that this proposal compares to those?

With a similar feature, I have only used languages (in the sense of "used in 
anger") where the delayed initialisation is allowed by allowing an undefined 
state (e.g. C++). For a not-really-applicable-to-Swift alternative approach, 
Haskell's laziness allows the recursive definition of variables for a similar 
effect.

Finally, I think it's interesting that the requirement for @noescape(once) 
arguments to be unconditionally executed has a similarity to linear type 
systems (Wikipedia ) 
and uniqueness or references. Except in this case, the reference is not to an 
object but a function. Such a function reference bears a certain similarity to 
the deinit of a uniquely held object. I think the proposed feature may later 
merge with a bigger language update that brings reference uniqueness to the 
type system.

> How much effort did you put into your review? A glance, a quick reading, or 
> an in-depth study?


Between quick reading and in-depth study.

— Pyry

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


Re: [swift-evolution] [Proposal] Improving operator requirements in protocols

2016-05-03 Thread Pyry Jahkola via swift-evolution
FWIW, the problems with class inheritance and Equatable can be fixed by 
changing the definition of Equatable into using an associatedtype for the RHS:

protocol Equatable {
typealias EqualSelf = Self
func == (lhs: Self, rhs: EqualSelf) -> Bool
func != (lhs: Self, rhs: EqualSelf) -> Bool
}
func != (lhs: T, rhs: T.EqualSelf) -> Bool {
return !(lhs == rhs)
}

This way, a generic function of type Subclass will expect a comparison of type 
`(Subclass, Subclass.EqualSelf) -> Bool`, i.e. `(Subclass, Base) -> Bool`, so 
it'll do the right comparison.

I'm not proposing this change because I haven't found but contrived use for it. 
But if there's demand (and a real use case) for e.g. making an existential of 
Equatable (say, a struct AnyEquatable), then this could be the fix.

Value types will obviously keep working just like before, since T and 
T.EqualSelf are synonymous for them.

— Pyry

>> We do have some problems today, such as above where using `==` on a `(Base, 
>> Subclass as Base)` pair ends up calling `==(Base, Base)` because we lack 
>> multiple dispatch. What surprised me though was that the `eq` call between 
>> two `Subclass` instances passed to the trampoline operator ended up calling 
>> `Base.eq`. I would have expected `Subclass.eq` to be called there since the 
>> generic argument `T` was bound to `Subclass`. Today, a non-generic 
>> `==(Subclass, Subclass)` operator *does* do the right thing.
> 
> The reason why the trampoline calls the ==(Base,Base) overload in
> Subclass is because it is a part of the override chain for the base
> class method that introduces the conformance.
> 
> The reason why the non-generic ==(Subclass,Subclass) operator does the
> right thing is because it is a better match for overload resolution of
> == at the callsite.  But if you have a (Subclass as Base, Subclass as
> Base) pair, even today it will call ==(Base,Base).
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0045: Add scan, prefix(while:), drop(while:), and iterate to the stdlib

2016-04-28 Thread Pyry Jahkola via swift-evolution
> I would really like a different name for scan. While it’s the term of art for 
> Haskell and co, it really seems meaningless to regular programmers (why is 
> “scanning” the way you produce an array of intermediate reduces?), and it 
> would be better to follow the pattern already established elsewhere in the 
> library to give friendlier names e.g. flatMap instead of bind, reduce instead 
> of fold.
> 
> I think Python calls it accumulate: 
> http://docs.python.org/3/library/itertools.html#itertools.accumulate 
> 

FWIW, Clojure calls it `reductions 
`
 which aligns pretty nicely with the `reduce` counterpart.

> I also think it would be nice for both scan and reduce to have overloads that 
> take the first value as the initial (and return an optional) but that’s 
> probably a separate proposal.

+1

— Pyry

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


Re: [swift-evolution] [Review] SE-0066: Standardize function type argument syntax to require parentheses

2016-04-28 Thread Pyry Jahkola via swift-evolution
> https://github.com/apple/swift-evolution/blob/master/proposals/0066-standardize-function-type-syntax.md
>  
> 
> What is your evaluation of the proposal?

-1, I'm mildly against but against.

In light of the observation 
(http://permalink.gmane.org/gmane.comp.lang.swift.evolution/15577 
) that we 
don't need Swift's type system to distinguish between function arity and a 
singular tuple argument, I don't think it's a good idea to add parentheses to 
the game.

Instead, I propose (in the above mail) to extend the notion of function name to 
always cover its argument labels.

> Is the problem being addressed significant enough to warrant a change to 
> Swift?


No. (Even in the current state of things, I don't think we should require the 
parentheses except maybe to disambiguate tuples.)

> Does this proposal fit well with the feel and direction of Swift?


When it comes to the core team's idea of function types, I don't have a good 
sense of direction where you want to take the argument list. However, I don't 
think introducing (or canonicalising) a new pseudo type for function argument 
lists is a good direction for Swift to take, as it would later make 
higher-level programming demand even more complex syntaxes to deal with the 
said function types (I'll take C++ as an alerting example).

As shown, we can represent a function's argument list as an unlabelled n-tuple 
(including n=1), and doing so can come with no loss in generality nor added 
ambiguity.

> If you have used other languages or libraries with a similar feature, how do 
> you feel that this proposal compares to those?

Haskell only has unary functions and functions extensively use currying (`A -> 
B -> R`). But you can also pass arguments in a tuple if you seriously don't 
want currying (`(A, B) -> R`). Like in Swift, parentheses are required together 
with the comma to create tuples. A type like `(A) -> B` is allowed but 
synonymous to `A -> B`. A crucial difference to Swift is that Haskell's 
functions are more like Swift's function variables (which is what I call the 
identifier you bind a closure to), with only a base name; whereas Swift 
cleverly uses argument labels to increase legibility at the call site.

Scala is much like Haskell in this regard, while currying isn't that extensive, 
it also leaves the parentheses optional (and often omitted) around single-type 
argument lists.

In C++, the syntax for n-argument functions gets crazy quickly, especially when 
the return type is also a function. What gets even more crazy is the (variadic) 
template code needed to program in terms of functions. And C++ also doesn't 
deal with argument labels!

This proposal feels to me like a tiny step towards C++'s direction. Not harmful 
but unnecessary.

> How much effort did you put into your review? A glance, a quick reading, or 
> an in-depth study?

In-depth.

— Pyry

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


Re: [swift-evolution] [Pitch] Richer function identifiers, simpler function types

2016-04-28 Thread Pyry Jahkola via swift-evolution

> On 28 Apr 2016, at 14:37, Tino Heth <2...@gmx.de> wrote:
> 
>> C1: Extend SE-0021 
>> 
>>  by adding the underscore-in-parentheses syntax `foo(_)` to refer to the 
>> zero-argument function #1.
> I don't think that's consistent with the other use cases of the underscore: 
> Afair, it never means "nothing", but always "there is something, but ignore 
> it"

Right, that was another choice I forgot to justify:

We already refer to `func foo(_ x: Int, _ y: Int)` as `foo(_:_:)` even if the 
function call only contains a comma and no colons nor underscores. Yes, `func 
foo()` neither has an underscore in the definition. But we need something to 
distinguish its from the function call `foo()`, so `foo(_)` is an honest 
attempt to stick to the existing SE-0021 practice.

Personally, I'm fine with the syntax introduced by SE-0021 and I'd rather keep 
its criticism out of this thread if possible.

However, we could consider the alternative that you proposed where `foo` alone 
may only refer to the zero-argument function and for everything else, the 
argument list is always required.

> (…) so unless I didn't miss any downsides of using square brackets, (…)
> 
> let f = foo
> let f = foo[x: Int]
> let f = foo[Int]
> let f = foo[(Int, Int)]
> let f = foo[x: Int, y: Int]
> let f = foo[x: Int, y: Int]

The square brackets do avoid the ambiguity too but FWIW, they look foreign to 
me. It's also pretty noisy having to spell out all the argument types (unless 
you meant that it's optional doing so). In the majority of cases, there is no 
overloading by type, or if there is then the type can be inferred at the point 
of use.

— Pyry

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


Re: [swift-evolution] [Proposal] Add Binary Search functions to SequenceType

2016-04-28 Thread Pyry Jahkola via swift-evolution
Bringing up this topic because it became relevant with Brent Royal-Gordon's 
"[Idea] Bringing the partial/total ordering distinction into Comparable 
".

If the `<=>` operator with a return type of a three-case `enum Order`, you can 
fully define the most generic versions of binary searches as:

lowerBound(compare: Self.Collection.Element -> Order) -> Index

etc.

> On 29 Mar 2016, at 13:43, Jeff Hajewski via swift-evolution 
>  wrote:
> 
> I've responded below, but just for the sake of being explicit, this is 
> roughly 
> the signature for lowerBound, upperBound, and binarySearch I have in 
> mind based on your comments of a unary predicate:
> 
> lowerBound(isOrderedBelow: Self.Collection.Element -> Bool) -> Index
> upperBound(isOrderedBelow: Self.Collection.Element -> Bool) -> Index
> binarySearch(isOrderedBelow: Self.Collection.Element -> Bool) -> Bool
> 
> That's the general structure - the key is that the exact same predicate is
> used in all signatures. The predicate would be defined along the lines of
> a binary predicate where one of the parameters is fixed as the search value.
> The unary predicate could be formed along the lines of:
> 
> let binaryPred = { $0 < $1 }
> let unnaryPred = binaryPred($0, value)
> 
> where value is the search value. The main point of illustrating that is that
> once the unary predicate is defined, we can't change the position of the
> search value within the predicate like they do in the C++ implementation.

You're right, there's no way a Bool-returning unary comparator could allow you 
to implement anything but lowerBound. With a three-value result, however, 
you've got all you need.

I've shamelessly plugged before but for the sake of proving a point, I'll do it 
once more: I think this little library we did works as a good starting point 
for a stdlib binary search API: 
https://github.com/knomi/Allsorts/blob/master/Allsorts/BinarySearch.swift 


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


Re: [swift-evolution] [Pitch] Richer function identifiers, simpler function types

2016-04-28 Thread Pyry Jahkola via swift-evolution
Corrections, additions below…

> Let's consider the following declarations:
> 
> class Bar {
> func baz()   // #8 Method named 'Bar.baz(_)' with 
> type 'Bar -> () -> ()'.
> func baz(x y: Int)   // #9 Method named 'Bar.baz(x:)' with 
> type 'Bar -> Int -> ()'.
> static func baz(x: Int = 0)  // #10 Static method named 
> 'Bar.Self.baz(x:)' with type 'Int -> ()'.
> }
> // ...
> let bar = Bar()
> let f10 = bar.baz// error: not a function reference, did 
> you mean 'bar.baz(_)' or 'bar.baz(x:)'?
> let f11 = bar.baz(_) // #18 Function synonymous to the 
> closure '{ bar.baz() }' with type '() -> ()'.
> let f12 = bar.baz(x:)// #19 Function synonymous to the 
> closure '{ bar.baz(x: $0) }' with type 'Int -> ()'.
> let f13 = Bar.Self.baz(x:)   // #20 Function synonymous to the 
> closure '{ Bar.baz(x: $0) }' with type 'Int -> ()'.
> let f14 = Bar.Self.baz(_)// #21 Function synonymous to the 
> closure '{ Bar.baz() }' with type '() -> ()'.

(…)

> C2: Extend SE-0021 
> 
>  by removing the ambiguity between instance and type members. From now on, 
> `Bar.baz(_)` 

That was meant to read:

"(…) From now on, `Bar.baz(_)` unambiguously refers to the instance method 
named `baz(_)`. To refer to the static or class method named `baz(_)`, put the 
keyword `.Self` between the type and the base name. This syntax should align 
with the outcome of SE-0068 

 such the keyword resembles the static method call `thing.Self.baz()` of a 
`thing` of type `Bar`."

(Alternatives considered: (1) the use of `Bar.self.baz(_)` with lower-case 
`self`, which is probably more confusing; and (2) inverting the choice and 
making the instance method require a keyword instead, which would harm 
readability as it's usually the instance method that you'd refer to and not the 
static one.)

> C6: Clarify that by using the base name `foo` for a function, the same scope 
> cannot define a variable with the name `foo`. And, vice versa, in a scope 
> that defines a variable named `foo`, there can be no function `foo(...)` 
> defined at the same scope level.

This doesn't prevent shadowing of course. E.g. An inner scope with a variable 
named `foo` would shadow all functions named `foo(...)` of an enclosing scope.

> The implications are:
> 
> I1: The use of a function's base name to refer to a function will cease to 
> work. It has, however, been buggy up to this date. Consider the following:
> 
> let f = [Int].prefix // '[Int] -> Int -> ArraySlice'
> 
> let g1 = [Int].dropFirst // Inexplicably chooses the '[Int] -> Int -> 
> ArraySlice' overload!
> let g2 = [Int].dropFirst as [Int] -> () -> ArraySlice // 
> Disambiguate by type.
> 
> let h1 = [Int].sorted // Chooses the '[Int] -> () -> [Int]' overload, 
> unlike 'dropFirst' above.
> let h2 = [Int].sorted as [Int] -> ((Int, Int) -> Bool) -> [Int] // 
> Disambiguate by type.

By the way, the same also happens with the current Swift (both 2.2 and 3 
master) when referring to the partially applied instance method like so:

let xs = [1,3,2]
let g = xs.dropFirst // Chooses the 'Int -> ArraySlice' overload.
let h = xs.sorted// Chooses the '() -> [Int]' overload, unlike 
'dropFirst' above.

> I3: Function argument lists are no longer that special and there's no need to 
> notate single-n-tuple argument lists separately from n-argument functions, 
> i.e. SE-0066 
> 
>  is not really needed anymore. The new intuition here is that it's the 
> function's name that defines how a function can be called, not its type.

In yet other words, we don't have to capture the arity of a function in the 
type system at all—it's enough to carry that information around in the function 
name.

~>

Finally, this was a fairly technical pitch but a pitch anyway. Any ideas pro or 
against?

— Pyry

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


[swift-evolution] [Pitch] Richer function identifiers, simpler function types

2016-04-28 Thread Pyry Jahkola via swift-evolution
This is another reaction to SE-0066 

 to which I'm mildly against.

I'd like to propose the following language changes to simplify function types 
and clarify what a function's name is. What gets removed is already ambiguous. 
And what is added makes higher-level programming with functions considerably 
simpler than currently. Furthermore, the proposed change considerably limits 
what constitutes the overload set of a function, which probably also speeds up 
the compilation process.

Let's consider the following declarations:

func foo()   // #1 Function named 'foo(_)' with type 
'() -> ()'.
func foo(x: Int) -> Int  // #2 Function named 'foo(x:)' with type 
'Int -> Int' (not an overload).
func foo(_ x: Int) -> Int// #3 Function named 'foo(_:)' with type 
'Int -> Int'
func foo(_ x: (Int, Int)) -> Int // #4 Function named 'foo(_:)' with type 
'(Int, Int) -> Int' (overload of #3).
func foo(x: Int, y: Int) -> Int  // #5 Function named 'foo(x:y:)' with type 
'(Int, Int) -> Int'.
func foo(x: Int, y: Int) -> Bool // #6 Function named 'foo(x:y:)' with type 
'(Int, Int) -> Bool' (overload of #5).
let foo: Int // error: invalid redeclaration of 'foo' 
(previously declared as a function)
let baz: (Int, Int) -> Int   // #7 Variable named 'baz' with type 
'(Int, Int) -> Int'.
class Bar {
func baz()   // #8 Method named 'Bar.baz(_)' with type 
'Bar -> () -> ()'.
func baz(x y: Int)   // #9 Method named 'Bar.baz(x:)' with type 
'Bar -> Int -> ()'.
static func baz(x: Int = 0)  // #10 Static method named 
'Bar.Self.baz(x:)' with type 'Int -> ()'.
}
let f1 = foo // error: not a function reference, did 
you mean 'foo(_)'?
let f2 = foo as () -> () // error: not a function reference, did 
you mean 'foo(_)'?
let f3 = foo(_)  // #11 Function reference to #1. Has type 
'() -> ()'.
let f4 = foo(x:) // #12 Function reference to #2. Has type 
'Int -> Int'.
let f5 = foo(_:) // error: ambiguous function reference. 
Could be 'Int -> Int' or '(Int, Int) -> Int'
let f6 = foo(_:) as Int -> Int   // #13 Function reference to #3. Has type 
'Int -> Int'.
let f7 = foo(_:) as (Int, Int) -> Int // #14 Function reference to #4. Has 
type '(Int, Int) -> Int'.
let x1: Int = foo(x:y:)(1, 2)// #15 Function application of #5. Picks 
the right overload by explicit return type.
let x2: Bool = foo(x:y:)((1, 2)) // #16 Function application of #6. 
Allowing a tuple here causes no ambiguity.
let f9 = baz // #17 Function reference synonymous to 
#7. Has type '(Int, Int) -> Int'.
let bar = Bar()
let f10 = bar.baz// error: not a function reference, did 
you mean 'bar.baz(_)' or 'bar.baz(x:)'?
let f11 = bar.baz(_) // #18 Function synonymous to the closure 
'{ bar.baz() }' with type '() -> ()'.
let f12 = bar.baz(x:)// #19 Function synonymous to the closure 
'{ bar.baz(x: $0) }' with type 'Int -> ()'.
let f13 = Bar.Self.baz(x:)   // #20 Function synonymous to the closure 
'{ Bar.baz(x: $0) }' with type 'Int -> ()'.
let f14 = Bar.Self.baz(_)// #21 Function synonymous to the closure 
'{ Bar.baz() }' with type '() -> ()'.

The following list of proposed changes sum up what's new above.

C1: Extend SE-0021 

 by adding the underscore-in-parentheses syntax `foo(_)` to refer to the 
zero-argument function #1.

C2: Extend SE-0021 

 by removing the ambiguity between instance and type members. From now on, 
`Bar.baz(_)` 

C3: Extend SE-0021 

 by banning the use of base name only to refer to a function, i.e. neither 
`foo` nor `Bar.baz` can be used to refer to refer to any of #1–#6 or #8–#10.

C4: Extend SE-0021 

 to allow the selective omission of defaulted arguments, e.g. `let f = 
print(_:separator:)` creates the function variable `f: (Any, String) -> ()` 
equivalent to `{ print($0, separator: $1) }`.

C5: Clarify the language specification by stating that functions with different 
labels (e.g. `foo(_:)` vs. `foo(x:)`) are not overloads of each other. Instead, 
two functions are considered overloads of each other if only if they have 
matching base names (e.g. `foo`) and matching argument labels (e.g. `(x:y:)`) 
but differing argument or return types (e.g. #3 and #4, or #5 and #6).

C6: Clarify that by using the base name `foo` for a function, the 

Re: [swift-evolution] mutating/non-mutating suggestion from a Rubyist

2016-04-28 Thread Pyry Jahkola via swift-evolution
> On 28 Apr 2016, at 10:59, Tyler Fleming Cloutier  
> wrote:
> 
> Yup, that pretty much addresses all of my concerns. So count me amongst the 
> fans. 

By the way,

I can be counted as +1 on reusing the keyword `mutating` here.

However, for the reasons stated in my previous email, I maintain that the 
keyword should go before the value being mutated rather than next to the 
function's name.

— Pyry

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


Re: [swift-evolution] mutating/non-mutating suggestion from a Rubyist

2016-04-28 Thread Pyry Jahkola via swift-evolution
Good that you brought the topic of "fluent" interfaces up. I don't see any 
problem with explicit value type mutation and method chaining because fluent 
interfaces are constrained to reference types by the language. Details below:

> On 28 Apr 2016, at 03:44, Tyler Cloutier  wrote:
> 
> How would this chain if I wanted to do something like:
> 
> let median = foo.calculateBigHugeArray().sort().medianValue()
> 
> and I want the sort to be done in place.

I think I can guess what you wanted the above to mean but, mind you, the 
in-place sort returns `()` so you wouldn't chain its result like that. On the 
other hand, the above code already works using the non-mutating `.sort()` (to 
be known as `.sorted()` in Swift 3), and—correct me if I'm wrong—the compiler 
probably optimises the copy away using copy-on-write anyway.

> Or will this type of thing just be disallowed in favor of.
> 
> let array = foo.calculateBigHugeArray()
> mutate array.sort()
> let median = array.medianValue() 

Yes, I think mutating code should be written in many statements rather than 
squeezing everything into one long expression.

Indeed, no currently working method chaining would be disallowed in my 
proposal. Let's consider the example of "fluent API" for value types, i.e. one 
where you'd extensively `return self` in `mutating` methods. Firstly, the 
stdlib doesn't practice that at all. And I failed to find any popular Swift 
libraries that would do so on Github either. The reason is simple: fluent 
mutating APIs on value types don't work.

Consider the following silly example that shortens an array in half (but 
demonstrates the use of `return self` in a `mutating` method):

extension Array {
mutating func halve() -> Array {
self = self[0 ..< count / 2]
return self
}
}

Suppose I want to get the result of halving an array twice. What happens?

var xs = [1,2,3,4,5,6,7,8]
xs.halve().halve()
// error: cannot use mutating member on immutable value: function call 
returns immutable value

So no, fluent APIs on value types are not a thing in Swift. Not now at least. 
Making mutation explicit along this proposal has nothing to do with fluent APIs.

> Alternately you could replace the method invocation operator with &
> 
> let median = foo.calculateBigHugeArray()().medianValue()

Don't you think that's too prone to getting mixed up with the binary `&` 
operator?

> Also, if you wanted to stick with consistent & syntax, you could do:
> 
> (i)
> and 
> let k = ()


Yeah, probably. However, one place where that notation falls short compared to 
a prefixing keyword like `mutate` is when mutating `self`:

extension Array {
// Apologies for not having the time to think of a less contrived 
example than this!
mutating func quarter() {
mutate self.halve() // Ever since SE-0009 
,
 it's unusual to use `self` here.
mutate halve()  // Where would you put the `&` prefix in this?
}
}

— Pyry

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


Re: [swift-evolution] mutating/non-mutating suggestion from a Rubyist

2016-04-23 Thread Pyry Jahkola via swift-evolution
I'd like to second James Campbell's suggestion of a `mutate` keyword. 
Clarifying comments inline below:

> On 23 Apr 2016, at 00:24, Dave Abrahams via swift-evolution 
>  wrote:
> 
> This is not a new idea.  Something almost identical to this has been
> explored and discussed quite thoroughly already:
>  >.
> In fact, it was implmented and later reverted because it raised
> language-design questions for which we had no good answers.

I don't know if the following are particularly good answers, but I'll try 
anyway:

> I don't believe the choice of glyph (& vs =) affects any of the
> fundamental issues:
> 
> * Should the x.=f() syntax be required for *every* mutating method
>  invocation?

Allow me to ask it differently: Should some specific syntax be required for 
every mutating method? — Yes.

Should the syntax be `x.=f()`? — Not necessarily. I kinda like James Campbell's 
idea of a `mutate` keyword. Consider the following:

var numbers = [5, 12, 6, 2]
mutate numbers.append(10)
mutate numbers.sort()
if let biggest = mutate numbers.popLast() {
print("The biggest number was:", biggest)
}

So `mutate` would work much like `try` but—unlike `try` which can move further 
to the left—`mutate` would have to always prefix the mutating receiver. Here's 
a contrived example of a corner case:

enum Error : ErrorType { case BadNumber }

func demo() throws -> Int {

}

> * Are assignment methods a redundant way to spell mutating methods?
>  Should we really have both mechanisms?

(I had to look up the definition of an assignment method. For the uninitiated, 
Dave is talking about what's written here: 
https://github.com/apple/swift/blob/master/docs/proposals/Inplace.rst#use-one-simple-name
 
.)

— Yes they are redundant, and no, we should not have both.

With `mutate` required at the call site, we could simply allow both overloads 
`func sort()` and `mutating func sort()` to coexist, because the call sites 
become unambiguous:

let originals = [2, 1, 3, 0, 4, 2]
var copies = originals

originals.sort()   // warning: result of call to 'sort()' is unused
mutate originals.sort()// compiler error
let xs = originals.sort()  // ok

copies.sort() // warning: result of call to 'sort()' is 
unused
mutate copies.sort()  // ok
let ys = copies.sort()// ok
let zs = mutate copies.sort() // warning: constant 'x' inferred to have 
type '()', which may be unexpected

The language could also allow the use of

mutate x.next()

as shorthand for

x = x.next()

when only the non-mutating variant `func next() -> Self` exists with compatible 
return type.

> * Can we really introduce this feature without having a way to apply it
>  to class types?

Yes we can. Why complicate the naming of value type members with the 
complexities of reference semantics? The current API naming conventions are 
good for reference types which sometimes come with unobvious to obscure 
behaviour (i.e. anything from bumping an internal counter to firing missiles 
and wiping hard drives).

But value types ought to have no side effects (besides memory allocation and 
logging maybe), and so we don't necessarily need that strong a naming 
convention to limit their collateral damage.

If the `mutate` keyword became required for calling `mutating` methods, then 
operators would remain the only place where naming convention were needed to 
distinguish mutation:

Mutating assignment is explicit: `xs = [1, 2] + xs + [2, 1]` (i.e. `=` without 
`let` or `var` means mutation)
Mutating method call becomes explicit: `mutate xs.sort()` and `let x = mutate 
xs.removeAtIndex(2)`
Mutating function arguments are explicit with the `&` prefix: `swap(, )`
Mutating operators are implicit and by convention, should end with the `=` 
symbol: `xs += [8, 9]`
Reference types have no notion of `mutating` members (and probably ought to 
remain that way) so they mutate implicitly.

> I should also point out that under the assignment method paradigm one
> would probably need to re-evalutate rules for naming.  Under the current
> API guidelines' approach, we'd write:
> 
>x.=sorted()  // sort x in-place
> 
> and I am not sure how easy that would be for people to swallow
> considering how much more straightforward
> 
>x.sort() // current way to sort x in-place
> 
> is, and because the language now contains explicit notation for
> mutation, it becomes harder to argue against theis pair:
> 
>y = x.sort()
>x.=sort()  // sort x in place

I agree that the current API guidelines wouldn't work for value types anymore. 
Both `sort` and `sorted` would be called `sort`.

> Lastly, I 

Re: [swift-evolution] [Proposal] Safer half-open range operator

2016-04-13 Thread Pyry Jahkola via swift-evolution
> On 11 Apr 2016, at 15:23, Luis Henrique B. Sousa via swift-evolution 
>  wrote:
> let a = [1,2,3]
> let b = a[0..<5]
> print(b)
> 

In the swift-3-indexing-model branch 
,
 you can clamp a range just like you could clamp intervals in Swift 2. So the 
following will work in the way you preferred:

let b = a[a.indices.clamped(to: 0 ..< 5)]

It was suggested to extend `Collection` with a subscript like `a[safe: 0 ..< 
5]` which resembles the current subsequence subscript 
.
 Alternatively, we could bring collections even closer to ranges by extending 
them with the equivalent `.clamped(to:)` method:

let b = a.clamped(to: 0 ..< 5) // "safe" subsequence

— Pyry


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


Re: [swift-evolution] [SR-933] Rename flatten to flattened

2016-04-08 Thread Pyry Jahkola via swift-evolution

> On 08 Apr 2016, at 13:19, Haravikk via swift-evolution 
>  wrote:
> 
> I think it makes sense to just rename them; it’s not as though flattened or 
> mapped is somehow far removed from the original meaning as the actual action 
> is the same, it’s just changing tense.

-1, and not only for the reasons we neither call trigonometric functions 
`sine`, `cosine`, and `tangent`. The existing names are widely known, commonly 
taught in modern introductory programming courses, to the point, and googleable.

In addition:

> If we want mutating forms of this methods then I much prefer .map() and 
> .mapped() to .map() and .mapInPlace() or whatever, as the latter contradicts 
> the naming convention used everywhere else which only adds confusion.

This idea of in-place versions is innocuous but absurd. In general, there's no 
way mapping `T -> U` over a `[T]` could possibly accommodate the result in the 
argument of type `[T]`:

var xs: [Int] = ...
xs.mapInPlace {String($0)} // ???

And the same goes for `flatMap`, and `Optional` and others. Likewise, 
`flatten()` couldn't possibly happen in place because the result type has one 
level of nesting less than the argument.

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


Re: [swift-evolution] Feature proposal: Range operator with step

2016-04-06 Thread Pyry Jahkola via swift-evolution

> On 06 Apr 2016, at 23:17, Dave Abrahams via swift-evolution 
>  wrote:
> 
> I don't think you can fix counterintuitive behavior with guidance.  
> 
> (1..<199).striding(by: -2) is the first way I'd reach for to express
> 197, 195, ..., 3, 1

I think a sensible specification would be that with a positive step size, the 
count starts from the lower bound, and with a negative one, it starts from the 
upper bound (inclusive or exclusive). Thus, the following examples should cover 
all the corner cases:

(0 ... 9).striding(by: 2) == [0, 2, 4, 6, 8]
(0 ..< 9).striding(by: 2) == [0, 2, 4, 6, 8]
(0 <.. 9).striding(by: 2) ==[2, 4, 6, 8]
(0 <.< 9).striding(by: 2) ==[2, 4, 6, 8]

(0 ... 9).striding(by: 3) == [0, 3, 6, 9]
(0 ..< 9).striding(by: 3) == [0, 3, 6]
(0 <.. 9).striding(by: 3) ==[3, 6, 9]
(0 <.< 9).striding(by: 3) ==[3, 6]

(0 ... 9).striding(by: -2) == [9, 7, 5, 3, 1]
(0 ..< 9).striding(by: -2) ==[7, 5, 3, 1]
(0 <.. 9).striding(by: -2) == [9, 7, 5, 3, 1]
(0 <.< 9).striding(by: -2) ==[7, 5, 3, 1]

(0 ... 9).striding(by: -3) == [9, 6, 3, 0]
(0 ..< 9).striding(by: -3) ==[6, 3, 0]
(0 <.. 9).striding(by: -3) == [9, 6, 3]
(0 <.< 9).striding(by: -3) ==[6, 3]

Lastly, if you want the positive stride reversed, you'd do just that:

(0 ... 9).striding(by: 2).reverse() == [8, 6, 4, 2, 0]

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


Re: [swift-evolution] [Pitch] Moving where Clauses Out Of Parameter Lists

2016-04-06 Thread Pyry Jahkola via swift-evolution
Joe,

Just from your experience on this topic, is there any reason not to also move 
the primary constraints into the trailing `where` clause?

So instead of what you wrote, we'd have it this way:

func foo(x: T, y: U) -> Result
   where T: Foo, U: Bar, T.Foo == U.Bar /*, etc. */
{
}

…as well as:

struct Foo
   where T: Foo, U: Bar, T.Foo == U.Bar
{
}

Like I said earlier in this thread, I think this would also make the 
`extension` syntax more uniform with types (by turning generic parameters into 
strictly locally visible things):

extension Foo where U == Baz { // (Could've used X and Y here as 
well.)
// Now it's clear where the names T and U come from.
var bazzes: [U] { return ... }
}

— Pyry

> I think this is a good idea, though I would put the `where` clause after the 
> function signature:
> 
> func foo(x: T, y: U) -> Result
>where T.Foo == U.Bar /*, etc. */
> {
> }
> 
> As others noted, it's also appealing to do this for type declarations too:
> 
> struct Foo
>where T.Foo == U.Bar
> {
> }
> 
> and that gives a consistent feeling with extensions and protocol declarations.


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


Re: [swift-evolution] [Pitch] Moving where Clauses Out Of Parameter Lists

2016-04-06 Thread Pyry Jahkola via swift-evolution
> The same would work for generic types  too:
> 
> public struct Dictionary
> where Key : Hashable
> {
>...
> }

And I'm not sure if people feel the same as me, but I haven't been happy with 
the current way generic arguments (such as Key and Value above) magically 
appear in type extensions but are inaccessible from anywhere else and can't be 
made public (`public typealias Key = Key` is an error).

The above syntax would make it possible to use whatever identifiers locally so 
that it's clear what they are:

extension Dictionary
// (unclear if `where K : Hashable` should be repeated here, though)
{
...
}

extension Array
where T : Comparable
{
...
}

extension Array
where T == String
{
...
}

etc.

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


Re: [swift-evolution] [Pitch] Moving where Clauses Out Of Parameter Lists

2016-04-06 Thread Pyry Jahkola via swift-evolution
> On 06 Apr 2016, at 21:30, Developer via swift-evolution 
>  wrote:
> 
> If you've ever gotten to the point where you have a sufficiently generic 
> interface to a thing and you need to constrain it, possibly in an extension, 
> maybe for a generic free function or operator, you know what a pain the 
> syntax can be for these kinds of operations.

+1 already!

> Or, if you're feeling ambitious, even
> 
> func anyCommonElements 
> where T : SequenceType, U : SequenceType,
> T.Generator.Element: Equatable, T.Generator.Element == U.Generator.Element
> (lhs: T, _ rhs: U) -> Bool

I would actually move them as far as after everything else, and right before 
the definition body. For the above function that would mean:

func anyCommonElements(lhs: T, _ rhs: U) -> Bool
where T : SequenceType,
  U : SequenceType,
  T.Generator.Element: Equatable,
  T.Generator.Element == U.Generator.Element
{
...
}

That would make the definition look closer to what the call site looks like.

The same would work for generic types  too:

public struct Dictionary
where Key : Hashable
{
   ...
}

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


Re: [swift-evolution] [Pre-Draft] Nil-coalescing and errors

2016-04-06 Thread Pyry Jahkola via swift-evolution
>>> Interesting, but I’m unsure if all of it is significantly better than just 
>>> using the guard that is effectively inside of the operator/func that is 
>>> being proposed:
>>> 
>>> guard let value = Int("NotANumber") else { throw 
>>> InitializerError.invalidString }
>> 
>> That is a pretty damn compelling argument.

Made me smile too. :-)

> For some cases, yes. For others…

Right. Continuing that thought, Swift is not a language where there's exactly 
one way of doing everything. For `Optional` unwrapping, we have `if let`, 
`guard let`, `x.map(f)`, `x.flatMap(f)`, `x?.member`, `x ?? y`, and a bunch of 
others. The fact that you can already do almost the same thing with a statement 
doesn't rule out the occasional need to do the same thing in just an expression.

But like it was said, it's pretty easy to add this in a user-defined extension 
too, so it remains a question of whether people in general see `x ??? error` or 
`x.orThrow(error)` as a useful thing to have.

>   myInt = Int("NotANumber") ?? throw InitializerError.invalidString

The following works already:

myInt = Int("NotANumber") ?? { throw InitializerError.invalidString }()

(Ping Erica, to the list of alternatives considered.)

> On the other hand, all we really need is a generalized "noneMap" function 
> marked as rethrowing, which can serve multiple purposes.
> 
>   myOtherInt = Int("NotANumber").noneMap(arc4random)
>   myInt = try Int("NotANumber").noneMap { throw 
> InitializerError.invalidString }

If I got it right, you're after this extension:

extension Optional {
func noneMap(ifNone: () throws -> Wrapped) rethrows -> Wrapped {
return try self ?? ifNone()
}
}

Since we have `??` already, I feel `noneMap` isn't different enough to justify 
being added to the standard library.

> On the gripping hand: I think this is only a problem because `throw` is a 
> statement, not an expression. Could it be changed to be an expression with an 
> unspecified return type? I believe that would allow you to simply drop it 
> into the right side of a ?? operator, and anywhere else you might want it 
> (boolean operators, for instance).

Why not. That's essentially making the `x ?? raise(error)` trick into a 
language feature. My guts say people wouldn't like how it looks. Would've 
suggested that as another option otherwise.

All in all, I think the error handling model introduced in Swift 2.0 was pretty 
heavy on syntax compared to how much new functionality it made possible (and 
even now, we don't have catch exhaustiveness checking or asynchronous error 
handling, to name a few). I'd rather improve Swift's error handling by 
introducing features on the library side and only inventing new syntax for 
things that can't be done in code.

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


Re: [swift-evolution] What's the best replacement if "Remove C-style for loops"?

2016-03-19 Thread Pyry Jahkola via swift-evolution
> On 17 Mar 2016, at 14:48, nebulabox via swift-evolution 
>  wrote:
> 
> I have several codes like the following:
> 
> for var i = 0; i < myarr.count; i += n { // the step is NOT 1
>// many codes
> }
> 
> (…) If no C-style for loop,  what's the best replacement for it ?

The stride is what you're looking for:

for i in stride(from: 0, to: myarr.count, by: n) {
// ...
}

In the current Swift release, you'd construct it like this though:

for i in 0.stride(to: myarr.count, by: n) {
// ...
}

— Pyry

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


Re: [swift-evolution] Beef up Imports

2015-12-27 Thread Pyry Jahkola via swift-evolution
> On 27 Dec 2015, at 07:12, Developer via swift-evolution 
>  wrote:
> 
> Therefore, I propose the introduction of 3 agda-esque operations for imports 
> to replace the usual `import {func|typealias|struct|class|enum|etc.}` syntax:
> 
>   • import Foo using (bar, Baz, qux, corge, …)
>   • import Foo hiding (bar, baz, qux, corge, …)
>   • import Foo renaming (grault to garply, waldo to fred, …)

+1, but why not just…?

import Foo using (bar, Baz, qux, waldo as fred)  // a "whitelist import"
import Foo hiding (bar, Baz, qux, waldo as fred) // a "blacklist import"

I've been able to work around identifier conflicts with the present import 
syntax but it gets clumsy with larger modules. I think both import-using and 
import-hiding would be very welcome in Swift, but the third notation made me 
double check its semantics from The Agda Wiki. Turns out 
 
the renaming (...) syntax is actually an extension to the other two and is 
often used as a part of the one or the other:

import Foo using (bar, Baz, qux) renaming (waldo to fred)
import Foo hiding (bar, Baz, qux) renaming (waldo to fred)

Why not do without renaming? Just allow both import-using and import-hiding to 
optionally rename imported identifiers. Further, while these keywords can and 
should be made context-specific, I think it's simplest to reuse "as" as the 
associating keyword.

That would lead us to the proposed syntax:

import Foo using (bar, Baz, qux, waldo as fred)  // a "whitelist import"
import Foo hiding (bar, Baz, qux, waldo as fred) // a "blacklist import"

where the tuple-like parentheses enclose a potentially empty list of 
identifiers or "identifier as identifier" mappings. The examples below should 
clarify the meaning and intended use of these two statements.

> Again, it should be obvious by uniqueness of identifiers what each one is 
> referencing, so qualification of each identifier is unnecessary.


Agreed. In addition, extending the import statement to class/enum/struct 
members doesn't make sense to me. Those don't conflict with the global scope at 
all.

— Pyry Jahkola


P.S. If this turns into a formal proposal, should we also address how imported 
operators should be dealt with? Can operators be selectively imported, hidden, 
or renamed? If renaming is made possible, we should be explicit on how the 
renamed operator inherits its associativity and precedence from the original 
one.


Examples

Suppose the module Foo contains the following identifiers:

// module Foo:
// - bar, Baz, qux, waldo

The "import-all" remains as it is in Swift 2:

import Foo

_ = (bar, Baz.self, qux, waldo) // All identifiers can be unqualified.

The "import-all" is synonymous with the longer "hide-nothing":

import Foo hiding ()

To hide or rename an identifier, fill in the parentheses:

import Foo hiding (Baz, waldo as fred)

_ = (bar, qux, fred)// These names can be unqualified.
_ = (Foo.Baz.self, Foo.waldo)   // These names must be qualified.
_ = Foo.fred// Compiler error!

To import selectively, potentially renaming identifiers, use the import-using 
syntax:

import Foo using (Baz as FooBaz, qux, waldo as fred)

_ = (FooBaz.self, qux, fred)// These names can be unqualified.
_ = (Foo.Baz.self, Foo.bar) // These names must be qualified.

Finally, it's possible to require qualified use of the Foo module:

import Foo using ()

_ = (Foo.bar, Foo.Baz.self, Foo.qux, Foo.waldo) // OK.
_ = (bar, Baz.self, qux, waldo) // Compiler error x 4!

End.


signature.asc
Description: Message signed with OpenPGP using GPGMail
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution