A path forward on rationalizing unicode identifiers and operators

Because, ideally, I’d love to be able to do:

infix operator and: LogicalConjunctionPrecedence // or whatever the

precedence is called

func and(lhs: Bool, rhs: Bool) → Bool { return lhs && rhs }

let truthyValue = true and false

+1 (i like your thinking, even if it is unlikely to happen in swift)

(noteworthy, your example used "RIGHTWARDS ARROW" (U+2192) instead of ->,
whether on purpose or not.)

speaking of &&, was it just a copy-paste from C or is there a more
fundamental reason to use that instead of &? in C they had to use two
different operators because of the implicit int <-> bool promotions, but in
swift "true & false" vs "1 & 2" would have been distinguishable.

Mike

···

on Tue, 3 Oct 2017 11:00:33 -0600 Dave DeLong <swift@davedelong.com> wrote:

The difference between the & and && operators isn't to do with the implicit conversions; it's to do with whether both sides of the expression are evaluated or not.

false && system('rm -rf')

You really don't want to do that if both sides are executed ...

Alex

···

On 4 Oct 2017, at 11:42, Mike Kluev via swift-evolution <swift-evolution@swift.org> wrote:

on Tue, 3 Oct 2017 11:00:33 -0600 Dave DeLong <swift@davedelong.com <mailto:swift@davedelong.com>> > wrote:

> Because, ideally, I’d love to be able to do:
>
> infix operator and: LogicalConjunctionPrecedence // or whatever the precedence is called
> func and(lhs: Bool, rhs: Bool) → Bool { return lhs && rhs }
>
> let truthyValue = true and false

+1 (i like your thinking, even if it is unlikely to happen in swift)

(noteworthy, your example used "RIGHTWARDS ARROW" (U+2192) instead of ->, whether on purpose or not.)

speaking of &&, was it just a copy-paste from C or is there a more fundamental reason to use that instead of &? in C they had to use two different operators because of the implicit int <-> bool promotions, but in swift "true & false" vs "1 & 2" would have been distinguishable.

> Because, ideally, I’d love to be able to do:
>
> infix operator and: LogicalConjunctionPrecedence // or whatever the precedence is called
> func and(lhs: Bool, rhs: Bool) → Bool { return lhs && rhs }
>
> let truthyValue = true and false

+1 (i like your thinking, even if it is unlikely to happen in swift)

(noteworthy, your example used "RIGHTWARDS ARROW" (U+2192) instead of ->, whether on purpose or not.)

Heh, right. That was unintentional. I have system text replacements set up to turn ->, =>, <->, etc in to their Unicode arrow versions: →, ⇒, ↔︎

And using words (and even phrases like “is not”) as operators is totally possible. It would just require the parser to have a known list of all operators, and then greedily match characters as long as there’s an operator that’s prefixed by the current token, and then backtrack when it fails.

I implemented this style of operator definition and parsing in my open source math parsing library: https://github.com/davedelong/DDMathParser

Dave

···

On Oct 4, 2017, at 6:41 AM, Alex Blewitt via swift-evolution <swift-evolution@swift.org> wrote:

On 4 Oct 2017, at 11:42, Mike Kluev via swift-evolution <swift-evolution@swift.org> wrote:
on Tue, 3 Oct 2017 11:00:33 -0600 Dave DeLong <swift@davedelong.com> >> wrote:

speaking of &&, was it just a copy-paste from C or is there a more fundamental reason to use that instead of &? in C they had to use two different operators because of the implicit int <-> bool promotions, but in swift "true & false" vs "1 & 2" would have been distinguishable.

The difference between the & and && operators isn't to do with the implicit conversions; it's to do with whether both sides of the expression are evaluated or not.

false && system('rm -rf')

You really don't want to do that if both sides are executed ...

Alex

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

true. however what would stop the hypothetical "logical &" operator to not
evaluate the right hand side if the left
side is false similar to how && behaves? yes, it would make it more
different to the "bitwise &" operator, but they are
already a bit different.

(it was always backwards to me even in C: bitwise *single* & is for and-ing
*multiple* bit pairs, whilst a
*multi-character* && is for and-ing a single bool pair.)

Mike

···

On 4 October 2017 at 13:41, Alex Blewitt <alblue@apple.com> wrote:

On 4 Oct 2017, at 11:42, Mike Kluev via swift-evolution < > swift-evolution@swift.org> wrote:

speaking of &&, was it just a copy-paste from C or is there a more
fundamental reason to use that instead of &? in C they had to use two
different operators because of the implicit int <-> bool promotions, but in
swift "true & false" vs "1 & 2" would have been distinguishable.

The difference between the & and && operators isn't to do with the
implicit conversions; it's to do with whether both sides of the expression
are evaluated or not.

false && system('rm -rf')

You really don't want to do that if both sides are executed ...

actually, thanks for bringing this up as it leads up to a question:

how in swift do i define my &&& operator (that i may need for whatever
reason, e.g. logging) that will short-circuit
the calculation of right hand side if the left hand side is false?

infix operator &&&: LogicalConjunctionPrecedence

func &&&(left: Bool, right: Bool) -> Bool {
return left && right
}

as written it doesn't short-circuit. is it possible at all in swift?

Mike

···

On 4 October 2017 at 13:41, Alex Blewitt <alblue@apple.com> wrote:

The difference between the & and && operators isn't to do with the
implicit conversions; it's to do with whether both sides of the expression
are evaluated or not.

false && system('rm -rf')

You really don't want to do that if both sides are executed ...

speaking of &&, was it just a copy-paste from C or is there a more fundamental reason to use that instead of &? in C they had to use two different operators because of the implicit int <-> bool promotions, but in swift "true & false" vs "1 & 2" would have been distinguishable.

The difference between the & and && operators isn't to do with the implicit conversions; it's to do with whether both sides of the expression are evaluated or not.

false && system('rm -rf')

You really don't want to do that if both sides are executed ...

true. however what would stop the hypothetical "logical &" operator to not evaluate the right hand side if the left
side is false similar to how && behaves? yes, it would make it more different to the "bitwise &" operator, but they are
already a bit different.

Whether you are dealing with boolean/int types and whether you short-circuit the operators are orthogonal concerns.

(it was always backwards to me even in C: bitwise *single* & is for and-ing *multiple* bit pairs, whilst a
*multi-character* && is for and-ing a single bool pair.)

The && (c.f. ||) is explicitly for short-circuiting and is nothing to do with bit pairs or booleans, by specification.

See e.g. section 6.5.13 and 6.5.14.

http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf

Alex

···

On 4 Oct 2017, at 13:55, Mike Kluev <mike.kluev@gmail.com> wrote:
On 4 October 2017 at 13:41, Alex Blewitt <alblue@apple.com <mailto:alblue@apple.com>> wrote:

On 4 Oct 2017, at 11:42, Mike Kluev via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

When you call the function, the arguments will be evaluated prior to the function body - so this won't work (as you correctly noted).

However, you can wrap the second argument in an @autoclosure, which means it replaces the body of the expression with a function that evaluates the expression automatically:

infix operator &&&: LogicalConjunctionPrecedence

func &&&(left: Bool, right: @autoclosure () -> Bool) -> Bool {
  return left && right()
}

func no() -> Bool {
  print("no")
  return false
}

func yes() -> Bool {
  print("yes")
  return true
}

print(no() &&& yes())

no
false

Alex

···

On 4 Oct 2017, at 14:12, Mike Kluev <mike.kluev@gmail.com> wrote:

On 4 October 2017 at 13:41, Alex Blewitt <alblue@apple.com <mailto:alblue@apple.com>> wrote:

The difference between the & and && operators isn't to do with the implicit conversions; it's to do with whether both sides of the expression are evaluated or not.

false && system('rm -rf')

You really don't want to do that if both sides are executed ...

actually, thanks for bringing this up as it leads up to a question:

how in swift do i define my &&& operator (that i may need for whatever reason, e.g. logging) that will short-circuit
the calculation of right hand side if the left hand side is false?

infix operator &&&: LogicalConjunctionPrecedence

func &&&(left: Bool, right: Bool) -> Bool {
  return left && right
}

as written it doesn't short-circuit. is it possible at all in swift?

great. as you just shown, the difference of short-circuiting or not is not
inside the operator declaration itself (like it is defined in C)
but in the actual operator implementation, so we can have:

infix operator &&&: LogicalConjunctionPrecedence

func &&&(left: Bool, right: @autoclosure () -> Bool) -> Bool {
return left && right()
}

func &&&(left: Int, right: Int) -> Int {
return left & right
}

where the logical one short-circuits and bit-wise one doesn't.

Mike

···

On 4 October 2017 at 14:24, Alex Blewitt <alblue@apple.com> wrote:

On 4 October 2017 at 13:41, Alex Blewitt <alblue@apple.com> wrote:

The difference between the & and && operators isn't to do with the
implicit conversions; it's to do with whether both sides of the expression
are evaluated or not.

However, you can wrap the second argument in an @autoclosure, which means
it replaces the body of the expression with a function that evaluates the
expression automatically:

infix operator &&&: LogicalConjunctionPrecedence

func &&&(left: Bool, right: @autoclosure () -> Bool) -> Bool {
return left && right()
}

func &&&(left: Bool, right: @autoclosure () -> Bool) -> Bool {

return left && right()
}

FTM, it would be nice to be able to "syntax sugar-ize" it into a better
looking:

func &&& (left: Bool, right: lazy Bool) -> Bool {
    return left && right // no parens here
}

Mike

···

On 4 October 2017 at 14:24, Alex Blewitt <alblue@apple.com> wrote: