Re: [swift-evolution] Optional Argument Chaining

2017-12-12 Thread Yuta Koshizawa via swift-evolution
I think evaluating them in the same way as `try` calls is consistent.

```
f(g()?, h()?, i(), j()?)?
// like
try f(try g(), try h(), i(), try j())
```

```
foo(bar(x()?)) + y()?
// like
foo(bar(try x())) + (try y())
```

--
Yuta


2017-12-12 7:42 GMT+09:00 Slava Pestov via swift-evolution
:
>
>
> On Dec 11, 2017, at 2:41 PM, Jared Khan via swift-evolution
>  wrote:
>
> I missed the previous threads! I’ve found one of the relevant threads here:
> https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160711/024201.html
>
> Thanks for this important point.
>
> If you were to write this logic out by hand then you would short-circuit it
> and this is analogous to current chaining behaviour so to me evaluating left
> to right (as Swift usually does) and stopping at the first failed unwrap
> would make sense. I wouldn’t necessarily say it’s intuitive but I don’t
> think it’s really less intuitive than the current chaining behaviour.
>
>
> I think it gets confusing when you have multiple levels of nested
> expressions, eg
>
> foo(bar(x?)) + y?
>
> Slava
>
>
> Jared
>
> On 11 Dec 2017, at 19:28, Xiaodi Wu via swift-evolution
>  wrote:
>
> This topic has been discussed at least two and maybe more times in the
> past.. It’s hard for me to post links at the moment, but it should be
> possible to find on Google.
>
> One major challenge to this idea, for which no satisfactory answer has been
> achieved after all these years, is the following issue:
>
> f(g()?, h()?, i(), j()?)?
>
> If g() evaluates to nil, is h() called or not? How about i(), which is not
> failable? Since any function or property access can have side effects, in
> what order are the arguments evaluated, and how does one reason about this
> code flow?
>
> To my mind, in the absence of an intuitive answer to the above—which does
> not appear to be possible—this idea is not feasible.
> On Mon, Dec 11, 2017 at 12:34 Magnus Ahltorp via swift-evolution
>  wrote:
>>
>>
>> > 12 Dec. 2017 02:58 Jared Khan  wrote:
>> >
>> > 2. It felt natural to me. It’s analogous to the existing optional
>> > chaining scenarios and composes nicely. I think it’s about as 
>> > understandable
>> > as existing chaining, a newbie would have to look it up to discover its
>> > meaning. What are your thoughts on this particular syntax (ignoring 3.
>> > momentarily)? Hopefully others in this thread can share their views too.
>>
>> Chaining methods is linear, while nesting fills a similar purpose when we
>> use function calls. This of course affects the way existing Swift code is
>> written, but that is something we have to live with if we want to use
>> familiar syntax patterns. However, I think we have to consider this
>> difference in this case, since the syntax becomes more convoluted. Your
>> suggestion is definitely not as easy to read as the optional chaining
>> syntax, and maybe it can't be.
>>
>> > As for how common I’d expect it to be, it’s something I’ve run into
>> > myself a few times. Again, I hope members of this list can give their view
>> > on if this would be useful to them.
>>
>> I don't have any real examples, but I certainly think that I have run into
>> it, so I'm quite open to solving the problem. For me, it is probably only a
>> matter of finding a syntax that is acceptable.
>>
>> > 3. I’m not entirely sure what the grammar situation is yet but afaik ‘?’
>> > has never been available as a postfix operator. Perhaps I’m missing your
>> > point, could you demonstrate where it is allowed?
>>
>> I did not expect that you would be able to answer that, it was more a
>> question directed to people who are more connected to the inner workings of
>> the parsing of Swift than I am. It is not allowed, but the error message is
>> not the one I expect, something that gives me a hint that it does have some
>> meaning early in the parsing.
>>
>> /Magnus
>>
>> ___
>> 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
>
>
> ___
> 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
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] async void

2017-11-12 Thread Yuta Koshizawa via swift-evolution
Sorry, I had got some confusion. Please let me retry to explain.

As you said, C# provides three kinds of async functions: `async Void`,
`async Task` and `async Task`. All of them are necessary and
Swift should provide same functionalities.

When we think about `async/await` in Swift, because we have already
had `throws/try`, it is desired that `async/await` in Swift is
consistent with `throws/try`. So it is better to have `async/await`
without introducing a type like `Task` (or `Promise`).

Even if we employ `async/await` without `Task`, Swift has to provides
functionalities to implement "three kinds of async functions" in C#.
However if `async -> Void` in Swift works similarly to `async Void` in
C#, how can we express ones like `async Task` in C#? I think there are
two possibilities:

1. Calling `async -> Void` functions without `await` in Swift works
like `async Void` in C# and calling them *with* `await` works like
`async Task` in C#.
2. Calling `async -> Void` functions without `await` in Swift works
like `async Void` in C# and never support something like `async Task`
in C#.

I think 2 is impermissible. For example, handling completion events of
asynchronous operations without result values needs something like
`async Task` in C#. However, with 1, we lose the benefit of static
checks by the compiler. Because both of `fooAsync()` without `await`
and `await fooAsync()` are allowed, even if we want it to work like
`async Task` in C# and forget to mark `await`, the compiler tell us
nothing and it works like `async Void` in C#. It causes unexpected
behaviors. It is hard to fix such kinds of bugs. So I think
introducing `beginAsync` is better.

--
Yuta


2017-11-12 10:23 GMT+09:00 Yuta Koshizawa via swift-evolution
<swift-evolution@swift.org>:
> 2017-11-12 2:57 GMT+09:00 Adam Kemp <adam.k...@apple.com>:
>>
>>
>>> On Nov 11, 2017, at 6:24 AM, Yuta Koshizawa <ko...@koherent.org> wrote:
>>>
>>> If you replace `async` with `throws`, you can get answers.
>>>
>>>
>>>> Can you declare an async closure variable?
>>>
>>> Yes. Like `let throwingClosure:() throws -> Void = { ... }`.
>>>
>>>
>>>> Can a non-async closure be passed to a function expecting a async closure?
>>>
>>> Yes. Like we can pass `() -> Void` to a function expecting a throwing
>>> closure `() throws -> Void`.
>>>
>>> It is possible because `(Foo) throws -> Bar` is a supertype of `(Foo)
>>> -> Bar`. `(Foo) async -> Bar` is a supertype of `(Foo) -> Bar` in the
>>> same way.
>>>
>>> To treat an async function as a sync function is legal. It is similar
>>> to make a `Promise` by `Promise(value)` which is completed
>>> immediately.
>>>
>>>
>>>> Can an async closure be passed to a function expecting a non-async closure?
>>>
>>> No. `() -> Void` is a subtype of `() async -> Void`. It is same as
>>> passing `() throws -> Void` to a function expecting `() -> Void` is
>>> not allowed.
>>
>> But why not? Just asserting that it must work the same as throws
>> is not a convincing argument. You have to justify why it must work
>> that way. I think there is good reason to allow it, which I have described.
>> What reason is there to disallow it?
>
> `() async -> Void` needs to be called with `await` because it prevents
> us from forgetting handling asynchronous operations.
>
> If we use callbacks to handle asynchronous operations, it is shown to
> us by a compiler as a compilation error.
>
> ```
> func fooAsync(_ handler: () -> Void) -> Void { ... }
>
> fooAsync() // compilation error
>
> fooAsync {
>   // handles a completion event here
> }
> ```
>
> With proposed `async/await`, it is realized similarly like below.
>
> ```
> func fooAsync() async -> Void { ... }
>
> fooAsync() // compilation error
>
> await fooAsync()
> // handles a completion event here
> ```
>
> However, if async void functions work like `beginAsync`, we can easily
> forget it and it can cause unexpected behaviors.
>
> ```
> func fooAsync() async -> Void { ... }
>
> fooAsync() // OK
> // hard to know this line is executed asynchronously
> ```
>
> Readability also suffers seriously. If we don't know `bar` in the
> following code is a async function, it is impossible to expect lines
> after `baz()` are executed asynchronously.
>
> ```
> foo()
> bar()
> baz()
> qux()
> ```
>
>
>>>> It’s weird to me that we would allow you to have async void closures but 
>>>> not async void functions
>>>
>>> I am not sure wha

Re: [swift-evolution] async void

2017-11-11 Thread Yuta Koshizawa via swift-evolution
2017-11-12 2:57 GMT+09:00 Adam Kemp :
>
>
>> On Nov 11, 2017, at 6:24 AM, Yuta Koshizawa  wrote:
>>
>> If you replace `async` with `throws`, you can get answers.
>>
>>
>>> Can you declare an async closure variable?
>>
>> Yes. Like `let throwingClosure:() throws -> Void = { ... }`.
>>
>>
>>> Can a non-async closure be passed to a function expecting a async closure?
>>
>> Yes. Like we can pass `() -> Void` to a function expecting a throwing
>> closure `() throws -> Void`.
>>
>> It is possible because `(Foo) throws -> Bar` is a supertype of `(Foo)
>> -> Bar`. `(Foo) async -> Bar` is a supertype of `(Foo) -> Bar` in the
>> same way.
>>
>> To treat an async function as a sync function is legal. It is similar
>> to make a `Promise` by `Promise(value)` which is completed
>> immediately.
>>
>>
>>> Can an async closure be passed to a function expecting a non-async closure?
>>
>> No. `() -> Void` is a subtype of `() async -> Void`. It is same as
>> passing `() throws -> Void` to a function expecting `() -> Void` is
>> not allowed.
>
> But why not? Just asserting that it must work the same as throws
> is not a convincing argument. You have to justify why it must work
> that way. I think there is good reason to allow it, which I have described.
> What reason is there to disallow it?

`() async -> Void` needs to be called with `await` because it prevents
us from forgetting handling asynchronous operations.

If we use callbacks to handle asynchronous operations, it is shown to
us by a compiler as a compilation error.

```
func fooAsync(_ handler: () -> Void) -> Void { ... }

fooAsync() // compilation error

fooAsync {
  // handles a completion event here
}
```

With proposed `async/await`, it is realized similarly like below.

```
func fooAsync() async -> Void { ... }

fooAsync() // compilation error

await fooAsync()
// handles a completion event here
```

However, if async void functions work like `beginAsync`, we can easily
forget it and it can cause unexpected behaviors.

```
func fooAsync() async -> Void { ... }

fooAsync() // OK
// hard to know this line is executed asynchronously
```

Readability also suffers seriously. If we don't know `bar` in the
following code is a async function, it is impossible to expect lines
after `baz()` are executed asynchronously.

```
foo()
bar()
baz()
qux()
```


>>> It’s weird to me that we would allow you to have async void closures but 
>>> not async void functions
>>
>> I am not sure what you mean. "async void closures" and "async void
>> functions" have a same type. Following two are almost same.
>>
>> ```
>> func foo() async -> Void { ... }
>> let foo: () async -> Void = { ... }
>> ```
>
> What started this thread is my suggestion that you should be able to write
> an async void function. The current proposal doesn’t allow that. That’s why
> you have to use beginAsync.
>
> I don’t think that makes sense. It sounds like you also think that would be 
> strange,
> hence your assumption that you could.

By the reasons I wrote above, we need `await` even for async void
functions for checks by compilers. Then it is required to provide a
way to write entry points of async functions. That is `beginAsync`.

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


Re: [swift-evolution] async void

2017-11-11 Thread Yuta Koshizawa via swift-evolution
If you replace `async` with `throws`, you can get answers.


> Can you declare an async closure variable?

Yes. Like `let throwingClosure:() throws -> Void = { ... }`.


> Can a non-async closure be passed to a function expecting a async closure?

Yes. Like we can pass `() -> Void` to a function expecting a throwing
closure `() throws -> Void`.

It is possible because `(Foo) throws -> Bar` is a supertype of `(Foo)
-> Bar`. `(Foo) async -> Bar` is a supertype of `(Foo) -> Bar` in the
same way.

To treat an async function as a sync function is legal. It is similar
to make a `Promise` by `Promise(value)` which is completed
immediately.


> Can an async closure be passed to a function expecting a non-async closure?

No. `() -> Void` is a subtype of `() async -> Void`. It is same as
passing `() throws -> Void` to a function expecting `() -> Void` is
not allowed.


> It’s weird to me that we would allow you to have async void closures but not 
> async void functions

I am not sure what you mean. "async void closures" and "async void
functions" have a same type. Following two are almost same.

```
func foo() async -> Void { ... }
let foo: () async -> Void = { ... }
```

--
Yuta


2017-11-11 11:02 GMT+09:00 Adam Kemp <adam_k...@apple.com>:
> I’m not sure that answered my questions.
>
> Can I do this?
>
> let asyncClosure:() async -> Void = { await doSomethingAsync() } // Can you
> declare an async closure variable?
>
> beginAsync(asyncClosure)
>
>
> What about this?
>
> let syncClosure:() -> Void = { doSomethingSync() }
>
> beginAsync(syncClosure) // Can a non-async closure be passed to a function
> expecting a async closure?
>
>
> And this?
>
>
> func callSyncClosure(_ closure:() -> ()) { closure() }
>
>
> let asyncClosure:() async -> Void = { await doSomethingAsync() }
>
>
> callSyncClosure(asyncClosure) // Can an async closure be passed to a
> function expecting a non-async closure?
>
>
> Here are my thoughts on each of these:
>
> Can you declare an async closure variable? If async is part of the type then
> it would be very strange not to allow this. I think the proposal implies
> that you can, but only by way of an example about inferring whether a
> closure is async or not.
>
> Can a non-async closure be passed to a function expecting a sync closure?
> This seems like an obvious conversion. I feel like disallowing this would
> probably make things harder, but I haven’t thought it through enough to say
> exactly how. Are there reasons that this shouldn’t work, though?
>
> Can an async closure be passed to a function expecting a sync closure? This
> may be controversial, but I think this should be allowed too. I think a
> caller that expects a void-returning synchronous function should be able to
> call an async function and treat it as a call-and-forget.
>
> It’s weird to me that we would allow you to have async void closures but not
> async void functions, but in order to support beginAsync we have to have
> async void closures. So if we can make that work then why couldn’t we just
> make async void functions work and dispense with beginAsync entirely?
>
> On Nov 10, 2017, at 1:38 AM, Yuta Koshizawa via swift-evolution
> <swift-evolution@swift.org> wrote:
>
> I’m not sure how the proposed design handles type checking for async
> closures. Is async part of the type? Can I declare a local closure variable
> as async? What are the rules for conversion between async and non-async
> closures? Is it a warning or error to use a closure literal without an async
> keyword that is assigned to an async closure variable or passed as an async
> closure argument?
>
>
> It has been already realized for `throws`.
>
> ```
> // This works in Swift 4
> func foo(_ f: (Bar) throws -> Baz)
>
> // This can be checked in the same way
> func foo(_ f: (Bar) async -> Baz)
> ```
>
> Proposed `async/await` in Swift are analogous to `throws/try`. So a
> lot of things about `async/await` can be imagined when we think about
> `throws/try`. It is also true for `(Foo) async -> Void`. We can use it
> in the same way as we use `(Foo) throws -> Void`.
>
> `async/await` as an analogy to `throws/try` works well because both of
> them can be mapped to monads. `throws` is similar to `Result` and
> `async` is similar to `Promise` ( `Future` ).
>
> ```
> // `a` and `b` are similar
> func a() throws -> Int
> func b() -> Result
>
> // `c` and `d` are similar
> func c() async -> Int
> func d() -> Promise
>
> // `a` : `b` == `c` : `d`
> // `a` : `c` == `b` : `d`
> ```
>
> `try` and `await` are also similar to `flatMap`. ( I think most
> p

Re: [swift-evolution] async void

2017-11-10 Thread Yuta Koshizawa via swift-evolution
> I’m not sure how the proposed design handles type checking for async
> closures. Is async part of the type? Can I declare a local closure variable
> as async? What are the rules for conversion between async and non-async
> closures? Is it a warning or error to use a closure literal without an async
> keyword that is assigned to an async closure variable or passed as an async
> closure argument?

It has been already realized for `throws`.

```
// This works in Swift 4
func foo(_ f: (Bar) throws -> Baz)

// This can be checked in the same way
func foo(_ f: (Bar) async -> Baz)
```

Proposed `async/await` in Swift are analogous to `throws/try`. So a
lot of things about `async/await` can be imagined when we think about
`throws/try`. It is also true for `(Foo) async -> Void`. We can use it
in the same way as we use `(Foo) throws -> Void`.

`async/await` as an analogy to `throws/try` works well because both of
them can be mapped to monads. `throws` is similar to `Result` and
`async` is similar to `Promise` ( `Future` ).

```
// `a` and `b` are similar
func a() throws -> Int
func b() -> Result

// `c` and `d` are similar
func c() async -> Int
func d() -> Promise

// `a` : `b` == `c` : `d`
// `a` : `c` == `b` : `d`
```

`try` and `await` are also similar to `flatMap`. ( I think most
popular `Promise` is one in JavaScript. Although it does not have
`flatMap`, its `then` method can be considered as `flatMap`. )

```
let x = try a()
// uses `x` here

b().flatMap { x in
  // uses `x` here
}

let y = await c()
// uses `y` here

d().flatMap { y in
  // uses `y` here
}
```

So `throws` : `try` : `Result` == `async` : `await` : `Promise` and
`throws` : `async` == `try` : `await` == `Result` : `Promise`. I think
those relations are beautiful and proposed `async/await` fits well to
Swift because we have already had `throws/try`.

--
Yuta


2017-11-10 6:45 GMT+09:00 Adam Kemp via swift-evolution
:
>
> On Nov 9, 2017, at 11:02 AM, Wallacy  wrote:
>
> So for me, this:
>
> func OnButtonClicked(_ sender:AnyObject) {
>
> let button = sender as! UIButton
> button.isEnabled = false
> beginAsync {
> await DoSomethingAsync()
> button.isEnabled = true
> }
> }
>
>
> Does not make any sense... Because await will not block the thread we can
> assume (like the exemple on proposal) that compiler will actually do the
> same what we will do using GDC and pick everyone to until the context ends
> and encapsulate as completion handle to the away call.
>
>
> I don’t understand what you’re saying here. In terms of GCD the above code
> is basically equivalent to this:
>
> func buttonClicked(_ sender:AnyObject) {
> let button = sender as! UIButton
> button.isEnabled = false
> doSomethingAsync { // completion callback, assume it’s on the main queue
> button.isEnabled = true
> }
> }
>
>
> And this one:
>
> @IBAction func buttonDidClick(sender:AnyObject) {
>   beginAsync {
> let image = await processImageData()
> // Do the update on the main thread/queue since it owns imageView.
> mainQ.async {
>   imageView.image = image
> }
>   }
> }
>
>
>
> Does not make any sense too.
>
> The only way to await to do not block the thread is make a early return like
> beginAsync and encapsulate as completion handle the rest of the code.
>
>
> This is why “await” can only be used in a function that is marked as
> “async”. The “async” keyword tells the compiler that this function will be
> broken up into parts, and its return value will be produced asynchronously.
>
> One thing that might be confusing is that in the examples using “beginAsync”
> the trailing closure is the async function. That’s not obvious because
> there’s no “async” keyword, but it’s there in the signature of the closure
> argument:
>
> func beginAsync(_ body: () async throws -> Void) rethrows -> Void
>
>
> I’m not sure how the proposed design handles type checking for async
> closures. Is async part of the type? Can I declare a local closure variable
> as async? What are the rules for conversion between async and non-async
> closures? Is it a warning or error to use a closure literal without an async
> keyword that is assigned to an async closure variable or passed as an async
> closure argument?
>
> C# dodges all of these issues because async isn't part of the type system.
> Closures that don’t return anything can be declared async just like void
> functions, and code that uses void-returning closures doesn’t need to care
> whether the implementation is async or not.
>
>
>
> ___
> 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


[swift-evolution] [Question] Why does `beginAsync` rethrow errors?

2017-11-07 Thread Yuta Koshizawa via swift-evolution
Although I posted about this topic before, let me post this again
because I think it is important and I have received just few replies.
Sorry if I missed some discussion about it.

In the proposal (
https://gist.github.com/lattner/429b9070918248274f25b714dcfc7619 ),
`beginAsync` has the following signature.

```
func beginAsync(_ body: () async throws -> Void) rethrows -> Void
```

However, I think it is better to forbid `body` to throw errors, that
is to say, to change its signature to the following one.

```
func beginAsync(_ body: () async -> Void) -> Void
```

Even if `beginAsync` allows that `body` throws errors, it can rethrow
ones which are thrown before only first `await` call. In following
cases, `beginAsync` just has to make the program crash when `foo`
throws an error. It breaks safety for error handing by typed
propagation realized by `throws/try`.

```
// throws errors asynchronously
func foo() async throws -> Int { ... }

do {
beginAsync {
let a = try await foo()
// uses `a` here
}
} catch _ {
// never reaches here
}
```

If `beginAsync` forbid `body` to throw errors, it can be detected as a
compilation error and is possible to fix it as follows.

```
beginAsync {
do {
let a = try await foo()
// uses `a` here
} catch _ {
//  error handling
}
}
```

And even when we want to write `try` calls in `beginAsync` before
first `await` call, those lines can be moved before the `beginAsync`
call.

```
// before ( `beginAsync` marked with `rethrows` )
do {
beginAsync {
let a = try bar()
let b = try baz()
let c = await qux(a, b)
// uses `c` here
}
catch _ {
// error handling
}

// after ( `beginAsync` without `rethrows` )
do {
let a = try bar()
let b = try baz()
beginAsync {
let c = await qux(a, b)
// uses `c` here
}
catch _ {
// error handling
}
```

So the functionalities of `beginAsync` seems be kept even if it forbid
`body` to throw errors.

What do you think about it?

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


Re: [swift-evolution] Two thoughts on concurrency

2017-08-24 Thread Yuta Koshizawa via swift-evolution
Hi,

Although `throws` and `async` are similar to return a `Result` and a
`Future` respectively as you say, However, `try` and `await` are
corresponding to `flatMap` theoretically.

// `throws/try`
func foo() throws -> Int { ... }

func bar() throws -> Int {
  let a: Int = try foo()
  let b: Int = try foo()
  return a + b
}

// `Result`
func foo() -> Result { ... }

func bar() -> Result {
  return foo().flatMap { a: Int in
foo().flatMap { b: Int in
  return a + b
}
  }
}

// `async/await`
func foo() async -> Int { ... }

func bar() async -> Int {
  let a: Int = await foo()
  let b: Int = await foo()
  return a + b
}

// `Future`
// `flatMap` works like `then` of JS's `Promise`
// I have an implementation of such `Promise` in Swift
// https://github.com/koher/PromiseK/tree/dev-3.0
func foo() -> Future { ... }

func bar() -> Future {
  return foo().flatMap { a: Int in
foo().flatMap { b: Int in
  return a + b
}
  }
}

Also, thinking about something like `do/catch` for `async/await`, I
think `do` for blocking is consistent because it should be possible to
return a value from inside `do {}` as well as `do/catch`. For example:

// `throws/try`
func bar() -> Int {
  do {
return try foo()
  } catch {
...
  }
}

// `async/await`
func bar() -> Int {
  do {
return await foo()
  } block
}

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


Re: [swift-evolution] [Concurrency] async/await + actors

2017-08-22 Thread Yuta Koshizawa via swift-evolution
>> On Aug 21, 2017, at 1:56 PM, John McCall  wrote:
>>
>> Personally, I think these sources of confusion are a good reason to keep the 
>> feature separate.
>>
>> The idea of using await! to block a thread is interesting but, as you say, 
>> does not fit with the general meaning of ! for logic errors.  I think it's 
>> fine to just have an API to block waiting for an async operation, and we can 
>> choose the name carefully to call out the danger of deadlocks.
>>
>> John.
>
> 2017-08-22 5:08 GMT+09:00 Karim Nassar :
>
> Thought about it in more depth, and I’m now firmly in the camp of: 
> ‘throws’/‘try' and ‘async’/‘await' should be orthogonal features. I think the 
> slight call-site reduction in typed characters ('try await’ vs ‘await’) is 
> heavily outweighed by the loss of clarity on all the edge cases.
>
> —Karim


I agree.

1. `async(nonthrowing)` and `async` as a subtype of `throws` can be an
obstacle when we want to add the third effect following `throws` and
`async` though I think `async(nonthrowing)` is an interesting idea.
Assuming that the new effect is named `foos`, we may want
`async(nonfooing)` or to make `async` be a subtype of `foos`. But it
is hard because they are destructive. We need to modify all code which
uses `async`. However, it is inconsistent with `throws` to give up
them and make `foos` orthogonal to `async`.

2. It is also true for `throws`. If we had introduced `async/await`
before `throws/try` were introduced, it would be hard to introduce
`async(nonthrowing)`  or `async` as a subtype of `throws` because they
are destructive. (Although `async/await` without `throws/try` seems
impractical, it is not impossible by something like `func bar() async
-> Result`)

So I think `async` and `throws` are essentially orthogonal, and just
factually used together in most cases. I guess choosing the essential
one will keep the language simpler and prevent unexpected problems in
the future.

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


Re: [swift-evolution] [Concurrency] async/await + actors

2017-08-20 Thread Yuta Koshizawa via swift-evolution
2017-08-21 2:20 GMT+09:00 John McCall via swift-evolution <
swift-evolution@swift.org>:

> On Aug 19, 2017, at 7:17 PM, Chris Lattner via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> On Aug 19, 2017, at 8:14 AM, Karim Nassar via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> This looks fantastic. Can’t wait (heh) for async/await to land, and the
> Actors pattern looks really compelling.
>
> One thought that occurred to me reading through the section of the
> "async/await" proposal on whether async implies throws:
>
> If ‘async' implies ‘throws' and therefore ‘await' implies ‘try’, if we
> want to suppress the catch block with ?/!, does that mean we do it on the
> ‘await’ ?
>
>
> guard let foo = await? getAFoo() else {  …  }
>
>
> Interesting question, I’d lean towards “no, we don’t want await? and
> await!”.  My sense is that the try? and try! forms are only occasionally
> used, and await? implies heavily that the optional behavior has something
> to do with the async, not with the try.  I think it would be ok to have to
> write “try? await foo()” in the case that you’d want the thrown error to
> turn into an optional.  That would be nice and explicit.
>
>
> try? and try! are quite common from what I've seen.
>

As analogous to `throws` and `try`, I think we have an option that `await!`
means blocking.

First, if we introduce something like `do/catch` for `async/await`, I think
it should be for blocking. For example:

```
do {
  return await foo()
} block
```

It is consistent with `do/try/catch` because it should allow to return a
value from inside `do` blocks for an analogy of `throws/try`.

```
// `throws/try`
func foo() -> Int {
  do {
return try bar()
  } catch {
...
  }
}

// `async/await`
func foo() -> Int {
  do {
return await bar()
  } block
}
```

And `try!` is similar to `do/try/catch`.

```
// `try!`
let x = try! foo()
// uses `x` here

// `do/try/catch`
do {
  let x = try foo()
  // uses `x` here
} catch {
  fatalError()
}
```

If `try!` is a sugar of `do/try/catch`, it also seems natural that `await!`
is a sugar of `do/await/block`. However, currently all `!` in Swift are
related to a logic failure. So I think using `!` for blocking is not so
natural in point of view of symbology.

Anyway, I think it is valuable to think about what `do` blocks for
`async/await` mean. It is also interesting that thinking about combinations
of `catch` and `block` for `async throws` functions: e.g. If only `block`,
the enclosing function should be `throws`.

That aside, I think `try!` is not so occasional and is so important. Static
typing has limitations. For example, even if we has a text field which
allows to input only numbers, we still get an input value as a string and
parsing it may fail on its type though it actually never fails. If we did
not have easy ways to convert such a simple domain error or a recoverable
error to a logic failure, people would start ignoring them as we has seen
in Java by `catch(Exception e) {}`. Now we have `JSONDecoder` and we will
see much more `try!` for bundled JSON files in apps or generated JSONs by
code, for which decoding fails as a logic failure.

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


Re: [swift-evolution] [Concurrency] async/await + actors

2017-08-18 Thread Yuta Koshizawa via swift-evolution
`beginAsync(_:)` is a sort of poor man's `Future`—it guarantees that the
async function will start, but throws away the return value, and *might*
throw away the error unless it happens to get thrown early. Given that its
ability to return information from the body is so limited, I frankly don't
think it's worth making this function rethrow only some errors. I would
instead make it accept only a non-throwing `async` function, and if you
need to call something that throws, you can pass an async closure with a
`do`/`catch` block.


I agree. I think `rethorws` for `beginAsync` is problematic.

For example, what happens when the `foo` in the following code throws an
`Error` asynchronously?

func foo() async throws { ... }
beginAsync(foo)

`foo` is acceptable as `beginAsync`'s `body` by its type. However its error
might be thrown asynchronously and it is impossible to rethrow it. So the
error must be ignored or treated as an universal error by untyped
propagation. It breaks type safety about error handling.

So I think the signature of `beginAsync` should be the following one.

func beginAsync(_ body: () async -> Void) -> Void

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


Re: [swift-evolution] [Concurrency] async/await + actors

2017-08-18 Thread Yuta Koshizawa via swift-evolution
Hi, I have a question about the proposed `async/await`.

Are `throws async` and `await try` allowed? I think we have three options.

1. allows only `async throws`-`try await`
2. allows both `async throws`-`try await` and `throws async`-`await try`
and does not distinguish them
3. allows both and distinguishes them like `Promise` and
`Result`

Although 3 is the most expressive, I think it is too complicated. In most
cases we need only something similar to `Promise`. To select 1
also makes it possible to support 3 in the future. So 1 seems a good choice
to me.

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


Re: [swift-evolution] [Concurrency] async/await + actors

2017-08-17 Thread Yuta Koshizawa via swift-evolution
I think we also need `reasync` like `rethrows`.


Sorry, I found it was referred in "rethrows could be generalized to support
potentially async operations".

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


Re: [swift-evolution] [Concurrency] async/await + actors

2017-08-17 Thread Yuta Koshizawa via swift-evolution
I think we also need `reasync` like `rethrows`.

extension Sequence {
func map(_ transform: (Element) async throws -> T) reasync
rethrows -> [T] { ... }
}

let urls: [URL] = ...
let foos: [Foo] = await try urls.map { await try downloadFoo($0) }

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


Re: [swift-evolution] [Pitch] range.contains(anotherRange)

2017-08-09 Thread Yuta Koshizawa via swift-evolution
I am not sure if removing initializers from `SetAlgebra` does not cause any
problems in the standard library, it seems reasonable for me if range types
could adopt `SetAlgebra`.


`SetAlgebra` contains some mutating methods like `insert`, `remove`,
`formUnion`. It means it is impossible for range types to adopt
`SetAlgebra`. In addition, even if we remove such methods from
`SetAlgebra`, because the return type of something like `union` is `Self`,
`2..3.union(5...7)` cannot be represented.

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


Re: [swift-evolution] [Pitch] range.contains(anotherRange)

2017-08-09 Thread Yuta Koshizawa via swift-evolution
2017-08-09 12:50 GMT+09:00 Robert Bennett :


It’s a shame that Range can’t be made to conform to SetAlgebra as it lacks
the required initializers. Is there anything that can be done about this?
Actually, it makes me wonder whether those initializers should even be a
part of SetAlgebra — why must something implementing SetAlgebra be able to
be initialized as empty or from a finite sequence?


I am not sure if removing initializers from `SetAlgebra` does not cause any
problems in the standard library, it seems reasonable for me if range types
could adopt `SetAlgebra`.

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


Re: [swift-evolution] [Pitch] range.contains(anotherRange)

2017-08-08 Thread Yuta Koshizawa via swift-evolution
2017-08-09 12:23 GMT+09:00 Xiaodi Wu :

>
For consistency, the name for this function would be `isSuperset(of:)`, and
it would be equally interesting to have `isStrictSuperset(of:)`,
`isSubset(of:)`, `isStrictSubset(of:)` and `isDisjoint(with:)`--all
currently available for types that conform to `SetAlgebra`.


Thank you for your feedback. It certainly seems better to rename `contains`
to `isSuperset(of:)`. Also I'll try to implement `isStrictSuperset(of:)`
and so on.

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


[swift-evolution] [Pitch] range.contains(anotherRange)

2017-08-08 Thread Yuta Koshizawa via swift-evolution
Hi,

Recently I needed to implement `contains` methods to check if a range
contains another range. I think those are basic operations and suitable for
the standard library.

Although it may seem easy to implement such `contains` methods whenever we
need them, their precise specifications are too complicated to do so.

e.g.

let a: ClosedRange = 2...7
a.contains(3...5) // `true`
a.contains(3...7) // also `true`
a.contains(3..<8) // still `true` because all values contained in `3..<8`
are also in `a`
a.contains(3..<9) // `false`

let b: ClosedRange = 2...7
b.contains(3...5) // `true`
b.contains(3...7) // `true`
b.contains(3..<8) // `false` because { x | 7.0 < x < 8.0 } is not contained
in `a`

let c: Range = 2..<7
c.contains(3...5) // `true`
c.contains(3..<7) // `true`
c.contains(3...7) // `false` because 7.0 is not contained in `a`

My experimental implementation is here:
https://github.com/koher/range-contains
(Currently does not support one-sided ranges)

What are your thoughts about them?

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


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

2017-06-29 Thread Yuta Koshizawa via swift-evolution
"In -Ounchecked builds, the optimizer may assume that this function is
never called. Failure to satisfy that assumption is a serious programming
error.”


Yes, and so the following `!!` can perform identically to `!` in
-Ounchecked builds when it is inlined.

public static func !!(optional: Optional, errorMessage: @autoclosure () ->
String) -> Wrapped { precondition(optional != nil, errorMessage()) return
optional! }

--
Yuta


2017-06-29 6:42 GMT+09:00 Jaden Geller <jaden.gel...@gmail.com>:

>
> > On Jun 28, 2017, at 7:47 AM, Erica Sadun via swift-evolution <
> swift-evolution@swift.org> wrote:
> >
> >
> >> On Jun 28, 2017, at 3:52 AM, Yuta Koshizawa via swift-evolution <
> swift-evolution@swift.org> wrote:
> >>
> >> Hi, I think it is an orthogonal issue if we need a new operator. It is
> >> also possible to introduce an infix `!` for it.
> >>
> >> I am sure that we do not need to avoid `precondition` as long as we
> >> use it appropriately. It is useful to realize consistent behavior with
> >> `Array`'s `subscript`, forced unwrapping `!`, `&+` and so on. In this
> >> context, `precondition` does not mean a general word "precondition"
> >> but the `precondition` function in the Swift standard library, which
> >> is removed when -Ounchecked.
> >
> >
> > How would the line run then? Would it simply act as a forced unwrapped
> under -Ounchecked?
>
> From the docs:
>
> "In -Ounchecked builds, the optimizer may assume that this function is
> never called. Failure to satisfy that assumption is a serious programming
> error.”
>
> Aka, v. bad things happen if the precondition does not hold.
>
> >
> > -- E
> >
> > ___
> > 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] Introducing the "Unwrap or Die" operator to the standard library

2017-06-28 Thread Yuta Koshizawa via swift-evolution
Hi, I think it is an orthogonal issue if we need a new operator. It is
also possible to introduce an infix `!` for it.

I am sure that we do not need to avoid `precondition` as long as we
use it appropriately. It is useful to realize consistent behavior with
`Array`'s `subscript`, forced unwrapping `!`, `&+` and so on. In this
context, `precondition` does not mean a general word "precondition"
but the `precondition` function in the Swift standard library, which
is removed when -Ounchecked.

However I noticed the possibility that -Ounchecked removed the `nil`
check by `??` in the following code using `preconditionFailure` as a
clue of the optimization.

let bar: Foo = optionalFoo ?? preconditionFailure("Reason why you
are sure that `optionalFoo` is not nil")

So now I think using `?? preconditionFailure(message)` with `Never` as
a bottom type is preferable to `!!` even in a standpoint of
-Ounckecked.

--
Yuta


2017-06-28 15:52 GMT+09:00 Elviro Rocca <retired.hunter.dj...@gmail.com>:
> Yep, "logic" failures are not supposed to be there if not for avoiding
> checks that could worsen performance in pieces of code that should run as
> fast as possible. I like Adrian's solution because it doesn't add a new
> operator to the standard library, something that could mean one more
> encouragement to force unwrap things.
>
> About preconditions, Cocoa with Love's Matt Gallagher wrote an article some
> months ago on partial functions, why you should avoid them and how to do so:
> it's a very interesting read
> http://www.cocoawithlove.com/blog/2016/01/25/partial-functions-part-one-avoidance.html
>
>
> Elviro
>
> Il giorno 28 giu 2017, alle ore 07:02, Yuta Koshizawa via swift-evolution
> <swift-evolution@swift.org> ha scritto:
>
> ...
>
> Logic failures are intended to be handled by fixing the code. It means
> checks of logic failures can be removed if the code is tested enough.
> Actually checks of logic failures for various operations, `!`,
> `array[i]`, `&+` and so on, are designed and implemented to be removed
> when we use `-Ounchecked`. It is useful for heavy computation like
> image processing and machine learning in which overhead of those
> checks is not permissible.
>
> So I think checks for `!!` should be removed with `-Ounchecked` as well.
>
> --
> Yuta
>
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


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

2017-06-27 Thread Yuta Koshizawa via swift-evolution
I like it, but I think the implementation can be improved like below.

public static func !!(optional: Optional, errorMessage:
@autoclosure () -> String) -> Wrapped {
precondition(optional != nil, errorMessage())
return optional!
}

Failures of forced unwrapping are "logic failures" and I think it is
same about `!!`.

https://github.com/apple/swift/blob/master/docs/ErrorHandlingRationale.rst#logic-failures

Logic failures are intended to be handled by fixing the code. It means
checks of logic failures can be removed if the code is tested enough.
Actually checks of logic failures for various operations, `!`,
`array[i]`, `&+` and so on, are designed and implemented to be removed
when we use `-Ounchecked`. It is useful for heavy computation like
image processing and machine learning in which overhead of those
checks is not permissible.

So I think checks for `!!` should be removed with `-Ounchecked` as well.

--
Yuta


2017-06-28 2:16 GMT+09:00 Erica Sadun via swift-evolution
:
> Using an operator to provide feedback on the context of a failed unwrap has
> become a commonly implemented approach in the Swift developer Community.
> What are your thoughts about adopting this widely-used operator into the
> standard library?
>
> guard !lastItem.isEmpty else { return }
> let lastItem = array.last !! "Array must be non-empty"
>
> Details here:
> https://gist.github.com/erica/423e4b1c63b95c4c90338cdff4939a9b
>
> Thank you for your thoughtful feedback, -- E
>
>
> ___
> 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] Never as a bottom type

2017-05-14 Thread Yuta Koshizawa via swift-evolution
Joe also referred to the following model in a thread about Typed Throws.

() -> () == () throws Never -> ()
() throws -> () == () throws Error -> ()

https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170213/032267.html

It means `Never` must be a subtype of `Error`. I think it is an
interesting use case of "Never as bottom type".


2017-05-15 7:27 GMT+09:00 André Videla via swift-evolution
:
> Hi Swift-Evolution,
>
> At the end of SE-0102
> (https://github.com/apple/swift-evolution/blob/master/proposals/0102-noreturn-bottom-type.md)
> it is mentioned that the Never type could be used as a universal bottom type
> but that is currently not the case.
>
> As of today the Never type is used as a return type of `fatalError` and as
> function which do not return by the virtue of calling `fatalError`.
> This allows for very useful behaviours for example:
>
> let anything: Any = …
>
> switch anything {
> case let view as UIView: …
> case let str as String: …
> default: fatalError("we got an unexpected type")
> }
>
> But it has its limits, most notably, it cannot be used as an expression
>
> let dunno: Int = fatalError("what should I put here?") // cannot convert
> value of type 'Never'
>
> It makes sense because Never is not a bottom type. If it were, this
> statement would be absolutely valid.
>
> Having a bottom type and a value for it has several advantages:
>
> - More informative error messages with forced unwrap:
>
> protocol WonkyAPI {
> func apiCall() -> Int? //this always return an Int, why is it optional?
> }
>
> func mycode() {
> let valueFromAPI = apiCall() ?? fatalError("The API used to always
> return a value, but now it does not!")
> …
> }
>
> It sometimes happen that some part of the code uses an optional but in your
> particular codepath, the optional is always containing a value (for example
> after an assignment).
> As of today, you can write
> guard let value = value else { fatalError("something terrible happened") }
> for the same effect with a more verbose syntax.
>
> - Use as a hole/placeholder during development
> During development it is very likely that you will want to write a piece of
> functionality but be stuck on an intermediate part of the computation.
> Assume we have an identifier `undefined` of type `Never` which would
> represent an impossible value as a bottom type. We would ben able to write:
>
> func transform(point: CGPoint) -> CGPoint {
> let translation =  Matrix3D(1, 0, 2,
> 0, 1, -2,
> 0, 0, 1)
> let rotation: Matrix3D = undefined //what was it? I forgot
> return (translation * rotation * point.homogenous).toPoint()
> }
>
> We can debate on the right naming for undefined. Haskell uses 'undefined',
> Scala uses `???`. `unimplemented`, `impossible`, `void`are all valid
> contenders.
>
> - Eliminate type annotations for generic covariant types
> As of today this is not valid
>
> struct Person {
> let name: String
> }
>
> var maybeSomeone = nil
> maybeSomeone = Person(name: "Doug”)
>
> Even though it is clear that maybeSomeone is of type Optional.
> That is because the compiler cannot guess which type the Optional wraps when
> `maybeSomeone` is declared. But with a bottom type, a naked nil can be
> mapped to `Optional` until the type inference figures out from the
> context what is the type of Optional. If it cannot because no use or no
> assignment is done, the compiler could emit an “unreachable” warning just
> like it does for
>
> func unreach() {
> fatalError("stop here")
> print("not printed”) // warning: will never be executed
> }
>
> Should I write a proposal?
>
> André Videla
>
> ___
> 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] [SHORT Review] SE-0133: Rename `flatten()` to `joined()`

2016-07-25 Thread Yuta Koshizawa via swift-evolution
> What is your evaluation of the proposal?

-1

- Certainly `flatten` and `joined` work similarly. I think, however,
the concepts behind them are different. When I use `flatten`, I want
to make nested monads flat. When I use `joined`, I want to concatenate
sequences, mainly `String`s, with a separator. So it is clearer for me
that `flatten` is separated from `joined`.
- `flatMap` means `map` + `flatten`. I feel `flatMap` with `joined`
does not make sense.

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

No. It is not a problem for me as described above.

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

I think proposed `joined` itself fits with the feel of Swift but it is
not the direction of Swift. It can cause problems to unite things
which just look similar ignoring the concepts behind them.

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

Kotlin has `flatten` and `flatMap`. Although Haskell has `join` as
`flatten`, it's `flatMap` is named `>>=` (bind).

I don't know any languages which have a combination of `joined` and
`flatMap`. I feel it is strange.

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

A quick reading the thread.

-- Yuta Koshizawa

2016-07-25 15:10 GMT+09:00 Chris Lattner via swift-evolution
:
> Hello Swift community,
>
> 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
>
> Reviews are an important part of the Swift evolution process. All reviews 
> should be sent to the swift-evolution mailing list at
>
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
> or, if you would like to keep your feedback private, directly to the review 
> manager.
>
> What goes into a review?
>
> The goal of the review process is to improve the proposal under review 
> through constructive criticism and contribute to the direction of Swift. When 
> writing your review, here are some questions you might want to answer in your 
> review:
>
> * What is your evaluation of the proposal?
> * Is the problem being addressed significant enough to warrant a 
> change to Swift?
> * Does this proposal fit well with the feel and direction of Swift?
> * If you have used other languages or libraries with a similar 
> feature, how do you feel that this proposal compares to those?
> * How much effort did you put into your review? A glance, a quick 
> reading, or an in-depth study?
>
> More information about the Swift evolution process is available at
>
> https://github.com/apple/swift-evolution/blob/master/process.md
>
> Thank you,
>
> -Chris Lattner
> Review Manager
> ___
> 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] [Pre-Draft] Nil-coalescing and errors

2016-04-11 Thread Yuta Koshizawa via swift-evolution
Hi.

Decoding a JSON is just an example. As I replied to Thorsten, we can
think about various cases we want to unwrap multiple optionals at
once.

This is another example (with the notation `|?` and the postfix
version I proposed instead of the infix `???`).

```
do {
  let sum = try Int(aString)|? + Int(bString)|?
} catch _ {
  // Error handling
}
```

With optional binding, we need to write something like the following.
It needs additional assignments (bindings) to `a` and `b`.

```
if let a = Int(aString), b = Int(bString) {
  let sum = a + b
} else {
  // Error handling
}
```

`Dictionary`'s subscript also returns an optional. Or simply we may
have optional values as properties. We have a lot of optional values
and cases in which we want to pass their unwrapped values directly to
functions. It seems endless to prepare domain-specific solutions for
all of them.

-- Yuta

2016-04-11 3:33 GMT+09:00 Radosław Pietruszewski <rade...@gmail.com>:
> Just FWIW:
>
> ```
> let foo: Foo? = curry(Foo.init) <^> Int(aString) <*> Int(bString) <*>
> Int(cString)
> ```
>
> But I think it is unreasonable to expect all programmers to understand
> and master it. So I want the postfix `???` or `|?`.
>
>
> I agree. But I would also say that deserializing from JSON is complex enough
> of a problem to warrant a domain-specific solution. There’s a ton of them,
> of course, but for example, with Freddy, it would look something like:
>
> extension Person: JSONDecodable {
> init(json j: JSON) throws {
> firstName = try j.string(“firstName”)
> lastName = try j.string(“lastName”)
> age = try j.int(“age”)
> }
> }
>
> let person = try Person(json: json)
>
>
> Even with the proposed `???`, a domain-specific solution would be arguably
> better. So I just don’t consider that a compelling use case.
>
> — Radek
>
> On 09 Apr 2016, at 16:56, Yuta Koshizawa via swift-evolution
> <swift-evolution@swift.org> wrote:
>
> I only wonder whether you really want to repeat Error() all over,
> possibly with `aString` etc. as argument.
>
>
> What I really want is the postfix version of `???` as I wrote in my
> first post in this thread.
>
> Besides the proposed infix `???`, I also want the postfix one which
> throws a `NilError` (something like `struct NilError: ErrorType {}`).
> It is useful to handle multiple `nil`s at once when we are not
> interested in the kind of the error.
>
>
> And also
>
> I think `???` is too long. Instead, I propose `|?`.
> For `foo: Foo?`, `try foo|?` can be read like `Foo` or `nil`. It
> separates (`|`) nil (`?`) from the value and return `Foo`.
> I think it makes sense.
>
>
> Then it becomes something like the following.
>
> ```
> do {
>let foo: Foo = try foo(
>a: Int(aString)|?,
>b: Int(bString)|?,
>c: Int(cString)|?
>)
> } catch _ {
>// Error handling
> }
> ```
>
> I think the infix version is also useful when we actually want to
> specify the types of errors.
>
> Swift provides two ways of error handling: optionals and do/try/catch.
> I think it lacks a way to handle multiple optionals easily in some
> cases. Someone uses applicative styles for it.
>
> ```
> let foo: Foo? = curry(Foo.init) <^> Int(aString) <*> Int(bString) <*>
> Int(cString)
> ```
>
> But I think it is unreasonable to expect all programmers to understand
> and master it. So I want the postfix `???` or `|?`.
>
> -- Yuta
>
>
> 2016-04-08 23:47 GMT+09:00 Thorsten Seitz <tseit...@icloud.com>:
>
>
> Am 08.04.2016 um 11:59 schrieb Brent Royal-Gordon <br...@architechies.com>:
>
> I only wonder whether you really want to repeat Error() all over, possibly
> with `aString` etc. as argument.
>
>
> `Error()`, no. `SpimsterKitError.invalidWicketField("a"`), yes, because even
> if `Int.init(_:)` threw *an* error, it wouldn't throw *your* error.
>
>
> That's why I thought that in a real use case that logic would likely be
> extracted.
>
> -Thorsten
>
> ___
> 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] [Pre-Draft] Nil-coalescing and errors

2016-04-09 Thread Yuta Koshizawa via swift-evolution
> I only wonder whether you really want to repeat Error() all over,
> possibly with `aString` etc. as argument.

What I really want is the postfix version of `???` as I wrote in my
first post in this thread.

> Besides the proposed infix `???`, I also want the postfix one which
> throws a `NilError` (something like `struct NilError: ErrorType {}`).
> It is useful to handle multiple `nil`s at once when we are not
> interested in the kind of the error.

And also

> I think `???` is too long. Instead, I propose `|?`.
> For `foo: Foo?`, `try foo|?` can be read like `Foo` or `nil`. It
> separates (`|`) nil (`?`) from the value and return `Foo`.
> I think it makes sense.

Then it becomes something like the following.

```
do {
let foo: Foo = try foo(
a: Int(aString)|?,
b: Int(bString)|?,
c: Int(cString)|?
)
} catch _ {
// Error handling
}
```

I think the infix version is also useful when we actually want to
specify the types of errors.

Swift provides two ways of error handling: optionals and do/try/catch.
I think it lacks a way to handle multiple optionals easily in some
cases. Someone uses applicative styles for it.

```
let foo: Foo? = curry(Foo.init) <^> Int(aString) <*> Int(bString) <*>
Int(cString)
```

But I think it is unreasonable to expect all programmers to understand
and master it. So I want the postfix `???` or `|?`.

-- Yuta


2016-04-08 23:47 GMT+09:00 Thorsten Seitz :
>
> Am 08.04.2016 um 11:59 schrieb Brent Royal-Gordon :
>
>>> I only wonder whether you really want to repeat Error() all over, possibly 
>>> with `aString` etc. as argument.
>>
>> `Error()`, no. `SpimsterKitError.invalidWicketField("a"`), yes, because even 
>> if `Int.init(_:)` threw *an* error, it wouldn't throw *your* error.
>
> That's why I thought that in a real use case that logic would likely be 
> extracted.
>
> -Thorsten
___
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-07 Thread Yuta Koshizawa via swift-evolution
Of course we can implement a library with `throws` by changing those
properties to methods. However we can think about similar cases.

```
do {
let foo: Foo = try foo(
a: Int(aString) ??? Error(),
b: Int(bString) ??? Error(),
c: Int(cString) ??? Error()
)
} catch _ {
// Error handling
}
```

`Dictionary` also returns optionals. We have already had various
functions/methods which returns optionals.

-- Yuta


2016-04-07 21:34 GMT+09:00 Thorsten Seitz via swift-evolution
<swift-evolution@swift.org>:
> Why not have throwing variants of the `string` and `int` methods (in
> addition to those returning an optional)?
>
> Then you could simply write:
>
> ```
> // Decodes a JSON with SwiftyJSON
> do {
>let person: Person = try Person(
>   firstName: json["firstName"].string,
>   lastName: json["lastName"].string,
>   age: json["age"].int)
> } catch _ {
> // Error handling
> }
> ```
>
> -Thorsten
>
>
> Am 07. April 2016 um 14:01 schrieb Yuta Koshizawa via swift-evolution
> <swift-evolution@swift.org>:
>
> I'd like to see some real-world examples of this before we did anything with
> it.
>
>
> The following is my real-world example.
>
> ```
> // Decodes a JSON with SwiftyJSON
> do {
> let person: Person = try Person(
> firstName: json["firstName"].string ??? Error(),
> lastName: json["lastName"].string ??? Error(),
> age: json["age"].int ??? Error()
> )
> } catch _ {
> // Error handling
> }
> ```
>
> With `guard`, we have to repeat the parameter names meaninglessly.
>
> ```
> do {
> guard let firstName = json["firstName"].string else { throw Error() }
> guard let lastName = json["lastName"].string else { throw Error() }
> guard let age = json["age"].string else { throw Error() }
> let person: Person = Person(firstName: firstName, lastName:
> lastName, age: age)
> } catch _ {
> // Error handling
> }
> ```
>
> `guard` is a statement. `???` makes an expression. Expressions are
> useful when we want to pass their return values as arguments directly.
> I think `???` is valuable to get an unwrapped value or throw an error
> as an expression.
>
> -- Yuta
>
> 2016-04-07 2:45 GMT+09:00 Jordan Rose via swift-evolution
> <swift-evolution@swift.org>:
>
> I think I'm with Sean on this one. Optionals and throwing don't have enough
>
> to do with each other to actually come up with a specific operator or method
>
> for this. I can't help but see this as two ideas glued together:
>
>
> - "By this point in my execution I need a non-optional value, otherwise
>
> __"
>
> - "_ happened, therefore execution has failed and I should throw an
>
> error"
>
>
> …and I'm not sure these ideas coincide enough to be worth gluing together.
>
> There are a lot of other ways to get a non-optional value out of an optional
>
> ('??', '!', and 'guard let' with some other action), and there are a lot of
>
> other ways to fail besides an optional being nil (status code came back as
>
> error, unexpected data, connection timeout).
>
>
> I'd like to see some real-world examples of this before we did anything with
>
> it.
>
>
> Jordan
>
>
>
> On Apr 6, 2016, at 8:00, Sean Heber via swift-evolution
>
> <swift-evolution@swift.org> wrote:
>
>
> 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 }
>
>
> It is only a couple of characters longer and already works (it’s what I use
>
> currently). If guard allowed for a special single-expression variation so
>
> that you didn’t need to specify the ugly braces or something, it’d look
>
> prettier and be nice for a lot of other situations, too:
>
>
> guard let value = Int("NotANumber") else: throw
>
> InitializerError.invalidString
>
> guard someVal < 10 else: return false
>
> guard mustBeTrue() else: return
>
> // etc
>
>
> Not to derail this, but I sort of want this ability anywhere as a shorthand
>
> for a single-expression block.
>
>
> if something < 42: doThing()
>
> for a in list: print(a)
>
>
> But I imagine that’ll never fly. :P
>
>
> l8r
>
> Sean
>
>
>
>
> On Apr 6, 2016, at 9:46 AM, Erica Sadun via swift-evolution
>
> <swift-evolution@swift.org> wrote:
>
>
> Pyry Jahkola and I have b

