[Idea] custom infix functions


(Adrian Zubarev) #1

I’d like to throw an idea in the room and see where this will go.

What if Swift would allow us to create custom infix functions?
Does Swift need to ability of infix functions?
How powerful can such a feature be?
Pros and cons?

There is a discussion about the `with` statement which we could develop with infix functions like so:

infix func with<T: AnyObject>(lhs: T, rhs: @noescape (T) -> Void) {

  rhs(lhs)
}

class A {

  func foo() {}
}

let instance: A = A() with {

  $0.foo()
}

So what does the Swift community think about that idea?

···

--
Adrian Zubarev


(Adrian Zubarev) #2

I must correct myself, I’m a bit sleepy.

infix func with<T: AnyObject>(lhs: T, rhs: @noescape (T) -> Void) -> T {

rhs\(lhs\)
return lhs

}

This one will do the trick.

···

--
Adrian Zubarev

Am 22. April 2016 bei 21:07:00, Adrian Zubarev (adrian.zubarev@devandartist.com) schrieb:

I’d like to throw an idea in the room and see where this will go.

What if Swift would allow us to create custom infix functions?
Does Swift need to ability of infix functions?
How powerful can such a feature be?
Pros and cons?

There is a discussion about the `with` statement which we could develop with infix functions like so:

infix func with<T: AnyObject>(lhs: T, rhs: @noescape (T) -> Void) {

rhs(lhs)
}

class A {

func foo() {}
}

let instance: A = A() with {

$0.foo()
}

So what does the Swift community think about that idea?

--
Adrian Zubarev


(Vladimir) #3

IMO Such construction will looks like a language construction and will confuse.

And the function you suggest as replacement for "with" feature will *not* correctly handle struct instances (Swift 3.0 mar 24):

struct B { var x = 10 }

func with<T: AnyObject>(lhs: T, rhs: @noescape (T) -> Void) { rhs(lhs) }

var b2 = B()
with(b2) { print($0.x) }

It will produce this error :

···

On 22.04.2016 22:06, Adrian Zubarev via swift-evolution wrote:

I’d like to throw an idea in the room and see where this will go.

What if Swift would allow us to create custom infix functions?
Does Swift need to ability of infix functions?
How powerful can such a feature be?
Pros and cons?

There is a discussion about the `with` statement which we could develop
with infix functions like so:

--------------
Error running code:
l-value expression does not have l-value access kind set
...
-------------

This is why I propose to introduce standard "with" feature(language feature or built-in method(s)/free function(s)) in Swift out-of-box i.e. tested and well-working solution in any situation. Not some hack/workaround that each one will write for himself and that will not work in some situation.

I can implement "with" method in some way for struct that will work like this:

struct B {
  var x = 10

  mutating func withInPlace(user: @noescape (inout B)->Void) -> B {
    var copy = self
    user(&copy)
    self = copy
    return self
  }

  func with(user: @noescape (inout B)->Void) -> B {
           var copy = self
    user(&copy)
    return copy
  }
}

var b1 = B().with {
     $0.x = 100
}

print("created b1.x = ", b1.x)

b1.withInPlace { $0.x = 1000 }

let c1 = b1.with {
     print("b1.x = ", $0.x)
     $0.x = 2000
}

print("b1.x = ", b1.x)
print("c1.x = ", c1.x)

But again, this is custom solution, we need standard and tested way to do this.

infix func with<T: AnyObject>(lhs: T, rhs: @noescape (T) -> Void) {

rhs(lhs)
}

class A {

func foo() {}
}

let instance: A = A() with {

$0.foo()
}

So what does the Swift community think about that idea?

--
Adrian Zubarev

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


(Adrian Zubarev) #4

I know that this might be a bit confusing but at least for a syntax highlighting editor this shouldn’t be a problem. Any custom function is displayed with a different color (at least Xcode do).

For structs one could use:

struct B { var x = 10 }

func with<T>(lhs: T, rhs: (inout T) -> Void) -> T {

var mutableValue = lhs
rhs(&mutableValue)
return mutableValue
}

let value = B() with {

$0.x = 40
}

This does even supports Swifty mutation if needed.

`with` statement is just a single example we could create with infix functions.

···

--
Adrian Zubarev

Am 22. April 2016 bei 22:05:11, Vladimir.S via swift-evolution (swift-evolution@swift.org) schrieb:

On 22.04.2016 22:06, Adrian Zubarev via swift-evolution wrote:

I’d like to throw an idea in the room and see where this will go.

What if Swift would allow us to create custom infix functions?
Does Swift need to ability of infix functions?
How powerful can such a feature be?
Pros and cons?

There is a discussion about the `with` statement which we could develop
with infix functions like so:

IMO Such construction will looks like a language construction and will
confuse.

And the function you suggest as replacement for "with" feature will *not*
correctly handle struct instances (Swift 3.0 mar 24):

struct B { var x = 10 }

func with<T: AnyObject>(lhs: T, rhs: @noescape (T) -> Void) { rhs(lhs) }

var b2 = B()
with(b2) { print($0.x) }

It will produce this error :
--------------
Error running code:
l-value expression does not have l-value access kind set
...
-------------

This is why I propose to introduce standard "with" feature(language feature
or built-in method(s)/free function(s)) in Swift out-of-box i.e. tested and
well-working solution in any situation. Not some hack/workaround that each
one will write for himself and that will not work in some situation.

I can implement "with" method in some way for struct that will work like this:

struct B {
var x = 10

mutating func withInPlace(user: @noescape (inout B)->Void) -> B {
var copy = self
user(&copy)
self = copy
return self
}

func with(user: @noescape (inout B)->Void) -> B {
var copy = self
user(&copy)
return copy
}
}

var b1 = B().with {
$0.x = 100
}

print("created b1.x = ", b1.x)

b1.withInPlace { $0.x = 1000 }

let c1 = b1.with {
print("b1.x = ", $0.x)
$0.x = 2000
}

print("b1.x = ", b1.x)
print("c1.x = ", c1.x)

But again, this is custom solution, we need standard and tested way to do this.

infix func with<T: AnyObject>(lhs: T, rhs: @noescape (T) -> Void) {

rhs(lhs)
}

class A {

func foo() {}
}

let instance: A = A() with {

$0.foo()
}

So what does the Swift community think about that idea?

--
Adrian Zubarev

_______________________________________________
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


(Adrian Zubarev) #5

Ooops, my bad, I didn’t scroll your reply to the very end and so I didn’t read your full answer.

The custom `with` statement with infix function was just an example that it might be possible to build.

It won’t look that 'hacky‘ if Swift would have an explicit protocol for all value types. Something like `AnyValueType`

Then we could easily overload such a custom infix function

infix func with<T: AnyValueType>(lhs: T, rhs: (inout T) -> Void) -> T {
    
  var mutableValue = lhs
  rhs(&mutableValue)
  return mutableValue
}

infix func with<T: AnyObject>(lhs: T, rhs: (T) -> Void) -> T {
    
  rhs(lhs)
  return lhs
}

There is also no chance of such usage, because the `with` function is marked as `infix`

struct B { var x = 10 }

let b = B()

with(b) { print($0.x) } // this won’t be possible at all, infix operators doesn’t allow that so why should infix functions?

As expected we will be able to do something like this:

let newImutableB = B() with {

$0.x = 40 // mutation here is allowed, because we copy internally and path the new value back
}

Infix functions should forbid reserved functions names like `if`, `do`, `else` etc.

···

--
Adrian Zubarev

Am 22. April 2016 bei 22:15:26, Adrian Zubarev (adrian.zubarev@devandartist.com) schrieb:

I know that this might be a bit confusing but at least for a syntax highlighting editor this shouldn’t be a problem. Any custom function is displayed with a different color (at least Xcode do).

For structs one could use:

struct B { var x = 10 }

func with<T>(lhs: T, rhs: (inout T) -> Void) -> T {

var mutableValue = lhs
rhs(&mutableValue)
return mutableValue
}

let value = B() with {

$0.x = 40
}

This does even supports Swifty mutation if needed.

`with` statement is just a single example we could create with infix functions.

--
Adrian Zubarev

Am 22. April 2016 bei 22:05:11, Vladimir.S via swift-evolution (swift-evolution@swift.org) schrieb:

On 22.04.2016 22:06, Adrian Zubarev via swift-evolution wrote:

I’d like to throw an idea in the room and see where this will go.

What if Swift would allow us to create custom infix functions?
Does Swift need to ability of infix functions?
How powerful can such a feature be?
Pros and cons?

There is a discussion about the `with` statement which we could develop
with infix functions like so:

IMO Such construction will looks like a language construction and will
confuse.

And the function you suggest as replacement for "with" feature will *not*
correctly handle struct instances (Swift 3.0 mar 24):

struct B { var x = 10 }

func with<T: AnyObject>(lhs: T, rhs: @noescape (T) -> Void) { rhs(lhs) }

var b2 = B()
with(b2) { print($0.x) }

It will produce this error :
--------------
Error running code:
l-value expression does not have l-value access kind set
...
-------------

This is why I propose to introduce standard "with" feature(language feature
or built-in method(s)/free function(s)) in Swift out-of-box i.e. tested and
well-working solution in any situation. Not some hack/workaround that each
one will write for himself and that will not work in some situation.

I can implement "with" method in some way for struct that will work like this:

struct B {
var x = 10

mutating func withInPlace(user: @noescape (inout B)->Void) -> B {
var copy = self
user(&copy)
self = copy
return self
}

func with(user: @noescape (inout B)->Void) -> B {
var copy = self
user(&copy)
return copy
}
}

var b1 = B().with {
$0.x = 100
}

print("created b1.x = ", b1.x)

b1.withInPlace { $0.x = 1000 }

let c1 = b1.with {
print("b1.x = ", $0.x)
$0.x = 2000
}

print("b1.x = ", b1.x)
print("c1.x = ", c1.x)

But again, this is custom solution, we need standard and tested way to do this.

infix func with<T: AnyObject>(lhs: T, rhs: @noescape (T) -> Void) {

rhs(lhs)
}

class A {

func foo() {}
}

let instance: A = A() with {

$0.foo()
}

So what does the Swift community think about that idea?

--
Adrian Zubarev

_______________________________________________
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


(Vladimir) #6

I don't think we should rely only on XCode editor as Swift is open source now and is used on other systems like Linux where we have no XCode. And IMO language should not rely on any editor.
Just my opinion. Probably others will find this idea useful.

As for "with". Yes, I understand that this is just an example. I just wanted to point that "with" feature has some difficulties in implementation and this is why I propose to have it out-of-box in language or in standard lib.

Btw, your code does not work. Please check. I replaced to
let value = with(B()) {
    $0.x = 40
}
and had the similar error message(Error running code: ...)

···

On 22.04.2016 23:15, Adrian Zubarev via swift-evolution wrote:

I know that this might be a bit confusing but at least for a syntax
highlighting editor this shouldn’t be a problem. Any custom function is
displayed with a different color (at least Xcode do).

For structs one could use:

struct B { var x = 10 }

func with<T>(lhs: T, rhs: (inout T) -> Void) -> T {

   var mutableValue = lhs
   rhs(&mutableValue)
   return mutableValue
}

let value = B() with {

   $0.x = 40
}

This does even supports Swifty mutation if needed.

`with` statement is just a single example we could create with infix functions.

--
Adrian Zubarev

Am 22. April 2016 bei 22:05:11, Vladimir.S via swift-evolution
(swift-evolution@swift.org <mailto:swift-evolution@swift.org>) schrieb:

On 22.04.2016 22:06, Adrian Zubarev via swift-evolution wrote:
> I’d like to throw an idea in the room and see where this will go.
>
> What if Swift would allow us to create custom infix functions?
> Does Swift need to ability of infix functions?
> How powerful can such a feature be?
> Pros and cons?
>
> There is a discussion about the `with` statement which we could develop
> with infix functions like so:

IMO Such construction will looks like a language construction and will
confuse.

And the function you suggest as replacement for "with" feature will *not*
correctly handle struct instances (Swift 3.0 mar 24):

struct B { var x = 10 }

func with<T: AnyObject>(lhs: T, rhs: @noescape (T) -> Void) { rhs(lhs) }

var b2 = B()
with(b2) { print($0.x) }

It will produce this error :
--------------
Error running code:
l-value expression does not have l-value access kind set
...
-------------

This is why I propose to introduce standard "with" feature(language feature
or built-in method(s)/free function(s)) in Swift out-of-box i.e. tested and
well-working solution in any situation. Not some hack/workaround that each
one will write for himself and that will not work in some situation.

I can implement "with" method in some way for struct that will work like
this:

struct B {
var x = 10

mutating func withInPlace(user: @noescape (inout B)->Void) -> B {
var copy = self
user(&copy)
self = copy
return self
}

func with(user: @noescape (inout B)->Void) -> B {
var copy = self
user(&copy)
return copy
}

var b1 = B().with {
$0.x = 100
}

print("created b1.x = ", b1.x)

b1.withInPlace { $0.x = 1000 }

let c1 = b1.with {
print("b1.x = ", $0.x)
$0.x = 2000
}

print("b1.x = ", b1.x)
print("c1.x = ", c1.x)

But again, this is custom solution, we need standard and tested way to do
this.

>
> infix func with<T: AnyObject>(lhs: T, rhs: @noescape (T) -> Void) {
>
> rhs(lhs)
> }
>
> class A {
>
> func foo() {}
> }
>
> let instance: A = A() with {
>
> $0.foo()
> }
>
> So what does the Swift community think about that idea?
>
> --
> Adrian Zubarev
>
> _______________________________________________
> 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