[swift-evolution] Brainstorming: New operator type - chaining

Howard Lovatt howard.lovatt at gmail.com
Sat Jan 30 20:51:21 CST 2016


I am probably completely mis-understanding what you want. Your 1st example,
isn't it equivalent to:

    foo!.bar()

On Sunday, 31 January 2016, Joseph Lord via swift-evolution <
swift-evolution at swift.org> wrote:

> On 31/01/2016 01:14, Howard Lovatt via swift-evolution wrote:
> > What is wrong with flatMap returning an Optional? Like Scala does.
> >
>
> Using map or a function taking a closure is less clear to read than an
> chaining mechanism.
>
> For the first usecase (which is really the most trivial case of optional
> chaining:
>
> >     assert(foo != nil)
> >     foo?.bar()
> >
> >     I would only want to do:
> >
> >     foo±.bar()
> >
>
> _ = foo.aMap { $0.bar() }
>
> If you can image a multiple step chain it could clearly get more
> complicated.
>
> I don't think that there is a way to avoid the closures within current
> Swift and any map/flatMap based approach.
>
> I'm not familiar with Scala so I may have misunderstood exactly what you
> meant.
>
> Joseph
>
>
> On Sunday, 31 January 2016, Joseph Lord via swift-evolution
>> <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>>
>>     Currently there are three types of operator: prefix, infix and
>>     postfix and most of the Swift operations can be defined using these
>>     and implemented for additional types and they cover most use cases
>>     but there are features in the Swift language which cannot be
>>     replicated and customised with these.
>>
>>     In particular there is the optional chaining use of `?` for which I
>>     can see no way of producing customised versions of or adapting to
>>     types other than optionals (e.g. custom Either types or other
>>     monadic types).
>>
>>     I’m not sure about the feasibility of this change or what knockon
>>     effects might be. This is meant as exploratory suggestion that may
>>     not reach proposal stage.
>>
>>     Would be interested to know:
>>     1) If this is feasible.
>>     2) If it is interesting to people.
>>     3) What if anything should be possible for l-values (optional
>>     chaining works on them but what should be possible.
>>     4) Any other good alternatives.
>>
>>     I picture that the chaining operator function would be called with
>>     the left hand side value and could be required to return a value of
>>     a type such as this ChainValueResult:
>>
>>     enum ChainValueResult<A,C,D> {
>>        case continue(A, C->D),
>>        case stop(D)
>>     }
>>
>>     The logic then applied to this enum would be in case of continue to
>>     apply the C->D function to the result of continuing the chain which
>>     is applied to the A value. In the case of stop it is to simply
>>     return the value of type D.
>>
>>     I have used this enum in the draft code below. Please note that the
>>     code below doesn't compile and that if really being used the
>>     inference system would need to account for the return type of the
>>     ongoing chain.
>>
>>     Use case 1 - Custom optional chaining behaviour
>>
>>     The particular thing that I would like use this for is to make a
>>     custom asserting variant of the optional chaining operator. I
>>     already do this with nil coalescing (it is currently the only custom
>>     operator in my code) but a shorthand for this would be good:
>>
>>     assert(foo != nil)
>>     foo?.bar()
>>
>>     I would only want to do:
>>
>>     foo±.bar()
>>
>>     func ± <A, C>(lhs: A?)->ChainValueResult<A, C->C? ,C?> {
>>              if let lhs = lhs {
>>                      return .continue(lhs, { $0 })
>>              } else {
>>                      assertionFailure()
>>                      return .stop(nil)
>>              }
>>     }
>>
>>     Use case 2 - Chaining on custom types
>>
>>     And this especially may not be feasible and I may be out of my depth
>>     describing the requirement but it feels like a more general case so
>>     at least worth airing):
>>
>>     It would be good for code like the following to be possible
>>     (hopefully with a little more type inference).
>>
>>     let c:Either<Int, Error> = Either<String, Error>(.Left(“boo"))^^.count
>>
>>     Now the user’s definition of the operator would probably have to
>>     look something like this:
>>
>>     func ^^<A,B, C>(lhs: Either<A,B>)->(ChainValueResult<A, C,
>>     Either<C,B>>   {
>>              switch lhs {
>>              case .Left(let a):
>>                      return .continue(a, { Either<C,B>(.Left($0) })
>>               case .Right(let b):
>>                      return .stop( Either<C, B>(.Right(b))
>>              }
>>     }
>>
>>     I couldn't find any significant discussion of optional chaining in
>>     the mailing list so far.
>>
>>     Joseph
>>     _______________________________________________
>>     swift-evolution mailing list
>>     swift-evolution at swift.org
>>     https://lists.swift.org/mailman/listinfo/swift-evolution
>>
>>
>>
>> --
>>    -- Howard.
>>
>>
>>
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>
>>
>
> --
> Human Friendly Ltd.
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>


-- 
  -- Howard.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160131/65db46a7/attachment.html>


More information about the swift-evolution mailing list