Re: [swift-evolution] [Pre-Draft] Nil-coalescing and errors

2016-04-07 Thread Yuta Koshizawa via swift-evolution
> I'd like to see some real-world examples of this before we did anything with 
> it.

The following is my real-world example.

```
// Decodes a JSON with SwiftyJSON
do {
  let person: Person = try Person(
firstName: json["firstName"].string ??? Error(),
lastName: json["lastName"].string ??? Error(),
age: json["age"].int ??? Error()
  )
} catch _ {
  // Error handling
}
```

With `guard`, we have to repeat the parameter names meaninglessly.

```
do {
guard let firstName = json["firstName"].string else { throw Error() }
guard let lastName = json["lastName"].string else { throw Error() }
guard let age = json["age"].string else { throw Error() }
let person: Person = Person(firstName: firstName, lastName:
lastName, age: age)
} catch _ {
  // Error handling
}
```

`guard` is a statement. `???` makes an expression. Expressions are
useful when we want to pass their return values as arguments directly.
I think `???` is valuable to get an unwrapped value or throw an error
as an expression.

-- Yuta

2016-04-07 2:45 GMT+09:00 Jordan Rose via swift-evolution
:
> I think I'm with Sean on this one. Optionals and throwing don't have enough
> to do with each other to actually come up with a specific operator or method
> for this. I can't help but see this as two ideas glued together:
>
> - "By this point in my execution I need a non-optional value, otherwise
> __"
> - "_ happened, therefore execution has failed and I should throw an
> error"
>
> …and I'm not sure these ideas coincide enough to be worth gluing together.
> There are a lot of other ways to get a non-optional value out of an optional
> ('??', '!', and 'guard let' with some other action), and there are a lot of
> other ways to fail besides an optional being nil (status code came back as
> error, unexpected data, connection timeout).
>
> I'd like to see some real-world examples of this before we did anything with
> it.
>
> Jordan
>
>
> On Apr 6, 2016, at 8:00, Sean Heber via swift-evolution
>  wrote:
>
> 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 }
>
> It is only a couple of characters longer and already works (it’s what I use
> currently). If guard allowed for a special single-expression variation so
> that you didn’t need to specify the ugly braces or something, it’d look
> prettier and be nice for a lot of other situations, too:
>
> guard let value = Int("NotANumber") else: throw
> InitializerError.invalidString
> guard someVal < 10 else: return false
> guard mustBeTrue() else: return
> // etc
>
> Not to derail this, but I sort of want this ability anywhere as a shorthand
> for a single-expression block.
>
> if something < 42: doThing()
> for a in list: print(a)
>
> But I imagine that’ll never fly. :P
>
> l8r
> Sean
>
>
>
> On Apr 6, 2016, at 9:46 AM, Erica Sadun via swift-evolution
>  wrote:
>
> Pyry Jahkola and I have been plugging away on the following which is
> preliminary enough not to qualify as an actual draft. He prefers the Mike
> Ash approach. I prefer the operator approach. So we have not actually
> settled on which one we would actually propose despite how I've written this
> up.
>
> I'm putting this out there to try to gain a consensus on:
>
> * Would this be a viable proposal?
> * If so, which of the options would work best within Swift's design and
> philosophy
>
> Thanks for your feedback.
>
> -- Erica
> Introduction
>
> Swift's try? keyword transforms error-throwing operations into optional
> values. We propose adding an error-throwing nil-coalescing operator to the
> Swift standard library. This operator will coerce optional results into
> Swift's error-handling system.
>
> This proposal was discussed on the Swift Evolution list in the name thread.
>
> Motivation
>
> Any decision to expand Swift's set of standard operators should be taken
> thoughtfully and judiciously. Moving unaudited or deliberately
> non-error-handling nil-returning methods and failable initializers into
> Swift's error system should be a common enough use case to justify
> introducing a new operator.
>
> Detail Design
>
> We propose adding a new operator that works along the following lines:
>
> infix operator ??? {}
>
> func ???(lhs: T?, @autoclosure error: () -> ErrorType) throws -> T {
>guard case let value? = lhs else { throw error() }
>return value
> }
>
> The use-case would look like this:
>
> do {
>let error = Error(reason: "Invalid string passed to Integer initializer")
>let value = try Int("NotANumber") ??? InitializerError.invalidString
>print("Value", value)
> } catch { print(error) }
>
> Note
>
> SE-0047 (warn unused result by default) and SE-0049 (move autoclosure) both
> affect many of the snippets in this 

Re: [swift-evolution] [Pre-Draft] Nil-coalescing and errors

2016-04-06 Thread Yuta Koshizawa via swift-evolution
I agree with this and I like the operator approach.

Besides the proposed infix `???`, I also want the postfix one which
throws a `NilError` (something like `struct NilError: ErrorType {}`).
It is useful to handle multiple `nil`s at once when we are not
interested in the kind of the error.

```
// Decodes a JSON with SwiftyJSON
do {
  let person: Person = try Person(
firstName: json["firstName"].string???,
lastName: json["lastName"].string???,
age: json["age"].int???
  )
} catch _ {
  // Error handling
}
```

Considering the postfix one, the operator approach for the infix one
is consistent.

One more thing; I think `???` is too long. Instead, I propose `|?`.
For `foo: Foo?`, `try foo|?` can be read like `Foo` or `nil`. It
separates (`|`) nil (`?`) from the value and return `Foo`. I think it
makes sense.

-- Yuta

2016-04-06 23:46 GMT+09:00 Erica Sadun via swift-evolution
:
> Pyry Jahkola and I have been plugging away on the following which is
> preliminary enough not to qualify as an actual draft. He prefers the Mike
> Ash approach. I prefer the operator approach. So we have not actually
> settled on which one we would actually propose despite how I've written this
> up.
>
> I'm putting this out there to try to gain a consensus on:
>
> * Would this be a viable proposal?
> * If so, which of the options would work best within Swift's design and
> philosophy
>
> Thanks for your feedback.
>
> -- Erica
>
> Introduction
>
> Swift's try? keyword transforms error-throwing operations into optional
> values. We propose adding an error-throwing nil-coalescing operator to the
> Swift standard library. This operator will coerce optional results into
> Swift's error-handling system.
>
> This proposal was discussed on the Swift Evolution list in the name thread.
>
> Motivation
>
> Any decision to expand Swift's set of standard operators should be taken
> thoughtfully and judiciously. Moving unaudited or deliberately
> non-error-handling nil-returning methods and failable initializers into
> Swift's error system should be a common enough use case to justify
> introducing a new operator.
>
> Detail Design
>
> We propose adding a new operator that works along the following lines:
>
> infix operator ??? {}
>
> func ???(lhs: T?, @autoclosure error: () -> ErrorType) throws -> T {
> guard case let value? = lhs else { throw error() }
> return value
> }
>
> The use-case would look like this:
>
> do {
> let error = Error(reason: "Invalid string passed to Integer
> initializer")
> let value = try Int("NotANumber") ??? InitializerError.invalidString
> print("Value", value)
> } catch { print(error) }
>
> Note
>
> SE-0047 (warn unused result by default) and SE-0049 (move autoclosure) both
> affect many of the snippets in this proposal
>
> Disadvantages to this approach:
>
> It consumes a new operator, which developers must be trained to use
> Unlike many other operators and specifically ??, this cannot be chained.
> There's no equivalent to a ?? b ?? c ?? dor a ?? (b ?? (c ?? d)).
>
> Alternatives Considered
>
> Extending Optional
>
> The MikeAsh approach extends Optional to add an orThrow(ErrorType) method
>
> extension Optional {
> func orThrow(@autoclosure error: () -> ErrorType) throws -> Wrapped {
> guard case let value? = self else { throw error() }
> return value
> }
> }
>
> Usage looks like this:
>
> do {
> let value = try Int("NotANumber")
> .orThrow(InitializerError.invalidString)
> print("Value", value)
> } catch { print(error) }
>
> An alternative version of this call looks like this: optionalValue.or(throw:
> error). I am not a fan of using a verb as a first statement label.
>
> Disadvantages:
>
> Wordier than the operator, verging on claustrophobic, even using Swift's
> newline dot continuation.
> Reading the code can be confusing. This requires chaining rather than
> separating error throwing into a clear separate component.
>
> Advantages:
>
> No new operator, which maintains Swift operator parsimony and avoids the
> introduction and training issues associated with new operators.
> Implicit Optional promotion cannot take place. You avoid mistaken usage like
> nonOptional ??? error and nonOptional ?? raise(error).
> As a StdLib method, autocompletion support is baked in.
>
> Introducing a StdLib implementation of raise(ErrorType)
>
> Swift could introduce a raise(ErrorType) -> T global function:
>
> func raise(error: ErrorType) throws -> T { throw error }
>
> do {
> let value = try Int("NotANumber") ??
> raise(InitializerError.invalidString)
> print("Value", value)
> } catch { print(error) }
>
> This is less than ideal:
>
> This approach is similar to using && as an if-true condition where an
> operator is abused for its side-effects.
> It is wordier than the operator approach.
> The error raising function promises to return a type but never will, which
> seems hackish.
>
> Overriding ??
>
> We also considered 

Re: [swift-evolution] Enable omitting `let` for constant declarations

2016-04-04 Thread Yuta Koshizawa via swift-evolution
> Radosław

Hi. I found Stephen Celis proposed exactly same notations in the
thread "Mutability inference". I guess it is what you talked about.

> let a: String = "string"
> b: String = "string" // short-hand avoids let
> b := "string" // shorter-hand

But it seems that it was not well discussed, and I think it is worth
discussing it.

> Macko

Thanks!

-- Yuta


2016-04-03 16:23 GMT+09:00 Macko Jeffrey <macko.jeff...@gmail.com>:
> I love your propositions Yuta.
>
> ---
> Macko Jeffrey
>
>> Le 1 avr. 2016 à 20:58, Yuta Koshizawa via swift-evolution 
>> <swift-evolution@swift.org> a écrit :
>>
>> Did you mean the thread "Mutability inference"? What I talked about is
>> different from it. I am against the idea of "Mutability inference".
>>
>> What I talked about is just enabling to omit `let` for constant
>> declarations. It distinguishes the following three explicitly.
>>
>>> - assignment
>>> - declaration of a constant
>>> - declaration of a mutable variable
>>
>> `:=` makes it possible to distinguish assignments and constant declarations.
>>
>> -- Yuta
>>
>>
>> 2016-04-01 23:55 GMT+09:00 Radosław Pietruszewski <rade...@gmail.com>:
>>> I can’t easily find it, but there’s been at least one thread proposing this 
>>> exact thing, and there was very little interest in the proposal.
>>>
>>> TL;DR is that Swift *by design* wants to make the difference between these 
>>> three concepts:
>>>
>>> - assignment
>>> - declaration of a constant
>>> - declaration of a mutable variable
>>>
>>> as explicit and obvious as possible.
>>>
>>> — Radek
>>>
>>>> On 01 Apr 2016, at 13:58, Yuta Koshizawa via swift-evolution 
>>>> <swift-evolution@swift.org> wrote:
>>>>
>>>> I think it would be good if the following three declarations were 
>>>> equivalent
>>>>
>>>> let a: Int = 42
>>>> a: Int = 42
>>>> a := 42
>>>>
>>>> and also the following two were.
>>>>
>>>> let a: Int
>>>> a: Int
>>>>
>>>> Then constant declarations become shorter than variable declarations.
>>>> It encourages people to use constants in preference to variables.
>>>>
>>>> It also prevents repeating `let` for property declarations and makes
>>>> type declarations simpler.
>>>>
>>>> struct Person {
>>>>   firstName: String
>>>>   lastName: String
>>>>   age: Int
>>>> }
>>>>
>>>> Omitting `let` is consistent with that we don't write `let` for
>>>> arguments of functions and iterated values in for-in loops.
>>>>
>>>> Not `=` but `:=` for type inferences because `=` cannot distinguish
>>>> whether it means a constant declaration or an assignment to a variable
>>>> declared in an outer scope. I think `:=` is a natural notation for
>>>> type inferences because omitting the type from `a: Int = 42` makes
>>>> `a:= 42`. Because I have not strictly checked if it can be parsed in
>>>> Swift properly, it may have some other parsing issues.
>>>>
>>>> What do you think about it?
>>>>
>>>> -- Yuta
>>>> ___
>>>> 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
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Enable omitting `let` for constant declarations

2016-04-01 Thread Yuta Koshizawa via swift-evolution
Did you mean the thread "Mutability inference"? What I talked about is
different from it. I am against the idea of "Mutability inference".

What I talked about is just enabling to omit `let` for constant
declarations. It distinguishes the following three explicitly.

> - assignment
> - declaration of a constant
> - declaration of a mutable variable

`:=` makes it possible to distinguish assignments and constant declarations.

-- Yuta


2016-04-01 23:55 GMT+09:00 Radosław Pietruszewski <rade...@gmail.com>:
> I can’t easily find it, but there’s been at least one thread proposing this 
> exact thing, and there was very little interest in the proposal.
>
> TL;DR is that Swift *by design* wants to make the difference between these 
> three concepts:
>
> - assignment
> - declaration of a constant
> - declaration of a mutable variable
>
> as explicit and obvious as possible.
>
> — Radek
>
>> On 01 Apr 2016, at 13:58, Yuta Koshizawa via swift-evolution 
>> <swift-evolution@swift.org> wrote:
>>
>> I think it would be good if the following three declarations were equivalent
>>
>> let a: Int = 42
>> a: Int = 42
>> a := 42
>>
>> and also the following two were.
>>
>> let a: Int
>> a: Int
>>
>> Then constant declarations become shorter than variable declarations.
>> It encourages people to use constants in preference to variables.
>>
>> It also prevents repeating `let` for property declarations and makes
>> type declarations simpler.
>>
>> struct Person {
>>firstName: String
>>lastName: String
>>age: Int
>> }
>>
>> Omitting `let` is consistent with that we don't write `let` for
>> arguments of functions and iterated values in for-in loops.
>>
>> Not `=` but `:=` for type inferences because `=` cannot distinguish
>> whether it means a constant declaration or an assignment to a variable
>> declared in an outer scope. I think `:=` is a natural notation for
>> type inferences because omitting the type from `a: Int = 42` makes
>> `a:= 42`. Because I have not strictly checked if it can be parsed in
>> Swift properly, it may have some other parsing issues.
>>
>> What do you think about it?
>>
>> -- Yuta
>> ___
>> 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] throws as returning a Result

2016-03-15 Thread Yuta Koshizawa via swift-evolution
2016-03-15 2:23 GMT+09:00 Joe Groff :
>
> Yeah, we extensively discussed adding a Result type internally, but
> ultimately couldn't justify it. The only real use case we could see in the
> wild was for threading errors through CPS-inversion-style abstractions like
> async promises, something we hope to provide proper language support for.
> More generally, expressing effects as monadic values is a pretty awful
> abstraction; aside from polluting the Internet with an endless deluge of
> unhelpful tutorials, they also don't compose cleanly, they impose nesting
> where is desired—you have to pick between Result and
> Async, or build ResultT out of monad
> transformers—and they don't do the natural thing when used with other
> higher-order abstractions—if you're mapping a `throws` function over a
> collection, you probably want to propagate that error like `rethrows` does,
> not end up with a collection of Result.

Yes, I know the pain of nested monads and I don't want to encourage
monadic error handling with awful nests.

To tell the truth, I ultimately desire to unify `Optional`s, `throws`
and `Result`s.

We have already had `Optional`s which can be used in a monadic way. To
prevent excessive monadic handling, I think we need Automatic
Propagation for `Optional`s.

```
// Automatic Propagation for `Optional`s
let a: Int? = ...
let b: Int? = ...

do {
  let sum: Int = (try a) + (try b)
  ...
} catch { // if `a` and/or `b` are `nil`
  ...
}
```

Although "Error Handling Rational and Proposal" says `Optional`s
should be used for simple domain errors and are suitable for Manual
Propagation, I think Automatic Propagation is also useful for
`Optional`s. We get `nil` not only as errors but also as empty values.
Our codes are full of `Optional`s. Handling them manually costs a lot.
So I think it is good to have Automatic Propagation for `Optional`s.

However it is confusing to mix `Optional`s and `throws` functions with
the same keyword `try`. So I think something like `typealias
Optional = Result`, which could be identical in a
binary form to current `Optional` with `struct NilError: ErrorType
{}`, and unified `throws` and `Result`s would be better. Then we would
have only `Result`s, but it could be used as `Optional`s and `throws`.

Although `Result`s might make it possible to abuse monadic error
handling, problems of abuses are also true for other language
features: e.g. `(Float, Float)` as `Vector2` instead of `struct
Vector2 { ... }` for tuples. Even if we keep `Optional`s and `throws`
separated, `Optional`s can be handled monadically and we need to
encourage people how and when to use them to prevent abuses. I think
language features cannot prevent abuses, and it is a role of coding
guidelines.

So I think it is good to unify `Optional`s, `throws` and `Result`s.
But because it seemed too radical, I proposed the part of it at first:
`throws -> Foo` as a syntactic sugar of `-> Result`.


> I'd rather see us adopt an
> extensible algebraic effects system, something like http://www.eff-lang.org,
> which provides a framework for `throws`, `async` and other control flow
> effects to be cleanly composed and abstracted over. I see `throws` as the
> first seed of that.

Thank you for the information. Because I am not familiar with Eff, I
will check it. If it composes multiple abstractions well, it must be
great!

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