What should x < y < z do?

Please compose all posts in Emacs.

Moderators: phlip, Moderators General, Prelates

What should (x < y < z) mean?

(x < y) < z
9
13%
(x < y) ∧ (y < z)
59
87%
 
Total votes: 68

User avatar
Robert'); DROP TABLE *;
Posts: 730
Joined: Mon Sep 08, 2008 6:46 pm UTC
Location: in ur fieldz

What should x < y < z do?

Postby Robert'); DROP TABLE *; » Sun Dec 12, 2010 7:26 pm UTC

A friend pointed this one out to me a couple of hours ago, so I'm asking what you think.

In mathematics, [imath]x < y < z[/imath] is true if y is in between, but not equal to, x and z. But in some programming languages, such as C, x < y < z is guaranteed to evaluate to true if z > 1, because it's actually evaluated as (x<y) < z. (x<y) returns either 0 or 1, and so [0,1] < z is true for all z > 1. In other languages, it works the math way.

Should programming work the math way, or the C way?
...And that is how we know the Earth to be banana-shaped.

User avatar
enk
Posts: 754
Joined: Mon Sep 10, 2007 12:20 am UTC
Location: Aalborg, Denmark
Contact:

Re: What should x < y < z do?

Postby enk » Sun Dec 12, 2010 11:11 pm UTC

The C way is meant for computers more than for humans, and it will lead to errors just like "if (x = 5) ohshit();".
phlip wrote:Ha HA! Recycled emacs jokes.

User avatar
Thesh
Made to Fuck Dinosaurs
Posts: 6165
Joined: Tue Jan 12, 2010 1:55 am UTC
Location: Colorado

Re: What should x < y < z do?

Postby Thesh » Mon Dec 13, 2010 12:28 am UTC

Outside of a programming language, x < y < z should mean x < y and y < z. Within a programming language, I am fine with having to write (x<y) && (y<z). Although I can see how it would be nice in some situations, it makes it more complicated to define the rules.
Summum ius, summa iniuria.

User avatar
phlip
Restorer of Worlds
Posts: 7551
Joined: Sat Sep 23, 2006 3:56 am UTC
Location: Australia
Contact:

Re: What should x < y < z do?

Postby phlip » Mon Dec 13, 2010 12:52 am UTC

I can't remember what language it was, but I'm sure I've used one once that has "a == b == c" meaning "(a==b) && (b == c)", and similarly for inequalities. Also "a == b or c" meaning "(a == b) || (a == c)". Some kind of special-purpose language... maybe Inform? I can't remember.

I guess it's handy syntactic sugar, but that's all it is, and it makes the grammar of the language much more complicated... the equality and inequality tests no longer being binary operators but now arbitrary-size operators...

Code: Select all

enum ಠ_ಠ {°□°╰=1, °Д°╰, ಠ益ಠ╰};
void ┻━┻︵​╰(ಠ_ಠ ⚠) {exit((int)⚠);}
[he/him/his]

User avatar
Thesh
Made to Fuck Dinosaurs
Posts: 6165
Joined: Tue Jan 12, 2010 1:55 am UTC
Location: Colorado

Re: What should x < y < z do?

Postby Thesh » Mon Dec 13, 2010 12:56 am UTC

phlip wrote:I can't remember what language it was, but I'm sure I've used one once that has "a == b == c" meaning "(a==b) && (b == c)", and similarly for inequalities. Also "a == b or c" meaning "(a == b) || (a == c)". Some kind of special-purpose language... maybe Inform? I can't remember.

I guess it's handy syntactic sugar, but that's all it is, and it makes the grammar of the language much more complicated... the equality and inequality tests no longer being binary operators but now arbitrary-size operators...


For those two, you could borrow from SQL and keep the grammar simple:

a == all (b,c)
a == any (b,c)
Summum ius, summa iniuria.

User avatar
Meteorswarm
Posts: 979
Joined: Sun Dec 27, 2009 12:28 am UTC
Location: Ithaca, NY

Re: What should x < y < z do?

Postby Meteorswarm » Mon Dec 13, 2010 3:32 am UTC

phlip wrote:I can't remember what language it was, but I'm sure I've used one once that has "a == b == c" meaning "(a==b) && (b == c)", and similarly for inequalities. Also "a == b or c" meaning "(a == b) || (a == c)". Some kind of special-purpose language... maybe Inform? I can't remember.

I guess it's handy syntactic sugar, but that's all it is, and it makes the grammar of the language much more complicated... the equality and inequality tests no longer being binary operators but now arbitrary-size operators...


a<b<c seems to work as intended in python:

Code: Select all

>>> a = 1
>>> b = 2
>>> c = 3
>>> a<b<c
True
>>> a<c<b
False
>>> b<a<c
False
>>> a<c
True


and so does a == b == c

Code: Select all

>>> d = 1
>>> a == 1 == d
True
>>> a == 1 == b
False
>>> a == b == d
False
>>> b == 1 == d
False
The same as the old Meteorswarm, now with fewer posts!

User avatar
Xanthir
My HERO!!!
Posts: 5310
Joined: Tue Feb 20, 2007 12:49 am UTC
Location: The Googleplex
Contact:

Re: What should x < y < z do?

Postby Xanthir » Tue Dec 14, 2010 11:41 pm UTC

Python supports chaining the boolean operators. So does Lisp, because they're not operators, just n-ary functions:

Code: Select all

(< x y z)
#| return true iff (and (< x y) (< y z)) |#
(= x y z)
#| return true iff (and (= x y) (= y z)) |#
(defun fibs (n &optional (a 1) (b 1)) (take n (unfold '+ a b)))

User avatar
enk
Posts: 754
Joined: Mon Sep 10, 2007 12:20 am UTC
Location: Aalborg, Denmark
Contact:

Re: What should x < y < z do?

Postby enk » Thu Dec 16, 2010 4:41 pm UTC

I like how someone changed their vote from the first to the second poll option :)
phlip wrote:Ha HA! Recycled emacs jokes.

User avatar
Robert'); DROP TABLE *;
Posts: 730
Joined: Mon Sep 08, 2008 6:46 pm UTC
Location: in ur fieldz

Re: What should x < y < z do?

Postby Robert'); DROP TABLE *; » Thu Dec 16, 2010 7:56 pm UTC

Xanthir wrote:Python supports chaining the boolean operators. So does Lisp, because they're not operators, just n-ary functions:

Code: Select all

(< x y z)
#| return true iff (and (< x y) (< y z)) |#
(= x y z)
#| return true iff (and (= x y) (= y z)) |#

Though I'd argue that Lisp sidesteps the issue by making (x < y < z) an invalid/nonsensical statement.
...And that is how we know the Earth to be banana-shaped.

troyp
Posts: 557
Joined: Thu May 22, 2008 9:20 pm UTC
Location: Lismore, NSW

Re: What should x < y < z do?

Postby troyp » Fri Dec 17, 2010 11:58 am UTC

phlip wrote:I can't remember what language it was, but I'm sure I've used one once that has "a == b == c" meaning "(a==b) && (b == c)", and similarly for inequalities. Also "a == b or c" meaning "(a == b) || (a == c)". Some kind of special-purpose language... maybe Inform? I can't remember.

I guess it's handy syntactic sugar, but that's all it is, and it makes the grammar of the language much more complicated... the equality and inequality tests no longer being binary operators but now arbitrary-size operators...

In Python you can chain as many comparison operators as you like and they're ANDed. I think this is a good choice for Python, and probably most languages. It's not that complicated and the operators are still binary, it's just instead of having, say, a left- or right-associating law, you have a chaining law to interpret a sequence of operations (*). The only thing a bit funny about this is that bool is actually an int subtype in Python, and you can add True + 1 to give 2, which makes a case for having associative comparison operators like in C. Still, no-one really *thinks* of bools as ints (well, I don't anyway), so what the hell - chained comparisons are way more convenient.
That ==...or syntax is just evil though - that's gotta make things more complicated.

I always wish Haskell had declarations for nonassociative (t->t->Bool) operators to allow this sort of chaining so you could just say "infixc 4 >" etc. Haskell already has a very mathy syntax and it should fit right in.

(*) of course, you have to "share" the middle operands between the 2 operators in order to regard them as just binary operators...which I guess is why you're considering them as n-ary compound operators.

User avatar
chridd
Has a vermicelli title
Posts: 822
Joined: Tue Aug 19, 2008 10:07 am UTC
Location: ...Earth, I guess?
Contact:

Re: What should x < y < z do?

Postby chridd » Tue Dec 21, 2010 6:07 am UTC

troyp wrote:I always wish Haskell had declarations for nonassociative (t->t->Bool) operators to allow this sort of chaining so you could just say "infixc 4 >" etc. Haskell already has a very mathy syntax and it should fit right in.
It's possible to define something sort of like that, if you use different symbols for the first and second operators (e.g., x <| y |< z instead of x < y < z).

Spoilered for length:
Spoiler:

Code: Select all

-- | Define chained operators, for ease of entering expressions like 1 < 2 < 3.
-- This module defines three extra variations of each of the operators '<',
-- '<=', and '==', for use at the beginning, middle, and end of such chains.
-- These operators have vertical bars on the inside of the chain, for instance:
--
-- >x <| y |< z
-- >1 <| 2 |<| 3 |<=| 3 |< 4
-- >square (0,0) ==| square (0,1) |== square (0,2)
--
-- These operators are defined to be left-associative and the same precedence
-- as the ordinary comparison operators.
--
-- Copyright (c) 2010 chridd
module ChainCompare where

chainBegin :: (a -> b -> Bool) -> a -> b -> Maybe b
chainBegin op x y = if x `op` y then Just y else Nothing

chainEnd :: (a -> b -> Bool) -> Maybe a -> b -> Bool
chainEnd op x y = maybe False (`op` y) x

chainMiddle :: (a -> b -> Bool) -> Maybe a -> b -> Maybe b
chainMiddle = chainBegin . chainEnd

infixl 4 <|, |<, |<|
(<|) :: Ord a => a -> a -> Maybe a
(<|) = chainBegin (<)
(|<) :: Ord a => Maybe a -> a -> Bool
(|<) = chainEnd (<)
(|<|) :: Ord a => Maybe a -> a -> Maybe a
(|<|) = chainMiddle (<)

infixl 4 <=|, |<=, |<=|
(<=|) :: Ord a => a -> a -> Maybe a
(<=|) = chainBegin (<=)
(|<=) :: Ord a => Maybe a -> a -> Bool
(|<=) = chainEnd (<=)
(|<=|) :: Ord a => Maybe a -> a -> Maybe a
(|<=|) = chainMiddle (<=)

infixl 4 ==|, |==, |==|
(==|) :: Eq a => a -> a -> Maybe a
(==|) = chainBegin (==)
(|==) :: Eq a => Maybe a -> a -> Bool
(|==) = chainEnd (==)
(|==|) :: Eq a => Maybe a -> a -> Maybe a
(|==|) = chainMiddle (==)
~ chri d. d. /tʃɹɪ.di.di/ (Phonotactics, schmphonotactics) · she(?)(?(?)(?))(?(?(?))(?))(?) · Forum game scores
I'm cool, just look at my sunglasses. 8-)
mittfh wrote:I wish this post was very quotable...
flicky1991 wrote:In both cases the quote is "I'm being quoted too much!"

Goplat
Posts: 490
Joined: Sun Mar 04, 2007 11:41 pm UTC

Re: What should x < y < z do?

Postby Goplat » Fri Dec 24, 2010 2:17 am UTC

Neither, it should be an error. x < y is a boolean, and it doesn't make sense to talk about a boolean being "less than" something unless you treat it as a number (which should require an explicit conversion).

User avatar
Xanthir
My HERO!!!
Posts: 5310
Joined: Tue Feb 20, 2007 12:49 am UTC
Location: The Googleplex
Contact:

Re: What should x < y < z do?

Postby Xanthir » Wed Dec 29, 2010 4:54 pm UTC

Well, duh. The question is if *that* behavior makes more sense, or if it's better to be smart about chained comparisons and treat them as sugar for the "(x<y) and (y<z)".
(defun fibs (n &optional (a 1) (b 1)) (take n (unfold '+ a b)))

troyp
Posts: 557
Joined: Thu May 22, 2008 9:20 pm UTC
Location: Lismore, NSW

Re: What should x < y < z do?

Postby troyp » Fri Dec 31, 2010 2:59 am UTC

chridd wrote:It's possible to define something sort of like that, if you use different symbols for the first and second operators (e.g., x <| y |< z instead of x < y < z).

I remember when I first learnt Haskell I made variadic functions and then I tried to modify them to make chained comparators. I had trouble getting it to work with the infix operators though. I didn't want to use new operators, let alone different ones at the first and last positions (but I was using a start and end symbol to enclose the entire expression). I think I gave up on it in the end (it wouldn't have been practical anyway).
Your implementation is quite nice: if you changed the vertical bars to dots, it would look pretty unobtrusive eg.

Code: Select all

1 <. 2 .<. 4 .>.3
assuming you're not already using those symbols.
Even so, once you need to use special symbols to chain the operators, I'd probably just prefer the usual syntax

Code: Select all

1<2 && 2<4 && 4>3
It's not so bad, although I would still prefer builtin support for chaining

User avatar
flying sheep
Posts: 63
Joined: Sun Jan 31, 2010 12:35 am UTC

Re: What should x < y < z do?

Postby flying sheep » Sun Jan 02, 2011 6:17 pm UTC

Goplat wrote:Neither, it should be an error. x < y is a boolean, and it doesn't make sense to talk about a boolean being "less than" something unless you treat it as a number (which should require an explicit conversion).

let’s talk about language design:
if you are designing a language and a certain phrase can be interpretted intuitively and unambiguously by humans, why throw a syntax error?

so this is really about typing and expectations:
if your language is statically typed, it should be interpretted the mathematical way. (x<y<z can only mean one thing or be a syntax error, so it should work)
if your language is dynamically typed (a bool can be compared with a non-bool), it should throw an error, except the language design has guidelines which only alow one way.
e.g. python has the principle of least surprise, so it works like you would expect (the mathematical way)
languages like perl, on the other hand, should really thow an error in this case, nobody has ever suspected perl of having guidelines or the principle of least surprise (more like the principle of least script size)

to sum things up: it should be interpretted the mathematical way or throw an error, if the language design isn’t clear.

Random-person
Posts: 21
Joined: Mon Dec 13, 2010 1:25 am UTC

Re: What should x < y < z do?

Postby Random-person » Sat Jan 08, 2011 1:28 am UTC

flying sheep wrote:
Goplat wrote:Neither, it should be an error. x < y is a boolean, and it doesn't make sense to talk about a boolean being "less than" something unless you treat it as a number (which should require an explicit conversion).

let’s talk about language design:
if you are designing a language and a certain phrase can be interpretted intuitively and unambiguously by humans, why throw a syntax error?

Because x < y < z is very much not something that can be interpreted intuitively and unambiguously by humans!

That's why it's better in some cases to throw an error. Sure, it might be annoying the first time, but you would prevent a bug that could be really nasty.
It all depends on what you think is most important: for a program to be bug free or for a program to be quick and easy to use. I think that both language types should exist, like they do today.

User avatar
Xanthir
My HERO!!!
Posts: 5310
Joined: Tue Feb 20, 2007 12:49 am UTC
Location: The Googleplex
Contact:

Re: What should x < y < z do?

Postby Xanthir » Sun Jan 09, 2011 6:28 pm UTC

Wait, what? You should have seen notation like "x < y < z" in high-school Algebra, if not sooner. It should be intuitively obvious.
(defun fibs (n &optional (a 1) (b 1)) (take n (unfold '+ a b)))

Goplat
Posts: 490
Joined: Sun Mar 04, 2007 11:41 pm UTC

Re: What should x < y < z do?

Postby Goplat » Tue Jan 11, 2011 7:30 am UTC

It's only obvious because we're used to it. Other operators don't work like that: x + y + z is (x + y) + z, x - y - z is (x - y) - z, x * y * z is (x * y) * z, and x / y / z is (x / y) / z. It's certainly not intuitive at all that just because OP returns a boolean, "x OP y OP z" should instead mean "(x OP y) && (y OP z)".

What if the || operator worked like that? x || y || z would be treated as (x || y) && (y || z), which is logically equivalent to y && (x || z). Not so intuitive now, is it :D

There is no place for inconsistency in programming languages. Writing bug-free code is hard enough as it is.

User avatar
flying sheep
Posts: 63
Joined: Sun Jan 31, 2010 12:35 am UTC

Re: What should x < y < z do?

Postby flying sheep » Tue Jan 11, 2011 12:14 pm UTC

Goplat wrote:It's only obvious because we're used to it […]
stop right here!
isn’t that what it’s all about?

User avatar
Robert'); DROP TABLE *;
Posts: 730
Joined: Mon Sep 08, 2008 6:46 pm UTC
Location: in ur fieldz

Re: What should x < y < z do?

Postby Robert'); DROP TABLE *; » Tue Jan 11, 2011 8:15 pm UTC

Goplat wrote:What if the || operator worked like that? x || y || z would be treated as (x || y) && (y || z), which is logically equivalent to y && (x || z). Not so intuitive now, is it :D

But it is, because this is functionally identical to the other possible meaning, (x || y) || z.
...And that is how we know the Earth to be banana-shaped.

User avatar
Yakk
Poster with most posts but no title.
Posts: 11082
Joined: Sat Jan 27, 2007 7:27 pm UTC
Location: E pur si muove

Re: What should x < y < z do?

Postby Yakk » Tue Jan 11, 2011 8:26 pm UTC

a OP1 b OP1 c "should" mean OP1( a, b, c ). In effect, demand that your operators be n-ary.

If operators can belong to an operator class, you can talk about operators whose n-ary definition is chained-left-to-right-binary or tree-binary, others whose n-ary definition is left-to-right, others whose n-ary definition is right-to-left, and others whose n-ary definition is pair-wise and and'd (or pairwise and or'd).

a OP1 b OP2 c ... means what? One rule is "you must use brackets". Another is to require that your operators specify order of application and binding.

a+b*c -- should we require brackets? If not, how do we allow user-defined operators as much freedom in terms of order-of-operations as built-in operators?
One of the painful things about our time is that those who feel certainty are stupid, and those with any imagination and understanding are filled with doubt and indecision - BR

Last edited by JHVH on Fri Oct 23, 4004 BCE 6:17 pm, edited 6 times in total.

User avatar
Xanthir
My HERO!!!
Posts: 5310
Joined: Tue Feb 20, 2007 12:49 am UTC
Location: The Googleplex
Contact:

Re: What should x < y < z do?

Postby Xanthir » Tue Jan 11, 2011 8:54 pm UTC

Goplat wrote:It's only obvious because we're used to it. Other operators don't work like that: x + y + z is (x + y) + z, x - y - z is (x - y) - z, x * y * z is (x * y) * z, and x / y / z is (x / y) / z. It's certainly not intuitive at all that just because OP returns a boolean, "x OP y OP z" should instead mean "(x OP y) && (y OP z)".

What if the || operator worked like that? x || y || z would be treated as (x || y) && (y || z), which is logically equivalent to y && (x || z). Not so intuitive now, is it :D

There is no place for inconsistency in programming languages. Writing bug-free code is hard enough as it is.

Math operators aren't comparison operators, nor are logical operators. Math operators take numbers as input and produce numbers as output. Logical operators take bools as input and produces bools as output. For both of these, it's sensical that chained operators work by reducing over the list, because the output is a valid input for another round of computation.

Comparison operators take arbitrary comparable values as input and produce bools as output. It does *not* make sense to evaluate these by reducing over the list (particularly as bools aren't comparable, except by arbitrary fiat). It *does* make sense to evaluate these pairwise and then take the AND of all the results.
(defun fibs (n &optional (a 1) (b 1)) (take n (unfold '+ a b)))


Return to “Religious Wars”

Who is online

Users browsing this forum: No registered users and 2 guests