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

Range-aware modulo operator -%

74 views
Skip to first unread message

Rick C. Hodgin

unread,
Dec 27, 2018, 9:07:42 PM12/27/18
to
I think C/C++ needs to have a range-aware modulo operator that will
continue ranging properly when it encounters negative values.

We have this:
i = (i + 1) % 10; // Always ranges 0..9

But what if you try this when i = 0:
i = (i - 1) % 10;

It won't produce the same result in the same pattern seen when you
started at a positive i and tended toward 0. It begins a new trend,
one which is useful, but not always desirable.

A range-aware modulo operator would know that it should always be
in the range 0..9 (from the example above), and also that it should
continue the pattern seen in the positive integers, such that when
given a negative input value, it handles the processing differently:

// v=value, m=modulo number
int range_modulo(int v, int m)
{
if (v >= 0) return (v % m);
else return ((m + (v % m)) % m);
}

int i;
for (i = 12; i >= -12; --i)
printf("%d --> mod 10 = %d\n", i, range_modulo(i, 10));

-----
I propose the -% symbol for the operator.

It would allow things that are sometimes needed in video games,
as just one example, when a player hits the left button instead
of the right button, and you need it to go the other way, AND you
want it to just work while using the same math.

Just sayin'... :-)

--
Rick C. Hodgin

Richard Damon

unread,
Dec 27, 2018, 9:34:22 PM12/27/18
to
It used to be that an implementation was allowed to define -1 % 10 to be
9, but they standard changed the rule for division so that that wasn't
allowed anymore. (It required -1/10 == -1)

The key fact is that given i, j, m, n as integral types and no overflow
occurring.

If i = m / n and j = m % n
then i * n + j == m

for j to always be positive, i needs to be the floor of the division,
not from round to 0.

The key to remember is that % is NOT the modulus operator, but the
remainder operator (which work the same for positive numbers).

It is simple enough to define a mod function that gets the results you
want, so not that much need for a new operator.

Ben Bacarisse

unread,
Dec 27, 2018, 10:06:10 PM12/27/18
to
"Rick C. Hodgin" <rick.c...@gmail.com> writes:

> I think C/C++ needs to have a range-aware modulo operator that will
> continue ranging properly when it encounters negative values.

It's just the modulus operator. I don't think there's a need for
another name, but 'range-aware' seems like an odd suggestion.

Modern C's % is the remainder operator defined to complement C's integer
division: (a/b)*b + a%b = a. (This was not guaranteed in C90.)

Some languages (e.g. Haskell) also have two division operators and two
corresponding 'remainder' operators.

(a `quot` b) * b + (a `rem` b) == a
(a `div` b) * b + (a `mod` b) == a

> We have this:
> i = (i + 1) % 10; // Always ranges 0..9

except when i < -1.

<snip>
--
Ben.

Robert Wessel

unread,
Dec 27, 2018, 10:31:09 PM12/27/18
to
On Fri, 28 Dec 2018 03:05:43 +0000, Ben Bacarisse
<ben.u...@bsb.me.uk> wrote:

>"Rick C. Hodgin" <rick.c...@gmail.com> writes:
>
>> I think C/C++ needs to have a range-aware modulo operator that will
>> continue ranging properly when it encounters negative values.
>
>It's just the modulus operator. I don't think there's a need for
>another name, but 'range-aware' seems like an odd suggestion.
>
>Modern C's % is the remainder operator defined to complement C's integer
>division: (a/b)*b + a%b = a. (This was not guaranteed in C90.)


I think that's wrong. C89/90 did guarantee that relationship, but did
not guarantee the sign of the reminder. IOW, -3/2 could result in
either -1 or -2, with a remainder of -1 or +1 respectively. That
changed in C99.


>Some languages (e.g. Haskell) also have two division operators and two
>corresponding 'remainder' operators.
>
> (a `quot` b) * b + (a `rem` b) == a
> (a `div` b) * b + (a `mod` b) == a
>
>> We have this:
>> i = (i + 1) % 10; // Always ranges 0..9
>
>except when i < -1.
>
><snip>


Forth does something similar.

Ben Bacarisse

unread,
Dec 27, 2018, 11:20:43 PM12/27/18
to
Robert Wessel <robert...@yahoo.com> writes:

> On Fri, 28 Dec 2018 03:05:43 +0000, Ben Bacarisse
> <ben.u...@bsb.me.uk> wrote:
>
>>"Rick C. Hodgin" <rick.c...@gmail.com> writes:
>>
>>> I think C/C++ needs to have a range-aware modulo operator that will
>>> continue ranging properly when it encounters negative values.
>>
>>It's just the modulus operator. I don't think there's a need for
>>another name, but 'range-aware' seems like an odd suggestion.
>>
>>Modern C's % is the remainder operator defined to complement C's integer
>>division: (a/b)*b + a%b = a. (This was not guaranteed in C90.)
>
> I think that's wrong.

So do I!

> C89/90 did guarantee that relationship, but did
> not guarantee the sign of the reminder.

Yes, I was remembering the wrong difference. Thanks.

<snip>
--
Ben.

Alf P. Steinbach

unread,
Dec 27, 2018, 11:37:44 PM12/27/18
to
Yes, C++11 narrowed the permissible behavior of integer division to
always round towards zero.

In contrast, Python always rounds towards negative infinity, like the
mathematical floor function.

So, in Python:


