[Proposal] Scoped import (of weirdly overladed logical operators)


(Marcel Jackwerth) #1

Sorry in advance for that slightly esoteric case.

From a quick survey of peers an overloaded == which returns some other

type than Bool isn't desirable (same goes for >=, <=, !=, &&, ||) and
should be forbidden (this would be the counter-proposal to this).

However it allows interesting DSLs like creating layout constraints
with https://github.com/indragiek/SwiftAutoLayout

let layoutConstraint = view1.al_width == view2.al_width * 0.5 + 10.0

Allowing to import these 'conflicting' operators closely to where the
DSL is actually used could hint other developers to that DSL and
wouldn't pollute the global scope of the ViewController for example.

I thought about a syntactical solution quite a bit but I failed to
find something that looked right. So here's a syntax draft which is
exceptionally wrong:

import SwiftAutoLayout without fancy operators

func compareSomething() -> Bool {
  return view1.al_width == view2.al_width // will fail since not
Equatable, but al_width is known
}

func createConstraints() -> [NSLayoutConstraints] {
  import fancy operators from SwiftAutoLayout
  return [view1.al_width == view2.al_width] // succeeds
}

OR (probably an implementation nightmare)

func createConstraints() -> [NSLayoutConstraints] {
  import SwiftAutoLayout
  return [view1.al_width == view2.al_width]
}

Opinions against the proposal:
- Module devs shouldn't overload those operators and modify the return
type but use ====, !===, <==, ==>, &&&, ||| instead - Swift should
prevent that devs from doing this then.
- Devs will learn over time that (==, <=, >=, !=) are just the same as
+ and - and will have a return type depending on the arguments.
- Module devs should keep operators in submodules. (But then get
cyclic dependencies if they want to use these operators in the core
themselves.)
- Users of DSL modules should move the DSL dependent code into a
different file where it isn't mixed with code that doesn't need the
DSL.

Releated are the explicit includes and excludes when importing Modules
in the "Beef Up Import" thread
https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151221/004553.html


(Félix Cloutier) #2

C# lambda expressions can be used to initialize an expression tree. This is how C# avoids using strings to interface with "embedded languages" (most notably and very usefully SQL, but as I'm about to show it could help deal with layout constraints in Swift as well if we had them).

If we could use an @autoclosure in Swift to initialize an expression tree, we could do something like:

protocol ExpressionTreeConvertible {
  init(expression: ExpressionTree)
}

class NSLayoutConstraint: ExpressionTreeConvertible {
  init(expression: ExpressionTree) { /* magic */ }
}

let constraint: NSLayoutConstraint = view1.frame.width == view2.frame.width * 0.5 + 10.0

and not require an == overload that doesn't return a Boolean.

That's not necessarily in support of limiting operator overloading, though.

Félix

···

Le 8 janv. 2016 à 05:41:53, Marcel Jackwerth via swift-evolution <swift-evolution@swift.org> a écrit :

Sorry in advance for that slightly esoteric case.

From a quick survey of peers an overloaded == which returns some other
type than Bool isn't desirable (same goes for >=, <=, !=, &&, ||) and
should be forbidden (this would be the counter-proposal to this).

However it allows interesting DSLs like creating layout constraints
with https://github.com/indragiek/SwiftAutoLayout

let layoutConstraint = view1.al_width == view2.al_width * 0.5 + 10.0

Allowing to import these 'conflicting' operators closely to where the
DSL is actually used could hint other developers to that DSL and
wouldn't pollute the global scope of the ViewController for example.

I thought about a syntactical solution quite a bit but I failed to
find something that looked right. So here's a syntax draft which is
exceptionally wrong:

import SwiftAutoLayout without fancy operators

func compareSomething() -> Bool {
return view1.al_width == view2.al_width // will fail since not
Equatable, but al_width is known
}

func createConstraints() -> [NSLayoutConstraints] {
import fancy operators from SwiftAutoLayout
return [view1.al_width == view2.al_width] // succeeds
}

OR (probably an implementation nightmare)

func createConstraints() -> [NSLayoutConstraints] {
import SwiftAutoLayout
return [view1.al_width == view2.al_width]
}

Opinions against the proposal:
- Module devs shouldn't overload those operators and modify the return
type but use ====, !===, <==, ==>, &&&, ||| instead - Swift should
prevent that devs from doing this then.
- Devs will learn over time that (==, <=, >=, !=) are just the same as
+ and - and will have a return type depending on the arguments.
- Module devs should keep operators in submodules. (But then get
cyclic dependencies if they want to use these operators in the core
themselves.)
- Users of DSL modules should move the DSL dependent code into a
different file where it isn't mixed with code that doesn't need the
DSL.

Releated are the explicit includes and excludes when importing Modules
in the "Beef Up Import" thread
https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151221/004553.html
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution