Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

>< swap operator

564 views
Skip to first unread message

skybu...@hotmail.com

unread,
Aug 13, 2018, 3:53:54 PM8/13/18
to
Hello,

I just had a funny idea how to implement a swap operator for types:

A >< B

would mean swap A and B.

Bye,
Skybuck.

Rick C. Hodgin

unread,
Aug 13, 2018, 4:05:09 PM8/13/18
to
On 08/13/2018 03:53 PM, skybu...@hotmail.com wrote:
> ... a swap operator for types:
> A >< B
> would mean swap A and B.

Clever.

--
Rick C. Hodgin

fir

unread,
Aug 13, 2018, 4:46:52 PM8/13/18
to
not like to much look of it

a><b for me looks more like a part of

a>c<d which would mean c is betweena nd d
[sorry no betwean but less on both a and b, between is a<c<b)
(and could be eventually introduced as it would be usefull)

i recently incidentally thinked on a<>b
as a "is not equal" operator (this is becouse when you use != you need to reach for ! which i liked to use as 'else' operator in sugar for ifs (a?b!c)
(more than : which in turn desines code
label) if use <> yourei in small family of relational operators (hovever even there is a problem as = is also assignment





Anton Shepelev

unread,
Aug 14, 2018, 4:20:00 AM8/14/18
to
fir:

> i recently incidentally thinked on a<>b

This is it is in Pascal.

--
() ascii ribbon campaign - against html e-mail
/\ http://preview.tinyurl.com/qcy6mjc [archived]

skybu...@hotmail.com

unread,
Aug 14, 2018, 9:16:24 AM8/14/18
to
I kinda do like the look of it.

It looks like an X of XOR.

And there is an XOR swapping method !

Google it, first entry should be wikipedia xor swap !

xor swap is risky if A and B is same and also if A and B is aliased.

But it's a nice reminder ! =D

Bye,
Skybuck =D

bart...@gmail.com

unread,
Aug 14, 2018, 10:50:55 AM8/14/18
to
How about just swap(x,y) then you don't need to explain what >< means.

--
Bart

David Brown

unread,
Aug 14, 2018, 10:59:24 AM8/14/18
to
On 14/08/18 16:50, bart...@gmail.com wrote:
> How about just swap(x,y) then you don't need to explain what >< means.
>

Or if you don't need to stick to C syntax:

x, y = y, x


Keith Thompson

unread,
Aug 14, 2018, 1:46:18 PM8/14/18
to
The problem is, that *is* C syntax. Due to the low precedence of the
comma operator, it's equivalent to

x, (y = y), x

This:

(x, y) = (y, x)

is also valid C syntax, but it's a constraint violation because (x, y)
is not an lvalue (and the value of y on the RHS would be discarded
anyway).

--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

David Brown

unread,
Aug 14, 2018, 2:03:27 PM8/14/18
to
On 14/08/18 19:46, Keith Thompson wrote:
> David Brown <david...@hesbynett.no> writes:
>> On 14/08/18 16:50, bart...@gmail.com wrote:
>>> How about just swap(x,y) then you don't need to explain what >< means.
>>
>> Or if you don't need to stick to C syntax:
>>
>> x, y = y, x
>
> The problem is, that *is* C syntax. Due to the low precedence of the
> comma operator, it's equivalent to
>
> x, (y = y), x
>
> This:
>
> (x, y) = (y, x)
>
> is also valid C syntax, but it's a constraint violation because (x, y)
> is not an lvalue (and the value of y on the RHS would be discarded
> anyway).
>

Yes, I realise the comma operator in C means you can't have multiple
assignment (or swap) like this. I assume no one in the thread was
talking about C - despite the newsgroup - but a hypothetical operator in
a hypothetical language. When creating a new language that is not
burdened by compatibility with C (like Rick or Bart's various
languages), no one in their right mind would come up with C's comma
operator. And that would leave you free to use multiple assignment like
this in a convenient and natural way - so no "swap" operator would be
needed.

fir

unread,
Aug 14, 2018, 2:32:14 PM8/14/18
to
a b = b a is also an option, hovever
there is realm of decision if "," should be more separator (compared to space) or more "gluer"

a b, c, d e f, g

this is if those above is more

a (b c d) e (f g) or
(ab) c (d e f) g

im not sure as to this (hovever recently thinked on what i call 'atoms' in c
(atoms are like operators but also include immediates and labels/identifiers) (when thinking on atoms i went to a concept of vectors:
some atoms naturally glue in particles /particoules like a+b glues together or
a+b/4-8 also glues in opne particle but then some not and you got vector, and nows the question what to do wit them

Keith Thompson

unread,
Aug 14, 2018, 2:37:51 PM8/14/18
to
David Brown <david...@hesbynett.no> writes:
[...]
> Yes, I realise the comma operator in C means you can't have multiple
> assignment (or swap) like this. I assume no one in the thread was
> talking about C - despite the newsgroup - but a hypothetical operator in
> a hypothetical language.
[...]

I didn't make that assumption -- but then I didn't see the first few
articles in the thread.

Thiago Adams

unread,
Aug 14, 2018, 2:50:44 PM8/14/18
to
On Monday, August 13, 2018 at 4:53:54 PM UTC-3, skybu...@hotmail.com wrote:
> Hello,
>
> I just had a funny idea how to implement a swap operator for types:
>
> A >< B
>
> would mean swap A and B.
>

I did the same suggestion some time ago. I consider swap a
basic operation like copy.

I think the C language is in a very stable point at this
moment.
It is not easy to find a feature that doesn't broke this
state. (some features are like that but others not)

As soon as a new feature is added it might have consequences,
and one feature will require another one in a domino effect.


Let's say we could create some parametrized function then
the swap becomes an redundant feature that could be implemented
using other language features , this is the puzzle to be solved.

It is like an evolutive process were we don't want to make mistakes
because we don't want to broke compatibility every generation.

I think there are much more algorithms and concepts like swap that
are universal operations.
I would say that destructor and init also are universal concepts,
so the puzzle should be make them all work and be customized.








David Brown

unread,
Aug 14, 2018, 3:17:09 PM8/14/18
to
On 14/08/18 20:37, Keith Thompson wrote:
> David Brown <david...@hesbynett.no> writes:
> [...]
>> Yes, I realise the comma operator in C means you can't have multiple
>> assignment (or swap) like this. I assume no one in the thread was
>> talking about C - despite the newsgroup - but a hypothetical operator in
>> a hypothetical language.
> [...]
>
> I didn't make that assumption -- but then I didn't see the first few
> articles in the thread.
>

I /did/ make that assumption, but of course I could have been wrong
about it (no one can guess what goes through Skybuck's mind), so it was
useful that you pointed out that "x, y = y, x" could not work in C.

bart...@gmail.com

unread,
Aug 14, 2018, 7:24:19 PM8/14/18
to
David Brown: "Or if you don't need to stick to C syntax:

x, y = y, x "

That will do the job but is not really the same as a proper, built-in swap.

Operands are evaluated twice for a start. And for complex ones, you need to double check that each x and y (representing complex terms) exactly matches the other x and y.

It is more error prone. Plus, you can't be sure whether someone has made a typo, or intends something other than a swap.

So, a real swap is better.
--
Bart.

Siri Cruise

unread,
Aug 14, 2018, 8:07:55 PM8/14/18
to
In article <36d546c5-b471-45fc...@googlegroups.com>,
skybu...@hotmail.com wrote:

> Hello,
>
> I just had a funny idea how to implement a swap operator for types:
>
> A >< B
>
> would mean swap A and B.

It's a special case of a more general operation missing from C, the parallel
assignment: A,B := B,A. For example you can generate Fibonacci with
int a, int b := 1, 1;
do true then a,b := b,a+b od

--
:-<> Siri Seal of Disavowal #000-001. Disavowed. Denied. Deleted. @
'I desire mercy, not sacrifice.' /|\
An almond doesn't lactate. This post / \
Yet another supercilious snowflake for justice. insults Islam. Mohammed

fir

unread,
Aug 15, 2018, 5:22:50 AM8/15/18
to
W dniu środa, 15 sierpnia 2018 02:07:55 UTC+2 użytkownik Siri Cruise napisał:
> In article <36d546c5-b471-45fc...@googlegroups.com>,
> skybu...@hotmail.com wrote:
>
> > Hello,
> >
> > I just had a funny idea how to implement a swap operator for types:
> >
> > A >< B
> >
> > would mean swap A and B.
>
> It's a special case of a more general operation missing from C, the parallel
> assignment: A,B := B,A. For example you can generate Fibonacci with
> int a, int b := 1, 1;
> do true then a,b := b,a+b od
>
good one

David Brown

unread,
Aug 15, 2018, 5:33:01 AM8/15/18
to
"x, y = y, x" is a multiple assignment. Yes, operands will be evaluated
twice, at least logically. In practice they will be simple enough for a
compiler to optimise - no decent compiler (for this hypothetical
language) is going to duplicate the address calculations needed for:

xs[2 * i + j], xs[2 * i + j + 1] = xs[2 * i + j + 1], xs[2 * i + j]

And no one is going to write:

xs[rand()], ys[rand()] = ys[rand()], xs[rand()]

thinking it is a swap.

I agree that an explicit "swap" function can be clearer and more
explicit, which is a good thing. But multiple assignment is more
flexible, and would be a fine way to implement a "swap" function.


fir

unread,
Aug 15, 2018, 5:35:04 AM8/15/18
to
yet maybe more general approach is to noticing that c generally not gandles vectors

(by vector i call something
like 1 2 3 4 5 or a b c g k where
those elements may be somewhat 'anything'
but separate)
c normally handles only this one separate
value but not work on vectors, and it would be nice not only make assigments
but give more general language suport for such 'vectors'

like someone could imagine vector arithmetic like

a = + ((a b c) * (d e f))

for

a = a*d + b*e + c*f

though maybe something better can be invented here

fir

unread,
Aug 15, 2018, 6:09:30 AM8/15/18
to
some alternative option here above it would be to make 3-vector of 3-vectors
(of 9 multipiles in summary) and then use
slecct operator like [2][] to take [][1]
rows or columns or elements
((a b c) * (d e f)) [0][0],[1][1],[2][2]
or/and use ** operator for such multiply and * for this diagonal only etc etc
though im not sure it it is all ok, feels a bit weird

back then i thinked on option of 2*(a b c d) like 2*a*b*c*d and (a b c d)*2 like (a*2 b*2 c*2 d*2) though also it feels a beet weird (so this is any way any
proposition of solution just some opening for the topic to think)

fir

unread,
Aug 15, 2018, 6:24:13 AM8/15/18
to
W dniu środa, 15 sierpnia 2018 11:22:50 UTC+2 użytkownik fir napisał:
same probably is when you calculate mandelbrot fractal you got

double re_n = re*re - im*im + cr;
double im_n = 2*re*im+ ci;

re = re_n;
im = im_n;

you must make those copies when it could probably be

re, im = re*re - im*im + cr,
2*re*im + ci;

(i was writing on this paralel form of execution form long time ago hovever..
some thread on p.comp.lnag.c where it was about it may be more friendly for internal chanells in x86 (called executions streams?) i dont remember the details)

Siri Cruise

unread,
Aug 15, 2018, 7:22:09 AM8/15/18
to
In article <ddc1a534-1402-43f2...@googlegroups.com>,
Edgser Dijkstra, god rest his soul.

fir

unread,
Aug 15, 2018, 7:51:27 AM8/15/18
to
W dniu środa, 15 sierpnia 2018 12:24:13 UTC+2 użytkownik fir napisał:
> W dniu środa, 15 sierpnia 2018 11:22:50 UTC+2 użytkownik fir napisał:
> > W dniu środa, 15 sierpnia 2018 02:07:55 UTC+2 użytkownik Siri Cruise napisał:
> > > In article <36d546c5-b471-45fc...@googlegroups.com>,
> > > skybu...@hotmail.com wrote:
> > >
> > > > Hello,
> > > >
> > > > I just had a funny idea how to implement a swap operator for types:
> > > >
> > > > A >< B
> > > >
> > > > would mean swap A and B.
> > >
> > > It's a special case of a more general operation missing from C, the parallel
> > > assignment: A,B := B,A. For example you can generate Fibonacci with
> > > int a, int b := 1, 1;
> > > do true then a,b := b,a+b od
> > >
> > good one
>
> same probably is when you calculate mandelbrot fractal you got
>
> double re_n = re*re - im*im + cr;
> double im_n = 2*re*im+ ci;
>
> re = re_n;
> im = im_n;
>
> you must make those copies when it could probably be
>
> re, im = re*re - im*im + cr,
> 2*re*im + ci;

in yet more vector form it would be hovever


re, im = (re*re-im*im, 2*re*im) + (cr, ci);

what in fact better describes what
is goin here, though there is that problem of "," being not accustomed to being read as gluer

without parenthesis it looks like assigning 3-vector to 2-vector (2v=3v)
(onles noy 4v with 2nd as assigent)

re, im = re*re-im*im, 2*re*im + cr, ci;

unles someone knows this is gluer and read it as 2v = 2v+ 2v - and now it seems there is some problem here as you would need to know what is glued together,
fro example if it is not

re, im = (re*re-im*im, 2*re) * (im + cr, ci);

and so on

eventually some may use , as a separator and then

re im = re*re-im*im 2*re*im + cr ci;

which may bring close problems to the above, it seems wnay you use parenthesis its all right, but if you would drop
some it probably will reduce to simple 4v form
if so

a,b = b,a will also stop work as its 3v
and you need (a b) = (b a) unles redefining , to be stronger then arithmetic but then

re, im = re*re-im*im, 2*re*im + cr, ci;

would look like

re, im = (re*re-im*im),(2*re*im) + cr, ci;

so its not much fortunate (unless for example assuming that operators with no spaces around, glue stronger than ' and those with spaces glue weaker

then probably

re,im = re*re-im*im,2*re*im + cr,ci;

that would compile but in turn no free spaces

fir

unread,
Aug 15, 2018, 8:06:13 AM8/15/18
to

note this previous form is easier to define ()-less

re, im = re*re - im*im + cr,
2*re*im + ci;

as it could be compiled in such ruleset
1) arithmetic glues/links/joins first

re, im = (re*re-im*im+cr), (2*re*im+ci);

2) then ' build 2-nd level of particule

(re,im) = ((re*re-im*im+cr), (2*re*im+ci));

3) then assignment

then the second form probably could be written

re, im = re*re-im*im, 2*re*im + (cr, ci);

so maybe this ruleset is not so bad, amongst some others (not saying its best thoug seem as some tb be considered)

Ben Bacarisse

unread,
Aug 15, 2018, 9:43:40 AM8/15/18
to
Siri Cruise <chine...@yahoo.com> writes:

> In article <ddc1a534-1402-43f2...@googlegroups.com>,
> fir <profes...@gmail.com> wrote:
>
>> W dniu środa, 15 sierpnia 2018 02:07:55 UTC+2 użytkownik Siri Cruise napisał:
>> > In article <36d546c5-b471-45fc...@googlegroups.com>,
>> > skybu...@hotmail.com wrote:
>> >
>> > > Hello,
>> > >
>> > > I just had a funny idea how to implement a swap operator for types:
>> > >
>> > > A >< B
>> > >
>> > > would mean swap A and B.
>> >
>> > It's a special case of a more general operation missing from C, the
>> > parallel
>> > assignment: A,B := B,A. For example you can generate Fibonacci with
>> > int a, int b := 1, 1;
>> > do true then a,b := b,a+b od
>> >
>> good one
>
> Edgser Dijkstra, god rest his soul.

In a way, C does have multiple assignments in that function calls are
done "as if by assignment" so, with a compiler that eliminates tail
calls, you can write the code above in C as

void fib(int a, int b)
{
printf("%d\n", b);
fib(b, a+b);
}

together with a call to fib(0, 1).

Using 0 and printing b gives you one number before overflow. The
overflow-checked version would be

void fib(int a, int b)
{
printf("%d\n", b);
if (a <= INT_MAX - b) fib(b, a+b);
}

--
Ben.

fir

unread,
Aug 15, 2018, 10:08:48 AM8/15/18
to
interesting, this may men one can write mandelbrot calculator also as recursive calls
n=1;

foo(double re, double im)
{
n++;
if(re*re+im*im>4) return;
if(n==100) return;

foo(re*re-im*im+cr, 2*re*im+ci);
return;
}

Ike Naar

unread,
Aug 15, 2018, 11:51:26 AM8/15/18
to
On 2018-08-15, Siri Cruise <chine...@yahoo.com> wrote:
> In article <ddc1a534-1402-43f2...@googlegroups.com>,
> fir <profes...@gmail.com> wrote:
>
>> W dniu ?roda, 15 sierpnia 2018 02:07:55 UTC+2 u?ytkownik Siri Cruise napisa?:
>> > In article <36d546c5-b471-45fc...@googlegroups.com>,
>> > skybu...@hotmail.com wrote:
>> >
>> > > Hello,
>> > >
>> > > I just had a funny idea how to implement a swap operator for types:
>> > >
>> > > A >< B
>> > >
>> > > would mean swap A and B.
>> >
>> > It's a special case of a more general operation missing from C, the
>> > parallel
>> > assignment: A,B := B,A. For example you can generate Fibonacci with
>> > int a, int b := 1, 1;
>> > do true then a,b := b,a+b od
>> >
>> good one
>
> Edgser Dijkstra, god rest his soul.

Edsger Dijkstra, Siri mangle his name.

Bart

unread,
Aug 15, 2018, 11:52:13 AM8/15/18
to
On 15/08/2018 14:43, Ben Bacarisse wrote:

>>> W dniu środa, 15 sierpnia 2018 02:07:55 UTC+2 użytkownik Siri Cruise napisał:

>>>> It's a special case of a more general operation missing from C, the
>>>> parallel
>>>> assignment: A,B := B,A. For example you can generate Fibonacci with
>>>> int a, int b := 1, 1;
>>>> do true then a,b := b,a+b od

> In a way, C does have multiple assignments in that function calls are
> done "as if by assignment"


Not really. Otherwise we could eliminate normal assignments with the
same reasoning. We can't. At least, without making it considerably
harder to write programs. (Not for you, obviously.)

--
bart

skybu...@hotmail.com

unread,
Oct 1, 2018, 10:46:57 AM10/1/18
to
I have seen "swap" functions that would surprise you, they do something different than you thought. Therefore it's still required to examine the "swap" function.

With A> going to B and <B going to A, I think it's much more clear what is going to happen :)

Plus it's the shortest notation so far ;)

Bye,
Skybuck =D

John Bode

unread,
Oct 1, 2018, 6:00:06 PM10/1/18
to
On Monday, August 13, 2018 at 2:53:54 PM UTC-5, skybu...@hotmail.com wrote:
> Hello,
>
> I just had a funny idea how to implement a swap operator for types:
>
> A >< B
>
> would mean swap A and B.
>
> Bye,
> Skybuck.

Personally, I would add a "swap" keyword:

a swap b;

rather than recycle relational operators.

Obviously, both operands must be modifiable lvalues.

What should the *result* of the expression be? The LHS after the swap? The RHS after
the swap? Should that result in itself be an lvalue? IOW, Should we allow expressions like

a swap b swap c

and if so, what should the result be? Obviously, this will require a fixed order of evaluation
and a sequence point after each operand is evaluated.

I can imagine some fun to be had with such an operator, especially if you allow things like

a swap b swap c swap d ...

Malcolm McLean

unread,
Oct 2, 2018, 6:06:32 AM10/2/18
to
That's the problem with a swap keyword.

A better idea is to add memswap() to string.h. A casual implementation
can provide a byte-copying loop very easily. A quality implementation
can special-case it to swapping out to a temporary, unless the size
argument is variable.

Bart

unread,
Oct 2, 2018, 6:43:52 AM10/2/18
to
On 01/10/2018 22:59, John Bode wrote:
> On Monday, August 13, 2018 at 2:53:54 PM UTC-5, skybu...@hotmail.com wrote:
>> Hello,
>>
>> I just had a funny idea how to implement a swap operator for types:
>>
>> A >< B
>>
>> would mean swap A and B.
>>
>> Bye,
>> Skybuck.
>
> Personally, I would add a "swap" keyword:
>
> a swap b;
>
> rather than recycle relational operators.
>
> Obviously, both operands must be modifiable lvalues.
>
> What should the *result* of the expression be?

Why does there need to be any result at all?

Either make swap a statement (for which 'swap(a,b)' works better), or
make it return void.

--
bart

Rick C. Hodgin

unread,
Oct 2, 2018, 8:21:02 AM10/2/18
to
On Monday, October 1, 2018 at 10:46:57 AM UTC-4, skybu...@hotmail.com wrote:
> On Tuesday, August 14, 2018 at 4:50:55 PM UTC+2, bart...@gmail.com wrote:
> > How about just swap(x,y) then you don't need to explain what >< means.
>
> I have seen "swap" functions that would surprise you, they do something different than you thought. Therefore it's still required to examine the "swap" function.
>
> With A> going to B and <B going to A, I think it's much more clear what is going to happen :)
>
> Plus it's the shortest notation so far ;)

I agree. I think "a >< b" is a great construction. I would
suggest that that operator should exist, along with "><=" so
that it works stand alone:

int a = 5, b = 3;

printf("a=%d, b=%d\n", a, b);

a ><= b;

printf("a=%d, b=%d\n", a, b);

The >< operator can still be used in-flight, in the middle of other
expressions, switching them there in place, which may yield the re-
sult of some intermediate able to be switched with the indicated
value.

I see a lot of potential for these swap operators.

--
Rick C. Hodgin

Bart

unread,
Oct 2, 2018, 8:58:15 AM10/2/18
to
On 02/10/2018 13:20, Rick C. Hodgin wrote:
> On Monday, October 1, 2018 at 10:46:57 AM UTC-4, skybu...@hotmail.com wrote:
>> On Tuesday, August 14, 2018 at 4:50:55 PM UTC+2, bart...@gmail.com wrote:
>>> How about just swap(x,y) then you don't need to explain what >< means.
>>
>> I have seen "swap" functions that would surprise you, they do something different than you thought. Therefore it's still required to examine the "swap" function.
>>
>> With A> going to B and <B going to A, I think it's much more clear what is going to happen :)
>>
>> Plus it's the shortest notation so far ;)
>
> I agree. I think "a >< b" is a great construction. I would
> suggest that that operator should exist, along with "><=" so
> that it works stand alone:
>
> int a = 5, b = 3;
>
> printf("a=%d, b=%d\n", a, b);
>
> a ><= b;

I think a><b is terrible. (And a><=b worse. Not least because I've no
idea what the difference is between ><= and ><. If a+b can be written
stand-alone, why can't a><b?)

One reason it's terrible is that it's just some random, made-up symbol
with no long history of use (unlike "+" for example).

And also, swap, IME, is quite an uncommon operation so doesn't need such
a compact and mysterious representation, and is never needed in an
expression so it doesn't need a result type.


(At one time I used ":=:" for swap, in a language where ":=" was
assignment so that ":=:" suggested a two-way assignment. But eventually
I dropped that and just used the much easier to type, and far more obvious:

swap(a,b)

What actually is the problem with just using this?)


> printf("a=%d, b=%d\n", a, b);
>
> The >< operator can still be used in-flight, in the middle of other
> expressions, switching them there in place, which may yield the re-
> sult of some intermediate able to be switched with the indicated
> value.

/Which/ intermediate value? Any return value must be an obvious one, but
there is no obvious result type from swap().

The only one I can think is for swap(a,b) to simply return the multiple
value (b,a), but such values are difficult to work with and require
further language features.

--
bart

Bart

unread,
Oct 2, 2018, 9:08:45 AM10/2/18
to
BTW if you're looking for a new language feature simple enough for
anyone to appreciate and understand, look at multiple assignments:

a, b, c = 10, 20, 30;

Here, this is equivalent to a=10, b=20, c=30, but it can also be used
like this:

a, b = b, a;

This is the equivalent of t1=b, t2=a, a=t1; b=t2, and has the effect of
swapping a and b. But it can also do more, like rotating a bunch of values.

(If you are using C syntax, then C's comma operator will screw this up:

a, b, c = 10, 20, 30;

is legal C, but has the effect of assigning 10 to c, and leaving a and b
unchanged. (This is somewhat surprising, I expected 30 to be assigned to
C.))


--
bart


Rick C. Hodgin

unread,
Oct 2, 2018, 9:09:02 AM10/2/18
to
On 10/2/2018 8:58 AM, Bart wrote:
> On 02/10/2018 13:20, Rick C. Hodgin wrote:
>> On Monday, October 1, 2018 at 10:46:57 AM UTC-4, skybu...@hotmail.com wrote:
>>> On Tuesday, August 14, 2018 at 4:50:55 PM UTC+2, bart...@gmail.com wrote:
>>>> How about just swap(x,y) then you don't need to explain what >< means.
>>>
>>> I have seen "swap" functions that would surprise you, they do something
>>> different than you thought. Therefore it's still required to examine the
>>> "swap" function.
>>>
>>> With A> going to B and <B going to A, I think it's much more clear what is
>>> going to happen :)
>>>
>>> Plus it's the shortest notation so far ;)
>>
>> I agree.  I think "a >< b" is a great construction.  I would
>> suggest that that operator should exist, along with "><=" so
>> that it works stand alone:
>>
>>      int a = 5, b = 3;
>>
>>      printf("a=%d, b=%d\n", a, b);
>>
>>      a ><= b;
>
> I think a><b is terrible. (And a><=b worse. Not least because I've no idea
> what the difference is between ><= and ><. If a+b can be written stand-alone,
> why can't a><b?)

"a + b" can be written stand-alone, but it has no effect unless
it's in some other context;

int a = 5, b = 3;

a + b;
a >< b;

What does "a + b;" do? Nothing. It would compute operations:

01: load a
02: load b
03: add
04: discard the result

The "a >< b;" swap operator does have meaning in that context:

01: load a
02: store t
03: load b
04: store b to a
05: store t to b

But, it's confusing in source code. That's why I say ><= should
exist. At least that way the eye will see it's an assignment.

> One reason it's terrible is that it's just some random, made-up symbol with
> no long history of use (unlike "+" for example).

There was a time when + didn't exist. I've seen ancient math
and they don't use a + sign. They use something else, often
simply being positional with no symbol.

All things have an inception date. Using * for a pointer didn't
always exist. It had an inception date. >< does too. And so
does ><=.

> And also, swap, IME, is quite an uncommon operation so doesn't need such a
> compact and mysterious representation, and is never needed in an expression
> so it doesn't need a result type.

Even if >< and ><= exist, there's nothing to prevent you using
swap:

#define swap(a,b) a >< b

Now you can have your swap() and eat it too. :-)

> (At one time I used ":=:" for swap, in a language where ":=" was assignment
> so that ":=:" suggested a two-way assignment. But eventually I dropped that
> and just used the much easier to type, and far more obvious:

:=: is a good syntax too. I like it as well.

My thinking on >< is it kind of goes along with the spaceship
operator. It's an extension that has a purpose.

>    swap(a,b)
>
> What actually is the problem with just using this?)

Unless you defined swap() to be swap(int& a, int& b), it would
not work. It would make more sense in C's context to be:

swap(&a, &b);

Using "a >< b;" or "a ><= b;" is much cleaner in my opinion.

>>      printf("a=%d, b=%d\n", a, b);
>>
>> The >< operator can still be used in-flight, in the middle of other
>> expressions, switching them there in place, which may yield the re-
>> sult of some intermediate able to be switched with the indicated
>> value.
>
> /Which/ intermediate value? Any return value must be an obvious one, but
> there is no obvious result type from swap().

I mean when it's used in an expression like this:

int new_value = 0;

// Only test if there are two valid samples in a row
if (new_value >< get_sample())
// Code here

> The only one I can think is for swap(a,b) to simply return the multiple value
> (b,a), but such values are difficult to work with and require further
> language features.

I think it should return the right-hand value. "a >< b" would
return the b value.

--
Rick C. Hodgin

Rick C. Hodgin

unread,
Oct 2, 2018, 9:16:54 AM10/2/18
to
On 10/2/2018 9:08 AM, Bart wrote:
> On 02/10/2018 13:58, Bart wrote:
>> On 02/10/2018 13:20, Rick C. Hodgin wrote:
>
>>> The >< operator can still be used in-flight, in the middle of other
>>> expressions, switching them there in place, which may yield the re-
>>> sult of some intermediate able to be switched with the indicated
>>> value.
>>
>> /Which/ intermediate value? Any return value must be an obvious one, but
>> there is no obvious result type from swap().
>>
>> The only one I can think is for swap(a,b) to simply return the multiple
>> value (b,a), but such values are difficult to work with and require further
>> language features.
>>
>
> BTW if you're looking for a new language feature simple enough for anyone to
> appreciate and understand, look at multiple assignments:
>
>   a, b, c = 10, 20, 30;

The syntax "a, b, c" already has meaning in CAlive, as it allows
multiple return values. For your version to work, it would need
to be encoded in CAlive as "a, b, c = (10, 20, 30);"

int a, b, c;

a, b, c = some_function(5);

// The function definition in CAlive
function some_function
| params int i
| returns int r1, r2, r3
{
r1 = i + 5;
r2 = i + 4;
r3 = i + 3;
}

By assigning the values to the return variables, rather
than issuing a simple "return x;" the ability to have
multiple return values becomes obvious.

Mechanically they are stored as pointers to those variables
and are handled that way. It would be the same as if you
wrote this in C:

void some_function(int i, int *r1, int *r2, int *r3)
{
*r1 = i + 5;
*r2 = i + 4;
*r3 = i + 3;
}

int a, b, c;

some_function(5, &a, &b, &c);

> Here, this is equivalent to a=10, b=20, c=30, but it can also be used like this:
>
>   a, b = b, a;

CAlive allows this as "a, b = (b, a);"

> This is the equivalent of t1=b, t2=a, a=t1; b=t2, and has the effect of
> swapping a and b. But it can also do more, like rotating a bunch of values.
>
> (If you are using C syntax, then C's comma operator will screw this up:
>
>   a, b, c = 10, 20, 30;
>
> is legal C, but has the effect of assigning 10 to c, and leaving a and b
> unchanged. (This is somewhat surprising, I expected 30 to be assigned to C.))

I have a lot of thought into CAlive. And to be honest, it's
a little scary the closer I get to it being viable.

--
Rick C. Hodgin

David Brown

unread,
Oct 2, 2018, 9:35:22 AM10/2/18
to
It would probably be more efficient to consider the function as
returning a struct of three int's, rather than passing three
pointers-to-int. Struct returns that are too big to fit in a register
are typically implemented by passing a pointer to the struct - but now
you are passing a single pointer, not three.

Rick C. Hodgin

unread,
Oct 2, 2018, 9:43:55 AM10/2/18
to
Yep. This is the design I added to my Arxoda CPU with the
addition of new base-pointer registers (lower-left):


http://www.libsf.org:8990/projects/LIB/repos/libsf/browse/arxoda/core/wex_register_mapping.png

wspp stands for "Stack Pointer Parameters," and wbpp stands
for "Base Pointer Parameters." It is that very way of hav-
ing large numbers of input or return values prepared at com-
pile time, and then passed in that way.

It's also more efficient, depending on how often r1, r2, and
r3 are used, to store them to temporary variables, and then
do an atexit() algorithm which assigns them to their pointer
values one time.

But, those are all mechanics ... and who cares? :-)

--
Rick C. Hodgin

Bart

unread,
Oct 2, 2018, 10:26:54 AM10/2/18
to
On 02/10/2018 14:08, Rick C. Hodgin wrote:
> On 10/2/2018 8:58 AM, Bart wrote:

>> I think a><b is terrible. (And a><=b worse. Not least because I've no
>> idea what the difference is between ><= and ><. If a+b can be written
>> stand-alone, why can't a><b?)
>
> "a + b" can be written stand-alone, but it has no effect unless
> it's in some other context;

Perhaps that was a bad example. "a=b" is better, as that has the same
syntax inside an expression and outside it. Or a+=b.

Although technically, it's impossible to be outside an expression, if
this is anywhere C-like.

Because in C, an expression can be a statement. So if a><b is legal in
an expression, then so is this:

a><b;

> There was a time when + didn't exist.  I've seen ancient math
> and they don't use a + sign.  They use something else, often
> simply being positional with no symbol.
>
> All things have an inception date.  Using * for a pointer didn't
> always exist.

* was an invention of C, but it occurs EVERYWHERE in the language. So it
deserves a compact representation. Anyone using C needs to know about
it, and that knowledge is constantly reinforced by seeing it all the time.

Swap is only used infrequently, and it doesn't need some meaningless
symbol to be created for it.

>     #define swap(a,b) a >< b
>
> Now you can have your swap() and eat it too. :-)

This is what I don't understand. You seem to think it's great that you
can make a><b work like swap(a,b). So why not just used swap(a,b); why
the preoccupation with cryptic symbols?

(And using #define is unsatisfactory for the same reasons such
'solutions' in C always are. Now you have drag a little library of such
#defines along with any code that uses swap. Everybody else will be
using SWAP or Swap for such a define. Or they will already have a 'swap'
macro that does something entirely different.)

>> (At one time I used ":=:" for swap, in a language where ":=" was
>> assignment so that ":=:" suggested a two-way assignment. But
>> eventually I dropped that and just used the much easier to type, and
>> far more obvious:
>
> :=: is a good syntax too.  I like it as well.

You're welcome to it. I found it a pain to type, because it's shift,
un-shift, shift.

> My thinking on >< is it kind of goes along with the spaceship
> operator.  It's an extension that has a purpose.

No, that was to do with compare, which doesn't modify its operands. It
is unrelated.

(On that note, I use <> for not-equals, which is similar to the <=>
spaceship operator. But <> was used in existing languages for not-equals.)

>
>>     swap(a,b)
>>
>> What actually is the problem with just using this?)
>
> Unless you defined swap() to be swap(int& a, int& b), it would
> not work.

I don't understand. This is a new feature, that /you/ implement, you
make it work as you like. It's not a function, but syntax that looks
like a function call.

And anyway, swap(int&,int&) [what language is that?], is not a swap
operator, as it would only swap ints.

Besides, it /does/ work [not C]:

int a:=100, b:=99999

println a,b
swap(a,b)
println a,b

Output:

100 99999
99999 100


>  It would make more sense in C's context to be:
>
>     swap(&a, &b);

I thought that (int&,int&) defined reference parameters so that you
didn't need & here?

Whatever, the question is why are you so worried about implementation
details for swap(a,b), but not a><b? It's not as though using the latter
syntax instead of the former gives you some magical free pass so that it
just works without having to think about how.

>
> Using "a >< b;" or "a ><= b;" is much cleaner in my opinion.

I would guess that would be a minority option. Ask 100 programmers of
any language what they think "a><b" means. Then ask them what they think
"swap(a,b)" means. Which one do you think they will get right more?

> I mean when it's used in an expression like this:
>
>     int new_value = 0;
>
>     // Only test if there are two valid samples in a row
>     if (new_value >< get_sample())

I have no idea what this is supposed to mean.

I thought that >< swapped the values of its operands in-place, so how
does that work with a function-call?

Perhaps you have another kind of operator in mind, but you'd have to
spell out, using conventional operators that everyone will know, how
this code fragment works.


--
bart

John Bode

unread,
Oct 2, 2018, 10:27:49 AM10/2/18
to
On Tuesday, October 2, 2018 at 5:43:52 AM UTC-5, Bart wrote:
> On 01/10/2018 22:59, John Bode wrote:
> > On Monday, August 13, 2018 at 2:53:54 PM UTC-5, skybu...@hotmail.com wrote:
> >> Hello,
> >>
> >> I just had a funny idea how to implement a swap operator for types:
> >>
> >> A >< B
> >>
> >> would mean swap A and B.
> >>
> >> Bye,
> >> Skybuck.
> >
> > Personally, I would add a "swap" keyword:
> >
> > a swap b;
> >
> > rather than recycle relational operators.
> >
> > Obviously, both operands must be modifiable lvalues.
> >
> > What should the *result* of the expression be?
>
> Why does there need to be any result at all?
>

*If* we create it as an operator, then it has to have a result (otherwise it would not fit
in the current operator and expression hierarchy). Again, the big question would be, what
*is* that result? How would that result be useful in a larger expression? Should that
result be an lvalue or not?

We already know at least one constraint, that both operands must be lvalues. What other
constraints should there be? Obviously, most of the constraints for an assignment
operator should apply, but what else?

I'm asking people like Rick and Skybuck to think through the idea in a little more detail than
just picking a symbol. Personally, I can't see it as being useful or meaningful (it's not
something I have many use cases for) , but obviously some number of people *do*, so I
want them to explain how to fit it in with the other operators in a way that makes sense.

> Either make swap a statement (for which 'swap(a,b)' works better), or
> make it return void.
>

Honestly, a swap *function* in the standard library would be a better solution than an
operator:

void swap( void * restrict lhs, void * restrict rhs, size_t size );

does a bytewise swap of its parameters.

This way we don't have to worry about operator semantics, or where it fits in the
expression syntax hierarchy, or anything else. But, at least two people think an *operator*
is a good idea, so I'd like them to flesh out the idea a bit more.

Bart

unread,
Oct 2, 2018, 10:44:07 AM10/2/18
to
On 02/10/2018 15:27, John Bode wrote:
> On Tuesday, October 2, 2018 at 5:43:52 AM UTC-5, Bart wrote:

>> Why does there need to be any result at all?
>>
>
> *If* we create it as an operator, then it has to have a result (otherwise it would not fit
> in the current operator and expression hierarchy).

Take this code:

void bill(void){puts("Bill");}
double ben(void){puts("Ben");}

int main(void) {
int c=0;

c ? bill() : ben();

The result of the ?: doesn't have a determinable type, and some
compilers will complain. Yet many will also run the code. Since the
result isn't used, it doesn't really matter.

A swap operator could work the same way. Or just make it return zero,
**if** you had to make it an operator.

>> Either make swap a statement (for which 'swap(a,b)' works better), or
>> make it return void.
>>
>
> Honestly, a swap *function* in the standard library would be a better solution than an
> operator:
>
> void swap( void * restrict lhs, void * restrict rhs, size_t size );
>
> does a bytewise swap of its parameters.

That would be useful addition to functions like memcpy(), to exchange
the contents of two blocks of memory. Blocks that might be of different
types, and might be sub-blocks of a larger type.

But the idea of swap() feature is to simply and quickly exchange the
values of two objects of the same type. And we'd also like it to be
efficient without /requiring/ an optimising compiler.

--
bart

Rick C. Hodgin

unread,
Oct 2, 2018, 10:52:46 AM10/2/18
to
On 10/2/2018 10:26 AM, Bart wrote:
> On 02/10/2018 14:08, Rick C. Hodgin wrote:
>>      #define swap(a,b) a >< b
>> Now you can have your swap() and eat it too. :-)
>
> This is what I don't understand. You seem to think it's great that you can
> make a><b work like swap(a,b). So why not just used swap(a,b); why the
> preoccupation with cryptic symbols?

Are these non-cryptic?

b = *c;
c = &a;

Things are only cryptic until they're not. I'll be honest,
when I first saw the spaceship operator, I immediately
thought back to what Vader's ship looked like:

https://www.starwars.com/databank/darth-vader-s-tie-fighter

I'm surprised someone hasn't called that operator the "vader."

> (And using #define is unsatisfactory for the same reasons such 'solutions' in
> C always are. Now you have drag a little library of such #defines along with
> any code that uses swap. Everybody else will be using SWAP or Swap for such a
> define. Or they will already have a 'swap' macro that does something entirely
> different.)
>
>>> (At one time I used ":=:" for swap, in a language where ":=" was
>>> assignment so that ":=:" suggested a two-way assignment. But eventually I
>>> dropped that and just used the much easier to type, and far more obvious:
>>
>> :=: is a good syntax too.  I like it as well.
>
> You're welcome to it. I found it a pain to type, because it's shift,
> un-shift, shift.

It's like step, bump, step, bump bump (at 1:02):

https://www.youtube.com/watch?v=D6VQDNIZH7U&t=1m2s

Only different. And I can't advocate everything on that
video, just the step bump, step bump bump part. Funny. :-)

>> My thinking on >< is it kind of goes along with the spaceship
>> operator.  It's an extension that has a purpose.
>
> No, that was to do with compare, which doesn't modify its operands. It is
> unrelated.

Okay, what if we used <=> for the vader1 operator (spaceship),
and >=< for for the vader2 operator (swap). Nothing confusing
about that.

> (On that note, I use <> for not-equals, which is similar to the <=> spaceship
> operator. But <> was used in existing languages for not-equals.)

I used to use <> for not-equal, and then I discovered !=. In
XBASE languages you can also use # for not-equal. It's sup-
posed to be like an equal with a line through it.

>>>     swap(a,b)
>>>
>>> What actually is the problem with just using this?)
>>
>> Unless you defined swap() to be swap(int& a, int& b), it would
>> not work.
>
> I don't understand. This is a new feature, that /you/ implement, you make it
> work as you like. It's not a function, but syntax that looks like a function
> call.

I think that part's confusing. It would be like "they're all
functions everywhere ... except swap, which is different." No
confusion there I'm sure. :-)

> And anyway, swap(int&,int&) [what language is that?], is not a swap operator,
> as it would only swap ints.

I was using it as an example.

> Besides, it /does/ work [not C]:
>
>     int a:=100, b:=99999
>
>     println a,b
>     swap(a,b)
>     println a,b
>
> Output:
>
>     100 99999
>     99999 100
>
>
>>   It would make more sense in C's context to be:
>>
>>      swap(&a, &b);
>
> I thought that (int&,int&) defined reference parameters so that you didn't
> need & here?

Yes. But this is one of my arguments against allowing a
user to pass in a and b to something like swap here, which
would have int& for the parameters, because on the call
there is no indication they could be updated in that way.
I think they should be passed in using:

swap(@a, @b);

In that way it indicates they are potentially updated.

> Whatever, the question is why are you so worried about implementation details
> for swap(a,b), but not a><b? It's not as though using the latter syntax
> instead of the former gives you some magical free pass so that it just works
> without having to think about how.

By introducing >< you gain the ability to use swap(a,b).
By introducing swap(a,b) you're stuck with it, and do
not have the >< ability.

I see one solution as addressing your wants, and other
people's wants who don't want to use swap(). And another
solution addressing those who don't mind using swap()
only.

>> Using "a >< b;" or "a ><= b;" is much cleaner in my opinion.
>
> I would guess that would be a minority option. Ask 100 programmers of any
> language what they think "a><b" means. Then ask them what they think
> "swap(a,b)" means. Which one do you think they will get right more?

That's true of most things in C. You ask most people
what many things in C mean and they'll tell you straight
up. "Nothing confusing here. Move along. Move along."

>> I mean when it's used in an expression like this:
>>
>>      int new_value = 0;
>>
>>      // Only test if there are two valid samples in a row
>>      if (new_value >< get_sample())
>
> I have no idea what this is supposed to mean.

It would be like this:

old_new_value = new_value;
t = get_sample();
swap(t, new_value);
if (old_new_value)

> I thought that >< swapped the values of its operands in-place, so how does
> that work with a function-call?

The function call returns a value. That value is in-flight
at that usage, allowing the value being returned to be swapped
with the prior value, which then assigns the new sample value
to new_value, and uses the old new_value to do the test.

> Perhaps you have another kind of operator in mind, but you'd have to spell
> out, using conventional operators that everyone will know, how this code
> fragment works.

I have lots of ideas. My brain is constantly in motion,
and not just when I'm walking. :-) Sometimes I can't shut
the darned thing off.

--
Rick C. Hodgin

Scott Lurndal

unread,
Oct 2, 2018, 11:04:22 AM10/2/18
to
Bart <b...@freeuk.com> writes:
>On 02/10/2018 14:08, Rick C. Hodgin wrote:

[please trim your posts]

>
>>> (At one time I used ":=:" for swap, in a language where ":=" was
>>> assignment so that ":=:" suggested a two-way assignment. But
>>> eventually I dropped that and just used the much easier to type, and
>>> far more obvious:
>>
>> :=: is a good syntax too.  I like it as well.
>

BPL (circa 1968):

identifier-3 := identifier-4 [XCH]; /* Swap identifier-3 with identifier-4 */

identifier-3 := identifier-4 [XCH] identifier-5; /* three-way swap */

All used the MVL (move links) instruction

http://vseries.lurndal.org/doku.php?id=instructions:mvl

Bart

unread,
Oct 2, 2018, 12:57:38 PM10/2/18
to
On 02/10/2018 15:52, Rick C. Hodgin wrote:
> On 10/2/2018 10:26 AM, Bart wrote:

> I think that part's confusing.  It would be like "they're all
> functions everywhere ... except swap, which is different."  No
> confusion there I'm sure. :-)

How about this in C:

f(a,b) // this doesn't modify a and b
g(a,b) // this modifies a and b
h(a,b) // h is a pointer to function, unlike f and g
i(a,b) // a and b are arrays
j(a,b) // a and b are pointers

Two kinds of function, two kinds of argument, two kinds of behaviour,
for the same x(y,z) function syntax. Or this:

k(a,b)

where k is a macro, so /anything/ is possible. And what exactly does f()
do anyway? You'd have to look at the docs. The docs for:

swap(a,b)

will say that a and b are modified.


> there is no indication they could be updated in that way.

But that is OK when using ><?

In my language, 'swap' can be used as though it was an operator, or a
function:

a swap b
swap(a, b)

It's just syntax.

> I think they should be passed in using:
>
>     swap(@a, @b);

> In that way it indicates they are potentially updated.

Only when using an operator like 'swap' isn't enough of a clue. And if
it isn't, then using @a and @b won't be enough: how exactly will they be
updated?


>> Whatever, the question is why are you so worried about implementation
>> details for swap(a,b), but not a><b? It's not as though using the
>> latter syntax instead of the former gives you some magical free pass
>> so that it just works without having to think about how.
>
> By introducing >< you gain the ability to use swap(a,b).
> By introducing swap(a,b) you're stuck with it, and do
> not have the >< ability.

By having the most sensible choice in the first place, there will be
less need to redefine built-in features.

Suppose (1) there was a way to define new infix operator symbols and to
attach those to an existing operation; (2) there was a swap operator
used as 'swap(a,b)'.

Then, how many would feel the need to create an operator version of
swap? How many would choose to use "><"?

(Didn't this come up in another thread where you were similarly
advocating using weird symbols for min and max, instead of just using
min and max?

That I can't remember what those symbols says enough about it I think.
For min and max at least, nothing has to be updated.)

>>>      if (new_value >< get_sample())
>>
>> I have no idea what this is supposed to mean.
>
> It would be like this:
>
>     old_new_value = new_value;
>     t = get_sample();
>     swap(t, new_value);
>     if (old_new_value)

Since t is not used anywhere else, this is equivalent to:

old_new_value = new_value;
new_value = get_sample();
if (old_new_value)

So nothing to do with swap. What it does is another feature that has
been discussed here in the past, some way to update a variable, but
return its prior value.

Trying to associate swap() with that is a big mistake I think.

--
bart

Rick C. Hodgin

unread,
Oct 2, 2018, 1:27:55 PM10/2/18
to
On 10/2/2018 12:57 PM, Bart wrote:
> On 02/10/2018 15:52, Rick C. Hodgin wrote:
>> On 10/2/2018 10:26 AM, Bart wrote:
>
>> I think that part's confusing.  It would be like "they're all
>> functions everywhere ... except swap, which is different."  No
>> confusion there I'm sure. :-)
>
> How about this in C:
>
>  f(a,b)          // this doesn't modify a and b
>  g(a,b)          // this modifies a and b
>  h(a,b)          // h is a pointer to function, unlike f and g
>  i(a,b)          // a and b are arrays
>  j(a,b)          // a and b are pointers

I agree completely. I think function pointers should also be
referenced using @h() so it indicates clearly what it is. I
might even desire the syntax *h() to indicate you're calling
the thing pointed to by h.

> Two kinds of function, two kinds of argument, two kinds of behaviour, for the
> same x(y,z) function syntax. Or this:
>
>  k(a,b)
>
> where k is a macro, so /anything/ is possible. And what exactly does f() do
> anyway? You'd have to look at the docs. The docs for:
>
>  swap(a,b)
>
> will say that a and b are modified.
>
>
>> there is no indication they could be updated in that way.
>
> But that is OK when using ><?
>
> In my language, 'swap' can be used as though it was an operator, or a function:
>
>     a swap b
>     swap(a, b)
>
> It's just syntax.

#define swap ><

You have your success then.

>> I think they should be passed in using:
>>
>>      swap(@a, @b);
>
>> In that way it indicates they are potentially updated.
>
> Only when using an operator like 'swap' isn't enough of a clue. And if it
> isn't, then using @a and @b won't be enough: how exactly will they be updated?

No. Who's to say it's not S-WAP, indicating a secure access prototol of some
kind? That's one of the easiest ways to obfuscate code is to call functions
by some other name. You can't go by that.
It exists that way, Bart. That is its operation.

I don't think we'll agree on this, so I'll agree to disagree.
I think >< is nice. I think we need ><= as well. I may add
them to CAlive. We'll see.

--
Rick C. Hodgin

Keith Thompson

unread,
Oct 2, 2018, 1:51:20 PM10/2/18
to
Bart <b...@freeuk.com> writes:
[...]
> (If you are using C syntax, then C's comma operator will screw this up:
>
> a, b, c = 10, 20, 30;
>
> is legal C, but has the effect of assigning 10 to c, and leaving a and b
> unchanged. (This is somewhat surprising, I expected 30 to be assigned to
> C.))

It's not surprising if you remember that the comma operator has
lower precedence than the assignment operator.

You can *very loosely* think of the comma operator as similar to
the semicolon, but separating expressions rather than statements.
(No need to enumerate the ways in which they differ.) (The idea
that an assignment is an expression may seem odd to some.)

Of course you can use parentheses:

c = (10, 20, 30);

which is useful if the operands are expressions with side effects.

--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Keith Thompson

unread,
Oct 2, 2018, 1:54:13 PM10/2/18
to
John Bode <jfbod...@gmail.com> writes:
[...]
>> > On Monday, August 13, 2018 at 2:53:54 PM UTC-5, skybu...@hotmail.com wrote:
>> >> I just had a funny idea how to implement a swap operator for types:
>> >>
>> >> A >< B
>> >>
>> >> would mean swap A and B.
[...]

> *If* we create it as an operator, then it has to have a result
> (otherwise it would not fit in the current operator and expression
> hierarchy). Again, the big question would be, what *is* that result?
> How would that result be useful in a larger expression? Should that
> result be an lvalue or not?
[...]

There's no reason an operator has to yield a non-void result.
`(void)` is a cast operator, and `(void)42` yields a void result
(or, if you prefer, doesn't yield a result). ?: can also yield a
void result.

*If* a swap operator were added to the language, it would be
perfectly sensible for a swap-expression to be a void expression.

Keith Thompson

unread,
Oct 2, 2018, 2:01:17 PM10/2/18
to
Bart <b...@freeuk.com> writes:
[...]
> Take this code:
>
> void bill(void){puts("Bill");}
> double ben(void){puts("Ben");}
>
> int main(void) {
> int c=0;
>
> c ? bill() : ben();
>
> The result of the ?: doesn't have a determinable type, and some
> compilers will complain. Yet many will also run the code. Since the
> result isn't used, it doesn't really matter.

In `x ? y : z`, if both y and z have void type the expression
has void type. If one has void type and the other doesn't,
the expression violates a constraint (6.5.15p3), so it has no
meaning in standard C. (Some compilers might permit it as an
extension. In that case the result type would obviously have to
be implementation-defined.)

Rick C. Hodgin

unread,
Oct 2, 2018, 2:52:42 PM10/2/18
to
On Tuesday, October 2, 2018 at 1:27:55 PM UTC-4, Rick C. Hodgin wrote:
> I don't think we'll agree on this, so I'll agree to disagree.
> I think >< is nice. I think we need ><= as well. I may add
> them to CAlive. We'll see.

Bart, I will add this general comment: I like operators. I
like their utility, I like the fact that they're fundamental
to the language, and I like that with #define references you
can create a word to represent them and use that word in your
code.

I believe operators should have a place. All they need is a
special encoding, and then you can #define any wrapper around
them you want.

I do not believe in adding special cases (like swap(a,b)) to
be a built-in compiler feature that behaves differently than
other functions.

--
Rick C. Hodgin

Thiago Adams

unread,
Oct 2, 2018, 3:39:56 PM10/2/18
to
I want to remind some conceptual problem.
Swap like other operations can have a custom
implementation.

The C language can copy structs. For instance,

*pX1 = *pX2;
This will copy the memory.

What do you do in your code?
Do you create X_Copy function, and them, if necessary,
you can change the implementation without to have to
change the callers or do you do the default operator
*Dest = *Source?

In my code I tend to create the function to represent
to concept I want.

The same when I need to delete the struct.
What do you do when you need to delete some struct?

1 - free(pX); ?
2 - X_Delete(pX); //function

This is also to create some protection against changes
in the operation. Let's say we add some pointer to heap
inside the struct. Then I cannot do just free because
I also have to free the internal pointer.
Creating the function I don't have to change the callers.
The callers just ask the "concept" they want. This is
generally represented in my code by X_Operation where X
is the name of the struct.

Swap has the same characteristic.
Very few cases when we have some pointers pointing to
the struct itself then we need custom swap to fix the
pointer destination.

This is the reason why I am suggesting to separate
concepts from implementation in a way we could say
"I want this effect" "this operation applied for these
operands" Then the correct function would be selected.

In practice I would just write
Swap(pX1, pX2) or Copy(pX1, pX2) instead of
X_Swap(pX1, pX2) or X_Copy(pX1, pX2).

But more than that I would like to have the default
implementation read to use and override just when
necessary. This would simplify the development making
easier to divide and conquer or in other words I can
change the implementation without change the caller.
And I don't need to repeat again and again (X_Swap, Y_Swap)
the same implementation. The concept, or the ideia about what
the operation does also would be universal if present on the
standard library.






Bart

unread,
Oct 2, 2018, 3:48:25 PM10/2/18
to
On 02/10/2018 19:52, Rick C. Hodgin wrote:
> On Tuesday, October 2, 2018 at 1:27:55 PM UTC-4, Rick C. Hodgin wrote:
>> I don't think we'll agree on this, so I'll agree to disagree.
>> I think >< is nice. I think we need ><= as well. I may add
>> them to CAlive. We'll see.
>
> Bart, I will add this general comment: I like operators. I
> like their utility, I like the fact that they're fundamental
> to the language, and I like that with #define references you
> can create a word to represent them and use that word in your
> code.
>
> I believe operators should have a place. All they need is a
> special encoding, and then you can #define any wrapper around
> them you want.

Slight problem: there is a limit to how many different operators you can
practically create out of combining any of < = > + - ! ~ * / & % | ? : ^.

A three character sequence will give 3000 combinations, but how many
would anyone remember beyond a dozen new ones?

Named operators on the other hand can easily contain 4, 5, 6 or more
characters with little trouble, and they can be chosen to spell out some
meaningful function, or serve as an aide-memoire more effectively than
!*@&. There is no real limit to how many could be created.

(My languages use identifiers for many operators; see a selection below.

I'd be really interested in what symbol you would choose for the 'in'
operator (a in b returns true when a occurs in b; the details depend on
the types). There is also the composite operator 'not in'.

BTW if you like operator-rich languages, have a look at K, a version of
APL but using ASCII. Very powerful language, but even a one-line program
is unreadable.)


> I do not believe in adding special cases (like swap(a,b)) to
> be a built-in compiler feature that behaves differently than
> other functions.

What not? You take arguments a and b, apply swap to them, and something
happens. Just the same as applying any function.

------------------------------------------------------

and infix
or
iand
ior
ixor
in
rem

min infix or function-style syntax
max
swap
clamp
concat
append


not prefix
inot
abs

sqrt Written as 'sqrt a'
sqr
sin
...

len Written as 'a.len'
lwb
upb
minvalue
maxvalue
bytes
bitwidth

isint
...


--
bart

Rick C. Hodgin

unread,
Oct 2, 2018, 3:56:44 PM10/2/18
to
On 10/2/2018 3:48 PM, Bart wrote:
> On 02/10/2018 19:52, Rick C. Hodgin wrote:
>> On Tuesday, October 2, 2018 at 1:27:55 PM UTC-4, Rick C. Hodgin wrote:
>>> I don't think we'll agree on this, so I'll agree to disagree.
>>> I think >< is nice.  I think we need ><= as well.  I may add
>>> them to CAlive.  We'll see.
>>
>> Bart, I will add this general comment:  I like operators.  I
>> like their utility, I like the fact that they're fundamental
>> to the language, and I like that with #define references you
>> can create a word to represent them and use that word in your
>> code.
>>
>> I believe operators should have a place.  All they need is a
>> special encoding, and then you can #define any wrapper around
>> them you want.
>
> Slight problem: there is a limit to how many different operators you can
> practically create out of combining any of < = > + - ! ~ * / & % | ? : ^.

You can introduce @ and # in use. CAlive makes use of @ and #
in new ways.

> A three character sequence will give 3000 combinations, but how many would
> anyone remember beyond a dozen new ones?

LOL! I actually laughed out loud on that part. :-)

That's not the issue. There are only so many operators that
are needed. We have code today that does what they do, and a
few new ones can be added like the spaceship operator, and like
swap. They're basic operations that make sense.

How many more do we need?

> Named operators on the other hand can easily contain 4, 5, 6 or more
> characters with little trouble, and they can be chosen to spell out some
> meaningful function, or serve as an aide-memoire more effectively than !*@&.
> There is no real limit to how many could be created.

I would say two characters plus an optional equal sign. I also
would have no problem defining a new character to represent an
operator, and make it a single character / keystroke on a special
programmer keyboard.

> (My languages use identifiers for many operators; see a selection below.
>
> I'd be really interested in what symbol you would choose for the 'in'
> operator (a in b returns true when a occurs in b; the details depend on the
> types). There is also the composite operator 'not in'.

I have function for those. I use in(needle, haystack1, hay2, ...
hayN); I also have occurs(needle, haystack); which searches the
string haystack for the string needle, and returns how many times
it occurs.

Those are ideal for functions.

> BTW if you like operator-rich languages, have a look at K, a version of APL
> but using ASCII. Very powerful language, but even a one-line program is
> unreadable.)

If it's unreadable ... it's not for me, but I'll look at it out
of curiosity. Did you ever have a chance to look at Julia?
I'd have to see them in use. RDC does allow for a target to
reference the things to the right or left of it, and if you
place the right priority on things, any of those could be
added as an operator and use the left and right relative objs
for input.

--
Rick C. Hodgin

Bart

unread,
Oct 2, 2018, 4:02:09 PM10/2/18
to
On 02/10/2018 19:52, Rick C. Hodgin wrote:
> On Tuesday, October 2, 2018 at 1:27:55 PM UTC-4, Rick C. Hodgin wrote:
>> I don't think we'll agree on this, so I'll agree to disagree.
>> I think >< is nice. I think we need ><= as well. I may add
>> them to CAlive. We'll see.
>
> Bart, I will add this general comment: I like operators. I
> like their utility, I like the fact that they're fundamental
> to the language, and I like that with #define references you
> can create a word to represent them and use that word in your
> code.

Here's an idea for another more generally useful feature:

Instead of just allowing #define like in C, to create a function-like
named alias for an operator, create a version that turns a operator
alias for function-like name into a symbol.

Then you can invent 1000 named operators with meaningful names, and only
create symbol alias for the dozen most commonly used, or the ones that
will most benefit.

--
bart

Thiago Adams

unread,
Oct 2, 2018, 4:05:15 PM10/2/18
to
The importance of operators in C, is that
they are built-in polymorphic operations.
People that want swap operator (I had suggested this also
some time ago) is because having this operator we
don't need to implement it for all types.
The min a max function doesn't have this problem because
they can be implemented with simple macros.
We can find other operations that have the same characteristic.

I find symbols hard to remember compared with names.
We have in math the symbol for set union, set intersection etc
and it is hard to remember. These operations also would be very
useful in computing.

Rick C. Hodgin

unread,
Oct 2, 2018, 4:06:51 PM10/2/18
to
On this, my friend, we are thinking in opposite directions.

--
Rick C. Hodgin

Rick C. Hodgin

unread,
Oct 2, 2018, 4:11:43 PM10/2/18
to
On 10/2/2018 4:01 PM, Bart wrote:
> On 02/10/2018 19:52, Rick C. Hodgin wrote:
>> On Tuesday, October 2, 2018 at 1:27:55 PM UTC-4, Rick C. Hodgin wrote:
>>> I don't think we'll agree on this, so I'll agree to disagree.
>>> I think >< is nice.  I think we need ><= as well.  I may add
>>> them to CAlive.  We'll see.
>>
>> Bart, I will add this general comment:  I like operators.  I
>> like their utility, I like the fact that they're fundamental
>> to the language, and I like that with #define references you
>> can create a word to represent them and use that word in your
>> code.
>
> Here's an idea for another more generally useful feature:
>
> Instead of just allowing #define like in C, to create a function-like named
> alias for an operator, create a version that turns a operator alias for
> function-like name into a symbol.

I will say that CAlive does already allow the creation of operator
functions, as in C++, and these are generic.

operator ><
| params any l, any r
| returns any
{
typeof(l) t;

t = l;
l = r;
r = t;
}

For each use of that symbol, it would create an instance based on
the types in use. It would potentially generate a compiler error
if you pass in a type that doesn't work with equal.

It's not efficient though. It actually generates code, and a call
to that function, processing return parameters and cleaning up the
stack. That could be removed with a good optimizer, which I do not
have and won't have for some time. My initial goals are function-
ality, not efficiency, though what I'm seeing so far is not too
terribly inefficient. It will just be like un-optimized code from
other C/C++ compilers.

Such an operator definition in CAlive is good in a pinch, and it
does simplify your code, but it's not fundamental, and imo, it's
not really a good idea for some of the more fundamental types to
work on what C++ would call PODs.

> Then you can invent 1000 named operators with meaningful names, and only
> create symbol alias for the dozen most commonly used, or the ones that will
> most benefit.

--
Rick C. Hodgin

Thiago Adams

unread,
Oct 2, 2018, 4:17:50 PM10/2/18
to
On Tuesday, October 2, 2018 at 5:02:09 PM UTC-3, Bart wrote:
> On 02/10/2018 19:52, Rick C. Hodgin wrote:
> > On Tuesday, October 2, 2018 at 1:27:55 PM UTC-4, Rick C. Hodgin wrote:
> >> I don't think we'll agree on this, so I'll agree to disagree.
> >> I think >< is nice. I think we need ><= as well. I may add
> >> them to CAlive. We'll see.
> >
> > Bart, I will add this general comment: I like operators. I
> > like their utility, I like the fact that they're fundamental
> > to the language, and I like that with #define references you
> > can create a word to represent them and use that word in your
> > code.
>
> Here's an idea for another more generally useful feature:
>
> Instead of just allowing #define like in C, to create a function-like
> named alias for an operator, create a version that turns a operator
> alias for function-like name into a symbol.

This is similar of my suggestion.
I suggested in the spaceship topic we have an alias.

void X_Swap(struct X* a, struct X* b) Swap;

The diference from _Generic is that this is decentralized.

But more than that I think we could have default implementations
for Swap etc..
Then we don't need to say anything and it works like operators.

int a, b;
Swap(a, b);

But I can override.

Se my comments on the spaceship topic.


Rick C. Hodgin

unread,
Oct 2, 2018, 4:22:29 PM10/2/18
to
On 10/2/2018 4:11 PM, Rick C. Hodgin wrote:
> I will say that CAlive does already allow the creation of operator
> functions, as in C++, and these are generic.
>
>     operator ><
>     | params any l, any r
>     | returns any
>     {
>         typeof(l) t;
>
>         t = l;
>         l = r;
>         r = t;
>     }

Should be:

operator ><
| params any l, any r
| returns any
{
typeof(l) t;

t = l;
l = r;
r = t;

// Pass the new right-hand-side value
return r;
}

Use of this one would result in the new left-hand-side value
being returned:

operator ><=
| params any l, any r
| returns any
{
typeof(l) t;

t = l;
l = r;
r = t;

// Pass the new left-hand-side value
return l;
}

--
Rick C. Hodgin

Thiago Adams

unread,
Oct 2, 2018, 4:24:27 PM10/2/18
to
On Tuesday, October 2, 2018 at 5:17:50 PM UTC-3, Thiago Adams wrote:
> On Tuesday, October 2, 2018 at 5:02:09 PM UTC-3, Bart wrote:
> > On 02/10/2018 19:52, Rick C. Hodgin wrote:
> > > On Tuesday, October 2, 2018 at 1:27:55 PM UTC-4, Rick C. Hodgin wrote:
> > >> I don't think we'll agree on this, so I'll agree to disagree.
> > >> I think >< is nice. I think we need ><= as well. I may add
> > >> them to CAlive. We'll see.
> > >
> > > Bart, I will add this general comment: I like operators. I
> > > like their utility, I like the fact that they're fundamental
> > > to the language, and I like that with #define references you
> > > can create a word to represent them and use that word in your
> > > code.
> >
> > Here's an idea for another more generally useful feature:
> >
> > Instead of just allowing #define like in C, to create a function-like
> > named alias for an operator, create a version that turns a operator
> > alias for function-like name into a symbol.

One diference between operators and functions is also
that operators can use the operands without take the address.

struct a, struct b;
a = b;

compared with
Copy(&a, &b);

the same for swap.



Keith Thompson

unread,
Oct 2, 2018, 4:26:42 PM10/2/18
to
Thiago Adams <thiago...@gmail.com> writes:
> On Tuesday, October 2, 2018 at 4:48:25 PM UTC-3, Bart wrote:
>> On 02/10/2018 19:52, Rick C. Hodgin wrote:
[...]
>> > I do not believe in adding special cases (like swap(a,b)) to
>> > be a built-in compiler feature that behaves differently than
>> > other functions.
>>
>> What not? You take arguments a and b, apply swap to them, and something
>> happens. Just the same as applying any function.
>
> The importance of operators in C, is that
> they are built-in polymorphic operations.
> People that want swap operator (I had suggested this also
> some time ago) is because having this operator we
> don't need to implement it for all types.
> The min a max function doesn't have this problem because
> they can be implemented with simple macros.
> We can find other operations that have the same characteristic.
>
> I find symbols hard to remember compared with names.
> We have in math the symbol for set union, set intersection etc
> and it is hard to remember. These operations also would be very
> useful in computing.

There's no reason the name of an operator has to be made up of
punctuation characters. Most of them are, but `sizeof` and `_Alignof`
are both operators, and their names are keywords.

*If* we wanted to add a swap operator to C, it could easily be defined
as an operator with two operands:
a swap b
with whatever semantics seem appropriate. (Of course "swap" is
already used as an identifier in existing code. We could have a
_Swap keyword and a new header defining "swap" as a macro.)

I would opppose making "swap" a new built-in operation whose syntax
makes it look like a function call:
swap(a, b)

(There's also std::swap in C++, which depends on features that C doesn't
have.)

Bart

unread,
Oct 2, 2018, 4:36:24 PM10/2/18
to
On 02/10/2018 21:26, Keith Thompson wrote:

> I would opppose making "swap" a new built-in operation whose syntax
> makes it look like a function call:
> swap(a, b)

But sizeof(a) is OK?

And as is any function-like macro invocation?

And as are many variable declarations when someone decides to add
parentheses? Example:

typedef int f;

f(a);

Anyway, 'sizeof' is a reserved word in C with its own rules, and so
would 'swap' be.

--
bart

Rick C. Hodgin

unread,
Oct 2, 2018, 4:37:20 PM10/2/18
to
On 10/2/2018 4:26 PM, Keith Thompson wrote:
> There's no reason the name of an operator has to be made up of
> punctuation characters. Most of them are, but `sizeof` and `_Alignof`
> are both operators, and their names are keywords.


Many of them should be replaced with something to convey their
meaning in something other than in words. Not everybody speaks
English. Symbols are good for certain things. They only have
to be learned once, and then used. The same can be said of the
English words, but why limit people to a specific language more
than need be?

sizeof(x) --> ?#(x) // # = number of characters
_Alignof(x) --> ?&&(x) // && = address of the address of x

And a lengthof(x), which is like sizeof(x) yet without the
trailing \0 being counted on strings:

lengthof(x) --> ?!(x) // ! = without \0 if char [], same
// as sizeof(x) otherwise

I also think when you use something built-in like that, it
shouldn't be using (), but rather []. It should be:

sizeof[x]
_Alignof[x]
lengthof[x]

And why introduce "_Alignof(x)" after sizeof(x) had already
been established? Why not alignof(x)?

It's like what posix did. "So many functions, do I prefix
this one with an underscore in this compiler? Is the posix
version supported? I don't know, let's try it and see if it
generates an error. Ope. An error. Try this alternate way
of spelling it. Another error. Let me try a third. Ah!
Got it."

I do not understand why those legacy things remain.

--
Rick C. Hodgin

Thiago Adams

unread,
Oct 2, 2018, 4:43:14 PM10/2/18
to
On Tuesday, October 2, 2018 at 5:26:42 PM UTC-3, Keith Thompson wrote:
And the language design is puzzle where we need to take in
account the problems we want to solve and we can find different
solutions.

For instance, adding gcc's typeof plus gcc's statements and
declarations in expression is also a different path do solve
the swap problem.
C++ templates plus references also is a different path.

Just to make clear again the problems that swap operator wants
to solve

- Hard to create a macro
- Creates duplicated code if repeated each time
- Boring to create swap function version for each type
- Functions needs to take the address of structs.

The problem that swap operator would not resolve is that
some code need custom swap.
(The same problem already exists with copy)



Bart

unread,
Oct 2, 2018, 4:45:50 PM10/2/18
to
Presumably you accept that assembler mnemonics generally use identifiers
for opcodes rather than symbols? Which is fortunate for everyone as ASM
programming is hard enough.

Anyway, I've suggested defining new features primarily with identifiers,
with the possibility of aliasing some of them with symbols. Or linking
them to particular overloads of existing operators.

This compares with your proposal of defining new features primarily with
symbols, and applying a function alias, which is severely limited by the
number of new symbols that can be practically invented, or remembered,
or for anyone to try and guess the meaning of.

--
bart

Keith Thompson

unread,
Oct 2, 2018, 4:47:11 PM10/2/18
to
A valid point.

Note that `sizeof(a)` where a is a type name is a special case syntax
(I wouldn't have called sizeof an "operator" in that case, but I
accept that the language calls it one). If a is an expression,
then the parentheses aren't part of the syntax of the operator,
it's just the operator applied to a parenthesized expression.
I write `sizeof a` rather than `sizeof(a)` for the same reason I
write `-1` rather than `-(1)`.

And if `swap` is an operator keyword, why not follow existing
convention and infix syntax for an operator that takes two operands?

Scott Lurndal

unread,
Oct 2, 2018, 5:01:42 PM10/2/18
to
Keith Thompson <ks...@mib.org> writes:

>
>There's no reason the name of an operator has to be made up of
>punctuation characters. Most of them are, but `sizeof` and `_Alignof`
>are both operators, and their names are keywords.
>
>*If* we wanted to add a swap operator to C, it could easily be defined
>as an operator with two operands:
> a swap b
>with whatever semantics seem appropriate. (Of course "swap" is
>already used as an identifier in existing code. We could have a
>_Swap keyword and a new header defining "swap" as a macro.)
>
>I would opppose making "swap" a new built-in operation whose syntax
>makes it look like a function call:
> swap(a, b)
>
>(There's also std::swap in C++, which depends on features that C doesn't
>have.)

Is there really enough usage of a 'swap' type operation such that
an operator would be genuinely useful?

I don't recall ever needing that functionality. Now byte swapping
for endianess reasons, that I use daily.

Bart

unread,
Oct 2, 2018, 5:03:05 PM10/2/18
to
On 02/10/2018 21:37, Rick C. Hodgin wrote:
> On 10/2/2018 4:26 PM, Keith Thompson wrote:
>> There's no reason the name of an operator has to be made up of
>> punctuation characters.  Most of them are, but `sizeof` and `_Alignof`
>> are both operators, and their names are keywords.
>
>
> Many of them should be replaced with something to convey their
> meaning in something other than in words.  Not everybody speaks
> English.  Symbols are good for certain things.  They only have
> to be learned once, and then used.  The same can be said of the
> English words, but why limit people to a specific language more
> than need be?
>
>     sizeof(x)    -->  ?#(x)     // #  = number of characters
>     _Alignof(x)  -->  ?&&(x)    // && = address of the address of x

You really think that would be a benefit to anybody?

If so I won't bother arguing further.

> And a lengthof(x),

Ah, you've sensibly created a version that tells you the number of
elements in an array, so or I thought at first.

which is like sizeof(x) yet without the
> trailing \0 being counted on strings:
>
>     lengthof(x)  -->  ?!(x)     // !  = without \0 if char [], same
>                                 //      as sizeof(x) otherwise

But apparently this promising-sounding new feature just does this:

sizeof(x)-1

Although even that is badly defined; what would it give here:

char x[11] = "bart";

sizeof(x) gives 11; sizeof(x)-1 gives 10, but it sounds like lengthof(x)
gives 10 too, which are all wrong of you want the length of the
contained string (4) rather than the size of the array (11).

For the length of a string, use strlen. For the length of a string
constant, use:

strlen("bart")-1;


> I also think when you use something built-in like that, it
> shouldn't be using (), but rather [].  It should be:
>
>     sizeof[x]
>     _Alignof[x]
>     lengthof[x]
>
> And why introduce "_Alignof(x)" after sizeof(x) had already
> been established?  Why not alignof(x)?
>
> It's like what posix did.  "So many functions, do I prefix
> this one with an underscore in this compiler?  Is the posix
> version supported?  I don't know, let's try it and see if it
> generates an error.  Ope.  An error.  Try this alternate way
> of spelling it.  Another error.  Let me try a third.  Ah!
> Got it."

You missed out the ones starting with two underscores. Or ending with
them. Or both. C is really paranoid about encroaching on the namespaces
of programs written decades before.

I'm sure there are ways to deal with that without inconveniencing future
programmers for eternity.

--
bart

Rick C. Hodgin

unread,
Oct 2, 2018, 5:09:37 PM10/2/18
to
On 10/2/2018 4:45 PM, Bart wrote:
> On 02/10/2018 21:06, Rick C. Hodgin wrote:
>> On 10/2/2018 4:01 PM, Bart wrote:
>>> Then you can invent 1000 named operators with meaningful names, and only
>>> create symbol alias for the dozen most commonly used, or the ones that
>>> will most benefit.
>>
>> On this, my friend, we are thinking in opposite directions.
>
> Presumably you accept that assembler mnemonics generally use identifiers for
> opcodes rather than symbols? Which is fortunate for everyone as ASM
> programming is hard enough.

Yes, but some of them can be done away with. My AAlive assembler
uses syntax for x86 like this:

; Traditional
mov eax,4

// AAlive
eax = 4;

And there are many such forms like that. Wherever they are
practical:

; Traditional
cmp eax,4
jnz skip_it
; code here
skip_it:

// AAlive
if (eax == 4) {
// Code here
}

I try to make things more readable for people (and for me). But
AAlive does work with either form. It is a full assembler able
to parse user-written assembly as well, rather than generated
assembly.

> Anyway, I've suggested defining new features primarily with identifiers, with
> the possibility of aliasing some of them with symbols. Or linking them to
> particular overloads of existing operators.

It's not a bad idea. It's just not any direction I've been headed
toward. I can potentially see the value of having that ability in
generic form anyway.

> This compares with your proposal of defining new features primarily with
> symbols, and applying a function alias, which is severely limited by the
> number of new symbols that can be practically invented, or remembered, or for
> anyone to try and guess the meaning of.

I have added a lot of new features using words. But, I don't always
think it's a good idea. In some cases, but in general I would prefer
to move toward a more non-English-based language.

--
Rick C. Hodgin

Rick C. Hodgin

unread,
Oct 2, 2018, 5:16:58 PM10/2/18
to
On 10/2/2018 5:02 PM, Bart wrote:
> On 02/10/2018 21:37, Rick C. Hodgin wrote:
>>      sizeof(x)    -->  ?#(x)     // #  = number of characters
>>      _Alignof(x)  -->  ?&&(x)    // && = address of the address of x
>
> You really think that would be a benefit to anybody?
> If so I won't bother arguing further.

#define sizeof ?#
#define _Alignof ?&&

Now everybody's happy. See how it works?

>> And a lengthof(x),
>
> Ah, you've sensibly created a version that tells you the number of elements
> in an array, so or I thought at first.

For that I have countof(x);

>  which is like sizeof(x) yet without the
>> trailing \0 being counted on strings:
>>
>>      lengthof(x)  -->  ?!(x)     // !  = without \0 if char [], same
>>                                  //      as sizeof(x) otherwise
>
> But apparently this promising-sounding new feature just does this:
>        sizeof(x)-1
>
> Although even that is badly defined; what would it give here:
>        char x[11] = "bart";

4 of course. :-) But, that is baked in at compile-time. If
you later populate x with something else, you couldn't use
lengthof(x), but would need strlen(x).

> sizeof(x) gives 11; sizeof(x)-1 gives 10, but it sounds like lengthof(x)
> gives 10 too, which are all wrong of you want the length of the contained
> string (4) rather than the size of the array (11).
>
> For the length of a string, use strlen. For the length of a string constant,
> use:
>     strlen("bart")-1;

Only if it's dynamic. I use lengthof(x) in my code as a
compile-time construct. It doesn't work well with C/C++
because it doesn't accommodate your char x[11] = "bart";
example, but I don't usually do that, and where I do I
manually add the special case code.

>> I also think when you use something built-in like that, it
>> shouldn't be using (), but rather [].  It should be:
>>
>>      sizeof[x]
>>      _Alignof[x]
>>      lengthof[x]
>>
>> And why introduce "_Alignof(x)" after sizeof(x) had already
>> been established?  Why not alignof(x)?
>>
>> It's like what posix did.  "So many functions, do I prefix
>> this one with an underscore in this compiler?  Is the posix
>> version supported?  I don't know, let's try it and see if it
>> generates an error.  Ope.  An error.  Try this alternate way
>> of spelling it.  Another error.  Let me try a third.  Ah!
>> Got it."
>
> You missed out the ones starting with two underscores. Or ending with them.
> Or both. C is really paranoid about encroaching on the namespaces of programs
> written decades before.

Each time I see them I literally shake my head, or at least
let out an exhale as I regather my concentration.

> I'm sure there are ways to deal with that without inconveniencing future
> programmers for eternity.

:-) I'd be keen to hear them, my friend.

Part of my goal with RDC is to allow add-ins that are dropped-
in at runtime, meaning the RDC CAlive database comes from the
factory as it does, allowing the parsing of files as is pre-
defined, but then a user can go into the editor and add-on
things they'd like to see in the language.

These add-ons are not trivial, but once they're developed, the
can be shared and passed around.

My goal is to change the way C/C++ developers write code, with
the great hope better compiler and debugger authors than myself
will come on board and make RDC and CAlive soar.

--
Rick C. Hodgin

Keith Thompson

unread,
Oct 2, 2018, 5:29:25 PM10/2/18
to
sc...@slp53.sl.home (Scott Lurndal) writes:
> Keith Thompson <ks...@mib.org> writes:
>>There's no reason the name of an operator has to be made up of
>>punctuation characters. Most of them are, but `sizeof` and `_Alignof`
>>are both operators, and their names are keywords.
>>
>>*If* we wanted to add a swap operator to C, it could easily be defined
>>as an operator with two operands:
>> a swap b
>>with whatever semantics seem appropriate. (Of course "swap" is
>>already used as an identifier in existing code. We could have a
>>_Swap keyword and a new header defining "swap" as a macro.)
>>
>>I would opppose making "swap" a new built-in operation whose syntax
>>makes it look like a function call:
>> swap(a, b)
>>
>>(There's also std::swap in C++, which depends on features that C doesn't
>>have.)
>
> Is there really enough usage of a 'swap' type operation such that
> an operator would be genuinely useful?

Probably not (thus my emphasis on the "*If*" above).

It's a simple enough operation that a predefined operator or
(overloaded) function doesn't provide all that much benefit over
writing the code inline:

int x, y;
...
const int old_x = x;
x = y;
y = old_x;

("temp" is a common name, but I find "old_x" to be more explicit and
harder to mess up.)

If I'm using a language that provides it as a feature (std::swap in C++,
(x, y) = (y, x) in Python, etc), that's great. If not, it's not that
big a deal.

> I don't recall ever needing that functionality. Now byte swapping
> for endianess reasons, that I use daily.

Bart

unread,
Oct 2, 2018, 5:38:12 PM10/2/18
to
On 02/10/2018 22:01, Scott Lurndal wrote:
> Keith Thompson <ks...@mib.org> writes:
>
>>
>> There's no reason the name of an operator has to be made up of
>> punctuation characters. Most of them are, but `sizeof` and `_Alignof`
>> are both operators, and their names are keywords.
>>
>> *If* we wanted to add a swap operator to C, it could easily be defined
>> as an operator with two operands:
>> a swap b
>> with whatever semantics seem appropriate. (Of course "swap" is
>> already used as an identifier in existing code. We could have a
>> _Swap keyword and a new header defining "swap" as a macro.)
>>
>> I would opppose making "swap" a new built-in operation whose syntax
>> makes it look like a function call:
>> swap(a, b)
>>
>> (There's also std::swap in C++, which depends on features that C doesn't
>> have.)
>
> Is there really enough usage of a 'swap' type operation such that
> an operator would be genuinely useful?

In my code, it's used very infrequently (once per 1000 lines at most,
usually), but when I need it it's very handy. It's also an easy to
understand and implement feature.

Usage is somewhat lower than min and max, which you frequently see
macros for in C. And those might be a little behind goto, which already
exists.

--
bart

Keith Thompson

unread,
Oct 2, 2018, 7:07:03 PM10/2/18
to
Bart <b...@freeuk.com> writes:
[...]
> For the length of a string, use strlen. For the length of a string
> constant, use:
>
> strlen("bart")-1;

I think you meant sizeof("bart")-1 .

[...]

Bart

unread,
Oct 2, 2018, 7:09:44 PM10/2/18
to
On 03/10/2018 00:06, Keith Thompson wrote:
> Bart <b...@freeuk.com> writes:
> [...]
>> For the length of a string, use strlen. For the length of a string
>> constant, use:
>>
>> strlen("bart")-1;
>
> I think you meant sizeof("bart")-1 .

Yes, thanks.

Lew Pitcher

unread,
Oct 2, 2018, 7:21:56 PM10/2/18
to
Keith Thompson wrote:

> Bart <b...@freeuk.com> writes:
> [...]
>> For the length of a string, use strlen. For the length of a string
>> constant, use:
>>
>> strlen("bart")-1;
>
> I think you meant sizeof("bart")-1 .

I'm not sure he did.

We can be certain that
strlen("abc\0def")-1
results in a value that is definitely /not/ "the length of a string
constant" (that constant being "abc\0def", 8 characters, including the
requisite string terminator byte).

OTOH,
sizeof("abc\0def")-1
results in a value that /almost/ reflects the length of the string constant,
only discounting the length of the string terminator byte.

I do believe that
sizeof("abc\0def")
results in the correct "length of the string constant".

--
Lew Pitcher
"In Skills, We Trust"

David Brown

unread,
Oct 3, 2018, 5:14:25 AM10/3/18
to
On 02/10/18 22:36, Bart wrote:
> On 02/10/2018 21:26, Keith Thompson wrote:
>
>> I would opppose making "swap" a new built-in operation whose syntax
>> makes it look like a function call:
>> swap(a, b)
>
> But sizeof(a) is OK?

The thing I would question about "swap(a, b)" in C is that it /changes/
"a" and "b". "sizeof" and "_Alignof" are operators with names rather
than symbols, but they don't change anything - they are only for inspection.

When you see "f(a, b)" in C, you expect "a" and "b" to be unchanged
afterwards. You can, of course, write a macro that breaks this rule -
but there is a solid tradition that it be written in all-caps, like
"SWAP(a, b)" to indicate there is something odd going on.

In C++, reference parameters mean it is fine to write functions that do
change things - so for C++ programmers, there would not be a problem.
(And they already have "std::swap(a, b)" that does the job.)

("sizeof" is also different in that you can write "sizeof a", which is
what many people prefer. Personally, I tend to use more parenthesis
than necessary and write "sizeof(a)", but that's just my habits. I
don't think "swap a, b;" would be a popular alternative.)

>
> And as is any function-like macro invocation?
>
> And as are many variable declarations when someone decides to add
> parentheses? Example:
>
> typedef int f;
>
> f(a);
>
> Anyway, 'sizeof' is a reserved word in C with its own rules, and so
> would 'swap' be.
>

If there were a point in having a "swap" operator as fundamental in C,
then I would like a syntax such as "_Swap(a, b)". "swap" is too common
a word to be made a keyword at this stage in the language.

However, I can't see the slightest benefit in having it in the language.
Swapping things is not a hugely common operation - it doesn't need an
operator or keyword of its own. And if you are writing code that does a
lot of swapping, you are likely to write a macro to do the job, or use
functions with pointers (letting the compiler optimise the code).

If you want to add something to the language to improve this, I would
much rather see the gcc "typeof" extension standardised so that you can
write:

#define swap(a, b) \
do { typeof(a) _a = a; \
a = b; \
b = _a; \
} while (0)

"typeof" is a vastly more useful and flexible extension, and will let
you write a "perfect" swap macro.

David Brown

unread,
Oct 3, 2018, 5:22:06 AM10/3/18
to
On 02/10/18 23:02, Bart wrote:
> On 02/10/2018 21:37, Rick C. Hodgin wrote:
<snip>
>> And why introduce "_Alignof(x)" after sizeof(x) had already
>> been established? Why not alignof(x)?
>>

People might have used "alignof" in their own code, or defined their own
"alignof" macro or function. When new features are added to C, the
committee is very reluctant to do anything that would break existing
code, no matter how unlikely you might think it is for some to use
"alignof" as an identifier. So they make the keyword _Alignof, which no
one would use (and if they did, it's their own fault). A quick #define
or #include <stdalign.h> and you get the friendlier version.

>> It's like what posix did. "So many functions, do I prefix
>> this one with an underscore in this compiler? Is the posix
>> version supported? I don't know, let's try it and see if it
>> generates an error. Ope. An error. Try this alternate way
>> of spelling it. Another error. Let me try a third. Ah!
>> Got it."
>
> You missed out the ones starting with two underscores. Or ending with
> them. Or both.

Those are usually implementation-specific. For example, gcc has a
"typeof" keyword as an extension. But because that could conflict with
valid use as an identifier, it is only available in "gnu" standards
modes. In stricter C modes, you can still use "__typeof__" to get the
same feature.

So if you are using the extension in your own code, "typeof" makes
sense. But if you are writing a flexible header for use by others,
"__typeof__" is the better choice.

> C is really paranoid about encroaching on the namespaces
> of programs written decades before.

Yes.

>
> I'm sure there are ways to deal with that without inconveniencing future
> programmers for eternity.
>

Yes - the way C standards and C compilers handle it seems fine.

David Brown

unread,
Oct 3, 2018, 5:25:45 AM10/3/18
to
On 02/10/18 23:16, Rick C. Hodgin wrote:
> On 10/2/2018 5:02 PM, Bart wrote:
>> On 02/10/2018 21:37, Rick C. Hodgin wrote:
>>> sizeof(x) --> ?#(x) // # = number of characters
>>> _Alignof(x) --> ?&&(x) // && = address of the address of x
>>
>> You really think that would be a benefit to anybody?
>> If so I won't bother arguing further.
>
> #define sizeof ?#
> #define _Alignof ?&&
>
> Now everybody's happy. See how it works?

No, /not/ everyone is happy. You always forget that people have to
/read/ code as well as write it.

Most people will write "sizeof" as before. And then you come across
code that uses "?#" no one (except you) has the slightest clue what it
might mean.

It might be uglier to write "_Alignof" than "alignof", and some will
write one version and other write the other version - but no one will
have trouble understanding what is written.


Bart

unread,
Oct 3, 2018, 5:52:56 AM10/3/18
to
On 03/10/2018 10:25, David Brown wrote:
> On 02/10/18 23:16, Rick C. Hodgin wrote:
>> On 10/2/2018 5:02 PM, Bart wrote:
>>> On 02/10/2018 21:37, Rick C. Hodgin wrote:
>>>> sizeof(x) --> ?#(x) // # = number of characters
>>>> _Alignof(x) --> ?&&(x) // && = address of the address of x
>>>
>>> You really think that would be a benefit to anybody?
>>> If so I won't bother arguing further.
>>
>> #define sizeof ?#
>> #define _Alignof ?&&
>>
>> Now everybody's happy. See how it works?
>
> No, /not/ everyone is happy. You always forget that people have to
> /read/ code as well as write it.
>
> Most people will write "sizeof" as before. And then you come across
> code that uses "?#" no one (except you) has the slightest clue what it
> might mean.

Not even Rick will know when he comes across:

a><f()??#(b):b>:c

Using normal identifiers, that would be:

swap(a,f())?sizeof(b):min(b,c) // or it might be max

This is not that meaningful as it applies swap() in a weird manner that
only makes sense to Rick, but at least you can now see what operations
are being used.

--
bart

Malcolm McLean

unread,
Oct 3, 2018, 8:08:09 AM10/3/18
to
swap is sometimes used as a cheap assignment, or what C++ calls a "move".
We have two payroll structures which consist of the list of employees
and a count. We want to assign the previous payroll to the current
payroll, and get rid of the old previous payroll. We can avoid a realloc
and a big copy by simply swapping current with previous, then destroying
the current.

David Brown

unread,
Oct 3, 2018, 8:29:39 AM10/3/18
to
Agreed - though I do wish you would learn how to use the space bar when
you write your code!

I can't see what sort of return value would make sense from a "swap"
operation, but maybe other people do.

Malcolm McLean

unread,
Oct 3, 2018, 8:52:46 AM10/3/18
to
No, it usually can't fail, and it inherently operates on the bit patterns
passed to it in place. So the return type isn't useful unless you can
return two values, when it ceases to be "swap" and becomes "assign".

Rick C. Hodgin

unread,
Oct 3, 2018, 9:03:54 AM10/3/18
to
On Wednesday, October 3, 2018 at 5:52:56 AM UTC-4, Bart wrote:
> Not even Rick will know when he comes across:
> a><f()??#(b):b>:c

I would never write code like that ... and for that reason.

The purpose of having ><, ?#, and the others, is to have
them available for use in places where it would be clear.
That sometimes means writing less-efficient code knowing
the compiler will come along behind you and make it more
efficient for you.

> Using normal identifiers, that would be:
> swap(a,f())?sizeof(b):min(b,c) // or it might be max
>
> This is not that meaningful as it applies swap() in a weird manner that
> only makes sense to Rick, but at least you can now see what operations
> are being used.

In cases like your example I would write it like this, which
removes the issue no matter the syntax:

t = swap(a, f());

// Then use it as:
((t) ? sizeof(b) : min(b, c))

Or to use my syntax:

// Swap a and f()'s result, store f() into t
t = a >< f();

// Then use it as:
((t) ? sizeof(b) : min(b, c))

The comment would explain what it's doing there, but I would
add the extra formatting and spacing so it's more visual,
along with the extra comments.

--
Rick C. Hodgin

Bart

unread,
Oct 3, 2018, 9:37:38 AM10/3/18
to
So when would you use ?#(b) or b>:c?

Why /wouldn't/ you combine them when they occur in the same expression?

And where did 'min' suddenly come from?

I thought you didn't have min at all except as a suggestion, for those
do didn't like >:, to use #define min(a,b) ...

With my example (which doesn't actually mean anything, but would be
legal using your proposals), that would more typically be written as:

a><f() ? ?#(b) : b >: c

The first part using swap or ><, is being used in a way you proposed
where you update a variable while returning its old variable. For that
reason, it needs to part of the expression. Other you don't need >< at all:

t = a;
a = f();
t ? ?#(b) : b >: c

(Phew, that's still quite a mix of shifted/unshifted punctuation in that
final line. C seriously needs even more punctuation....)

--
bart

David Brown

unread,
Oct 3, 2018, 9:39:38 AM10/3/18
to
On 03/10/18 15:03, Rick C. Hodgin wrote:
> On Wednesday, October 3, 2018 at 5:52:56 AM UTC-4, Bart wrote:
>> Not even Rick will know when he comes across:
>> a><f()??#(b):b>:c
>
> I would never write code like that ... and for that reason.
>
> The purpose of having ><, ?#, and the others, is to have
> them available for use in places where it would be clear.
> That sometimes means writing less-efficient code knowing
> the compiler will come along behind you and make it more
> efficient for you.

I fully agree with the idea of writing code based on clarity, and
letting the compiler turn it into efficient object code.

I simply disagree that your new operators are in any way a benefit to
clarity.

>
>> Using normal identifiers, that would be:
>> swap(a,f())?sizeof(b):min(b,c) // or it might be max
>>
>> This is not that meaningful as it applies swap() in a weird manner that
>> only makes sense to Rick, but at least you can now see what operations
>> are being used.
>
> In cases like your example I would write it like this, which
> removes the issue no matter the syntax:
>
> t = swap(a, f());
>
> // Then use it as:
> ((t) ? sizeof(b) : min(b, c))
>
> Or to use my syntax:
>
> // Swap a and f()'s result, store f() into t
> t = a >< f();

I still don't understand what it would mean to "swap a and f()'s
result", unless you language supports references and f() returns a
reference.

>
> // Then use it as:
> ((t) ? sizeof(b) : min(b, c))
>
> The comment would explain what it's doing there, but I would
> add the extra formatting and spacing so it's more visual,
> along with the extra comments.
>

As a general point, if you ever feel you need to write a comment to say
what a line of code /does/ (as distinct from /why/ it does it), then
your code is not clear enough.

Rick C. Hodgin

unread,
Oct 3, 2018, 9:51:26 AM10/3/18
to
On 10/3/2018 9:37 AM, Bart wrote:
> So when would you use ?#(b) or b>:c?

I forgot they existed. :-)

> Why /wouldn't/ you combine them when they occur in the same expression?
> And where did 'min' suddenly come from?
>
> I thought you didn't have min at all except as a suggestion, for those do
> didn't like >:, to use #define min(a,b) ...

I don't remember that. It's possible, but it's not coming
back to me just now.

> With my example (which doesn't actually mean anything, but would be legal
> using your proposals), that would more typically be written as:
>
>      a><f() ? ?#(b) : b >: c

If I were to do as you suggest here, I would write it as:

((a >< f()) ? (?#(b)) : (b >: c))

It would break out each section, and indicate it clearly.
However, the reason why you'd use ?#(x) is when you have a
space issue, like on a long for ( ; ; ) line. If you don't
have the space constraint, then there's no reason not to use
the sizeof(x).

> The first part using swap or ><, is being used in a way you proposed where
> you update a variable while returning its old variable. For that reason, it
> needs to part of the expression. Other you don't need >< at all:
>
>     t = a;
>     a = f();
>     t ? ?#(b) : b >: c

I don't think so. >< returned the left-side value. ><=
returned the right-side value.

> (Phew, that's still quite a mix of shifted/unshifted punctuation in that
> final line. C seriously needs even more punctuation....)

I would never write code like that even though it could be
written like that.

The goal of having these new features is they are another tool
in the tool box, but as I've used as a common reference for
describing when to use which tool, it's possible to rebuild an
engine using end-wrenches and crescent wrenches. But, it's
not advisable. It's better to have more specialized tools
like 6-point sockets, torque wrenches, breaker bars, etc.

The same is true for coding, Bart. You don't write code the
way you can just because you can. You write what makes sense,
is easy to read, easy to maintain, is clear, etc. I would
never actually write this either:

((a >< f()) ? (?#(b)) : (b >: c))

I would probably write it thusly:

t = a >< f();
size = ?#(b);
maxVal = (b >: c);

((t) ? size : maxVal)

Or, I would write this:

// Based on a, store sizeof(b) or use max of b,c
((a >< f()) ? (?#(b)) : (b >: c))

It would depend on the situation, and what other code nearby
is doing. If I've already added a comment up above explaining
how these things work, then I wouldn't add additional comments.
If it is part of a known sequence of operations, then I wouldn't
add an additional comment, etc.

It's all situational, Bart. Fluid. Flexible. You have to have
a type of philosophy of understanding to know what to use where,
and why you're doing it is intuitive, not rigorously mechanical.

--
Rick C. Hodgin

Rick C. Hodgin

unread,
Oct 3, 2018, 10:05:18 AM10/3/18
to
On 10/3/2018 9:39 AM, David Brown wrote:
> On 03/10/18 15:03, Rick C. Hodgin wrote:
>> // Swap a and f()'s result, store f() into t
>> t = a >< f();
>
> I still don't understand what it would mean to "swap a and f()'s
> result", unless you language supports references and f() returns a
> reference.

This particular use of the >< function returns the value of a,
so it would be the same as this operation:

t = a;
a = f();

> As a general point, if you ever feel you need to write a comment to say
> what a line of code /does/ (as distinct from /why/ it does it), then
> your code is not clear enough.

I have a goal in developing code, David, which is to be able
to single-step through comments, not code, because, to be
honest, I don't really care what the code is doing so long
as it's working. It should be doing what the comments say.

Having this feature allows lesser programmers the ability to
go in and debug complex code. They don't have to know what
it's doing mechanically, but the operation.

// Load the largest value into x
x = { .. multi-line complex code here .. };

When they they see that in the comment single-step debugger,
they can get to the "Load the largest value into x" line, and
see the operation and know that it should be doing what is
says.

They can test x and see if it's the largest of what they know
was the input. If not, they may not know how to fix it, but
they can add an issue ticket to the project saying, "Hey, on
lines such-and-such in program xyz, I noticed it says that x
should be the largest value, but it isn't."

The developers can then go in and look at that code and figure
out what it's not working.

The CFSCA model I've had since the late 90s is always there in
the back of my mind, driving this thinking more than the type
of guidance you give me here.

CFSCA = Comments, Flow chart, Source Code, Assembly

Envision a window with parallel panes:

+-+-+----------------+-+
|C|F|Source Code |A|
+-+-+----------------+-+
| | |#include <io.h> | |
| | | | |
| | |int main() | |
| | |{ | |
| | | return 0; | |
| | |} | |
+-+-+----------------+-+

In the combination editor/debugger, you're able to hit Ctrl+
Alt+Left/Right to navigate between panes. You can look at
the source code primarily, but also single-step through your
code at the Flow chart or Comments level, or if there's a
real issue, go down into assembly and single-step there.

The ability to move in thoughts, in concepts, in ideas,
rather than the minutia of details, is what I'm after in
the big picture grand scheme of things.

It's a long-term goal.

--
Rick C. Hodgin

Rick C. Hodgin

unread,
Oct 3, 2018, 10:09:51 AM10/3/18
to
On 10/3/2018 10:05 AM, Rick C. Hodgin wrote:
> The CFSCA model I've had since the late 90s is always there in
> the back of my mind, driving this thinking more than the type
> of guidance you give me here.
>
>     CFSCA = Comments, Flow chart, Source Code, Assembly

CFSCA is pronounced as cough-ska.

> Envision a window with parallel panes:
>
>     +-+-+----------------+-+
>     |C|F|Source Code     |A|
>     +-+-+----------------+-+
>     | | |#include <io.h> | |
>     | | |                | |
>     | | |int main()      | |
>     | | |{               | |
>     | | |   return 0;    | |
>     | | |}               | |
>     +-+-+----------------+-+

To be clear about this, the CFSCA design associates flow
chart elements with literal code, and the comments that
exist are not line or block comments in source code, but
are comments that convey the sentiment of what's happening
in broad strokes, like when you're mapping out the flow of
a large system.

> In the combination editor/debugger, you're able to hit Ctrl+
> Alt+Left/Right to navigate between panes.  You can look at
> the source code primarily, but also single-step through your
> code at the Flow chart or Comments level, or if there's a
> real issue, go down into assembly and single-step there.
>
> The ability to move in thoughts, in concepts, in ideas,
> rather than the minutia of details, is what I'm after in
> the big picture grand scheme of things.
>
> It's a long-term goal.

You can see my early workings with it here, where you see
the assembly language pane front-and-center, and the panes
to the left of that window are the CFSC panes, with the
assembly one open and visible:

If you can't see the video, use VLC (videolan.org):
http://www.visual-freepro.org/videos/2014_02_13__exodus_debi_debugger.ogv

--
Rick C. Hodgin

David Brown

unread,
Oct 3, 2018, 10:22:43 AM10/3/18
to
On 03/10/18 16:05, Rick C. Hodgin wrote:
> On 10/3/2018 9:39 AM, David Brown wrote:
>> On 03/10/18 15:03, Rick C. Hodgin wrote:
>>> // Swap a and f()'s result, store f() into t
>>> t = a >< f();
>>
>> I still don't understand what it would mean to "swap a and f()'s
>> result", unless you language supports references and f() returns a
>> reference.
>
> This particular use of the >< function returns the value of a,
> so it would be the same as this operation:
>
> t = a;
> a = f();
>

So why not write that? Everyone can see what that does. There is no
need for a comment - just write code that says what you mean.

>> As a general point, if you ever feel you need to write a comment to say
>> what a line of code /does/ (as distinct from /why/ it does it), then
>> your code is not clear enough.
>
> I have a goal in developing code, David, which is to be able
> to single-step through comments, not code, because, to be
> honest, I don't really care what the code is doing so long
> as it's working. It should be doing what the comments say.

I really am not sure how to respond to that. Are you trying to tell me
you want your tools to interpret the comments and "run" them, regardless
of what the code says? Presumably that would require comments being in
some kind of fixed syntax with defined meanings. In that case, why
bother with the code - the comments /are/ code!

The reality of programming is that it is an extraordinarily bad idea to
try to have the functionality of something defined in two ways here.
And any coding that tries to have comments that say what code does is
doomed to confusing misinformation after code is editing and comments
invariably get out of sync with the code.

>
> Having this feature allows lesser programmers the ability to
> go in and debug complex code. They don't have to know what
> it's doing mechanically, but the operation.
>
> // Load the largest value into x
> x = { .. multi-line complex code here .. };
>
> When they they see that in the comment single-step debugger,
> they can get to the "Load the largest value into x" line, and
> see the operation and know that it should be doing what is
> says.
>
> They can test x and see if it's the largest of what they know
> was the input. If not, they may not know how to fix it, but
> they can add an issue ticket to the project saying, "Hey, on
> lines such-and-such in program xyz, I noticed it says that x
> should be the largest value, but it isn't."

You can do that with a total disregard for the comments. Put the
complex code in a function called "load_the_largest_value", and do a
step-over-function debug operation.

>
> The developers can then go in and look at that code and figure
> out what it's not working.
>
> The CFSCA model I've had since the late 90s is always there in
> the back of my mind, driving this thinking more than the type
> of guidance you give me here.
>
> CFSCA = Comments, Flow chart, Source Code, Assembly
>
> Envision a window with parallel panes:
>
> +-+-+----------------+-+
> |C|F|Source Code |A|
> +-+-+----------------+-+
> | | |#include <io.h> | |
> | | | | |
> | | |int main() | |
> | | |{ | |
> | | | return 0; | |
> | | |} | |
> +-+-+----------------+-+
>
> In the combination editor/debugger, you're able to hit Ctrl+
> Alt+Left/Right to navigate between panes. You can look at
> the source code primarily, but also single-step through your
> code at the Flow chart or Comments level, or if there's a
> real issue, go down into assembly and single-step there.
>
> The ability to move in thoughts, in concepts, in ideas,
> rather than the minutia of details, is what I'm after in
> the big picture grand scheme of things.
>
> It's a long-term goal.
>

I don't really want to put into words what I think of this idea - it
would only upset you, and you would not listen to my advice or opinion
anyway.


Rick C. Hodgin

unread,
Oct 3, 2018, 10:29:50 AM10/3/18
to
On 10/3/2018 10:22 AM, David Brown wrote:
> On 03/10/18 16:05, Rick C. Hodgin wrote:
>> On 10/3/2018 9:39 AM, David Brown wrote:
>>> On 03/10/18 15:03, Rick C. Hodgin wrote:
>>>> // Swap a and f()'s result, store f() into t
>>>> t = a >< f();
>>>
>>> I still don't understand what it would mean to "swap a and f()'s
>>> result", unless you language supports references and f() returns a
>>> reference.
>>
>> This particular use of the >< function returns the value of a,
>> so it would be the same as this operation:
>>
>> t = a;
>> a = f();
>
> So why not write that? Everyone can see what that does. There is no
> need for a comment - just write code that says what you mean.

You can. Nothing stopping you.

>>> As a general point, if you ever feel you need to write a comment to say
>>> what a line of code /does/ (as distinct from /why/ it does it), then
>>> your code is not clear enough.
>>
>> I have a goal in developing code, David, which is to be able
>> to single-step through comments, not code, because, to be
>> honest, I don't really care what the code is doing so long
>> as it's working. It should be doing what the comments say.
>
> I really am not sure how to respond to that. Are you trying to tell me
> you want your tools to interpret the comments and "run" them, regardless
> of what the code says? Presumably that would require comments being in
> some kind of fixed syntax with defined meanings. In that case, why
> bother with the code - the comments /are/ code!

Two models, one to operate at the main outer comment level,
one to operate at the comments-in-code level.

When you step over a comment, you run the code between it
and the next comment.

> The reality of programming is that it is an extraordinarily bad idea to
> try to have the functionality of something defined in two ways here.
> And any coding that tries to have comments that say what code does is
> doomed to confusing misinformation after code is editing and comments
> invariably get out of sync with the code.

They are explicitly different. One is a high-level overview
level, the other is coding-level comments.

You can choose which one to step over, which will be obvious,
because on one you're on the C pane for Comments, on the other
you're in the SC pane or Source Code, and you're in the mode
of stepping via comments.

>> Having this feature allows lesser programmers the ability to
>> go in and debug complex code. They don't have to know what
>> it's doing mechanically, but the operation.
>>
>> // Load the largest value into x
>> x = { .. multi-line complex code here .. };
>>
>> When they they see that in the comment single-step debugger,
>> they can get to the "Load the largest value into x" line, and
>> see the operation and know that it should be doing what is
>> says.
>>
>> They can test x and see if it's the largest of what they know
>> was the input. If not, they may not know how to fix it, but
>> they can add an issue ticket to the project saying, "Hey, on
>> lines such-and-such in program xyz, I noticed it says that x
>> should be the largest value, but it isn't."
>
> You can do that with a total disregard for the comments. Put the
> complex code in a function called "load_the_largest_value", and do a
> step-over-function debug operation.

Yes, and now you're relying on the developer to have done that.
With this /NEW/ ability, you'll be able to leave the details
there, and still accomplish the same thing.

It goes back to having:

#define swap ><

By having ><, and the ability to have #define, you have both.
But by only having swap(a,b) or the swap keyword, you're stuck.

With this /NEW/ ability to step-over comments, you'll be able
to step over comments at the various levels, so that code with
blocks could be stepped into/over multiple ways.

> I don't really want to put into words what I think of this idea - it
> would only upset you, and you would not listen to my advice or opinion
> anyway.

You're always against the things I'm moving toward. It is
literally the enemy within you working against me to do me
harm, even though you'll swear up and down it isn't.

It is like this continually for all people who are not born
again by having their sin forgiven by Jesus Christ. Those
with more sin in their lives will see it more pronounced.

You don't have any of these new ideas I've come up with be-
for you. You're judging them based on what you think they'll
be like, rather than on their merits. That is a bad idea.

--
Rick C. Hodgin

Niles Rogoff

unread,
Oct 3, 2018, 2:28:19 PM10/3/18
to
On Tue, 02 Oct 2018 15:26:42 +0100, Bart wrote:

> On 02/10/2018 14:08, Rick C. Hodgin wrote:
> [...]
>> On 10/2/2018 8:58 AM, Bart wrote:
>> [...]
>>  It would make more sense in C's context to be:
>>
>>     swap(&a, &b);
>
> I thought that (int&,int&) defined reference parameters so that you
> didn't need & here?
>

Reference parameters are a C++ thing.

David Brown

unread,
Oct 3, 2018, 2:52:14 PM10/3/18
to
On 03/10/18 16:29, Rick C. Hodgin wrote:
> On 10/3/2018 10:22 AM, David Brown wrote:
>> On 03/10/18 16:05, Rick C. Hodgin wrote:
>>> On 10/3/2018 9:39 AM, David Brown wrote:
>>>> On 03/10/18 15:03, Rick C. Hodgin wrote:
>>>>>       // Swap a and f()'s result, store f() into t
>>>>>       t = a >< f();
>>>>
>>>> I still don't understand what it would mean to "swap a and f()'s
>>>> result", unless you language supports references and f() returns a
>>>> reference.
>>>
>>> This particular use of the >< function returns the value of a,
>>> so it would be the same as this operation:
>>>
>>>      t = a;
>>>      a = f();
>>
>> So why not write that?  Everyone can see what that does.  There is no
>> need for a comment - just write code that says what you mean.
>
> You can.  Nothing stopping you.

I want something stopping /you/ from writing anything else.

If a language is going to be useful, then it should fulfil two criteria:

1. It should be as easy as possible to write good code.
2. It should be as hard as possible to write bad code.

You make a good effort at number 1 here. You completely miss out on
number 2.

>
>>>> As a general point, if you ever feel you need to write a comment to say
>>>> what a line of code /does/ (as distinct from /why/ it does it), then
>>>> your code is not clear enough.
>>>
>>> I have a goal in developing code, David, which is to be able
>>> to single-step through comments, not code, because, to be
>>> honest, I don't really care what the code is doing so long
>>> as it's working.  It should be doing what the comments say.
>>
>> I really am not sure how to respond to that.  Are you trying to tell me
>> you want your tools to interpret the comments and "run" them, regardless
>> of what the code says?  Presumably that would require comments being in
>> some kind of fixed syntax with defined meanings.  In that case, why
>> bother with the code - the comments /are/ code!
>
> Two models, one to operate at the main outer comment level,
> one to operate at the comments-in-code level.
>
> When you step over a comment, you run the code between it
> and the next comment.

As I said, I have no sensible response here that you would not deem
insulting. All I can say is that of all the misfeatures of your
language, this one takes special place. But I am not your target
audience, so if you think this makes sense, it's up to you.

>
> You're always against the things I'm moving toward.  It is
> literally the enemy within you working against me to do me
> harm, even though you'll swear up and down it isn't.

No, you just pick those cases and forget all the times I have encouraged
you or said that I think something was a good idea. To be fair, of the
ideas you have posted in this group I think a large proportion have been
bad, but I have been quick to say when I think something is good or when
I agree with you. I make technical comments and opinions on the
technical solutions you present - this is not judgement on the language
itself or your goals. (I've talked about them too, but that is a
different matter.) When I make such technical comments, I really don't
care why you are making the software, where your inspiration or
motivation comes from, or anything else involved - I judge entirely on
the information you post about the feature in question.

I do exactly the same for your language suggestions as for Bart's,
Jacob's or anyone else's. It is natural that I think most ideas are
bad, because it is very difficult to come up with good new ideas. But
it would be nice if you (and Bart, and Jacob) stopped thinking that I
and others are working against you or always negative. Show me an idea
I like, and I will be positive.

Rick C. Hodgin

unread,
Oct 3, 2018, 2:57:51 PM10/3/18
to
On 10/3/2018 2:52 PM, David Brown wrote:
> On 03/10/18 16:29, Rick C. Hodgin wrote:
>> On 10/3/2018 10:22 AM, David Brown wrote:
>>> On 03/10/18 16:05, Rick C. Hodgin wrote:
>>>> On 10/3/2018 9:39 AM, David Brown wrote:
>>>>> On 03/10/18 15:03, Rick C. Hodgin wrote:
>>>>>>       // Swap a and f()'s result, store f() into t
>>>>>>       t = a >< f();
>>>>>
>>>>> I still don't understand what it would mean to "swap a and f()'s
>>>>> result", unless you language supports references and f() returns a
>>>>> reference.
>>>>
>>>> This particular use of the >< function returns the value of a,
>>>> so it would be the same as this operation:
>>>>
>>>>      t = a;
>>>>      a = f();
>>>
>>> So why not write that?  Everyone can see what that does.  There is no
>>> need for a comment - just write code that says what you mean.
>>
>> You can.  Nothing stopping you.
>
> I want something stopping /you/ from writing anything else.

I know. We won't agree on anything here, David ... so, thank you
for contributing again to my life.

--
Rick C. Hodgin

Ben Bacarisse

unread,
Oct 3, 2018, 4:31:25 PM10/3/18
to
In the context of a >< b being a swap operation...
Malcolm McLean <malcolm.ar...@gmail.com> writes:
> On Wednesday, October 3, 2018 at 1:29:39 PM UTC+1, David Brown wrote:
<snip>
>> I can't see what sort of return value would make sense from a "swap"
>> operation, but maybe other people do.
>>
> No, it usually can't fail, and it inherently operates on the bit patterns
> passed to it in place.

Why do you say that swap inherently operates on bit patterns? It would
make perfect sense to define swap in terms of values, just as C defines
assignment in terms of values and not bit patterns.

> So the return type isn't useful unless you can
> return two values, when it ceases to be "swap" and becomes "assign".

If a swap expression were to be an lvalue then

a >< b >< c;

gets a natural meaning: it rotates the values in a, b and c. The main
argument against defining it like this is that the operator is no longer
symmetric, despite being written with a symmetric symbol.

a >< b >< c rotates right or left depending on whether a >< b yields the
lvalue of a or b and the operator gives the reader no clue as to which
is the lvalue.

--
Ben.

Rick C. Hodgin

unread,
Oct 3, 2018, 4:47:41 PM10/3/18
to
On 10/3/2018 4:31 PM, Ben Bacarisse wrote:
> If a swap expression were to be an lvalue then
> a >< b >< c;
>
> gets a natural meaning: it rotates the values in a, b and c. The main
> argument against defining it like this is that the operator is no longer
> symmetric, despite being written with a symmetric symbol.

The"a >< b >< c;" expression would return this result:

// Initial values:
int a = 1, b = 2, c = 3;

// Rewrite, working on the part in parenthesis
(a >< b) >< c;

01: t1 = b;
02: b = a;
03: a = t1;
// Right now, a = 2, b = 1, t1 = 2
// Now: "t1 >< c;"

04: t2 = c;
05: c = t1;
06: t1 = t2;
// Right now, t1 = 3, c = 2, t2 = 3
// Now: "t2;"

After one iteration, the initial c value is lost to the
intermediate expression calculation, which was not con-
sumed in this form.

Start End
----- -----
a = 1 ---> a = 2
b = 2 ---> b = 1
c = 3 ---> c = 2

If you had used:

a = (a >< b >< c);

Then it would've returned the t2 value, which was 3, and it would
be a cycle to the right one step.

> a >< b >< c rotates right or left depending on whether a >< b yields the
> lvalue of a or b and the operator gives the reader no clue as to which
> is the lvalue.

Based on what was discussed previously, a >< b returns a. And
a ><= b would return b; (takes the thing on the right, and,
while swapping, returns the result of the store, which is ef-
fectively b going into a, even though simultaneously a went
into b).

--
Rick C. Hodgin

Ben Bacarisse

unread,
Oct 3, 2018, 10:43:46 PM10/3/18
to
"Rick C. Hodgin" <rick.c...@gmail.com> writes:

> On 10/3/2018 4:31 PM, Ben Bacarisse wrote:
>> If a swap expression were to be an lvalue then
>> a >< b >< c;
>>
>> gets a natural meaning: it rotates the values in a, b and c. The main
>> argument against defining it like this is that the operator is no longer
>> symmetric, despite being written with a symmetric symbol.
>
> The"a >< b >< c;" expression would return this result:

You are free to define it any way you like, but what you write below
suggests you are not talking about my suggestion. If a >< b is an
lvalue expression (that's the way the C standard uses the term) then
there are only two reasonable lvalues to consider -- the left hand side
or the right hand side.

> // Initial values:
> int a = 1, b = 2, c = 3;
>
> // Rewrite, working on the part in parenthesis
> (a >< b) >< c;
>
> 01: t1 = b;
> 02: b = a;
> 03: a = t1;
> // Right now, a = 2, b = 1, t1 = 2
> // Now: "t1 >< c;"
>
> 04: t2 = c;
> 05: c = t1;
> 06: t1 = t2;
> // Right now, t1 = 3, c = 2, t2 = 3
> // Now: "t2;"
>
> After one iteration, the initial c value is lost to the
> intermediate expression calculation, which was not con-
> sumed in this form.

This is very odd. Why would you chose the temporary to be the lvalue to
use? And of you are using the temporary to get the ordinary (r)value,
why do even permit (a >< b) >< c? It should be a constraint violation
in the same what that 2 = b is.

Note that with my suggestion the associativity of >< makes no
difference. (a >< b) >< c gives the same result as a >< (b >< c).

Maybe you are not sure what an lvalue is?

<snip>
--
Ben.

Rick C. Hodgin

unread,
Oct 3, 2018, 10:47:58 PM10/3/18
to
On 10/03/2018 10:43 PM, Ben Bacarisse wrote:
> "Rick C. Hodgin" <rick.c...@gmail.com> writes:
>> The"a >< b >< c;" expression would return this result:
>>
>> // Initial values:
>> int a = 1, b = 2, c = 3;
>>
>> // Rewrite, working on the part in parenthesis
>> (a >< b) >< c;
>>
>> 01: t1 = b;
>> 02: b = a;
>> 03: a = t1;
>> // Right now, a = 2, b = 1, t1 = 2
>> // Now: "t1 >< c;"
>>
>> 04: t2 = c;
>> 05: c = t1;
>> 06: t1 = t2;
>> // Right now, t1 = 3, c = 2, t2 = 3
>> // Now: "t2;"
>>
>> After one iteration, the initial c value is lost to the
>> intermediate expression calculation, which was not con-
>> sumed in this form.
>
> This is very odd. Why would you chose the temporary to be the lvalue to
> use? And of you are using the temporary to get the ordinary (r)value,
> why do even permit (a >< b) >< c? It should be a constraint violation
> in the same what that 2 = b is.

Because >< is an operator. It is evaluated left-to-right as if
you had used a + b + c.

> Note that with my suggestion the associativity of >< makes no
> difference. (a >< b) >< c gives the same result as a >< (b >< c).

I didn't realize you were suggesting something new. I thought
you were misunderstanding what had already been discussed. My
reply was given relative to the prior discussion between myself
and Bart.

--
Rick C. Hodgin

Ben Bacarisse

unread,
Oct 3, 2018, 11:26:07 PM10/3/18
to
But >< is not like +. It is more like = where one side must be an
lvalue, except with >< both side must be. Thus (a >< b) >< c only makes
sense if the expression a >< b is itself an lvalue.

You can't assign to the result of an expression that yields an ordinary
value (like (a + b) = c) and you should not be able to swap c with the
result of an expression that yields an ordinary value. That's why I
pointed out that a >< b should really be an lvalue expression, not an
ordinary one.

>> Note that with my suggestion the associativity of >< makes no
>> difference. (a >< b) >< c gives the same result as a >< (b >< c).
>
> I didn't realize you were suggesting something new.

I started out with "If a swap expression were to be an lvalue..." and as
far as I know that had not been proposed up to that point. I don't see
how you could think I was not introducing a new idea. You weren't
talking about lvalue expressions where you?

> I thought
> you were misunderstanding what had already been discussed. My
> reply was given relative to the prior discussion between myself
> and Bart.

Ah. It should have been given relative to what I wrote which was
clearly introducing the notion that a swap should be an lavlue so that
expressions like a >< b >< c would be useful.

I had nothing to say about what you are Bart were discussing. I replied
to *Malcolm* when he said that the expression's result is not useful.

--
Ben.

Rick C. Hodgin

unread,
Oct 3, 2018, 11:44:26 PM10/3/18
to
On Wednesday, October 3, 2018 at 11:26:07 PM UTC-4, Ben Bacarisse wrote:
> "Rick C. Hodgin" <rick.c...@gmail.com> writes:
> > Because >< is an operator. It is evaluated left-to-right as if
> > you had used a + b + c.
>
> But >< is not like +. It is more like = where one side must be an
> lvalue, except with >< both side must be. Thus (a >< b) >< c only makes
> sense if the expression a >< b is itself an lvalue.

It's an arbitrary choice. >< returns the left side, ><= returns
the right side, but apart from moving data in two directions, it's
otherwise identical to other operators.

> You can't assign to the result of an expression that yields an ordinary
> value (like (a + b) = c) and you should not be able to swap c with the
> result of an expression that yields an ordinary value. That's why I
> pointed out that a >< b should really be an lvalue expression, not an
> ordinary one.

I understand your point. I disagree. I think >< and ><= are
special case operators, but traditional in all other ways.

--
Rick C. Hodgin

Ben Bacarisse

unread,
Oct 4, 2018, 6:53:43 AM10/4/18
to
"Rick C. Hodgin" <rick.c...@gmail.com> writes:

> On Wednesday, October 3, 2018 at 11:26:07 PM UTC-4, Ben Bacarisse wrote:
>> "Rick C. Hodgin" <rick.c...@gmail.com> writes:
>> > Because >< is an operator. It is evaluated left-to-right as if
>> > you had used a + b + c.
>>
>> But >< is not like +. It is more like = where one side must be an
>> lvalue, except with >< both side must be. Thus (a >< b) >< c only makes
>> sense if the expression a >< b is itself an lvalue.
>
> It's an arbitrary choice. >< returns the left side, ><= returns
> the right side, but apart from moving data in two directions, it's
> otherwise identical to other operators.

I don't think you know what an lvalue is. "returns the left side" is
ambiguous in a context where you seem to be talking about ordinary
values and I am talking about lvalues.

>> You can't assign to the result of an expression that yields an ordinary
>> value (like (a + b) = c) and you should not be able to swap c with the
>> result of an expression that yields an ordinary value. That's why I
>> pointed out that a >< b should really be an lvalue expression, not an
>> ordinary one.
>
> I understand your point.

No, I really don't think you do. Can you at least see how a >< b >< c
rotates the contents of a, b and c if >< is an lvalue expression? If
not (and you certainly claimed before that it doesn't) then you are not
seeing what I am suggesting.

> I disagree. I think >< and ><= are
> special case operators, but traditional in all other ways.

I am not sure what it is you disagree with. Why, if you favour having a
swap operator, would you not want a >< b >< c to have a useful meaning?
You can still use a >< b in other expressions (since lvalues "decay" to
ordinary values).

If you also make ><= be an lvalue expression you get a ><= b ><= c being
a rotate in the other direction. What is there to disagree with here?

(By the way, if I were going to provide both operators I'd make them
mirrors of each other, for example =>< and ><=. However, I don't think
there is much value in having both.)

Here it is in C++ using << and >> for the two versions of swap. You can
do it with a swap function in C, but (a) I wanted to illustrate it with
operators, (b) in C you have to use pointers so there is no direct
analogue of the lvalue.

template <class T> class Swappable {
T content;
public:
Swappable(T v) : content(v) {}
operator T (){ return content; }

Swappable &operator<<(Swappable &s) {
T tmp = content; content = s.content; s.content = tmp;
return *this;
}
Swappable &operator>>(Swappable &s) {
T tmp = content; content = s.content; s.content = tmp;
return s;
}
};

#include <iostream>

int main()
{
Swappable<int> a = 1, b = 2, c = 3;
std::cout << a << " " << b << " " << c << "\n";

a << b << c;
std::cout << a << " " << b << " " << c << "\n";
a << b << c;
std::cout << a << " " << b << " " << c << "\n";
a << b << c;
std::cout << a << " " << b << " " << c << "\n";

a >> b >> c;
std::cout << a << " " << b << " " << c << "\n";
a >> b >> c;
std::cout << a << " " << b << " " << c << "\n";
a >> b >> c;
std::cout << a << " " << b << " " << c << "\n";
}

Do you see what I mean now?

Note that the only difference is which "side" is referenced in the
return. Note also that you get the same results, in both cases, if you
bracket the expression the "other" way: a << (b << c).

Since this is comp.lang.c, here it is in C. But with no operators and
using explicit pointers to "fake" the lvalue, it's all much less clear.


int *swapl(int *a, int *b) { int t = *a; *a = *b; *b = t; return a; }
int *swapr(int *a, int *b) { int t = *a; *a = *b; *b = t; return b; }

#include <stdio.h>

int main(void)
{
int a = 1, b = 2, c = 3;
printf("%d %d %d\n", a, b, c);

swapl(swapl(&a, &b), &c);
printf("%d %d %d\n", a, b, c);
swapl(swapl(&a, &b), &c);
printf("%d %d %d\n", a, b, c);
swapl(swapl(&a, &b), &c);
printf("%d %d %d\n", a, b, c);

swapr(swapr(&a, &b), &c);
printf("%d %d %d\n", a, b, c);
swapr(swapr(&a, &b), &c);
printf("%d %d %d\n", a, b, c);
swapr(swapr(&a, &b), &c);
printf("%d %d %d\n", a, b, c);
}

--
Ben.

Rick C. Hodgin

unread,
Oct 4, 2018, 8:15:41 AM10/4/18
to
On Thursday, October 4, 2018 at 6:53:43 AM UTC-4, Ben Bacarisse wrote:
> "Rick C. Hodgin" <rick.c...@gmail.com> writes:
> > It's an arbitrary choice. >< returns the left side, ><= returns
> > the right side, but apart from moving data in two directions, it's
> > otherwise identical to other operators.

While shaving this morning I had the thought ><= should return
the right side value, and =>< should return the left side value,
and these should be called "dance" operators when they affect both
sides.

> I don't think you know what an lvalue is. "returns the left side" is
> ambiguous in a context where you seem to be talking about ordinary
> values and I am talking about lvalues.

Both sides are being updated. The normal nomenclature does not
lend well to this type of dual target.

> >> You can't assign to the result of an expression that yields an ordinary
> >> value (like (a + b) = c) and you should not be able to swap c with the
> >> result of an expression that yields an ordinary value. That's why I
> >> pointed out that a >< b should really be an lvalue expression, not an
> >> ordinary one.
> >
> > I understand your point.
>
> No, I really don't think you do.

Oh I really do.

> Can you at least see how a >< b >< c
> rotates the contents of a, b and c if >< is an lvalue expression?

Yes, but it isn't, nor can it be.

> If
> not (and you certainly claimed before that it doesn't) then you are not
> seeing what I am suggesting.

I see what you're suggesting, and did see before also. I think
you are wrong in your thinking.

> Why, if you favour having a
> swap operator, would you not want a >< b >< c to have a useful meaning?

It does (as I demonstrated).

> You can still use a >< b in other expressions (since lvalues "decay" to
> ordinary values).
>
> If you also make ><= be an lvalue expression you get a ><= b ><= c being
> a rotate in the other direction. What is there to disagree with here?

It doesn't work that way. The result would be an rvalue with a required
special consideration due to the dual target updates.

> (By the way, if I were going to provide both operators I'd make them
> mirrors of each other, for example =>< and ><=.

My same thought this morning.

> However, I don't think
> there is much value in having both.)

One returns the right hand value, the other the left. Much value.

--
Rick C. Hodgin
It is loading more messages.
0 new messages