---------------------------------------------------------------------
n_persons = int( input( "How many persons? " ) )
max_per_taxi = int( input( "Maximum passengers per taxi? " ) )
n_taxis = -(-n_persons//max_per_taxi)
print( "You need {} taxis. :)".format( n_taxis ) )
---------------------------------------------------------------------


But in C++:


---------------------------------------------------------------------
#include <iostream>
#include <stdexcept>
#include <stdlib.h> // EXIT_...
#include <string>
using namespace std;

auto fail( const string& s ) -> bool { throw runtime_error( s ); }

auto line_from( istream& stream )
-> string
{
string result;
getline( stream, result ) or fail( "Bah, getline" );
return result;
}

auto input( const string& prompt )
-> string
{
cout << prompt;
return line_from( cin );
}

void doit()
{
const int n_persons = stoi( input( "How many persons? " ) );
const int max_per_taxi = stoi( input( "Maximum passengers per taxi?
" ) );
const int n_taxis = (n_persons + max_per_taxi - 1)/max_per_taxi;
cout << "You need " << n_taxis << " taxis. :)" << endl;
}

auto main() -> int
{
try
{
doit();
return EXIT_SUCCESS;
}
catch( const exception& x )
{
cerr << "!" << x.what() << endl;
}
return EXIT_FAILURE;
}
---------------------------------------------------------------------


Main test case that 13 persons and max 4 per taxi gives 4 taxis, but 12
persons and max 4 per taxi gives 3 taxis.


> The key fact is that given i, j, m, n as integral types and no overflow
> occurring.
>
> If i = m / n and j = m % n
> then i * n + j == m
>
> for j to always be positive, i needs to be the floor of the division,
> not from round to 0.
>
> The key to remember is that % is NOT the modulus operator, but the
> remainder operator (which work the same for positive numbers).

Yes.


> It is simple enough to define a mod function that gets the results you
> want, so not that much need for a new operator.


---------------------------------------------------------------------
#include <iostream>
#include <stdexcept>
#include <stdlib.h> // EXIT_..., div
#include <string>
using namespace std;

auto fail( const string& s ) -> bool { throw runtime_error( s ); }

auto line_from( istream& stream )
-> string
{
string result;
getline( stream, result ) or fail( "Bah, getline" );
return result;
}

auto input( const string& prompt )
-> string
{
cout << prompt;
return line_from( cin );
}

namespace math
{
auto is_negative( const int x )
-> bool
{ return (x < 0); }

auto div( const int a, const int b )
-> int
{
const div_t r = ::div( a, b );
return (r.quot < 0 and r.rem != 0? r.quot - 1 : r.quot);
}

auto mod( const int a, const int b )
-> int
{ return a - b*div( a, b ); }
} // namespace math

void doit()
{
const int n_persons = stoi( input( "How many persons? " ) );
const int max_per_taxi = stoi( input( "Maximum passengers per taxi?
" ) );
const int n_taxis = -math::div( -n_persons, max_per_taxi );
cout << "You need " << n_taxis << " taxis. :)" << endl;
}

auto main() -> int
{
try
{
doit();
return EXIT_SUCCESS;
}
catch( const exception& x )
{
cerr << "!" << x.what() << endl;
}
return EXIT_FAILURE;
}

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


Considering that what C++ offers over Python for this task, is strong
type checking, I wonder if that extreme verbosity and effort is worth it?

Well I'm working on a little C++ band aid library that reduces the above to


---------------------------------------------------------------------
#include <cppx-band-aid/_all_.hpp>
namespace math = cppx::math;
using namespace std;
using cppx::input_line;

void doit()
{
const int n_persons = stoi( input_line( "How many persons? " ) );
const int max_per_taxi = stoi( input_line( "Maximum passengers per
taxi? " ) );
const int n_taxis = -math::div( -n_persons, max_per_taxi );
cout << "You need " << n_taxis << " taxis. :)" << endl;
}

auto main() -> int { cppx::run_app( doit ); }
---------------------------------------------------------------------


Standardizing such band-aid functionality for students could be of
interest to the new working group on supporting C++ in education. But I
think I remember that they got a very narrow mandate, next to worthless?


Cheers!,

- Alf

Bart

unread,
Dec 28, 2018, 7:29:23 AM12/28/18
to
I used this loop to better show the differences:

for (i = 12; i >= -12; --i) {
if (i==0) puts("");
printf("rmod(%3d,10) = %3d, %3d%%10 = %3d\n", i,
range_modulo(i, 10),i,i%10);
if (i==0) puts("");
}

The % operator [which in my language is called 'rem'] shows symmetrical
behaviour around zero, while your range_modulo doesn't.

Both behaviours are useful for different purposes. But the simplest
thing to do is to just keep it as a function, as like that it will work
/now/ on a hundred compilers.

"-%" is unlikely to ever work on any. Apart from which, there's already
enough confusion as to exactly what "%" does, let alone "-%", especially
with the /four/ combinations of negative operands.

(Note that when m is negative, eg. i/(-10), then both appear to have the
same behaviour. The modulo nature of your range_modulo disappears. You
may wish to use abs(m) inside that function, and perhaps re-apply the
sign to the result, if that is important.)

--
bart

Rick C. Hodgin

unread,
Dec 28, 2018, 8:09:35 AM12/28/18
to
I think -% is a truly fundamental operation and should have operator
support. It has utility in various cases.

> "-%" is unlikely to ever work on any. Apart from which, there's already
> enough confusion as to exactly what "%" does, let alone "-%", especially with
> the /four/ combinations of negative operands.
>
> (Note that when m is negative, eg. i/(-10), then both appear to have the same
> behaviour. The modulo nature of your range_modulo disappears. You may wish to
> use abs(m) inside that function, and perhaps re-apply the sign to the result,
> if that is important.)

Interesting. I've never used a negative value that way, so it never
occurred to me.

--
Rick C. Hodgin

Richard Damon

unread,
Dec 28, 2018, 10:25:22 AM12/28/18
to
On 12/28/18 8:10 AM, Rick C. Hodgin wrote:
> On 12/28/2018 7:29 AM, Bart wrote:
>> On 28/12/2018 02:09, Rick C. Hodgin wrote:
>>> I think C/C++ needs to have a range-aware modulo operator that will
>>> continue ranging properly when it encounters negative values.
>>>
>>> We have this:
>>>      i = (i + 1) % 10;   // Always ranges 0..9
>>>
>>> But what if you try this when i = 0:
>>>      i = (i - 1) % 10;
>>>
>>> It won't produce the same result in the same pattern seen when you
>>> started at a positive i and tended toward 0.  It begins a new trend,
>>> one which is useful, but not always desirable.
>>>
>>> A range-aware modulo operator would know that it should always be
>>> in the range 0..9 (from the example above), and also that it should
>>> continue the pattern seen in the positive integers, such that when
>>> given a negative input value, it handles the processing differently:
>>>
>>>      // v=value, m=modulo number
>>>      int range_modulo(int v, int m)
>>>      {
>>>          if (v >= 0)    return (v % m);
>>>          else           return ((m + (v % m)) % m);
>>>      }

In my mind, a cleaner (and actually working) version would be more like:

int modulo(int v, int m) {
int mod = v % m;
if (mod < 0) mod += m;
return mod;
}

This will work even if v is less than -m and not need multiple divide
operations. (For machines with fast divide but bad behavior for
branching, your expression (m + (v % m) % m could also be used all the
time, if you are going to use the conditional, you don't need the second
% if you do it right.

Neither of these work 'right' if m can be negative, and for that we need
to come up with a real definition of what it means to have a negative
modulus.

>>>
>>>      int i;
>>>      for (i = 12; i >= -12; --i)
>>>          printf("%d --> mod 10 = %d\n", i, range_modulo(i, 10));
>>>
>>> -----
>>> I propose the -% symbol for the operator.
>>>
>>> It would allow things that are sometimes needed in video games,
>>> as just one example, when a player hits the left button instead
>>> of the right button, and you need it to go the other way, AND you
>>> want it to just work while using the same math.
>>
>> I used this loop to better show the differences:
>>
>>      for (i = 12; i >= -12; --i) {
>>          if (i==0) puts("");
>>          printf("rmod(%3d,10) = %3d, %3d%%10 = %3d\n", i,
>>             range_modulo(i, 10),i,i%10);
>>          if (i==0) puts("");
>>      }
>>
>> The % operator [which in my language is called 'rem'] shows
>> symmetrical behaviour around zero, while your range_modulo doesn't.
>>
>> Both behaviours are useful for different purposes. But the simplest
>> thing to do is to just keep it as a function, as like that it will
>> work /now/ on a hundred compilers.
>
> I think -% is a truly fundamental operation and should have operator
> support.  It has utility in various cases.

There are LOTS of operations that could be argued are worthy of operator
support for some applications. There actually is a language that tried
to give them all operator symbols, the language APL. Many consider APL a
write only language, because it can be nearly impossible to read and
understand a program written in APL if you didn't just write it recently.

Rather than create a bunch of new symbols as part of the language, I
have thought it would be interesting if C++ allowed the creation of new
operators with NAMES, like operator mod(int v, int m) so you could say
something like v mod m. You would need to be able to define their
'precedence' so the compiler would know how to parse the expression, the
simplest would likely be to define them to act like and existing type of
operator, so

>
>> "-%" is unlikely to ever work on any. Apart from which, there's
>> already enough confusion as to exactly what "%" does, let alone "-%",
>> especially with the /four/ combinations of negative operands.
>>
>> (Note that when m is negative, eg. i/(-10), then both appear to have
>> the same behaviour. The modulo nature of your range_modulo disappears.
>> You may wish to use abs(m) inside that function, and perhaps re-apply
>> the sign to the result, if that is important.)
>
> Interesting.  I've never used a negative value that way, so it never
> occurred to me.
>

Let me make a small comment about what I see in CAlive. It seems that
you are trying to define what you want to call a 'Language' by going
something (a bit crudely) like:

Lets start with something like C (which I don't really fully
understand), and then remove these features that don't make sense to me
so I could never make them work right.

Lets then mix in some bits of C++, but not too much, because that
langauge is so complicated that I can't understand it much of it.

Lets then add in all sorts of nifty little micro-tricks that I wish were
in C and/or C++, not worrying about how they might interact.

I can't understand formal documentation, so I can't write anything like
that myself, so I will document the language as with just a list of the
Hodge-podge rules that I built it with, but that's ok, the formal
specification will be the program I will eventually write (which I guess
means there can't be problems in the language definition, as the
language definition will be exactly as what that implementation did)

I have nothing against the idea that you want to create this new
programming environment with all the nifty bells and whistles that you
want. When (and if) it is done, it may even be useful to others, IF you
are able to produce a coherent set of documentation that tells people
how to use it. What does bother me a bit is the idea that you have that
this is somehow something very important (or should be to others). From
what I have heard you describe, your Grand Design is enormous, and very
likely beyond your reach and ability.

There actually isn't anything wrong with aiming for something you likely
can't reach, as long at the journey to it is something that can be
worthwhile (as in the story of Don Quixote). The issues come when you
try to insist that others need to follow or value your efforts.

Bart

unread,
Dec 28, 2018, 10:54:36 AM12/28/18
to
On 28/12/2018 15:25, Richard Damon wrote:
> On 12/28/18 8:10 AM, Rick C. Hodgin wrote:

> Rather than create a bunch of new symbols as part of the language, I
> have thought it would be interesting if C++ allowed the creation of new
> operators with NAMES, like operator mod(int v, int m) so you could say
> something like v mod m. You would need to be able to define their
> 'precedence' so the compiler would know how to parse the expression, the
> simplest would likely be to define them to act like and existing type of
> operator, so

I think, to start with, it would be more useful to have overloaded
functions. That means you can write this new feature as mod(v,m), so no
issues with precedence. And you don't get the problem of parsing an
expression that looks like this:

a b c d e f g h

of which some are variables, and some are operators (a mix of prefix,
infix and postfix), but you have to resolve all of them before you can
start to parse. (I understand one feature of CAlive is that definitions
for all these can come later.)

This doesn't help the human reader much either.

> Let me make a small comment about what I see in CAlive.

> I have nothing against the idea that you want to create this new
> programming environment with all the nifty bells and whistles that you
> want. When (and if) it is done, it may even be useful to others, IF you
> are able to produce a coherent set of documentation that tells people
> how to use it. What does bother me a bit is the idea that you have that
> this is somehow something very important (or should be to others). From
> what I have heard you describe, your Grand Design is enormous, and very
> likely beyond your reach and ability.

I think the problem is also the proliferation of weird and wonderful
features, which are hard to understand, look hard to use, and would make
any code that uses them completely unreadable:

https://groups.google.com/forum/#!forum/caliveprogramminglanguage

Whether these all these features can interact with each other is another
matter.

--
bart

Rick C. Hodgin

unread,
Dec 28, 2018, 11:42:41 AM12/28/18
to
On 12/28/2018 10:25 AM, Richard Damon wrote:
> ... The issues come when you
> try to insist that others need to follow or value your efforts.

Where have I ever insisted that anyone needs to follow or value my
efforts? I have told people recently, "Don't use [CAlive]... You
won't hurt my feelings."

I have only ever asked people to come and help. They will when
the time is right if this task is for me to complete. If not, it
will still have been my best attempt at giving back to the Lord
what He first gave me, and there is no failure in that pursuit.

-----
If you'd like to help formalize CAlive's design, come on board
and do so. It's not my forte, but I know it's other people's.
I truly admire people like Keith Thompson, who can have so much
of the standard memorized and be able to recall it appropriately
on command. I am that way on Star Trek in many areas. :-) But,
not for things I must read to absorb.

I welcome people to come on board and help. It's a design given
over to holiness and prayer, serving the Lord's goals in this
world, meaning we don't go by a pursuit of profit-seeking, or
money-making. We are designing things correctly from inception,
with the goal being truly to empower people by giving them the
source code in the Public Domain. It is a goal to replace busi-
ness models with helping-one-another models. It is a goal to
use our talents to remove the burdens and shackles of proprietary
software and hardware models (as my goals extend not just to
CAlive and RDC, but also to a new operating system (one similar
to a modernized version of OS/2), as well as new hardware (I have
a CPU design called Inspire that's revolutionary in how it ap-
proaches data processing), and I want to provide people with a
full hardware and software stack that allows us to manufacture
things together, for one another, and not for avarice, greed, or
personal gain, but that our gains would all come in helping one
another achieve more and succeed in their personal goals and in-
terests, and then to teach them to have the same goals and inter-
ests in the things they pursue in their life.

It's a goal of togetherness. It's the motto I've used since
about 2013 on my project:

In God's sight, we've come together.
We've come together to help each other.
Let's grow this project up ... together!
In service and Love to The Lord, forever

It is a full-on vision of "Thy Kingdom come, Thy will be done,
on Earth as it is in Heaven."

These are the areas to which I have interest and expertise. I
pursue them, but my goals are to teach other people to use their
personal interests and areas of expertise to serve the Lord from
where they are, in their station, with their calling.

It is a grand vision. It is in my heart, soul, mind, and pressed
hard upon my spirit ... and I am pursuing it. Others will come
on board to help when they are so moved to do so.

--
Rick C. Hodgin

Rick C. Hodgin

unread,
Dec 28, 2018, 12:15:37 PM12/28/18
to
On 12/28/2018 10:25 AM, Richard Damon wrote:
>>> On 28/12/2018 02:09, Rick C. Hodgin wrote:
>>>>      // v=value, m=modulo number
>>>>      int range_modulo(int v, int m)
>>>>      {
>>>>          if (v >= 0)    return (v % m);
>>>>          else           return ((m + (v % m)) % m);
>>>>      }
>
> In my mind, a cleaner (and actually working) version would be more like:
>
> int modulo(int v, int m) {
> int mod = v % m;
> if (mod < 0) mod += m;
> return mod;
> }
>
> This will work even if v is less than -m and not need multiple divide
> operations. (For machines with fast divide but bad behavior for
> branching, your expression (m + (v % m) % m could also be used all the
> time, if you are going to use the conditional, you don't need the second
> % if you do it right.
>
> Neither of these work 'right' if m can be negative, and for that we need
> to come up with a real definition of what it means to have a negative
> modulus.

I'm all for creating an encompassing algorithm. I only ever use a
positive m in my code, and my values of v should never be more than
relatively small integers away from 0 positive or negative, so it's
not a large need in my specific task. But, if it works another way,
I'm all for it.

>> I think -% is a truly fundamental operation and should have operator
>> support.  It has utility in various cases.
>
> There are LOTS of operations that could be argued are worthy of operator
> support for some applications. There actually is a language that tried
> to give them all operator symbols, the language APL. Many consider APL a
> write only language, because it can be nearly impossible to read and
> understand a program written in APL if you didn't just write it recently.
>
> Rather than create a bunch of new symbols as part of the language, I
> have thought it would be interesting if C++ allowed the creation of new
> operators with NAMES, like operator mod(int v, int m) so you could say
> something like v mod m. You would need to be able to define their
> 'precedence' so the compiler would know how to parse the expression, the
> simplest would likely be to define them to act like and existing type of
> operator, so

How many new symbols have I created, or implemented in CAlive?

When I post things here, it is to gain knowledge about C/C++, so I can
learn something I may not know (most times I'm pretty sure the thing
I'm in pursuit of doesn't already exist) ... and then also to convey
the thought I have so that other people can take it, modify it, extend
it, revise it, and implement it however they want to.

With CAlive, I'm moving forward as I am doing. With C/C++, these are
all offerings given to spark the minds and creative resources of those
people involved in authoring their compilers for those languages, or
those who are influential in moving things this way or that way within
the ecosystem.

People are free to disregard (or mock, as Leigh does), my posts to their
full pleasure. While it sometimes hurts and is annoying, I'm pretty
tough. I can take it. I have a solid foundation in knowing who it is
I serve, and my goals are to please Him first, the rest of the world
will either see value in what I do/post or not. That's not up to me.
I do my best at all points continuously, and I still fail a lot. But
my heart's intent is right, true, proper, and is becoming even more
honed over time. It is from that place, sanctified and focused unto
the Lord, that I continue with all of these efforts.

It's a real thing. Not a trifle. Not a joke. Not a delusion. And
I do not have one negative thing at work in any of my intents or
goals. I may make mistakes, but that's different from a purposeful
intent away from doing all things positive.

I stand before the Lord regularly in prayer asking Him if this is for
me to do, being willing many times to walk away from it all because it
is such a big task. Every time, literally every time I've begun to
have those thoughts, something comes along to re-encourage me, and I
go back into prayer and again ask the Lord if I am to continue as I
press in again toward the goal.

My life is not just lived. I have a purpose in the things I do. They
are not for trivial wants, wishes, desires, etc. I am truly seeking
to give the world something better than it has, and to lift people up
from their pressed-down place by entities that focus on money-interests,
on proprietary goals. I am seeking to free everyone from those chains
with my labor, my talent focused to improve and augment and enhance
their personal lives.

It is a proper goal on all accounts, and it's the one I've been pursu-
ing now for seven years this Spring, and formally as an effort seven
years on July 12, 2019.

--
Rick C. Hodgin

Richard Damon

unread,
Dec 28, 2018, 5:08:43 PM12/28/18
to
Looking over the past 6 months of messages, I see suggested:

min/max: \/ /\ \/= /\=
swap: ><
shortcut indirect: ~> which later became ~~
modulus: -%

and that doesn't count syntax changes like a < b < c

I don't know how many have actually been implemented (and is CAlive
actually far enough along to 'implement' something?

> When I post things here, it is to gain knowledge about C/C++, so I can
> learn something I may not know (most times I'm pretty sure the thing
> I'm in pursuit of doesn't already exist) ... and then also to convey
> the thought I have so that other people can take it, modify it, extend
> it, revise it, and implement it however they want to.
>

But you DON'T ask to gain knowledge. You post that there should be a way
to do xyz, and then state how you think it will work in CAlive.

> With CAlive, I'm moving forward as I am doing.  With C/C++, these are
> all offerings given to spark the minds and creative resources of those
> people involved in authoring their compilers for those languages, or
> those who are influential in moving things this way or that way within
> the ecosystem.
>
> People are free to disregard (or mock, as Leigh does), my posts to their
> full pleasure.  While it sometimes hurts and is annoying, I'm pretty
> tough.  I can take it.  I have a solid foundation in knowing who it is
> I serve, and my goals are to please Him first, the rest of the world
> will either see value in what I do/post or not.  That's not up to me.
> I do my best at all points continuously, and I still fail a lot.  But
> my heart's intent is right, true, proper, and is becoming even more
> honed over time.  It is from that place, sanctified and focused unto
> the Lord, that I continue with all of these efforts.

But this is comp.lang.c and comp.lang.c++ so extensive discussion of
CAlive is really off topic in both of these, as CAlive is NOT either of
these languages, or even a minor variation/extension on it like gcc
c/c++ (many of those extension are still conformant to the C/C++
Standards.)

You seem to want to pretend that you are offering 'legitimate' ideas for
extensions to C and/or C++ but seem to have zero understanding of the
hows and whys these languages are the way they are, and you don't seem
to care.

It would be one thing if you came here asking HOW to implement some
feature of CAlive in your chosen implementation language in the
appropriate group (but choose the language to use, and thus the group to
ask, as things are done significantly differently between those two
languages).

You could also ask about general language design issues in a different
appropriate group (NOT clc or clc++).

>
> It's a real thing.  Not a trifle.  Not a joke.  Not a delusion.  And
> I do not have one negative thing at work in any of my intents or
> goals.  I may make mistakes, but that's different from a purposeful
> intent away from doing all things positive.
>
> I stand before the Lord regularly in prayer asking Him if this is for
> me to do, being willing many times to walk away from it all because it
> is such a big task.  Every time, literally every time I've begun to
> have those thoughts, something comes along to re-encourage me, and I
> go back into prayer and again ask the Lord if I am to continue as I
> press in again toward the goal.
>
> My life is not just lived.  I have a purpose in the things I do.  They
> are not for trivial wants, wishes, desires, etc.  I am truly seeking
> to give the world something better than it has, and to lift people up
> from their pressed-down place by entities that focus on money-interests,
> on proprietary goals.  I am seeking to free everyone from those chains
> with my labor, my talent focused to improve and augment and enhance
> their personal lives.
>
> It is a proper goal on all accounts, and it's the one I've been pursu-
> ing now for seven years this Spring, and formally as an effort seven
> years on July 12, 2019.
>

Scripture tells us to obey the rules of the land. The one exception
given is if those rules tell you to do something that directly
contradicts a rule of God. One of these rules is that these groups have
a defined topic space, which is discussion of things closely related to
the C or C++ languages and their use. Unless you can find some direct
command of God that following this rule will make you violate, you
should try to follow that rule, for to do otherwise inflicts a bad
report onto your God.

Your posts as 'offerings' are really nothing but SPAM, which is not
something I think God wants, nor does he want to be thought of as
connected to a spammer.

Richard Damon

unread,
Dec 28, 2018, 5:26:26 PM12/28/18
to
On 12/28/18 10:56 AM, Bart wrote:
> On 28/12/2018 15:25, Richard Damon wrote:
>> On 12/28/18 8:10 AM, Rick C. Hodgin wrote:
>
>> Rather than create a bunch of new symbols as part of the language, I
>> have thought it would be interesting if C++ allowed the creation of new
>> operators with NAMES, like operator mod(int v, int m) so you could say
>> something like v mod m. You would need to be able to define their
>> 'precedence' so the compiler would know how to parse the expression, the
>> simplest would likely be to define them to act like and existing type of
>> operator, so
>
> I think, to start with, it would be more useful to have overloaded
> functions. That means you can write this new feature as mod(v,m), so no
> issues with precedence. And you don't get the problem of parsing an
> expression that looks like this:
>
>    a b c d e f g h
>
> of which some are variables, and some are operators (a mix of prefix,
> infix and postfix), but you have to resolve all of them before you can
> start to parse. (I understand one feature of CAlive is that definitions
> for all these can come later.)
>
> This doesn't help the human reader much either.
>

First, yes using functions (as currently available) is currently
available, and in C++ you can use overloaded functions, and in C you can
use _Generics to build such expressions.

The issue is that building an equation with explicit function calls can
get hard to read also. That is why C++ included opererator overloading
and the C added _Generics. And expression like:

assign(d, mult( diff(ax, bx), diff(ay, by)));

just gets hard to read, compare to

d = (ax - bx) * (ay - by); is much clearer.

Yes, misused it can make things an unreadable mess, but an expression like

e(b(a, c(d)), g(f,h));

isn't really any more readable, maybe you know a bit more about what the
various symbols are, but you still need to explore each of them to
figure out what is what. Using good names is always important.

New operators, being effectively globals, would need to be used
sparingly, and well named.

Sjouke Burry

unread,
Dec 28, 2018, 5:45:59 PM12/28/18
to
In a c newsgroup, why are you blabbering about c++?

James Kuyper

unread,
Dec 29, 2018, 4:04:23 PM12/29/18
to
On 12/27/18 21:34, Richard Damon wrote:
...
> It used to be that an implementation was allowed to define -1 % 10 to be
> 9, but they standard changed the rule for division so that that wasn't
> allowed anymore. (It required -1/10 == -1)

C90 allowed -1/10 to be either 0 or -1. C99 and later requires -1/10 to
be 0. In all versions of the standard, the values returned by the %
operator are defined by requiring that (a/b)*b + (a%b) == a.

Richard Damon

unread,
Dec 29, 2018, 7:13:29 PM12/29/18
to
My comment meant that for -1 % 10 to be 9 required that -1/10 to be -1,
if -1/10 was 0 then -1 % 10 wouild need to be -1 (giving an example of
liking / and % )

Rick C. Hodgin

unread,
Dec 31, 2018, 9:03:31 AM12/31/18
to
On 12/28/2018 5:08 PM, Richard Damon wrote:
> On 12/28/18 12:16 PM, Rick C. Hodgin wrote:
>> How many new symbols have I created, or implemented in CAlive?
>
> Looking over the past 6 months of messages, I see suggested:
>
> min/max: \/ /\ \/= /\=
> swap: ><
> shortcut indirect: ~> which later became ~~
> modulus: -%

The swap operator wasn't my idea. I just happen to think it's
an excellent idea. I also introduced ><= as a follow-up, one
which operates standalone and conveys more meaning than simply
the "a >< b;" syntax on a stand-alone line, but it is otherwise
synonymous when used in stand-alone. When ><= is used in-flight,
it doesn't just swap the values for the remainder of the expres-
sion, but rather permanently update the target variables.

https://groups.google.com/d/msg/comp.lang.c/S0Y0yfuY8bk/JcW-H8p6AQAJ

> and that doesn't count syntax changes like a < b < c

I have also introduced the underscore-bang operator: _!

https://groups.google.com/d/msg/comp.lang.c/TerqLu1Rvg4/bD4xkKizBgAJ

It was added to augment legacy systems with new struct / class
information the new additions to the app are aware of, but old
code is not. It allows traditional uses of prior structures,
such as dynamically linked external modules which have not been
recompiled and are not aware of the new fields, to still operate
properly while allowing the code that has been recompiled to use
the new features. It doesn't work on legacy arrays, but does
work apart from that, such as single instance structures that
need to convey more cargo than their finite size allows. By
passing the pointer, the pre and post portions remain visible
to apps that are aware of it. And the _ptr! syntax indicates
it's being conveyed with pre and/or post data.

I've added predicates:

// Old way:
if (units > 1) qty /= units;

// As a predicate
((units > 1)) qty /= units;

I've added the /% divide-modulo operator, which operates to
obtain the divide value and remainder in one op:

// Old way:
divide_value = a / b;
remainder = a % b;

// Using divide-modulo
divide_value = a /% b : remainder;

I've introduced the @ character for use when passing a variable
to indicate it's being passed by reference.

I've introduced the ability to perform a bit rotate operation
using <<< and >>>, which include <<<= and >>>= as well as the
ability to rotate a sub-portion using start#length syntax, as
in <<7#4<< to begin rotating at the 7th bit and extend for 4
bits to the 7th,8th,9th,10th bit.

x <<<= 5; // Rotate the bits in x 5 positions
y >>>= 5 : carry; // Rotate the bits in y right 5 pos-
// itions, and rotate not just in y,
// but rotate each bit through the
// carry variable.

I've added mated ctors / dtors, so that when something is in-
stantiated with a particular constructor it calls the associated
destructor, which can then also call an explicitly named one by
using the constructor's name, as ~name().

class Xyz
{
Xyz(void) name1
{ /* ctor code */ }
~ { /* dtor code */ }

Xyz(int a) name2
{ /* ctor code */ }
~ { /* dtor code */ }
};

I've added associated pre {} and post {} blocks to everything:

pre {
// Code here

} if (x == 5) {
// Code here

} post {
// Code here
}

It encapsulates code associated with the inner thing. Works
with anything that can be in a block. Can also be explicitly
moved to using pre; or post;, or you can name them and call
the one explicit one if you have more than one defined using
the pre name; and post name; syntaxes.

Using a post block allows for easy structured exit from a
multi-nested inner loop.

-----
Many features in CAlive. They are all well into development,
including most of the newer ones over the past couple months.

--
Rick C. Hodgin

Bart

unread,
Dec 31, 2018, 1:08:17 PM12/31/18
to
On 31/12/2018 14:04, Rick C. Hodgin wrote:
> On 12/28/2018 5:08 PM, Richard Damon wrote:
>> On 12/28/18 12:16 PM, Rick C. Hodgin wrote:
>>> How many new symbols have I created, or implemented in CAlive?
>>
>> Looking over the past 6 months of messages, I see suggested:
>>
>> min/max: \/  /\  \/=  /\=
>> swap:    ><
>> shortcut indirect: ~> which later became ~~
>> modulus:  -%

> I have also introduced the underscore-bang operator:  _!
>
>     https://groups.google.com/d/msg/comp.lang.c/TerqLu1Rvg4/bD4xkKizBgAJ

I must have missed that one. Looking at it now, I still don't understand
what it does or how it might be useful.

Looking through your CAlive newgroup articles, I can see these new
operators and symbols, in addition to those above:

((...)) as alternative to if (...)
<<<, >>> rotates
/% divide/mod, but used in very peculiar way
==# ?
f32#2 The #2 means 2 decimals??
# Concatenation of some sort
!+ +! ?
[x] Same as *x
~|...|~ different kinds of 'casks'
<|...|>
[|...|]
(|...|)
/|...|/
\|...|/
| Alignment operator (to do away with {} and indents)
<- Note sure (can't read the note I made)
_ Dereference? (as in _x and x_f...)
? As in 'if (x?)'
b<-a Means same as a->b
|-, -| ? 'lbar' and 'rbar'
<- To do with pointers again (3rd overload?)
@ 'pass by pointer'
#x 'before value of x'?
##x reset something or other
#= ?
i|++ I think still increment

Together with the dozens of other puzzling features, I really look
forward to seeing what a program in this language will look like that
when using all this lot.

And that's not meant to be complimentary. (Combining this with all of
supercat's ideas would be even more intriguing.)


>     // As a predicate
>     ((units > 1)) qty /= units;

Why is that better than:

if (units > 1) qty /= units;

>
> I've added the /% divide-modulo operator, which operates to
> obtain the divide value and remainder in one op:
>
>     // Old way:
>     divide_value = a / b;
>     remainder    = a % b;
>
>     // Using divide-modulo
>     divide_value = a /% b : remainder;

People will want to write:

divide_value, remainder = a /% b;

(Your use of ":" interferes with "?:" if you still have that.)

> I've introduced the @ character for use when passing a variable
> to indicate it's being passed by reference.

You seem to use & for that purpose, so what's the point of @?

, which include <<<= and >>>= as well as the
> ability to rotate a sub-portion using start#length syntax, as
> in <<7#4<<

<< or <<<?

to begin rotating at the 7th bit and extend for 4
> bits to the 7th,8th,9th,10th bit.
>
>     x <<<= 5;           // Rotate the bits in x 5 positions
>     y >>>= 5 : carry;

And yet one more use of ":". And another example where two things are
modified in the same expression. (What happens with 'y>>>=5:y;' ?)

> Many features in CAlive.

Clearly.

Rick C. Hodgin

unread,
Dec 31, 2018, 2:21:12 PM12/31/18
to
On 12/31/2018 1:07 PM, Bart wrote:
> On 31/12/2018 14:04, Rick C. Hodgin wrote:
>> On 12/28/2018 5:08 PM, Richard Damon wrote:
>>> On 12/28/18 12:16 PM, Rick C. Hodgin wrote:
>>>> How many new symbols have I created, or implemented in CAlive?
>>>
>>> Looking over the past 6 months of messages, I see suggested:
>>>
>>> min/max: \/  /\  \/=  /\=
>>> swap:    ><
>>> shortcut indirect: ~> which later became ~~
>>> modulus:  -%
>
>> I have also introduced the underscore-bang operator:  _!
>>
>>      https://groups.google.com/d/msg/comp.lang.c/TerqLu1Rvg4/bD4xkKizBgAJ
>
> I must have missed that one. Looking at it now, I still don't understand what
> it does or how it might be useful.
>
> Looking through your CAlive newgroup articles, I can see these new operators
> and symbols, in addition to those above:
>
>   ((...))      as alternative to if (...)
>   <<<, >>>     rotates
>   /%           divide/mod, but used in very peculiar way
>   ==#          ?
>   f32#2        The #2 means 2 decimals??

These are used to compare floating point values to that many decimals in
base-10. It allows values like 1.999999999 and 2.00000001 to compare as
equal.

>   #            Concatenation of some sort

For readability. It allows a single operator to span multiple sources,
with each one being together with its cohort in the nth position. The
example I use is (c1#c2 == 13#10), rather than (c1 == 13 && c2 == 10).
It conveys more clearly you're looking for a 13/10 (CR/LF) pair in two
variables, where as c1 == 13 && c2 == 10 breaks it out and it's not
completely clear.

>   !+ +!        ?

I don't remember these. I think they were going to be nested comments.
I've since changed the syntax to be /+ and +/ to follow D's syntax.

>   [x]          Same as *x

A new pointer syntax. And [[x]] for pointer-to-pointer.

>   ~|...|~      different kinds of 'casks'
>   <|...|>
>   [|...|]
>   (|...|)
>   /|...|/
>   \|...|/

Each has a particular purpose. ~|utility|~ for ad hoc code. <|logic|>
for decisions, or responding to flow control. [|definition|] for def-
ining things. (|reference|) for referencing things.

Other syntaxes are not generally for visible use, but are internal, to
be injected by the compiler, used by the gui editor, etc.

>   |            Alignment operator (to do away with {} and indents)
>   <-           Note sure (can't read the note I made)

Pointers can go either way a->b or b<-a. It's provided to give con-
textual meaning, such as prev<-p and p->next so they indicate visually
their direction.

>   _            Dereference? (as in _x and x_f...)

All variables have an implicit underscore variable form unless there
is an explicitly created underscore variable name in scope. If you
create "char* x" there's an implicit _x which is the unsigned integer
equivalent value that can be used.

>   ?            As in 'if (x?)'

An immediate evaluation of x to 0, and returns true or false. It is
not required, but has utility in something like "if (x? == validState)".
It's the same as "if ((x != NULL) == validState)".

>   b<-a         Means same as a->b
>   |-, -|       ? 'lbar' and 'rbar'

Same as <- and ->, except they categorize the data in the struct
or class as being primary members, or lesser used members. An
lbar or rbar member is typically set at instantiation, and then
not altered. It's designed to provide a visual cue that this data
is different than other oft-changing data.

>   <-           To do with pointers again (3rd overload?)

Only one. If there's more than one please point it out.

>   @            'pass by pointer'

This has changed since that content was originally posted. The
@ is now used for reference members, and can be an enforced re-
quirement.

>   #x           'before value of x'?

During an assignment, it allows the value to be conveyed with
its before-assignment value, such as "if ((x == f()))" would
now return the value of f(x), but it allows the prior value
of x before it was assigned.

>   ##x          reset something or other

Allows the before value to propagate through the expression
from that point forward, even though it's now been assigned
a new value.

>   #=           ?

Another syntax for #x, one which is specified on the equal
operator.

>   i|++         I think still increment

Yes. It adds a visual differentiation to let the person know
the value being used is before the increment. It's only for
postfix operations, since it really is two operations.

I've also added "bit = x?<<;" to do a bit scan and report the
position where the first bit is set. Same with "bit = >>?x;"
to scan down from msb to lsb.

I've also added ^ parent pointers, so you can reference an
encapsulating structure when you know the pointer or variable
you're referencing is contained in a parent structure.

>> I've added the /% divide-modulo operator, which operates to
>> obtain the divide value and remainder in one op:
>>
>>      // Using divide-modulo
>>      divide_value = a /% b : remainder;
>
> (Your use of ":" interferes with "?:" if you still have that.)

The ?: syntax has the ?, then the colon. This syntax only has
the colon.

> , which include <<<= and >>>= as well as the
>> ability to rotate a sub-portion using start#length syntax, as
>> in <<7#4<<
>
> << or <<<?

The syntax when you use n#m is two before, two after, so it
would be more like <<<<, but with the n#m injected in the
middle.

>  to begin rotating at the 7th bit and extend for 4
>> bits to the 7th,8th,9th,10th bit.
>>
>>      x <<<= 5;           // Rotate the bits in x 5 positions
>>      y >>>= 5 : carry;
>
> And yet one more use of ":". And another example where two things are
> modified in the same expression. (What happens with 'y>>>=5:y;' ?)

Everything in CAlive follows the logical sequence of operations.

The code "y >>>= 5 : y;" will be processed in operator terms.
The : y is an assignment, so after y is loaded, rotated through
carry, it will store the result of the rotate into y, then it
will overwrite y with the 1 or 0 from the carry? bit.

--
Rick C. Hodgin

Bart

unread,
Dec 31, 2018, 4:06:01 PM12/31/18
to
On 31/12/2018 19:22, Rick C. Hodgin wrote:
> On 12/31/2018 1:07 PM, Bart wrote:

>>    #            Concatenation of some sort
>
> For readability.  It allows a single operator to span multiple sources,
> with each one being together with its cohort in the nth position.  The
> example I use is (c1#c2 == 13#10), rather than (c1 == 13 && c2 == 10).
> It conveys more clearly you're looking for a 13/10 (CR/LF) pair in two
> variables, where as c1 == 13 && c2 == 10 breaks it out and it's not
> completely clear.

In my dynamic language, there is no specific operator like this, but
there are several ways of expressing that using existing features:

if (c1,c2) = (13,10) then # compare two lists
if c1..c2 = 13..10 than # compare two ranges (ordering
# doesn't matter here)
case (c1,c2)
when (13,10) then # test 1st of several pairs

Such syntax can be adapted for static code. The advantage is that is
much clearer what is being attempted.


>>    !+ +!        ?
>
> I don't remember these.  I think they were going to be nested comments.
> I've since changed the syntax to be /+ and +/ to follow D's syntax.
>
>>    [x]          Same as *x

Assuming you are still using * from C, that means that for dereferencing
a pointer to struct member, you can use:

(*p).m
p->m
m<-p
[p].m
p~~m

For dereferencing a double pointer to a struct member, the choices are:

(*(*q)).m
(*q)->m
m<-(*q)
[[q]].m
[q]->m
m<-[q]
q~~m # ???

You see the problem? The syntax I use has ONE way to dereference a
pointer (postfix "^"), and ONE way to select a member ("."):

These examples must be written

p^.m # one pointer level, one ^
q^^.m # two pointer levels, two ^

Both access one member, so both have one ".". Take out member select:

p^ # access the whole struct
q^^

Try and take out the member select part of the 10 or 12 examples in your
syntax; you can't just remove the ".m", because most of them don't use it.

C syntax has always been a mess that way. Your additions make it worse.


>>    <|...|>
>>    [|...|]
>>    (|...|)
>>    /|...|/
>>    \|...|/
>
> Each has a particular purpose.  ~|utility|~ for ad hoc code.  <|logic|>
> for decisions, or responding to flow control.  [|definition|] for def-
> ining things.  (|reference|) for referencing things.

Who's ever going to remember that lot? And don't tell me the last two,
/|...|/ and \|...|/ aren't going to get mixed up, unless that was a typo
and the last was meant to be \|...|\ (although all of them are a
complete pain to type).

To add attributes, just have the ONE syntax. The name of the attribute
will tell you which kind it is.

> Pointers can go either way a->b or b<-a.  It's provided to give con-

In Algol 68, p.m or p->m would be written as m OF p. (There is no
explicit dereferencing.) But it has just the one choice.) Most languages
went with variations on p.m.

> All variables have an implicit underscore variable form unless there
> is an explicitly created underscore variable name in scope.  If you
> create "char* x" there's an implicit _x which is the unsigned integer
> equivalent value that can be used.

Say again? I expected you to say that _x means *x, some syntactic sugar.
You mean that _x means '*(unsigned char)x'?

(My old language could do the first example like this:

ref char x
ref. char _x @x
char c:='A'

x := &c
print x # display pointer address
print x^ # display A
print _x # display A

Again, features of more general use. The "." in the second line
indicated an auto-deref point. This has now been dropped, while @
(equivalence) only works for a native target.)

>>    ?            As in 'if (x?)'
>
> An immediate evaluation of x to 0, and returns true or false.  It is
> not required, but has utility in something like "if (x? == validState)".
> It's the same as "if ((x != NULL) == validState)".

I actually have this in the form of 'istrue'. But it is so rarely used
that I had to try it to see if it was available in user code.

In any case, C programs can use 'if (!!x)' for exactly this purpose.

>>    b<-a         Means same as a->b
>>    |-, -|       ? 'lbar' and 'rbar'
>
> Same as <- and ->, except they categorize the data in the struct
> or class as being primary members, or lesser used members.  An
> lbar or rbar member is typically set at instantiation, and then
> not altered.  It's designed to provide a visual cue that this data
> is different than other oft-changing data.

Ugh. How about some features that simplify coding and make it easier to
write, read, and understand?

>>    #x           'before value of x'?
>
> During an assignment, it allows the value to be conveyed with
> its before-assignment value, such as "if ((x == f()))" would
> now return the value of f(x), but it allows the prior value
> of x before it was assigned.

I think this was discussed before in this group. No one could come up
with a suitable syntax for it, and #x isn't it.

It's a kind of assignment inside an expression, which returns the value
of the lhs before it was assigned to.

> I've also added "bit = x?<<;" to do a bit scan and report the
> position where the first bit is set.  Same with "bit = >>?x;"
> to scan down from msb to lsb.

What's the point of all these cryptic symbol that might be used once in
a blue moon? There would be so long between each use, that you will have
long forgotten what x?<< was ever supposed to be.

x64 calls these ops BSF and BSR. Or bitscanforward and bitscanreverse.
Just use those names, and no one will ever need to scratch their head
about them.

> I've also added ^ parent pointers, so you can reference an
> encapsulating structure when you know the pointer or variable
> you're referencing is contained in a parent structure.

This is typical of your explanations that I have to read several and
still can't grok the meaning or purpose of your feature.

Maybe I am particularly thick, or not very receptive to new ideas. Or
maybe I am fairly typical and this is a poor feature that is hard to get
your head around.

>>> I've added the /% divide-modulo operator, which operates to
>>> obtain the divide value and remainder in one op:
>>>
>>>      // Using divide-modulo
>>>      divide_value = a /% b : remainder;
>>
>> (Your use of ":" interferes with "?:" if you still have that.)
>
> The ?: syntax has the ?, then the colon.  This syntax only has
> the colon.

Can /% be used anywhere an expression can be, or only in conjunction
with "="? If the former, than /% and ?: can be used in the same
expression and there can be clashes.

Even if only as above, then someone can write:

x = a ? b /% c : d ? e @ r : d;

I think the problem is clear.

--
bart

Rick C. Hodgin

unread,
Dec 31, 2018, 4:31:02 PM12/31/18
to
On 12/31/2018 4:05 PM, Bart wrote:
> On 31/12/2018 19:22, Rick C. Hodgin wrote:
>> On 12/31/2018 1:07 PM, Bart wrote:
>
>>>    #            Concatenation of some sort
>>
>> For readability.  It allows a single operator to span multiple sources,
>> with each one being together with its cohort in the nth position.  The
>> example I use is (c1#c2 == 13#10), rather than (c1 == 13 && c2 == 10).
>> It conveys more clearly you're looking for a 13/10 (CR/LF) pair in two
>> variables, where as c1 == 13 && c2 == 10 breaks it out and it's not
>> completely clear.
>
> In my dynamic language, there is no specific operator like this, but there
> are several ways of expressing that using existing features:
>
>    if (c1,c2) = (13,10) then       # compare two lists
>    if c1..c2 = 13..10 than         # compare two ranges (ordering
>                                    # doesn't matter here)
>    case (c1,c2)
>    when (13,10) then               # test 1st of several pairs
>
> Such syntax can be adapted for static code. The advantage is that is much
> clearer what is being attempted.

I like your language, Bart. I think you have some interesting ideas
and perspectives.

>>>    <|...|>
>>>    [|...|]
>>>    (|...|)
>>>    /|...|/
>>>    \|...|/
>>
>> Each has a particular purpose.  ~|utility|~ for ad hoc code.  <|logic|>
>> for decisions, or responding to flow control.  [|definition|] for def-
>> ining things.  (|reference|) for referencing things.
>
> Who's ever going to remember that lot? And don't tell me the last two,
> /|...|/ and \|...|/ aren't going to get mixed up, unless that was a typo and
> the last was meant to be \|...|\ (although all of them are a complete pain to
> type).

The last two are not designed to be typed by people. They are unique
identifiers used by the compiler and GUI editor for the purposes of
conveying compile-time information.

\|cask|/ -- Side coding
/|cask|\ -- Auto-injected content
@|cask|@ -- Anchor cask

They serve specific purposes that will be handled automatically and
invisibly by the GUI editor. That's why they have that syntax.

>> All variables have an implicit underscore variable form unless there
>> is an explicitly created underscore variable name in scope.  If you
>> create "char* x" there's an implicit _x which is the unsigned integer
>> equivalent value that can be used.
>
> Say again? I expected you to say that _x means *x, some syntactic sugar. You
> mean that _x means '*(unsigned char)x'?

char* x = "Hi, mom!";

x was assigned an address by the compiler to reference that data. Let
us suppose it was 0x123456. That means printf("0x%x\n"), _x) would print
out 0x123456.

> In any case, C programs can use 'if (!!x)' for exactly this purpose.

Yeah, and I still don't know what that operator does. :-) I think the
x? conveys information similar to what we see in assembly, with the
carry? flag, sign? flag, zero? flag, etc. It's actually where I got
that inspiration.

>>>    b<-a         Means same as a->b
>>>    |-, -|       ? 'lbar' and 'rbar'
>>
>> Same as <- and ->, except they categorize the data in the struct
>> or class as being primary members, or lesser used members.  An
>> lbar or rbar member is typically set at instantiation, and then
>> not altered.  It's designed to provide a visual cue that this data
>> is different than other oft-changing data.
>
> Ugh. How about some features that simplify coding and make it easier to
> write, read, and understand?

I have those too. And I would argue these do make it easier, because
the editor can reveal the -| as a -> and put the variables in use in
another color, so it's more clear they're not oft used. They can also
be declared that way when created using [|lbar|] and [|rbar|] definition
casks (to define something, an attribute about their data, type, or in
this case, utility).

It's all designed to make it easier to read in the editor.

>>>    #x           'before value of x'?
>>
>> During an assignment, it allows the value to be conveyed with
>> its before-assignment value, such as "if ((x == f()))" would
>> now return the value of f(x), but it allows the prior value
>> of x before it was assigned.
>
> I think this was discussed before in this group. No one could come up with a
> suitable syntax for it, and #x isn't it.
>
> It's a kind of assignment inside an expression, which returns the value of
> the lhs before it was assigned to.

Yes, it's like (auto t = x, x = f(x), t). #x is an excellent syntax
for it, Bart. :-) If I had an anchor syntax, I would use it as I
think that would be a better symbol.

>> I've also added "bit = x?<<;" to do a bit scan and report the
>> position where the first bit is set.  Same with "bit = >>?x;"
>> to scan down from msb to lsb.
>
> What's the point of all these cryptic symbol that might be used once in a
> blue moon? There would be so long between each use, that you will have long
> forgotten what x?<< was ever supposed to be.
>
> x64 calls these ops BSF and BSR. Or bitscanforward and bitscanreverse. Just
> use those names, and no one will ever need to scratch their head about them.

#define BSF(x) x?<<
#define BSR(x) >>?x

Done.

>> I've also added ^ parent pointers, so you can reference an
>> encapsulating structure when you know the pointer or variable
>> you're referencing is contained in a parent structure.
>
> This is typical of your explanations that I have to read several and still
> can't grok the meaning or purpose of your feature.
>
> Maybe I am particularly thick, or not very receptive to new ideas. Or maybe I
> am fairly typical and this is a poor feature that is hard to get your head
> around.

It allows you to pass in a single variable to a remote function,
and gain access to it, it's parent, its grandparent if you know
the scope it comes from, and all other variables of that struc
or class relative to it.

It's a notable stack saver.

>>>> I've added the /% divide-modulo operator, which operates to
>>>> obtain the divide value and remainder in one op:
>>>>
>>>>      // Using divide-modulo
>>>>      divide_value = a /% b : remainder;
>
> Can /% be used anywhere an expression can be, or only in conjunction with
> "="? If the former, than /% and ?: can be used in the same expression and
> there can be clashes.

It currently has no syntax for use anywhere outside of an explicit
equal assignment as above.

> Even if only as above, then someone can write:
>
>   x = a ? b /% c : d ? e @ r : d;
>
> I think the problem is clear.

That syntax is not allowed presently. I don't have a good syntax
for using it as a stand-alone operator. It only makes sense with
the double-assignment.

I suppose it could use:

{a /% b : divide_value, remainder};

That might work. I'll think about it. It might be better defined
for CAlive in a cask:

(||a /% b | divide_value | remainder ||)

That way it's encapsulated no matter where it appears. Casks are
always in this format:

(||
left
| middle
| right
||)

The ends determine what it is:

() reference
[] definition
<> logic (like a flow chart)
And the ~|utility|~ cask injects arbitrary code.

If you only have a middle, it appears as: (|middle|)
If you have a left and middle, it's: (||left|middle|)
If you have a right and middle, it's: (|middle|right||)
If you have all three, it appears as: (||left|middle|right||)

It's very straight-forward, it's just not well known (yet). :-)

--
Rick C. Hodgin

Keith Thompson

unread,
Dec 31, 2018, 4:34:54 PM12/31/18
to
Bart <b...@freeuk.com> writes:
[...]
> Looking through your CAlive newgroup articles, I can see these new
> operators and symbols, in addition to those above:
[...]

Oh, there's a CAlive newsgroup?

Wouldn't that be a better place to discuss CAlive than comp.lang.c *and*
comp.lang.c++?

--
Keith Thompson (The_Other_Keith) k...@mib.org <http://www.ghoti.net/~kst>
Will write code for food.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Richard Damon

unread,
Dec 31, 2018, 4:44:01 PM12/31/18
to
On 12/31/18 4:34 PM, Keith Thompson wrote:
> Bart <b...@freeuk.com> writes:
> [...]
>> Looking through your CAlive newgroup articles, I can see these new
>> operators and symbols, in addition to those above:
> [...]
>
> Oh, there's a CAlive newsgroup?
>
> Wouldn't that be a better place to discuss CAlive than comp.lang.c *and*
> comp.lang.c++?
>

It isn't a 'real' NNTP newsgroup, just one of the pseudo newsgroups on,
if I remember right, googlegroups (so accessible on web through it as if
it was a newsgroup, but doesn't leave google).

Richard Damon

unread,
Dec 31, 2018, 4:57:33 PM12/31/18
to
your syntax isn't that different than C in my view.

In C *p, in your p^
Both get you 'the object pointed to by p), to which you can add more
indirection of member selection.

C adds a 'shortcut' of p->m as the syntax sugar for (*p).m

Perhaps having the indirect operation being postfix instead of prefix
cleans up some issue with syntax, getting rid of some needs of parenthesis.

For C, with the need of the parenthesis, the shortcut seems useful, and
having 2 notations doesn't seem that bad.

Rick's multitude of options seems much less useful, and I suspect he is
going to run into parsing issues with his grammar.

...

>> All variables have an implicit underscore variable form unless there
>> is an explicitly created underscore variable name in scope.  If you
>> create "char* x" there's an implicit _x which is the unsigned integer
>> equivalent value that can be used.
>
> Say again? I expected you to say that _x means *x, some syntactic sugar.
> You mean that _x means '*(unsigned char)x'?
>

I think Rick means that _x is like (uintptr_t)x

Bart

unread,
Dec 31, 2018, 5:33:18 PM12/31/18
to
On 31/12/2018 21:57, Richard Damon wrote:
> On 12/31/18 4:05 PM, Bart wrote:

>> C syntax has always been a mess that way. Your additions make it worse.
>>
>>
>
> your syntax isn't that different than C in my view.
>
> In C *p, in your p^
> Both get you 'the object pointed to by p), to which you can add more
> indirection of member selection.
>
> C adds a 'shortcut' of p->m as the syntax sugar for (*p).m
>
> Perhaps having the indirect operation being postfix instead of prefix
> cleans up some issue with syntax, getting rid of some needs of parenthesis.

That is the crucial part. It means pointers to arrays in C would have
been more popular if accesses could be written A^[i] ('*' wouldn't work)
instead of (*A)[i].

Pointers to struct members could be written consistently as P^.m instead
of either (*P).m or P->m, while adding or removing an indirection is
just adding or removing ^, instead of having to add or remove (*) or to
transform between -> and (*) or between -> and . or between (*) and .

And calls via function pointers could be consistently written F^(x)
instead of (*F)(x) or via the confusing F(x).

> For C, with the need of the parenthesis, the shortcut seems useful, and
> having 2 notations doesn't seem that bad.
>
> Rick's multitude of options seems much less useful, and I suspect he is
> going to run into parsing issues with his grammar.

Almost certainly.

--
bart

Keith Thompson

unread,
Dec 31, 2018, 6:20:42 PM12/31/18
to
My point stands.

Bart

unread,
Dec 31, 2018, 6:44:14 PM12/31/18
to
On 31/12/2018 21:32, Rick C. Hodgin wrote:
> On 12/31/2018 4:05 PM, Bart wrote:

>> Say again? I expected you to say that _x means *x, some syntactic
>> sugar. You mean that _x means '*(unsigned char)x'?
>
>     char* x = "Hi, mom!";
>
> x was assigned an address by the compiler to reference that data.  Let
> us suppose it was 0x123456.  That means printf("0x%x\n"), _x) would print
> out 0x123456.

Isn't that what happens now with printing 'x'?

>> In any case, C programs can use 'if (!!x)' for exactly this purpose.
>
> Yeah, and I still don't know what that operator does. :-)

not not. The first converts (-3, -2, -1, 0, 1, 2, 3) to (0, 0, 0, 1, 0,
0, 0). The second to (1, 1, 1, 0, 1, 1, 1).



  I think the
> x? conveys information similar to what we see in assembly, with the
> carry? flag, sign? flag, zero? flag, etc.  It's actually where I got
> that inspiration.

If you write if(x), while(x), or for(;x;), then it automatically applies
the effective equivalent of !! to give a true (x!=0) or false (x==0)
result. (The same with (x && y) and any such combinations.)

You don't need an explicit !! or ?.

I don't see it being the same as carry and zero flags at all. Certainly
not the zero flag, which does the opposite thing.

> #define BSF(x) x?<<
> #define BSR(x) >>?x
>
> Done.

Yes, you demonstrated this back-to-front thinking before.

Tell me, what operator do you use to extract (or set) the nth bit of an
integer value? /That/ would be more useful.


> I suppose it could use:
>
>     {a /% b : divide_value, remainder};

The lldiv function in C returns a struct of two values. /% ought to also
return two values, which could also be in the form of a struct, to avoid
adding more features.

>
> That might work.  I'll think about it.  It might be better defined
> for CAlive in a cask:
>
>     (||a /% b | divide_value | remainder ||)
>
> That way it's encapsulated no matter where it appears.  Casks are
> always in this format:
>
>     (||
>         left
>              | middle
>                       | right
>                               ||)
>
> The ends determine what it is:
>
>     () reference
>     [] definition
>     <> logic (like a flow chart)
>     And the ~|utility|~ cask injects arbitrary code.
>
> If you only have a middle, it appears as:        (|middle|)
> If you have a left and middle, it's:       (||left|middle|)
> If you have a right and middle, it's:            (|middle|right||)
> If you have all three, it appears as:      (||left|middle|right||)
>
> It's very straight-forward, it's just not well known (yet). :-)

I've always had a divrem operator, but have never implemented it. When I
do, it will simply be like this:

d := a divrem b # d:=a%b (% is integer division)
d,r := a divrem b # d:=a%b, r:=a rem b

At the moment it would need to be done like this via a function that
returns both values:

d := xdivrem(a,b) # ignore the second value
d, r := xdivrem(a,b)

so not inline. But notice I'm not bothered about having a symbol for the
operator; and I use 'rem' for C's "%".

Notice also I don't need 'casks'.

--
bart

Keith Thompson

unread,
Dec 31, 2018, 7:44:48 PM12/31/18
to
Bart <b...@freeuk.com> writes:
[...]
> If you write if(x), while(x), or for(;x;), then it automatically applies
> the effective equivalent of !! to give a true (x!=0) or false (x==0)
> result. (The same with (x && y) and any such combinations.)
[...]

That's one way to describe it. It's now how the standard describes it.

For example, the description of the "if" statement says "the first
substatement is executed if the expression compares unequal to 0",
which I find clearer and simpler than your reformulation.

Bart

unread,
Dec 31, 2018, 8:07:03 PM12/31/18
to
On 01/01/2019 00:44, Keith Thompson wrote:
> Bart <b...@freeuk.com> writes:
> [...]
>> If you write if(x), while(x), or for(;x;), then it automatically applies
>> the effective equivalent of !! to give a true (x!=0) or false (x==0)
>> result. (The same with (x && y) and any such combinations.)
> [...]
>
> That's one way to describe it. It's now how the standard describes it.
>
> For example, the description of the "if" statement says "the first
> substatement is executed if the expression compares unequal to 0",
> which I find clearer and simpler than your reformulation.

That's the whole expression. It doesn't really explain how a complex
expression ends up as zero or not zero. Or the difference between A && B
when B is 'b==x' and when B is just 'b'.

From a design and implementation point of view, you have to go into it
in more detail.

Perhaps simpler might be to say that operands of if(), while(), for(;;),
&&, || unary !, need to be either already Bool, or have to be converted
to Bool.

It is that last that can also be done with !!.

--
bart

Kenny McCormack

unread,
Dec 31, 2018, 8:53:50 PM12/31/18
to
In article <lnd0phm...@kst-u.example.com>,
Keith Thompson <ks...@mib.org> wrote:
>Bart <b...@freeuk.com> writes:
>[...]
>> If you write if(x), while(x), or for(;x;), then it automatically applies
>> the effective equivalent of !! to give a true (x!=0) or false (x==0)
>> result. (The same with (x && y) and any such combinations.)
>[...]
>
>That's one way to describe it. It's now how the standard describes it.

That's good to know. I assume it used to describe it some other way, but
it (the standard) has now seen the light of Bart's way. That's good.

--
Faced with the choice between changing one's mind and proving that there is
no need to do so, almost everyone gets busy on the proof.

- John Kenneth Galbraith -

Rick C. Hodgin

unread,
Dec 31, 2018, 10:14:59 PM12/31/18
to
On Monday, December 31, 2018 at 6:44:14 PM UTC-5, Bart wrote:
> On 31/12/2018 21:32, Rick C. Hodgin wrote:
> > On 12/31/2018 4:05 PM, Bart wrote:
> >     char* x = "Hi, mom!";
> > x was assigned an address by the compiler to reference that data.  Let
> > us suppose it was 0x123456.  That means printf("0x%x\n"), _x) would print
> > out 0x123456.
>
> Isn't that what happens now with printing 'x'?

Yes, but the point is _x is a type unsigned int (either 32-bit or
64-bit depending on the side of the pointer).

> >> In any case, C programs can use 'if (!!x)' for exactly this purpose.
> > Yeah, and I still don't know what that operator does. :-)
> not not. The first converts (-3, -2, -1, 0, 1, 2, 3) to (0, 0, 0, 1, 0,
> 0, 0). The second to (1, 1, 1, 0, 1, 1, 1).

Perfectly clear. Thank you.

> If you write if(x), while(x), or for(;x;), then it automatically applies
> the effective equivalent of !! to give a true (x!=0) or false (x==0)
> result. (The same with (x && y) and any such combinations.)
>
> You don't need an explicit !! or ?.

It's useful for testing against a state, not merely against true
or false.

> I don't see it being the same as carry and zero flags at all. Certainly
> not the zero flag, which does the opposite thing.
>
> > #define BSF(x) x?<<
> > #define BSR(x) >>?x
> >
> > Done.
>
> Yes, you demonstrated this back-to-front thinking before.

We all have our opinions. :-)

> Tell me, what operator do you use to extract (or set) the nth bit of an
> integer value? /That/ would be more useful.

Given the operation [x = (x >> shift) & mask] it seems clear the
operator should be y >shift#msk>= x, doncha think? :-)

And to set a value [x = (x & ~(mask << shift)) | (n << shift)] it
seems clear the operator should be y &~<<m#s|#n<<= x, wouldn't you
say?

>n#m>= -- Get bits
&~<<m#s|#n<<= -- Set bits

Easy as cake, yes? :-)

> > I suppose it could use:
> >
> >     {a /% b : divide_value, remainder};
>
> The lldiv function in C returns a struct of two values. /% ought to also
> return two values, which could also be in the form of a struct, to avoid
> adding more features.

IMO, certain classes of operations require their own distinct
character of processing due to their nature. This type of div-
ision + remainder is one of them.

> I've always had a divrem operator, but have never implemented it. When I
> do, it will simply be like this:
>
> d := a divrem b # d:=a%b (% is integer division)
> d,r := a divrem b # d:=a%b, r:=a rem b
>
> At the moment it would need to be done like this via a function that
> returns both values:
>
> d := xdivrem(a,b) # ignore the second value
> d, r := xdivrem(a,b)
>
> so not inline. But notice I'm not bothered about having a symbol for the
> operator; and I use 'rem' for C's "%".
>
> Notice also I don't need 'casks'.

I don't NEED casks either, but they are an integral component of
computer programming. The introduce the ability to inject arbi-
trary source code into the middle of an otherwise syntactically
correct expression. It introduces the ability, for example, to
use a <|logic|> cask to perform an operation based on the inter-
mediate result of a logic test.

if (x == 4 <|meta|some_code1()||>) // meta = run if true
// Code here

if (y == 3 <|mefa|some_code2()||>) // mefa = run if false
// Code here

The <|meta|> and <|mefa|> casks can be shorted to <|t|> and <|f|>,
and they are logic casks, which run the code contained within if
the condition matches. You can also do both conditions:

if (x == 3 <||meta|if_true()|if_false()||>)
// Code here

It is similar to x ? y : z;, if x is true, then y, otherwise z.
In this case <||x|y|z||>, or <||meta|y|z||>.

It really is very logical. :-)

--
Rick C. Hodgin
0 new messages