[swift-evolution] Normalizing operator's types

Vladimir.S svabox at gmail.com
Thu Jun 16 13:12:56 CDT 2016


Just checked with Swift 3.0 (Jun 6, 2016),

func f(_ arg: (Int, Int)) -> Int { return arg.0 + arg.1 } // type :  (Int, 
Int) -> Int

This won't compile:
f(4, 5) // returns 9
ERROR : extra argument in call

This works as expected:
f((4,56)) // returns 60

On 16.06.2016 21:08, J. Charles N. MBIADA via swift-evolution wrote:
>
>
> --
> J. Charles
>
>> Le 16 juin 2016 à 15:57, Jeremy Pereira <jeremy.j.pereira at googlemail.com>
>> a écrit :
>>
>>
>>> On 15 Jun 2016, at 21:07, J. Charles N. MBIADA via swift-evolution
>>> <swift-evolution at swift.org> wrote:
>>>
>>> Hi Swift,
>>>
>>> Since the "removal" of curried function, I am looking for some elegant
>>> ways to work with partial functions (and reduce creation of closure and
>>> nested func for the developper).
>>>
>>> And now I am asking myself if it's not better to align operator's types
>>> to the arrow style instead of using tuple argument style.
>>>
>>> For example:
>>> Why Int.multiplyWithOverflow's type is (Int, Int) -> (Int, overflow:
>>> Bool) instead of (Int -> Int) -> (Int, overflow: Bool)
>>
>> That looks wrong to me. That says that Int.multiplyWithOverflow is a
>> function that takes another function (of type (Int) -> Int) and returns a
>> tuple.
>>
> Function which takes a function require parenthesis as you showed up: (Int)
> -> Int I am saying that using this fact, we can bring back auto curried
> function by eliminating parenthesis.
> Int -> Int -> Int will be interpreted as a func which permit to generate
> partial function when arguments are missing.
>
>
>> What you really want is a function that takes an Int and returns another
>> function that takes an Int and returns the tuple i.e. its signature would
>> look like this
>>
>> (Int) -> ((Int) -> (Int, Bool))
>>
> This last one will be interpreted as a final function which need exactly
> one parameter to be valid when it's called.
>
> Plus seeing the example below work show how things are not clear if
> programmers doesn't want to go in a deep understanding of the language..
> But it works well...
>
> func f(_ arg: (Int, Int)) -> Int { return arg.0 + arg.1 } // type :  (Int,
> Int) -> Int
>
> f(4,5) // returns 9
>
> f((4,56)) // returns 60
>
>
> func g(_ arg: Int, _ a: Int) -> Int { return arg + a } // type : (Int, Int)
> -> Int
>
> g(4, 5) // returns 9
>
> g((4,56)) // fails
>
> // Ok putting label could help to distinguish but
>
> func f( a:Int,  b:Int) -> Int { return a + b } and func h(_ arg: (a:Int,
> b:Int)) -> Int { return arg.0 + arg.1 } still has the same type
>
>
> Clearifying this situation IMHO seem to me as complicated  (maybe more) as
> clarifying Int -> Int -> Int. Explaining the lambda concept once should be
> sufficient to clarify this one. Explaining Tuple concept could not help to
> clarify the behavior of the example above.
>
>
>
>> If we assume -> is right associative we can simplify to
>>
>> (Int) -> (Int) -> (Int, Bool)
>
> Chris proposal to enforce parenthesis around arguments could be the
> opportunity to use that syntax to distinct curried functions from the others.
> Then (Int) -> (Int) -> (Int, Bool) is valid and say that full
> implementation was handled by the developer since Int -> Int -> (Int, Bool)
> is valid too but some workaround could be handled by the compiler.
> Making these functions some how different in programmer's intent.
> fun f(a:Int, b:Int) -> Int { return (a/b, a%b != 0)} has type Int -> Int ->
> (Int, Bool)
> and h(a:Int) -> Int { return { b:Int in return (a/b, a%b != 0)} } has type
> (Int) -> (Int -> (Int, Bool))
>
> f(4, 5); f(4)(5) // OK
> h(4)(5) // OK
> h(4, 5) // fails, or why not works as well
>
> f(a:Int) -> Int { return { b:Int in return (a/b, a%b != 0)} } has type
> (Int) -> (Int -> (Int, Bool))
> Of course this need to be refined and formalized.
>
>> which makes more sense but is less clear to most programmers than the
>> current syntax.
>
> In my opinion, what are clear for programmers are what they understand, a
> reference section explaining these concepts could do the work of clarifying
> things.
>
>>>
>>> When curried function will come back (if it come back, which is a
>>> personal hope) that will avoid many refactoring.
>>>
>>> I think that, write this : let f:(Int, Int) throws -> Int = (+) seem a
>>> bit ugly for this purpose
>>> let f:(Int -> Int) -> Int = (+) seem more suitable.
>>>
>>> We could imagine that in the future the compile could automatically
>>> create a closure if the programmer define something like
>>>
>>> let lmul: (Int) -> (Int) -> (Int) = (*)
>>>
>>> and then, doing the habitual stuffs : let mulOfTwo = lmul(2)
>>>
>>>
>>> Kind regards,
>>> --
>>> jcnm
>>>
>>> _______________________________________________
>>> swift-evolution mailing list
>>> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>
>
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>


More information about the swift-evolution mailing list