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

C: 100 Things

88 views
Skip to first unread message

BartC

unread,
Apr 29, 2014, 12:57:25 PM4/29/14
to
"BartC" <b...@freeuk.com> wrote in message
news:94y7v.153301$AI5....@fx32.am4...
> "Kaz Kylheku" <k...@kylheku.com> wrote in message

>> Nobody really needs alternatives to C which are almost the same thing,
>> just with more clunky syntax and pointless limitations.
>
> Yes we do. It wouldn't take me long to list a hundred things that are
> wrong
> with C, yet after fixing all those the resulting language wouldn't do that
> much more.

"BartC" <b...@freeuk.com> wrote in message
news:57B7v.161805$Qm2.1...@fx16.am4...
> "James Harris" <james.h...@gmail.com> wrote in message

>> That's interesting. I think we could all come up with a list of
>> improvements we would like.
>
> I'll try and put something together. I may or may not post it. As I think
> you say somewhere, such a list will be different for everyone.

Well, I put together my list. About 115 things listed actually. Too long to
show here so is at: http://pastebin.com/vUVpF1uA (will be edited later).

I didn't specifically set out to find faults with C, but a lot of this is
how I'm used to doing things, and wondered why C used its own unique
approach.

And as promised, little of this actually results in a particularly higher
level language (no OOP, no templates, no dynamic datatypes, no exceptions,
no threading, nothing about the runtime library (actually that can be item #
116...).) It just makes more sense.

--
Bartc

James Harris

unread,
Apr 30, 2014, 2:40:31 AM4/30/14
to
"BartC" <b...@freeuk.com> wrote in message
news:3SQ7v.155346$AI5....@fx32.am4...

...

(re the C language)

>>> That's interesting. I think we could all come up with a list of
>>> improvements we would like.
>>
>> I'll try and put something together. I may or may not post it. As I think
>> you say somewhere, such a list will be different for everyone.
>
> Well, I put together my list. About 115 things listed actually. Too long
> to
> show here so is at: http://pastebin.com/vUVpF1uA (will be edited later).

That's an amazingly long list. There are too many to comment on but I agree
with lots of them.

> I didn't specifically set out to find faults with C, but a lot of this is
> how I'm used to doing things, and wondered why C used its own unique
> approach.
>
> And as promised, little of this actually results in a particularly higher
> level language (no OOP, no templates, no dynamic datatypes, no exceptions,
> no threading, nothing about the runtime library (actually that can be item
> #
> 116...).) It just makes more sense.

Yes, a good approach, IMO. I wouldn't be against adding things to a design
but the temptation especially among those most familiar with a language -
and who would know it better than its developer(s) - is to just keep adding.
ISTM that C++, Java, Python, Ada have all become bloated over time. C has at
least retained a minimalism.

James


BartC

unread,
Apr 30, 2014, 7:16:19 AM4/30/14
to


"James Harris" <james.h...@gmail.com> wrote in message
news:ljq5sv$coh$1...@dont-email.me...
> "BartC" <b...@freeuk.com> wrote in message
> news:3SQ7v.155346$AI5....@fx32.am4...

>> And as promised, little of this actually results in a particularly higher
>> level language (no OOP, no templates, no dynamic datatypes, no
>> exceptions,
>> no threading, nothing about the runtime library (actually that can be
>> item #
>> 116...).) It just makes more sense.
>
> Yes, a good approach, IMO. I wouldn't be against adding things to a design
> but the temptation especially among those most familiar with a language -
> and who would know it better than its developer(s) - is to just keep
> adding. ISTM that C++, Java, Python, Ada have all become bloated over
> time. C has at least retained a minimalism.

I think there is a place for a low-level language placed roughly where C is,
but it seems to have completely dominated this area to the exclusion of
everything else.

Doubtless there will be competitive languages we've never heard of (perhaps
people creating their own projects like me), but it would be nice to have
something mainstream that I could actually like! (I don't really like C, in
case that's not already apparent.)

It's interesting to know what other approaches are possible in this area (my
ideas come from experience with Algol, Pascal and (to a lesser extent)
Fortran (all a long time ago), so are probably dated.

As for C being minimalist, I don't know if a language needing these types
and macros (remembering to substitute all the combinations of 8 16, 32 and
64 every time you see N):

intN_t
uintN_t
int_leastN_t
uint_leastN_t
int_fastN_t
uint_fastN_t
intptr_t
uintptr_t
intmax_t
uintmax_t
INTN_MIN
INTN_MAX
UINTN_MAX
INT_LEASTN_MIN
INT_LEASTN_MAX
UINT_LEASTN_MAX
INT_FASTN_MIN
INT_FASTN_MAX
UINT_FASTN_MAX
INTPTR_MIN
INTPTR_MAX
UINTPTR_MAX
INTMAX_MIN
INTMAX_MAX
UINTMAX_MAX
PTRDIFF_MIN
PTRDIFF_MAX
SIG_ATOMIC_MIN
SIG_ATOMIC_MAX
SIZE_MAX
WCHAR_MIN
WCHAR_MAX
WINT_MIN
WINT_MAX
INTN_C(value)
UINTN_C(value)
INTMAX_C(value)
UINTMAX_C(value

and maybe this lot too, as some of these seem to be different from those
above:

#define CHAR_BIT 8
#define CHAR_MAX UCHAR_MAX or SCHAR_MAX
#define CHAR_MIN 0 or SCHAR_MIN
#define INT_MAX +32767
#define INT_MIN -32767
#define LONG_MAX +2147483647
#define LONG_MIN -2147483647
#define LLONG_MAX +9223372036854775807
#define LLONG_MIN -9223372036854775807
#define MB_LEN_MAX 1
#define SCHAR_MAX +127
#define SCHAR_MIN -127
#define SHRT_MAX +32767
#define SHRT_MIN -32767
#define UCHAR_MAX 255
#define USHRT_MAX 65535
#define UINT_MAX 65535
#define ULONG_MAX 4294967295
#define ULLONG_MAX 18446744073709551615

and much more, could actually be called minimalist. (More like maximalist,
as this lot could easily be condensed into a handful of language features.)

It's a joke really, but not particularly funny as this language and its
ideas seem to have permeated everywhere. You take the crude C for-loop,
which is 'for (expr; expr; expr)', and you see it practically unchanged in
C++, C#, Java, Javascript, PHP, Perl, even newer ones such as Go and Dart
(although Go has at least dropped the parentheses!).

That is actually astonishing; has it really never occurred to anyone to add
a /simple/ iterative loop statement to any of these? It must apparently have
affected their minds too! (Fortunately a few other languages: Lua, Ruby and
Python for example, have finally seen the light regarding for-loops at
least. Those aren't low-level languages though.)

(I wouldn't be surprised if it's because they all start off with
off-the-shelf lexing and parsing tools that come with a ready-made C
grammar.)

--
Bartc

James Harris

unread,
Apr 30, 2014, 8:54:00 AM4/30/14
to
"BartC" <b...@freeuk.com> wrote in message
news:kY48v.181432$Ey6.1...@fx24.am4...

...

> I think there is a place for a low-level language placed roughly where C
> is,
> but it seems to have completely dominated this area to the exclusion of
> everything else.
>
> Doubtless there will be competitive languages we've never heard of
> (perhaps
> people creating their own projects like me), but it would be nice to have

Yes, there could well be some good replacements that we have never heard of.

> something mainstream that I could actually like! (I don't really like C,
> in
> case that's not already apparent.)

Unlike you I believe C is great even though it has its faults.

> It's interesting to know what other approaches are possible in this area
> (my
> ideas come from experience with Algol, Pascal and (to a lesser extent)
> Fortran (all a long time ago), so are probably dated.

I too would like to know of alternatives. What I wouldn't want to do,
though, is to invest considerable time in learning something new only to
find out later that either the language or its toolchain was not mature
enough to allow some things to be done.

It is relatively easy to produce a language which does a few things better
than C but also does some other things not as well or not at all!

> As for C being minimalist, I don't know if a language needing these types
> and macros (remembering to substitute all the combinations of 8 16, 32 and
> 64 every time you see N):

... (snipped the many examples)

Yes, very valid. I completely agree.

I don't know why data sizes are so poorly managed in C and other languages.
Sub-word and multi-word arithmetic is not too hard for a code generator to
do.

If a programmer wants an 8-bit or 128-bit integer shouldn't they be inbuilt?
IMO it should not be necessary to add a library and make library calls to
handle things like wide integers.

One thing I would say in defence of C is that, at least with some
machinations, it does allow a programmer to specify integer sizes. Most
languages just give you an integer and that's it!

> and much more, could actually be called minimalist. (More like maximalist,
> as this lot could easily be condensed into a handful of language
> features.)

Yes.

> It's a joke really, but not particularly funny as this language and its
> ideas seem to have permeated everywhere. You take the crude C for-loop,
> which is 'for (expr; expr; expr)', and you see it practically unchanged in
> C++, C#, Java, Javascript, PHP, Perl, even newer ones such as Go and Dart
> (although Go has at least dropped the parentheses!).
>
> That is actually astonishing; has it really never occurred to anyone to
> add
> a /simple/ iterative loop statement to any of these? It must apparently
> have
> affected their minds too!

I cannot speak for their minds! but IMO C's for statement is much better
than you suggest. Do you remember reading computer science texts on how
loops were formed? Books I read years ago used to talk about categorising
loops into definite and indefinite iteration and, at some length, about what
could happen to the loop control variable at the end of the loop and whether
it should even be in scope.

In one stroke C's for loop removes those issues and makes it manifest in the
syntax what steps the program will take to control the loop. It reduces a
loop to the essentials and it means that one compact loop control statement
can be used in almost all types of loop. IMO that's quite brilliant! I'm not
surprised if it got copied to other languages.

James


BartC

unread,
Apr 30, 2014, 9:39:06 AM4/30/14
to
"James Harris" <james.h...@gmail.com> wrote in message
news:ljqrp2$pli$1...@dont-email.me...
> "BartC" <b...@freeuk.com> wrote in message

>>(I don't really like C, in
>> case that's not already apparent.)
>
> Unlike you I believe C is great even though it has its faults.

I first used Algol60 and then Pascal (at college), so when I was first came
across C it already looked primitive. That opinion hasn't improved greatly..

> It is relatively easy to produce a language which does a few things better
> than C but also does some other things not as well or not at all!

It doesn't need to be all or nothing. For example, it's usually possible to
have modules in C as well as whatever other language is being used. However,
if you're locked in to a C 'ecosystem', with the OS using C as an interface
language; using linkers that come with C compilers; using the C runtime
library; using 'make'; using a host of third party libraries which come with
C header files so that you can only use them easily from C; are used to a
debugger which assumes C sources etc. then I agree it can be hard to break
out of all that or find a way for new language to fit it.

>You take the crude C for-loop,

>> That is actually astonishing; has it really never occurred to anyone to
>> add
>> a /simple/ iterative loop statement to any of these? It must apparently
>> have
>> affected their minds too!
>
> I cannot speak for their minds! but IMO C's for statement is much better
> than you suggest. Do you remember reading computer science texts on how
> loops were formed? Books I read years ago used to talk about categorising
> loops into definite and indefinite iteration and, at some length, about
> what could happen to the loop control variable at the end of the loop and
> whether it should even be in scope.

> In one stroke C's for loop removes those issues and makes it manifest in
> the syntax what steps the program will take to control the loop. It
> reduces a loop to the essentials and it means that one compact loop
> control statement can be used in almost all types of loop. IMO that's
> quite brilliant! I'm not surprised if it got copied to other languages.

Yes, C's for loop is quite powerful and very flexible (although so are 'if'
and 'goto'!). But it is possible to have both that, and a dedicated loop for
the 99% of situations (in my case) where I do need a for-loop to just count
from A to B.

(Actually my syntax, as well has having 'for', 'to', 'do' and so on (all
from Algol68 really, where they are versions of a general for-loop) also
have a C-style for-loop, with syntax 'cfor a,b,c do ...' to acknowledge the
extra potential it has. But so far I haven't used it!)

C (and some of those derived languages) do allow you to create a macro such
as FOR(i,a,b), but it might raise eyebrows if you showed such code to anyone
else. This basic stuff really needs to be part of the language proper.

--
Bartc

James Harris

unread,
Apr 30, 2014, 3:18:36 PM4/30/14
to
"BartC" <b...@freeuk.com> wrote in message
news:K278v.218753$vB1.1...@fx36.am4...

...

>> In one stroke C's for loop removes those issues and makes it manifest in
>> the syntax what steps the program will take to control the loop. It
>> reduces a loop to the essentials and it means that one compact loop
>> control statement can be used in almost all types of loop. IMO that's
>> quite brilliant! I'm not surprised if it got copied to other languages.
>
> Yes, C's for loop is quite powerful and very flexible (although so are
> 'if'
> and 'goto'!). But it is possible to have both that, and a dedicated loop
> for
> the 99% of situations (in my case) where I do need a for-loop to just
> count
> from A to B.

That reminds me of some more benefits of C's for construct. In addition to
those mentioned before if you want a step of something other than 1 your
languages might accept a step as in

A to B step C

but then if C can be positive or negative the compiler won't know whether
you want the loop to execute or not. If you intend the loop to always ascend
and C to be positive but don't know for sure that it is, for example, you
might have to code

if C > 0 then for X = A to B step C

Programmers would often omit the initial test of C and then because it
didn't know whether C would be positive or negative the compiler would have
to select different loop termination conditions dynamically - one for a
rising step and the other for a falling step. Or perhaps the programmer
wanted the difference between A and B to control the direction of the
iteration and not the step. No one can know unless the syntax is changed so
that something is added to the statement like a stepup or stepdown keyword.
The whole thing is a terrible bundle of questions and uncertainties. C's for
loop does away with all of them by allowing the programmer to state exactly
what he or she wants.

Another issue is the terminating value. I remember in Basic having to write
things like

for i = a to b - 1

where the - 1 or something like it had to be added to modify the termination
value. C's for loop allows a natural slight adjustment to the termination
condition by means of < vs <=. Contrast these two

for (i = 0; i < len; i++)
for (i = 1; i <= len; i++)

Both of those are idiomatic. The requirement for a slight adjustment is
common and can be expressed easily in C.

Further, a loop can be controlled by all kinds of things other than a
stepping integer if that's what the programmer wants: input, lists,
pointers, even floats can make sense with the < or <= qualifiers where they
would be inappropriate for the A to B form.

Oh, and one more thing. This is related to the problems with your preference
that I mentioned in the earlier post. Significant text has been written
about whether the index might be modified during the course of the loop. And
also whether the terminating value has to be constant or not. There are a
number of permutations: loop index yes, terminating value no, neither, both
etc. Different languages have chosen differently and their choices need to
be documented in the language definition. These are yet more things for the
programmer to remember. Again, C's for loop does away with all of that. The
C code shows exactly what the programmer has chosen to be done. What you see
in the code will be what the program is expected to do. No complex rules to
remember. Very sweet, great design, IMO!

James


BartC

unread,
Apr 30, 2014, 5:40:07 PM4/30/14
to


"James Harris" <james.h...@gmail.com> wrote in message
news:ljria6$8ka$1...@dont-email.me...
> "BartC" <b...@freeuk.com> wrote in message
> news:K278v.218753$vB1.1...@fx36.am4...

>> Yes, C's for loop is quite powerful and very flexible (although so are
>> 'if'
>> and 'goto'!). But it is possible to have both that, and a dedicated loop
>> for
>> the 99% of situations (in my case) where I do need a for-loop to just
>> count
>> from A to B.
>
> That reminds me of some more benefits of C's for construct. In addition to
> those mentioned before if you want a step of something other than 1 your
> languages might accept a step as in
>
> A to B step C
>
> but then if C can be positive or negative the compiler won't know whether
> you want the loop to execute or not. If you intend the loop to always
> ascend and C to be positive but don't know for sure that it is, for
> example, you might have to code
>
> if C > 0 then for X = A to B step C
>
> Programmers would often omit the initial test of C and then because it
> didn't know whether C would be positive or negative the compiler would
> have to select different loop termination conditions dynamically - one for
> a rising step and the other for a falling step.

But how would C's for-loop help here? Surely you still have to choose
between a <= or >= terminating condition?

> Or perhaps the programmer wanted the difference between A and B to control
> the direction of the iteration and not the step. No one can know unless
> the syntax is changed so that something is added to the statement like a
> stepup or stepdown keyword. The whole thing is a terrible bundle of
> questions and uncertainties.

Maybe. Although over many years of programming the number of times I've
needed a step other then 1 or -1 has been so few, that I actually removed
the 'step' option from my for-loops for a couple of decades. I've put it
back now, but require the direction to be known or indicated at compile
time, otherwise it assumes positive. A dynamic loop-counting direction is
too unusual a requirement for it to compromise the simplicity of the
standard for-loop construct. There any number of ways to code such a thing
without special language support. But if you say it's easy in C, then the C
version is still there waiting to be dusted off!

> Another issue is the terminating value. I remember in Basic having to
> write things like
>
> for i = a to b - 1
>
> where the - 1 or something like it had to be added to modify the
> termination value. C's for loop allows a natural slight adjustment to the
> termination condition by means of < vs <=. Contrast these two
>
> for (i = 0; i < len; i++)
> for (i = 1; i <= len; i++)

Yes, C is zero-based so 0..N-1 loops might be more common than 1..N.

My languages tend to be 1-based, but are also any-based, so loops might be

for i :=A.lwb to A.upb do ....

But I can also write a for-loop as;

for i in A.bounds do ....

or as just:

for i in A do ...

(This 'in' form expects a range value, one of the new types I suggested in
my list).

Alternatively, if we are iterating over an array, it's possible to just do:

forall x in A do.... # x is each value of A in turn
forall i,x in A do .... # and here supplies the index too.

These forms will work for arrays of any base include C's 0-based ones.

I suppose an alternative to 'to', such as 'upto' can indicate a count to N-1
instead of 1, but it hints a bit of tackiness. (I already have, in addition,
'downto', 'in' and 'inrev'. But so far just writing -1 hasn't been a
problem, and does away with an extra language feature to document.

> Further, a loop can be controlled by all kinds of things other than a
> stepping integer if that's what the programmer wants: input, lists,
> pointers, even floats can make sense with the < or <= qualifiers where
> they would be inappropriate for the A to B form.

Sure. I'm not saying discard this complex loop completely and just have a
basic iterative loop. I'm saying have the basic forms too for the simple
cases: 'for', 'to' and 'do'. Syntax is free!

> Oh, and one more thing. This is related to the problems with your
> preference that I mentioned in the earlier post. Significant text has been
> written about whether the index might be modified during the course of the
> loop. And also whether the terminating value has to be constant or not.
> There are a number of permutations: loop index yes, terminating value no,
> neither, both etc. Different languages have chosen differently and their
> choices need to be documented in the language definition. These are yet
> more things for the programmer to remember. Again, C's for loop does away
> with all of that. The C code shows exactly what the programmer has chosen
> to be done.

Not really. What happens here:

for (i=0; i<strlen(s); ++i) ?

Is strlen(s) always called once; is it called once if the compiler can
determine that s won't change; or is it called per-iteration?

--
Bartc

Kaz Kylheku

unread,
Apr 30, 2014, 6:09:12 PM4/30/14
to
On 2014-04-30, BartC <b...@freeuk.com> wrote:
> Not really. What happens here:
>
> for (i=0; i<strlen(s); ++i) ?
>
> Is strlen(s) always called once; is it called once if the compiler can
> determine that s won't change; or is it called per-iteration?

Since strlen is a standard C function, the compiler can know that it has
no side effects, and that it can be hoisted out of the loop if the loop
doesn't alter the variable s, and doesn't potentially modify any memory
that could be inside s.

BartC

unread,
Apr 30, 2014, 6:36:32 PM4/30/14
to


"Kaz Kylheku" <k...@kylheku.com> wrote in message
news:201404301...@kylheku.com...
But in the absence of optimisation, or if the compiler can't determine what
happens to s, the expectation seems to be that the terminating expression is
calculated repeatedly.

That's what I used to do, but now I calculate any such expression just once,
whether it can change or not. That's a slightly saner way of doing things as
the maximum loop iterations are known in advance. (That probably suits a
simpler iteration statement better than C's more open-ended one.)

(It also gives the compiler I'm working on now its first performance edge
over gcc:

int main(void) {
char* s="one two three four five six seven eight nine ten eleven twelve";
int i,n;

for (n=1; n<=10000000; ++n)
for (i=0; i<strlen(s); ++i) {}
}

20 seconds for the above (using -O0; anything else would just eliminate the
whole thing). But 2 seconds for my effort:

import clib

proc start=
ichar s:="one two three four five six seven eight nine ten eleven twelve"

to 10 million do
to strlen(s) do
od
od

end

)

--
Bartc

Ian Collins

unread,
Apr 30, 2014, 7:01:51 PM4/30/14
to
BartC wrote:
> "James Harris" <james.h...@gmail.com> wrote
>
>> In one stroke C's for loop removes those issues and makes it manifest in
>> the syntax what steps the program will take to control the loop. It
>> reduces a loop to the essentials and it means that one compact loop
>> control statement can be used in almost all types of loop. IMO that's
>> quite brilliant! I'm not surprised if it got copied to other languages.
>
> Yes, C's for loop is quite powerful and very flexible (although so are 'if'
> and 'goto'!). But it is possible to have both that, and a dedicated loop for
> the 99% of situations (in my case) where I do need a for-loop to just count
> from A to B.

Well C++ has a range for construct that simplifies things considerably.
For example, given some vector v,

for ( auto x : v ) doSomething(x);

will iterate through v. I don't see any reason why this couldn't be
added to C.

--
Ian Collins

Ian Collins

unread,
Apr 30, 2014, 7:03:31 PM4/30/14
to
BartC wrote:
> "Kaz Kylheku" <k...@kylheku.com> wrote:
>>
>> Since strlen is a standard C function, the compiler can know that it has
>> no side effects, and that it can be hoisted out of the loop if the loop
>> doesn't alter the variable s, and doesn't potentially modify any memory
>> that could be inside s.
>
> But in the absence of optimisation, or if the compiler can't determine what
> happens to s, the expectation seems to be that the terminating expression is
> calculated repeatedly.
>
> That's what I used to do, but now I calculate any such expression just once,
> whether it can change or not. That's a slightly saner way of doing things as
> the maximum loop iterations are known in advance. (That probably suits a
> simpler iteration statement better than C's more open-ended one.)
>
> (It also gives the compiler I'm working on now its first performance edge
> over gcc:

Comparing performance without optimisation (or regards to correctness!)
is pointless.

--
Ian Collins

James Harris

unread,
Apr 30, 2014, 7:35:04 PM4/30/14
to
"BartC" <b...@freeuk.com> wrote in message
news:85e8v.227832$gV7.1...@fx21.am4...
C's for loop allows the programmer to explicitly select <, <=, > or >. In
what I understand to be your preferred syntax, though, there is nowhere to
put the <= or >= terminating condition and there's nothing there to tell the
compiler whether X is supposed to increase from A to B or to decrease from A
to B. When the step is a signed variable or an expression that could be
positive or negative and when the semantics of the language state that the
sign of the step controls the direction of iteration how can the compiler
generate code for the loop termination test? It needs to know the direction
so that it knows whether to code the loop test as, say, <= or >=.

Alternatively if the language design is that the direction of the loop is to
be controlled by the relative values of A and B rather than the step the
compiler still has the same problem. It doesn't know whether X should ascend
or descend and, hence, it doesn't know whether to go on while X <= B or to
go on while X >= B. Poor compiler! I think it would have no choice but to
write code for both tests and select between them at run time. Am I wrong?

By contrast I meant that in C one could write

for (i = A; i <= B; i += C) /* for an ascending loop */

or

for (i = A; i >= B; i -= C) /* for a descending loop */

and the job is done. Then there is no ambiguity over whether the loop
variable is expected to increase or decrease. The effect in C doesn't need
to be documented or remembered. What the programmer intends can be expressed
clearly in the source code.

Don't get me wrong. I didn't just choose this at random. When I started on a
design for loops I looked at the kinds of loop control you prefer. I spent
some time on it, went over some of the same ground as I've mentioned and
wrestled with the necessary choices: what I thought the semantics should be
and/or how I could change the syntax so that the programmer's intentions
could be made clear. In the end I realised the transparent simplicity of C's
for statement removed all of those issues and just allows the programmer to
state what is wanted.

That's not to say that there's no way to improve on C's for loop. ;-)

>> Or perhaps the programmer wanted the difference between A and B to
>> control
>> the direction of the iteration and not the step. No one can know unless
>> the syntax is changed so that something is added to the statement like a
>> stepup or stepdown keyword. The whole thing is a terrible bundle of
>> questions and uncertainties.
>
> Maybe. Although over many years of programming the number of times I've
> needed a step other then 1 or -1 has been so few, that I actually removed
> the 'step' option from my for-loops for a couple of decades. I've put it
> back now, but require the direction to be known or indicated at compile
> time, otherwise it assumes positive. A dynamic loop-counting direction is
> too unusual a requirement for it to compromise the simplicity of the
> standard for-loop construct. There any number of ways to code such a thing
> without special language support. But if you say it's easy in C, then the
> C
> version is still there waiting to be dusted off!

Yes, acknowledged that you can have both.

>> Another issue is the terminating value. I remember in Basic having to
>> write things like
>>
>> for i = a to b - 1
>>
>> where the - 1 or something like it had to be added to modify the
>> termination value. C's for loop allows a natural slight adjustment to the
>> termination condition by means of < vs <=. Contrast these two
>>
>> for (i = 0; i < len; i++)
>> for (i = 1; i <= len; i++)
>
> Yes, C is zero-based so 0..N-1 loops might be more common than 1..N.
>
> My languages tend to be 1-based, but are also any-based, so loops might be
>
> for i :=A.lwb to A.upb do ....
>
> But I can also write a for-loop as;
>
> for i in A.bounds do ....
>
> or as just:
>
> for i in A do ...
>
> (This 'in' form expects a range value, one of the new types I suggested in
> my list).
>
> Alternatively, if we are iterating over an array, it's possible to just
> do:
>
> forall x in A do.... # x is each value of A in turn
> forall i,x in A do .... # and here supplies the index too.
>
> These forms will work for arrays of any base include C's 0-based ones.

Am going off topic a bit but I would be interested to hear your views on
this. Because

for x in A

is a good concept but, at the same time, a loop might need to iterate over
two or more arrays rather than just one I have toyed with the following

x = nextof A

Then each time the statement is reached x gets assigned the next value of A.
Of course, this would normally appear in a loop. It could head a loop by
writing something like

loop x = nextof A
... loop body
end loop

It is similar to your x in A approach but also allows other loop controls to
be added to the same loop if required, along the lines of

loop x = nextof A, y = nextof B
... loop body
end loop

Exhaustion of either A or B would terminate the loop. A or B could be
functions that generate sequences.

I like that the above is flexible (and also compact) but I don't think it's
quite right yet. Any thoughts on it?

> I suppose an alternative to 'to', such as 'upto' can indicate a count to
> N-1
> instead of 1, but it hints a bit of tackiness. (I already have, in
> addition,
> 'downto', 'in' and 'inrev'. But so far just writing -1 hasn't been a
> problem, and does away with an extra language feature to document.
>
>> Further, a loop can be controlled by all kinds of things other than a
>> stepping integer if that's what the programmer wants: input, lists,
>> pointers, even floats can make sense with the < or <= qualifiers where
>> they would be inappropriate for the A to B form.
>
> Sure. I'm not saying discard this complex loop completely and just have a
> basic iterative loop. I'm saying have the basic forms too for the simple
> cases: 'for', 'to' and 'do'. Syntax is free!

Syntax is free and I freely acknowledge that you make good syntax choices.
But consider: if a language includes the simpler form then its designer has
to deal with and document its semantics for the age-old issues mentioned
above and earlier. A given programmer may choose not to use the simpler form
at all but if he or she has to read someone else's code the programmer might
still need to learn the complex and somewhat arbitrary rules that the
language applies to those loops.

>> Oh, and one more thing. This is related to the problems with your
>> preference that I mentioned in the earlier post. Significant text has
>> been
>> written about whether the index might be modified during the course of
>> the
>> loop. And also whether the terminating value has to be constant or not.
>> There are a number of permutations: loop index yes, terminating value no,
>> neither, both etc. Different languages have chosen differently and their
>> choices need to be documented in the language definition. These are yet
>> more things for the programmer to remember. Again, C's for loop does away
>> with all of that. The C code shows exactly what the programmer has chosen
>> to be done.
>
> Not really. What happens here:
>
> for (i=0; i<strlen(s); ++i) ?
>
> Is strlen(s) always called once; is it called once if the compiler can
> determine that s won't change; or is it called per-iteration?

As you know, in the expressed form strlen is at least nominally called once
per iteration. An optimising compiler might improve on that if it can prove
that strlen(s) will not change in the loop but the programmer's intention is
clear (even if unwise).

It's easy to rewrite in a better form such as either of these

for (i = strlen(s) - 1; i >= 0; --i)
for (i = 0, slen = strlen(s); i < slen; ++i)

Apart from processing the string in the same order as your original the
latter has the advantage that if the code changes the length of the string
then both slen and i can be adjusted as the iterations progress.

Don't worry. I don't expect to convince you and I can see the appeal of the
simpler form.

James


Rod Pemberton

unread,
Apr 30, 2014, 9:13:29 PM4/30/14
to
On Wed, 30 Apr 2014 07:16:19 -0400, BartC <b...@freeuk.com> wrote:

> As for C being minimalist, I don't know if a language needing these types
> and macros (remembering to substitute all the combinations of 8 16, 32
> and 64 every time you see N): [list]
>
> and maybe this lot too, as some of these seem to be different from those
> above: [list]
>
> and much more, could actually be called minimalist. (More like
> maximalist,
> as this lot could easily be condensed into a handful of language
> features.)
>

How often do you use those?

> It's a joke really, but not particularly funny as this language and its
> ideas seem to have permeated everywhere. You take the crude C for-loop,
> which is 'for (expr; expr; expr)', and you see it practically unchanged
> in C++, C#, Java, Javascript, PHP, Perl, even newer ones such as Go and
> Dart (although Go has at least dropped the parentheses!).
>

C's for() was a huge improvement over other languages of the time.
It put all the loop conditions in the same place. This was very nice
when both programming and reading. I used to love this. However,
after over two decades of C, I don't like it anymore. The problem isn't
the either of those two issues. Those are still great. The problem is
many C compilers optimize a "while(1)" loop with an "if() break;" better.
So, now, I'm unrolling for() loops in some instances ...

If C was truly minimalist, it'd just have a "loop" keyword for all loops,
no conditions, no termination, infinite. "break" and "continue" would
still work.


Rod Pemberton

Ian Collins

unread,
Apr 30, 2014, 9:42:00 PM4/30/14
to
BartC wrote:
>
> As for C being minimalist, I don't know if a language needing these types
> and macros (remembering to substitute all the combinations of 8 16, 32 and
> 64 every time you see N):

<snip long list>

Give a lowish level language such as C works "close to the metal" on a
wide variety of hardware, how would you avoid having a collection of
fixed width types?

I agree there's a better way of (but not within the limits of C) to
specify the limits, but they require some form of generics (such as C++
std::numeric_limits).

--
Ian Collins

Rod Pemberton

unread,
Apr 30, 2014, 10:08:04 PM4/30/14
to
On Tue, 29 Apr 2014 12:57:25 -0400, BartC <b...@freeuk.com> wrote:

> Well, I put together my list. About 115 things listed actually.
> Too long to show here so is at:

What do I do with my "about 115" replies?

Don't worry, I can't handle a full blow conversation on all of
those. You'd need to limit it to just a few.

> [link]
>

I didn't see any way to reply to that there. If it's not totally
anonymous, no email, no signup account, no personal info, then I
wouldn't use it anyway.


Rod Pemberton

BartC

unread,
May 1, 2014, 4:26:11 AM5/1/14
to


"Rod Pemberton" <dont_us...@xnothavet.cqm> wrote in message
news:op.xe5porqb6zenlw@localhost...
> On Wed, 30 Apr 2014 07:16:19 -0400, BartC <b...@freeuk.com> wrote:
>
>> As for C being minimalist, I don't know if a language needing these types
>> and macros (remembering to substitute all the combinations of 8 16, 32
>> and 64 every time you see N): [list]

[intN_t etc]

> How often do you use those?

It's common to use some of those at some time or other, if not all at the
same time. You've never used CHARBIT or needed an exact 32-bit signed int?

>You take the crude C for-loop,
>> which is 'for (expr; expr; expr)', and you see it practically unchanged
>> in C++, C#, Java, Javascript, PHP, Perl, even newer ones such as Go and
>> Dart (although Go has at least dropped the parentheses!).
>>
>
> C's for() was a huge improvement over other languages of the time.

At the time being around 1970, means the world already had Algol60, Algol 68
and even Fortran. These all had a dedicated way of doing a straightforward
iteration. Not as general as C's effort, but when you did have a simple
loop, it was as lot easier to type (and to get right).

> If C was truly minimalist, it'd just have a "loop" keyword for all loops,
> no conditions, no termination, infinite. "break" and "continue" would
> still work.

(The first time I had a compiler output C code, it was a kind of 'flat' C
with all statement structure removed. It just used 'goto' and 'if (...)
goto' for control flow. The resultant code was just as fast as a properly
structured program. So there are degrees of minimalism (and I could have
gone a lot further).)

--
Bartc

BartC

unread,
May 1, 2014, 4:35:42 AM5/1/14
to


"Ian Collins" <ian-...@hotmail.com> wrote in message
news:bsdn38...@mid.individual.net...
> BartC wrote:
>>
>> As for C being minimalist, I don't know if a language needing these types
>> and macros (remembering to substitute all the combinations of 8 16, 32
>> and
>> 64 every time you see N):
>
> <snip long list>
>
> Give a lowish level language such as C works "close to the metal" on a
> wide variety of hardware, how would you avoid having a collection of fixed
> width types?

You don't avoid having the range of different types (you need many of those
anyway have a flexible set of types for storing data). But there are elegant
ways of doing it without having sprawling lists of macros and typedefs.

For example, if T is any primitive type, then T:n could define a version
which is n bits wide.

> I agree there's a better way of (but not within the limits of C) to
> specify the limits, but they require some form of generics (such as C++
> std::numeric_limits).

If T is a numeric type, then T'min and T'max could give you the lower and
upper limits (as could T'bounds, giving a range type). And you can write
X'min etc when you have an expression.

You don't need exotic things such as generics. (I know the point of C++ is
apparently as a tool to build your own language, but when some feature is a
morning's work on a compiler, then that's a far simpler route.)

--
Bartc

BartC

unread,
May 1, 2014, 4:47:27 AM5/1/14
to


"Ian Collins" <ian-...@hotmail.com> wrote in message
news:bsddq3...@mid.individual.net...
It's optimisation that would be pointless here because the fragment of code
did nothing useful and so would be optimised away.

The point of interest is that C seems to specify that a loop terminator
expression is expected to be re-evaluated on each iteration (unless it can
figure out it doesn't need to be), whereas I've decided that it should be
evaluated once at the start of the loop. That gives a very easy advantage
(which I will need because there's no way I will match gcc's -O3
optimisations).

It's useful to the programmer as well because they then have the confidence
to write:

for (i=0; i<strlen(s); ++i) ....

without having reservations about whether strlen(s) is going to be evaluated
once or strlen() times, or going to the trouble of storing strlen() is a
variable first.a

(And I have used this approach for many years without it being a problem. If
a loop limit is in fact a moving target, then that would need to be coded
differently, but needs a lot more care anyway.)

--
Bartc

Ian Collins

unread,
May 1, 2014, 5:02:29 AM5/1/14
to
BartC wrote:
>
>
> "Ian Collins" <ian-...@hotmail.com> wrote in message
> news:bsdn38...@mid.individual.net...
>> BartC wrote:
>>>
>>> As for C being minimalist, I don't know if a language needing these types
>>> and macros (remembering to substitute all the combinations of 8 16, 32
>>> and
>>> 64 every time you see N):
>>
>> <snip long list>
>>
>> Give a lowish level language such as C works "close to the metal" on a
>> wide variety of hardware, how would you avoid having a collection of fixed
>> width types?
>
> You don't avoid having the range of different types (you need many of those
> anyway have a flexible set of types for storing data). But there are elegant
> ways of doing it without having sprawling lists of macros and typedefs.
>
> For example, if T is any primitive type, then T:n could define a version
> which is n bits wide.

So you substitute an underscore for a colon?

What about the least and fast types? The former don't appear very
often, but the latter are very useful.

>> I agree there's a better way of (but not within the limits of C) to
>> specify the limits, but they require some form of generics (such as C++
>> std::numeric_limits).
>
> If T is a numeric type, then T'min and T'max could give you the lower and
> upper limits (as could T'bounds, giving a range type). And you can write
> X'min etc when you have an expression.
>
> You don't need exotic things such as generics. (I know the point of C++ is
> apparently as a tool to build your own language, but when some feature is a
> morning's work on a compiler, then that's a far simpler route.)

Generics save you from having to extend the language.

--
Ian Collins

Dmitry A. Kazakov

unread,
May 1, 2014, 5:08:41 AM5/1/14
to
On Thu, 1 May 2014 09:35:42 +0100, BartC wrote:

> For example, if T is any primitive type, then T:n could define a version
> which is n bits wide.

Let T be ... IEEE 754 float, UCS-2 character ... Does Int32:31 make
Positive? Negative? Maybe, Odd?

It is not that simple, and an abstraction inversion, to constrain a type,
even a scalar type, by the length of its memory representation.

Semantic constraints must be related to the type semantics. Representation
constraints (e.g. that Boolean is packed, 1 bit-length) is an absolutely
different thing and rarely required thing even in systems programming.

>> I agree there's a better way of (but not within the limits of C) to
>> specify the limits, but they require some form of generics (such as C++
>> std::numeric_limits).
>
> If T is a numeric type, then T'min and T'max could give you the lower and
> upper limits (as could T'bounds, giving a range type).

This is again a simplification. There is no min/max if T is Complex. And
Complex is numeric (mathematically speaking, a field). If T is IEEE float
what T'Min means? The minimal number proper or -Inf?

The point is that stuff like T'Min is a part of interface (of some ordered
finite set, which Integer is, and Complex is not). The language must
support such interfaces and programs must be written in terms of such
interfaces.

> You don't need exotic things such as generics.

Yes. Parametric polymorphism (a decent name for macros) has no place in a
good (=typed) language. C++ templates proved that point.

--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

BartC

unread,
May 1, 2014, 5:40:06 AM5/1/14
to
"Ian Collins" <ian-...@hotmail.com> wrote in message
news:bsegt5...@mid.individual.net...
> BartC wrote:

>> You don't avoid having the range of different types (you need many of
>> those
>> anyway have a flexible set of types for storing data). But there are
>> elegant
>> ways of doing it without having sprawling lists of macros and typedefs.
>>
>> For example, if T is any primitive type, then T:n could define a version
>> which is n bits wide.
>
> So you substitute an underscore for a colon?

You mean when int32_t, for example, is written as int:32?

The "_t" could have been eliminated anyway, just have int32 as the type.
(int32 becomes a reserved word, what's the big deal?)

But the little thing with the colon thing actually eliminates dozens of
typedefs from the official headers. And the thing with the 'min and 'max
attributes eliminates dozens more. If you have:

unsigned long long int A;

then you need ULLONG_MAX for the highest value of A. But if the type of A
changes, you then have to search for and update all these ULLONG_MAXs. Or
you could just write A'max.

It is actually a big deal having these things properly supported by the
language and not crudely bolted on.

> What about the least and fast types? The former don't appear very often,
> but the latter are very useful.

I don't really know what they are for. However, the T:n syntax (which is
only a suggestion after all), does give you the flexibility to specify /any/
width, not just those the C implementers have deigned to list in the include
file. int:36 for example.

>>> I agree there's a better way of (but not within the limits of C) to
>>> specify the limits, but they require some form of generics (such as C++
>>> std::numeric_limits).
>>
>> If T is a numeric type, then T'min and T'max could give you the lower and
>> upper limits (as could T'bounds, giving a range type). And you can write
>> X'min etc when you have an expression.
>>
>> You don't need exotic things such as generics. (I know the point of C++
>> is
>> apparently as a tool to build your own language, but when some feature is
>> a
>> morning's work on a compiler, then that's a far simpler route.)
>
> Generics save you from having to extend the language.

By having every user extend his own version, and in a different style to
everyone else? Because /someone/ has to add those 'min and 'max features!
BTW, if someone did want to do that, how exactly do they determine the
minimum and maximum values of a type?

Basic stuff like this should really be built-in. (I know language-building
features are intriguing, but my experience is that just implementing it
directly is a lot less work.)

--
Bartc

BartC

unread,
May 1, 2014, 6:02:17 AM5/1/14
to


"Dmitry A. Kazakov" <mai...@dmitry-kazakov.de> wrote in message
news:8muqscxvu33i$.22498hadddgj.dlg@40tude.net...
> On Thu, 1 May 2014 09:35:42 +0100, BartC wrote:
>
>> For example, if T is any primitive type, then T:n could define a version
>> which is n bits wide.
>
> Let T be ... IEEE 754 float, UCS-2 character ... Does Int32:31 make
> Positive? Negative? Maybe, Odd?
>
> It is not that simple, and an abstraction inversion, to constrain a type,
> even a scalar type, by the length of its memory representation.

At the level we're talking about, generally we know the hardware can deal
with integer values that are 8, 16, 32 or 64 bits wide, and floating point
values that are 32 or 64 bits. (There might be a few extra odd ones such as
80-bit floats, or software-supported 128-bit ints.)

One way of choosing whether to use 8, 16, 32 or 64 bits for a storage type
(for storing data in memory), is to actually specify 8, 16, 32, or bits! It
can't get any simpler.

(And I've tried using ranges to specify a width, but it doesn't really work
for me. Besides, does the range 10'000 .. 10'100 need 16 bits, or 8?)

> Semantic constraints must be related to the type semantics. Representation
> constraints (e.g. that Boolean is packed, 1 bit-length) is an absolutely
> different thing and rarely required thing even in systems programming.

I need to do this quite a lot. Try talking to Win32, for example, and dare
to so in a language which is not MS C or C++, or even not C at all, then you
need to go into to excruciating detail to get the various structs and so on
exactly compatible.

>> If T is a numeric type, then T'min and T'max could give you the lower and
>> upper limits (as could T'bounds, giving a range type).
>
> This is again a simplification. There is no min/max if T is Complex. And
> Complex is numeric (mathematically speaking, a field). If T is IEEE float
> what T'Min means? The minimal number proper or -Inf?

A minor detail. I never use Complex so can't comment on that, but min/max
can simply not be defined where it doesn't make sense.

But as this is about alternatives to C's list of limit macros, then it
doesn't mention any limits for Complex. While for floating point, 'min is be
the lowest non-zero value that can be represented, while 'max is be the
highest before it overflows to Inf (some 1e-308 to 1e+308 for 64-bits.)
Anything else wouldn't be that useful.

--
bartc

Andy Walker

unread,
May 1, 2014, 6:03:18 AM5/1/14
to
On 01/05/14 00:35, James Harris wrote:
> "BartC" <b...@freeuk.com> wrote in message
> news:85e8v.227832$gV7.1...@fx21.am4...

[Not really the topic of this article, but I was (pleasantly)
surprised by how many of Bart's 115 Things I agreed with! Anyway ...]

> C's for loop allows the programmer to explicitly select <, <=, > or >.

Or, in other words, *forces* the programmer explicitly to select
[or, of course, to supply some other Boolean construct or (empty)], with
a decent chance of a resultant bug.

> In
> what I understand to be your preferred syntax, though, there is nowhere to
> put the <= or >= terminating condition and there's nothing there to tell the
> compiler whether X is supposed to increase from A to B or to decrease from A
> to B. When the step is a signed variable or an expression that could be
> positive or negative and when the semantics of the language state that the
> sign of the step controls the direction of iteration how can the compiler
> generate code for the loop termination test? It needs to know the direction
> so that it knows whether to code the loop test as, say, <= or >=.

Yes, that's the sort of thing that compilers do. But since a large
majority of loops in practice are incrementing by 1, a large majority of the
others are decrementing by 1, and a large majority of the few left over are
incrementing/decrementing by a compile-time constant, you're talking about
less than 1% of loops for which the test is slightly complicated, and so
performance takes a tiny hit. That same hit is still there in C; it's
inherent in not knowing at compile-time which way the loop will run [and
so the programmer having to write in that complexity "by hand"].

> Alternatively if the language design is that the direction of the loop is to
> be controlled by the relative values of A and B rather than the step the
> compiler still has the same problem. It doesn't know whether X should ascend
> or descend and, hence, it doesn't know whether to go on while X <= B or to
> go on while X >= B. Poor compiler! I think it would have no choice but to
> write code for both tests and select between them at run time. Am I wrong?

No; that's what compilers do. See above!

> By contrast I meant that in C one could write
> for (i = A; i <= B; i += C) /* for an ascending loop */
> or
> for (i = A; i >= B; i -= C) /* for a descending loop */
> and the job is done. Then there is no ambiguity over whether the loop
> variable is expected to increase or decrease.

Even when you don't know the sign of C? That way lie bugs!
But in any case, if you want that degree of control, C already has
the "while" loop. The problem, such as it is, with C's loops is the
existence of *three* different loop syntaxes when only one is needed,
while still not having a proper "loop-and-a-half" syntax [beyond what
can be done with "break" and "continue"].

> The effect in C doesn't need
> to be documented or remembered. What the programmer intends can be expressed
> clearly in the source code.

Not really. It's only "clear" because C has acquired various
standard forms, so that "everyone knows" what "for (i = 0; i < n; i++)"
means, and we [with any luck] no longer get obscure bugs by writing
"i <= n" or by changing the value of "n" or "i" within the loop. It's
easy to forget how hard programming is to a beginner, or when you first
use a language which has made different choices from the language(s)
you are familiar with.

[...]
>>> Further, a loop can be controlled by all kinds of things other than a
>>> stepping integer if that's what the programmer wants: input, lists,
>>> pointers, even floats can make sense with the < or <= qualifiers where
>>> they would be inappropriate for the A to B form.
>> Sure. I'm not saying discard this complex loop completely and just have a
>> basic iterative loop. I'm saying have the basic forms too for the simple
>> cases: 'for', 'to' and 'do'.

For loops other than with a stepping integer, you can, in all
sensible languages, use "while" instead:

while read (x); x > 0 do print (sqrt(x)) od;
while ptr /= 0 do { whatever }; ptr := ptr.next od

and so on. Horses for courses!

>> Syntax is free!
> Syntax is free [...].

No it isn't. It's very cheap in compilation time, but that is
very cheap anyway these days. It's not free in complexity of manuals
or syntax charts or however else people get used to your language, and
it's not free in design time if people have to deliberate [eg, in C]
over the choice between "for", "while" and "do" -- *especially* if [as
in C] the choice is not that important.

> But consider: if a language includes the simpler form then its designer has
> to deal with and document its semantics for the age-old issues mentioned
> above and earlier. A given programmer may choose not to use the simpler form
> at all but if he or she has to read someone else's code the programmer might
> still need to learn the complex and somewhat arbitrary rules that the
> language applies to those loops.

This seems a bit strained! How long does it take to learn that
"for i to n do stmt od" will evaluate "n" once and will obey "stmt" with
"i" set successively to 1, 2, 3, ,,,, n [and not at all if "n" is zero or
negative], whereas "while expr do stmt od" will repeatedly evaluate "expr"
and obey "stmt" for as long as "expr" returns the value "true"? Now your
turn to explain the allegedly less complex and arbitrary rules that C has
for "for", "while" and "do" in less than four lines.

--
Andy Walker,
Nottingham.

Ian Collins

unread,
May 1, 2014, 6:06:35 AM5/1/14
to
BartC wrote:
> "Ian Collins" <ian-...@hotmail.com> wrote:
>>
>> Generics save you from having to extend the language.
>
> By having every user extend his own version, and in a different style to
> everyone else? Because /someone/ has to add those 'min and 'max features!
> BTW, if someone did want to do that, how exactly do they determine the
> minimum and maximum values of a type?

No, by including them in the language's library and allowing users to
apply the standard rules to their own types.

> Basic stuff like this should really be built-in. (I know language-building
> features are intriguing, but my experience is that just implementing it
> directly is a lot less work.)

The you have to change the language for any new types.

--
Ian Collins

BartC

unread,
May 1, 2014, 7:44:41 AM5/1/14
to
"James Harris" <james.h...@gmail.com> wrote in message
news:ljs1cm$kig$1...@dont-email.me...
> "BartC" <b...@freeuk.com> wrote in message
> news:85e8v.227832$gV7.1...@fx21.am4...
>> "James Harris" <james.h...@gmail.com> wrote in message

>> But how would C's for-loop help here? Surely you still have to choose
>> between a <= or >= terminating condition?
>
> C's for loop allows the programmer to explicitly select <, <=, > or >. In
> what I understand to be your preferred syntax, though, there is nowhere to
> put the <= or >= terminating condition and there's nothing there to tell
> the compiler whether X is supposed to increase from A to B or to decrease
> from A to B.

Pretty much every language with a conventional (non-C) 'for' statement will
have a way to iterate up or down. I use:

for i:=A to B do Step +1
for i:=A downto B do Step -1
for i:=A to B by C do
for i:=A downto B by C do

With the 'by' forms expecting C to be a constant (either positive or
negative; it will make 'to' into 'downto' as needed). (If not, it is assumed
to be positive or negative respectively).

(BTW the 'downto' method is from Pascal, which I thought was a good
simplification in forcing a loop direction to be known at compile-time.)

> When the step is a signed variable or an expression that could be positive
> or negative and when the semantics of the language state that the sign of
> the step controls the direction of iteration how can the compiler generate
> code for the loop termination test? It needs to know the direction so that
> it knows whether to code the loop test as, say, <= or >=.

This is easy. You just don't worry about it. Or prohibit it when the
compiler can't figure out what to do.

> Alternatively if the language design is that the direction of the loop is
> to be controlled by the relative values of A and B rather than the step
> the compiler still has the same problem. It doesn't know whether X should
> ascend or descend and, hence, it doesn't know whether to go on while X <=
> B or to go on while X >= B. Poor compiler! I think it would have no choice
> but to write code for both tests and select between them at run time. Am I
> wrong?

(Have you ever looked at the code you've written, and counted how many times
you've used 'for', and what proportion use simple +1 or -1 iteration, and
what proportion used anything more complex?

You might be overestimating the number of times you need a more complex
loop.)

>> Alternatively, if we are iterating over an array, it's possible to just
>> do:
>>
>> forall x in A do.... # x is each value of A in turn
>> forall i,x in A do .... # and here supplies the index too.

> Am going off topic a bit but I would be interested to hear your views on
> this. Because
>
> for x in A
>
> is a good concept but, at the same time, a loop might need to iterate over
> two or more arrays rather than just one I have toyed with the following
>
> x = nextof A
>
> Then each time the statement is reached x gets assigned the next value of
> A. Of course, this would normally appear in a loop. It could head a loop
> by writing something like
>
> loop x = nextof A
> ... loop body
> end loop
>
> It is similar to your x in A approach

I'm not sure x=nextof A will work in the body, unless x is recognised as
being the official loop index or variable. Because some state is needed to
remember where it's up to.

At the head of a loop, then yes it's just another syntax for stepping to the
next value.

(In my 'for x in A' form, there is an implicit loop index behind the scenes
storing the state, which can be exposed by using 'for i,x in A'. You need
the index to write back into A (when x is the value of the element and not a
reference), to index a parallel array, for all sorts of things.

I haven't gotten around to using proper iterators yet. But probably too
advanced at this level.)

> but also allows other loop controls to be added to the same loop if
> required, along the lines of
>
> loop x = nextof A, y = nextof B
> ... loop body
> end loop
>
> Exhaustion of either A or B would terminate the loop. A or B could be
> functions that generate sequences.

I do allow multiple arrays, but it is sometimes difficult to get across
exactly what they mean. If I write this (which is dynamic code);

a:=(10,20,30,40)
b:=(100,200,300,400,500)

forall i,x,y in a,b do
println i,x,y
od

then the output is:

1 10 100
2 20 200
3 30 300
4 40 400

It goes with the length of A, so B needs to be at least the same length
(otherwise there's an array bounds error).

However, someone might expect the iteration to be nested (ie. the equivalent
of 'for x in a do for y in b do' but within the convenience of a single
'for') and perform 5x6 iterations.

> I like that the above is flexible (and also compact) but I don't think
> it's quite right yet. Any thoughts on it?

No, it's fine, provided it's made clear the arrays are scanned in parallel.
Accessing the loop index however, either explicitly as I have it, or through
some construct, I think would be useful.

You might also have to clarify what happens when the arrays are modified
(made shorter or longer) within the loop. (As I implement it, the number of
iterations is fixed at the start of the loop. So it will miss out elements
if a list is extended, and generate a bounds error if shortened. Not a
sophisticated way to do it, but simple. and efficient.)

And, you might need 'prevof' in order to iterate backwards. (As you have it,
you scan scan A forwards, and B backwards in the same loop, which I can't do
easily.)

--
Bartc


Dmitry A. Kazakov

unread,
May 1, 2014, 7:57:13 AM5/1/14
to
On Thu, 1 May 2014 11:02:17 +0100, BartC wrote:

> "Dmitry A. Kazakov" <mai...@dmitry-kazakov.de> wrote in message
> news:8muqscxvu33i$.22498hadddgj.dlg@40tude.net...
>> On Thu, 1 May 2014 09:35:42 +0100, BartC wrote:
>>
>>> For example, if T is any primitive type, then T:n could define a version
>>> which is n bits wide.
>>
>> Let T be ... IEEE 754 float, UCS-2 character ... Does Int32:31 make
>> Positive? Negative? Maybe, Odd?
>>
>> It is not that simple, and an abstraction inversion, to constrain a type,
>> even a scalar type, by the length of its memory representation.
>
> At the level we're talking about, generally we know the hardware can deal
> with integer values that are 8, 16, 32 or 64 bits wide, and floating point
> values that are 32 or 64 bits. (There might be a few extra odd ones such as
> 80-bit floats, or software-supported 128-bit ints.)
>
> One way of choosing whether to use 8, 16, 32 or 64 bits for a storage type
> (for storing data in memory), is to actually specify 8, 16, 32, or bits! It
> can't get any simpler.

What do you do when there is no given machine type? Let you compile for
32-bit i686. There is no 64-bit integer. Wait, there is but you need
special instructions. It is not the way to deal with this. You don't make
the language semantics dependent on the target machine.

> (And I've tried using ranges to specify a width, but it doesn't really work
> for me. Besides, does the range 10'000 .. 10'100 need 16 bits, or 8?)

Why not 7 bits? It can be 32 bits on a DSP. Why should the programmer care?
I he cares he should spell his care in the language as a representation
constraint.

>> Semantic constraints must be related to the type semantics. Representation
>> constraints (e.g. that Boolean is packed, 1 bit-length) is an absolutely
>> different thing and rarely required thing even in systems programming.
>
> I need to do this quite a lot. Try talking to Win32, for example, and dare
> to so in a language which is not MS C or C++, or even not C at all, then you
> need to go into to excruciating detail to get the various structs and so on
> exactly compatible.

Win32 defines a set of types, like BYTE, DWORD, LPARAM etc. The only thing
you should do is define these types using the means the language offers.
You don't need to have these types built-in.

BTW, speaking of representation constraints, it is not only memory unit
size (not all machines have byte as the memory unit), it is endianness and
complement.

>>> If T is a numeric type, then T'min and T'max could give you the lower and
>>> upper limits (as could T'bounds, giving a range type).
>>
>> This is again a simplification. There is no min/max if T is Complex. And
>> Complex is numeric (mathematically speaking, a field). If T is IEEE float
>> what T'Min means? The minimal number proper or -Inf?
>
> A minor detail. I never use Complex so can't comment on that, but min/max
> can simply not be defined where it doesn't make sense.

As it does not make sense for numeric types in general. The point is, it is
finer than numeric even in such simplistic cases as merely upper and lower
bounds. You cannot build this in into the language. It should be deal with
in a more general manner.

> But as this is about alternatives to C's list of limit macros, then it
> doesn't mention any limits for Complex. While for floating point, 'min is be
> the lowest non-zero value that can be represented, while 'max is be the
> highest before it overflows to Inf (some 1e-308 to 1e+308 for 64-bits.)

According to which definition? Min and Max are defined in a certain way to
solve problems. From the definition depends which propositions hold and
which do not. E.g. for some sorting algorithm you might well prefer -Inf as
the starting point over least number greater than -Inf. Or consider a
program that checks if X in T'Min..T'Max. Is it a tautology? Must it be
tautology for any ordered type? Is NaN ordered?

> Anything else wouldn't be that useful.

Prove that.

BartC

unread,
May 1, 2014, 10:12:34 AM5/1/14
to
"Dmitry A. Kazakov" <mai...@dmitry-kazakov.de> wrote in message
news:i8gmjwf2beyz.12f8p3m5cxcnh$.dlg@40tude.net...
> On Thu, 1 May 2014 11:02:17 +0100, BartC wrote:

>> At the level we're talking about, generally we know the hardware can deal
>> with integer values that are 8, 16, 32 or 64 bits wide, and floating
>> point
>> values that are 32 or 64 bits. (There might be a few extra odd ones such
>> as
>> 80-bit floats, or software-supported 128-bit ints.)
>>
>> One way of choosing whether to use 8, 16, 32 or 64 bits for a storage
>> type
>> (for storing data in memory), is to actually specify 8, 16, 32, or [64]
>> bits! It
>> can't get any simpler.
>
> What do you do when there is no given machine type? Let you compile for
> 32-bit i686. There is no 64-bit integer. Wait, there is but you need
> special instructions. It is not the way to deal with this. You don't make
> the language semantics dependent on the target machine.

That machines generally work in powers-of-two bitwidths is well-known. It
doesn't matter so much if the machine doesn't fully support each width. Some
might have 32-bit operations but byte-addressed memory. Or 64-bits may need
a bit more work on a 32-bit processor (and may not be feasible on anything
less). It doesn't matter.

Whatever the likely choices are, there is a place for a low-level language
to specify those directly in terms of bit widths. The next level up can deal
with it your way.

>> (And I've tried using ranges to specify a width, but it doesn't really
>> work
>> for me. Besides, does the range 10'000 .. 10'100 need 16 bits, or 8?)
>
> Why not 7 bits? It can be 32 bits on a DSP. Why should the programmer
> care?
> I he cares he should spell his care in the language as a representation
> constraint.

Because 7-bits isn't a likely memory-width size. The likelihood is that it
will be 8 or 16 or 32.

(If someone needs to buy stationery, they might specify A5 or A4 or A3.
Those are the standard choices (in the EU). They might order it by
specifying a requirement in mm or cm, but that would be unusual. They work
out for themselves what a suitable standard size is.)

>>> Semantic constraints must be related to the type semantics.
>>> Representation
>>> constraints (e.g. that Boolean is packed, 1 bit-length) is an absolutely
>>> different thing and rarely required thing even in systems programming.
>>
>> I need to do this quite a lot. Try talking to Win32, for example, and
>> dare
>> to so in a language which is not MS C or C++, or even not C at all, then
>> you
>> need to go into to excruciating detail to get the various structs and so
>> on
>> exactly compatible.
>
> Win32 defines a set of types, like BYTE, DWORD, LPARAM etc. The only thing
> you should do is define these types using the means the language offers.
> You don't need to have these types built-in.

You need to find out what those types actually mean. Usually the API will
not tell you. One way is to run the MS compiler with 'sizeof(LONG)'. Or
maybe that info is buried deep in the docs somewhere.

That's the first step. But once you've found out that WORD means signed
16-bits, then what? You need to express this in your own language. But how?
Suddenly that int:16 denotation isn't so useless after all! Better than
defining a type around -32768..32767, which could conceivably be
represented, for reasons best known to the compiler, as 32 bits in the range
1000000 to 1065535. That's not good at all.

> BTW, speaking of representation constraints, it is not only memory unit
> size (not all machines have byte as the memory unit), it is endianness and
> complement.

Those are issues I've never really had to deal with. So it's up to someone
else to offer suggestions as to how that can be handled, for example to
create a struct where the values are the right way around when transmitted
between
machines.

I'm not trying to create the perfect language here. (And AFAIK, C doesn't
concern itself with endian-ness either.)

> As it does not make sense for numeric types in general.

Yes it does. The odometer in my car displays a 6-digit decimal unsigned
type. The 'min value is 000000, and the 'max is 999999. That means I know
when it approaches 999999, that something will happen (probably, wrap around
to 000000, if the car lasts that long).

>> But as this is about alternatives to C's list of limit macros, then it
>> doesn't mention any limits for Complex. While for floating point, 'min is
>> be
>> the lowest non-zero value that can be represented, while 'max is be the
>> highest before it overflows to Inf (some 1e-308 to 1e+308 for 64-bits.)
>
> According to which definition?

According to 'DBL_MAX' and similar macros in the C standard. Implementations
provide their own actual values. My suggestion is simply to do with
different ways to provide or access that information.

> Or consider a
> program that checks if X in T'Min..T'Max. Is it a tautology? Must it be
> tautology for any ordered type? Is NaN ordered?

If X is of type T, then perhaps that is not so useful. If not, then it could
certainly be useful, because if X is in byte'range (a more compact way of
writint it; 0..255 in other words), then it can be written to a file using
one byte.

Or in a compiler, if X in int32'range then that constant can be assigned
type int32. Etc.

>> Anything else wouldn't be that useful.

> Prove that.

You need to define what 'useful' might be. I certainly find them useful, but
not indispensable (I know most of the int limits already - for twos
complement machines anyway - or can express them in hex without much
trouble. But writing int64'max is easier).

--
Bartc

Dmitry A. Kazakov

unread,
May 1, 2014, 11:18:57 AM5/1/14
to
On Thu, 1 May 2014 15:12:34 +0100, BartC wrote:

> "Dmitry A. Kazakov" <mai...@dmitry-kazakov.de> wrote in message
> news:i8gmjwf2beyz.12f8p3m5cxcnh$.dlg@40tude.net...
>> On Thu, 1 May 2014 11:02:17 +0100, BartC wrote:
>
>>> At the level we're talking about, generally we know the hardware can deal
>>> with integer values that are 8, 16, 32 or 64 bits wide, and floating point
>>> values that are 32 or 64 bits. (There might be a few extra odd ones such
>>> as 80-bit floats, or software-supported 128-bit ints.)
>>>
>>> One way of choosing whether to use 8, 16, 32 or 64 bits for a storage
>>> type (for storing data in memory), is to actually specify 8, 16, 32, or [64]
>>> bits! It can't get any simpler.
>>
>> What do you do when there is no given machine type? Let you compile for
>> 32-bit i686. There is no 64-bit integer. Wait, there is but you need
>> special instructions. It is not the way to deal with this. You don't make
>> the language semantics dependent on the target machine.
>
> That machines generally work in powers-of-two bitwidths is well-known.

And those that don't, you program in another language... Right?

What should be the properties of this, another, clearly better language,
since it can be used for programming any machine?

>>> (And I've tried using ranges to specify a width, but it doesn't really work
>>> for me. Besides, does the range 10'000 .. 10'100 need 16 bits, or 8?)
>>
>> Why not 7 bits? It can be 32 bits on a DSP. Why should the programmer
>> care? I he cares he should spell his care in the language as a representation
>> constraint.
>
> Because 7-bits isn't a likely memory-width size.

1-bit of Boolean isn't either. So what?

> (If someone needs to buy stationery, they might specify A5 or A4 or A3.
> Those are the standard choices (in the EU).

It does not mean you could not write a poem on a piece of letter paper
size.

>>>> Semantic constraints must be related to the type semantics. Representation
>>>> constraints (e.g. that Boolean is packed, 1 bit-length) is an absolutely
>>>> different thing and rarely required thing even in systems programming.
>>>
>>> I need to do this quite a lot. Try talking to Win32, for example, and dare
>>> to so in a language which is not MS C or C++, or even not C at all, then
>>> you need to go into to excruciating detail to get the various structs and so
>>> on exactly compatible.
>>
>> Win32 defines a set of types, like BYTE, DWORD, LPARAM etc. The only thing
>> you should do is define these types using the means the language offers.
>> You don't need to have these types built-in.
>
> You need to find out what those types actually mean. Usually the API will
> not tell you.

Ah, but they do:

http://msdn.microsoft.com/en-us/library/windows/desktop/aa383751%28v=vs.85%29.aspx

>> BTW, speaking of representation constraints, it is not only memory unit
>> size (not all machines have byte as the memory unit), it is endianness and
>> complement.
>
> Those are issues I've never really had to deal with.

You must if you deal with any I/O, which is a big part of systems
programming. I must deal with endianness daily, since much of hardware we
are talking with is big-endian. Intel is little-endian.

> I'm not trying to create the perfect language here. (And AFAIK, C doesn't
> concern itself with endian-ness either.)

C does not concern itself with pretty much anything. It is one of languages
designed ad-hoc. Guys had a free machine in their hands and nothing to
do... I envy them.

>> As it does not make sense for numeric types in general.
>
> Yes it does.

Again, complex numbers *are* numbers.

>>> But as this is about alternatives to C's list of limit macros, then it
>>> doesn't mention any limits for Complex. While for floating point, 'min is be
>>> the lowest non-zero value that can be represented, while 'max is be the
>>> highest before it overflows to Inf (some 1e-308 to 1e+308 for 64-bits.)
>>
>> According to which definition?
>
> According to 'DBL_MAX' and similar macros in the C standard.

C standard might define "-" to be "+". There must be more serious reasons
why the upper bound of a real numeric type is to be defined this or other
way.

>> Or consider a
>> program that checks if X in T'Min..T'Max. Is it a tautology? Must it be
>> tautology for any ordered type? Is NaN ordered?
>
> If X is of type T, then perhaps that is not so useful. If not, then it could
> certainly be useful, because if X is in byte'range (a more compact way of
> writint it; 0..255 in other words), then it can be written to a file using
> one byte.

The question was, if X in T'Min..T'Max is a tautology then the check can be
optimised away. If not, it cannot be. Let you implement binary search, you
can do it in a certain way when the above holds [the search invariant is
that the root is within the interval]. If not, then you must change the
code.

> Or in a compiler, if X in int32'range then that constant can be assigned
> type int32. Etc.

It was not about type conversions, as I have explained.

>>> Anything else wouldn't be that useful.
>
>> Prove that.
>
> You need to define what 'useful' might be.

No, *you* need to define it. I am trying to avoid arguing to usefulness,
and am aiming much lower, at merely correctness. Once the language is
correct (more or less), one can progress to its usefulness.

Yes, you could say that C is useful, though incorrect. But you didn't.
(:-))

BartC

unread,
May 1, 2014, 12:04:22 PM5/1/14
to
"Dmitry A. Kazakov" <mai...@dmitry-kazakov.de> wrote in message
news:yryqqrizlv6f$.brqhfwfl79vg.dlg@40tude.net...
> On Thu, 1 May 2014 15:12:34 +0100, BartC wrote:

>> That machines generally work in powers-of-two bitwidths is well-known.
>
> And those that don't, you program in another language... Right?

Yes, exactly. C# supports 8, 16, 32 and (I assume) 64-bit data types, and so
does Java. The sensibly decided not to try and support every conceivable
computing platform, past and future, and up with a language that would tie
itself up in knots.

> What should be the properties of this, another, clearly better language,
> since it can be used for programming any machine?
>
>>>> (And I've tried using ranges to specify a width, but it doesn't really
>>>> work
>>>> for me. Besides, does the range 10'000 .. 10'100 need 16 bits, or 8?)
>>>
>>> Why not 7 bits? It can be 32 bits on a DSP. Why should the programmer
>>> care? I he cares he should spell his care in the language as a
>>> representation
>>> constraint.
>>
>> Because 7-bits isn't a likely memory-width size.
>
> 1-bit of Boolean isn't either. So what?

OK, if we extend it a little to include sub-byte types, then in the sequence
1, 2, 4, 8, 16, 32, 64 bits, 8 or 16 are still the best choices.

(The int:N syntax does, nevertheless, let you write int:7 if you want.
Although I reject that at the moment since I don't support odd sizes. Not as
a type anyway; it is possible to work with such such bit-fields though.)

>> (If someone needs to buy stationery, they might specify A5 or A4 or A3.
>> Those are the standard choices (in the EU).
>
> It does not mean you could not write a poem on a piece of letter paper
> size.

>>> Win32 defines a set of types, like BYTE, DWORD, LPARAM etc. The only
>>> thing
>>> you should do is define these types using the means the language offers.
>>> You don't need to have these types built-in.
>>
>> You need to find out what those types actually mean. Usually the API will
>> not tell you.
>
> Ah, but they do:
>
> http://msdn.microsoft.com/en-us/library/windows/desktop/aa383751%28v=vs.85%29.aspx

Thanks. When I first delved into this, I didn't have the internet. But
notice that the sizes, when given, are in terms of bits, and whether signed
or unsigned. It would be simplest if the language to be used for interfacing
to it could also define its own types the same way. In the language /you're/
proposing, it would be difficult.

>>> As it does not make sense for numeric types in general.
>>
>> Yes it does.
>
> Again, complex numbers *are* numbers.

Most people who are not mathematicians would disagree (actually most people
would not know what a complex number is).

If you want to make 'max meaningful for complex, then fine; let's say that
Complex'max just returns the same scalar value as Real'max (assuming the
former is composed of two Reals), otherwise just apply 'max on each
component.

(BTW what /is/ the largest value that can be represented in IEEE 754 64-bit
floating point, which is not Inf?)

--
Bartc

Kaz Kylheku

unread,
May 1, 2014, 2:26:14 PM5/1/14
to
On 2014-05-01, Dmitry A. Kazakov <mai...@dmitry-kazakov.de> wrote:
> On Thu, 1 May 2014 15:12:34 +0100, BartC wrote:
>
>> "Dmitry A. Kazakov" <mai...@dmitry-kazakov.de> wrote in message
>> news:i8gmjwf2beyz.12f8p3m5cxcnh$.dlg@40tude.net...
>>> On Thu, 1 May 2014 11:02:17 +0100, BartC wrote:
>>
>>>> At the level we're talking about, generally we know the hardware can deal
>>>> with integer values that are 8, 16, 32 or 64 bits wide, and floating point
>>>> values that are 32 or 64 bits. (There might be a few extra odd ones such
>>>> as 80-bit floats, or software-supported 128-bit ints.)
>>>>
>>>> One way of choosing whether to use 8, 16, 32 or 64 bits for a storage
>>>> type (for storing data in memory), is to actually specify 8, 16, 32, or [64]
>>>> bits! It can't get any simpler.
>>>
>>> What do you do when there is no given machine type? Let you compile for
>>> 32-bit i686. There is no 64-bit integer. Wait, there is but you need
>>> special instructions. It is not the way to deal with this. You don't make
>>> the language semantics dependent on the target machine.
>>
>> That machines generally work in powers-of-two bitwidths is well-known.
>
> And those that don't, you program in another language... Right?

Anyway, C doesn't specify bitwidths that are powers of two. In fact,
it originally ran on some machines that had 18 bit ints.

C specifies minimum sizes for certain types. The CHAR_BIT preprocessor constant
gives how many bits are in a signed or unsigned char (and therefore byte).
It is at least eight but doesn't have to be. Example: IBM mainframes
with 9 bit bytes, and 36 bit words.

Since C99, C also has some exact width types in popular power-of-two-bits sizes
like int32_t, declared as a typedef in a header. Since this might not be
available, there is a way to test for it at preprocessing time.

C code that needs, say, 32 bit two's complement arithmetic, and run on any
machine, just needs to use an unsigned type which is at least 32 bits wide,
mask down results to fall into that range, and interpret bit 31 as a sign bit.

In C, you can easily write, say, an emulator for the Motorola 68000 that will
run anywhere there is an ISO conforming compiler which can accept a program
that large, targetting a machine with enough resources to run it.

Kaz Kylheku

unread,
May 1, 2014, 2:30:17 PM5/1/14
to
On 2014-05-01, BartC <b...@freeuk.com> wrote:
> "Dmitry A. Kazakov" <mai...@dmitry-kazakov.de> wrote in message
> news:yryqqrizlv6f$.brqhfwfl79vg.dlg@40tude.net...
>> On Thu, 1 May 2014 15:12:34 +0100, BartC wrote:
>
>>> That machines generally work in powers-of-two bitwidths is well-known.
>>
>> And those that don't, you program in another language... Right?
>
> Yes, exactly. C# supports 8, 16, 32 and (I assume) 64-bit data types, and so
> does Java.

These languages support *only* these types.

"All the world is VAX (or x86 or SPARC)."

> The sensibly decided not to try and support every conceivable
> computing platform, past and future, and up with a language that would tie
> itself up in knots.

C doesn't tie itself in knots; it is able to conform to the types provided
by the hardware, for the best efficiency.

On a 36 bit machine, a Java compiler has to generate wasteful instructions to
reduce intermediate numeric results to 32 bits in cases where it's not
necessary, and also denies the programmer the use of those four bits.

BartC

unread,
May 1, 2014, 3:16:41 PM5/1/14
to
"Andy Walker" <ne...@cuboid.co.uk> wrote in message
news:JZo8v.62500$FD6....@fx10.fr7...
> On 01/05/14 00:35, James Harris wrote:
>> "BartC" <b...@freeuk.com> wrote in message

>>> Syntax is free!
>> Syntax is free [...].
>
> No it isn't. It's very cheap in compilation time, but that is
> very cheap anyway these days. It's not free in complexity of manuals
> or syntax charts or however else people get used to your language, and

Control statements are usually a tiny part of any language reference. (In a
C# book I have, 'for' takes up one page out of 200. In a Lua reference,
'for' is one screen out of about 100.)

But define your general 'for' statement like this example:

for var := expr to expr by expr while expr do .... end

And make it possible to leave parts out, then you get at least four loop
statements in one: for, to, do, and while.

Anyway additional statements, that do not need to be part of the core
language, can be in an appendix. When someone has become familiar with the
language, then they can understand more easily these extra features without
needing detailed explanations.

> it's not free in design time if people have to deliberate [eg, in C]
> over the choice between "for", "while" and "do" -- *especially* if [as
> in C] the choice is not that important.

I think more time can be spent in figuring out how to express their
requirements when the only constructs available are lacking (breaking out of
a two-level loop for example), or in simply typing (and sorting out typos)
when there is a lot of fiddly, unnecessary syntax:

for (i=0; i<M; ++i)
for (j=0; i<N; ++i)
....

The above is an interesting example; I had intended to leave in one typo
(the last 'i'), to show a typical problem, but eventually realised there
were two! Neither would occur with a statement that only requires a loop
variable to be written once. And sometimes a loop variable can be dispensed
with altogether, if it is not needed (eg. to M do ... ).

So throwing in extra syntax of the right kind, can increase productivity
(and improve readability).

(I know you can go too far if the syntax gets too 'cute', or puts too much
emphasis on compactness (Ruby for example), so it is necessary to be
restrained.)

--
Bartc

Dmitry A. Kazakov

unread,
May 1, 2014, 4:00:44 PM5/1/14
to
On Thu, 1 May 2014 17:04:22 +0100, BartC wrote:

> "Dmitry A. Kazakov" <mai...@dmitry-kazakov.de> wrote in message
> news:yryqqrizlv6f$.brqhfwfl79vg.dlg@40tude.net...
>> On Thu, 1 May 2014 15:12:34 +0100, BartC wrote:
>
>>> Because 7-bits isn't a likely memory-width size.
>>
>> 1-bit of Boolean isn't either. So what?
>
> OK, if we extend it a little to include sub-byte types, then in the sequence
> 1, 2, 4, 8, 16, 32, 64 bits, 8 or 16 are still the best choices.

No, they are not. Bit size is pretty much irrelevant for wast majority of
programming problems.

In the cases where memory layout is relevant (e.g. I/O), bit size is not
sufficient.

>>> You need to find out what those types actually mean. Usually the API will
>>> not tell you.
>>
>> Ah, but they do:
>>
>> http://msdn.microsoft.com/en-us/library/windows/desktop/aa383751%28v=vs.85%29.aspx
>
> Thanks. When I first delved into this, I didn't have the internet. But
> notice that the sizes, when given, are in terms of bits, and whether signed
> or unsigned. It would be simplest if the language to be used for interfacing
> to it could also define its own types the same way. In the language /you're/
> proposing, it would be difficult.

Why should it be difficult? I didn't say that memory layout should not be
controllable in some cases. But defining types in terms of layout is
rubbish.

You must *always* specify the type in terms of the semantics of its values,
e.g. range, if we consider ranged integer types.

You may add representation constraints to the above, if and only if
necessary, which is well beyond under 1% of all cases.

>>>> As it does not make sense for numeric types in general.
>>>
>>> Yes it does.
>>
>> Again, complex numbers *are* numbers.
>
> Most people who are not mathematicians would disagree (actually most people
> would not know what a complex number is).

In that case they don't know what number is, and should probably avoid
using numbers.

> (BTW what /is/ the largest value that can be represented in IEEE 754 64-bit
> floating point, which is not Inf?)

The largest value is ( 2 - 1 / 2**52 ) * 2**1023

Rod Pemberton

unread,
May 1, 2014, 4:08:03 PM5/1/14
to
On Thu, 01 May 2014 04:26:11 -0400, BartC <b...@freeuk.com> wrote:
> "Rod Pemberton" <dont_us...@xnothavet.cqm> wrote in message
> news:op.xe5porqb6zenlw@localhost...
>> On Wed, 30 Apr 2014 07:16:19 -0400, BartC <b...@freeuk.com> wrote:

>>> [intN_t etc]
>>
>> How often do you use those?
>
> It's common to use some of those at some time or other, if not all at
> the same time. You've never used CHARBIT

Um, I can say I generally never use them, and probably never. I can't
say with 100% certainty that I've never, ever used them. I'd need to
search my code which I have no desire to do. It's possible I used them
long ago or in special, rare situations.

Mostly, I use a subset of ANSI C. So, they're not a part of that subset,
but sometimes I do use other C features, library calls, and include
files, although I use those other things very rarely.

> or needed an exact 32-bit signed int?

Until recently, I've almost never used signed, unsigned only. I've been
working on getting comfortable without 'unsigned' and dropping some of
the "unecessary" or "useless" 'unsigned' keywords with simple things
like 'int' returns or 'char'.

I do have one program that I'm aware of that uses signed. It needed
to keep a value which could go positive or negative. That can be done
with unsigned, but requires more work. Also, I needed to display the
sign, and detecting negative values makes that easier. So, I went
ahead and used signed for it. I'm probably used signed decades ago
when I was first learning C. Of course, I don't change other people's
code to use unsigned.

So, I use 'unsigned long' for 32-bits. Fortunately, on x86, the compilers
I'm using use 32-bits for it, short 16, char 8. If 'unsigned long' is
64-bits on some/all 64-bit compilers and 'unsigned long long' is 128-bits,
that could break some of my code, but probably not. If 'unsigned long
long'
is 64-bits on most 64-bit compilers, I'm probably good. That would likely
mean 'unsigned long' is 32, short 16, char 8, as I prefer. I.e.,each a
progressively larger multiple by 2 starting at 8.

I generally try to keep to ANSI C, so the C99 'uint' extensions aren't
formally available. GCC generally allows but warns. E.g., I sometimes
use 'long long' C99 sprintf() format specifiers in ANSI C code (-ansi)
with GCC. Other compilers will fail that.


Rod Pemberton

Rod Pemberton

unread,
May 1, 2014, 4:08:34 PM5/1/14
to
On Thu, 01 May 2014 14:30:17 -0400, Kaz Kylheku <k...@kylheku.com> wrote:
> On 2014-05-01, BartC <b...@freeuk.com> wrote:
>> "Dmitry A. Kazakov" <mai...@dmitry-kazakov.de> wrote in message
>> news:yryqqrizlv6f$.brqhfwfl79vg.dlg@40tude.net...
>>> On Thu, 1 May 2014 15:12:34 +0100, BartC wrote:

>>>> That machines generally work in powers-of-two bitwidths is well-known.
>>>
>>> And those that don't, you program in another language... Right?
>>
>> Yes, exactly. C# supports 8, 16, 32 and (I assume) 64-bit data types,
>> and so> does Java.
>
> These languages support *only* these types.
>

By "these languages", I'm assuming you mean C/C++ and derivatives.

If so, you've been doing pretty good with your understanding of C,
but not on that one. C doesn't define a byte as 8-bits as defined
by the creators of EBCDIC and ASCII: Bob Bemer and Hugh McGregor Ross,
and Dr. Werner Buchholtz who defined a byte as 8-bits. It defines
a byte as the natural word size or minimal address unit of the machine
or somesuch. I'm not going to re-read the specifications on this.
E.g., most microprocessors have an 8-bit word size or address unit.
So, for those machines, a byte and a char are 8-bits. They also
typically have an integer that is an even multiple of 8-bits, e.g,
16-bits, 32-bits, etc. But, if we have a central processing unit
(cpu) with a 16-bit minimum address unit, then a C byte is 16-bits,
so is C's nul '\0' terminator. It must have all 16-bits cleared.
This is to locate the end-of-string quickly without having to mask
or unpack characters. This is documented in one of Ritchie's papers.
However, a char on such a machine could be 8-bits, for two char's
per C byte, or it could be 9-bits etc with only one char per C byte.


Rod Pemberton

Rod Pemberton

unread,
May 1, 2014, 4:08:47 PM5/1/14
to
On Thu, 01 May 2014 14:26:14 -0400, Kaz Kylheku <k...@kylheku.com> wrote:

> C specifies minimum sizes for certain types. The CHAR_BIT preprocessor
> constant gives how many bits are in a signed or unsigned char (and
> therefore byte). It is at least eight but doesn't have to be. Example:
> IBM mainframes with 9 bit bytes, and 36 bit words.

Upon first read, I took the "doesn't have to be" to mean it could be
7-bits or 6-bits etc. C would work with that. However, the C
specifications
requires 8-bits or more. So, to be clear:

s/doesn't have to be/or more/

I.e., one of those can mean above or below, while the other is above only.

;-)


Rod Pemberton

Ian Collins

unread,
May 1, 2014, 4:30:49 PM5/1/14
to
Rod Pemberton wrote:
> On Thu, 01 May 2014 14:30:17 -0400, Kaz Kylheku <k...@kylheku.com> wrote:
>> On 2014-05-01, BartC <b...@freeuk.com> wrote:
>>> "Dmitry A. Kazakov" <mai...@dmitry-kazakov.de> wrote in message
>>> news:yryqqrizlv6f$.brqhfwfl79vg.dlg@40tude.net...
>>>> On Thu, 1 May 2014 15:12:34 +0100, BartC wrote:
>
>>>>> That machines generally work in powers-of-two bitwidths is well-known.
>>>>
>>>> And those that don't, you program in another language... Right?
>>>
>>> Yes, exactly. C# supports 8, 16, 32 and (I assume) 64-bit data types,
>>> and so> does Java.
>>
>> These languages support *only* these types.
>>
>
> By "these languages", I'm assuming you mean C/C++ and derivatives.

Your understanding is arse about face.

--
Ian Collins

BartC

unread,
May 1, 2014, 6:24:26 PM5/1/14
to
"Dmitry A. Kazakov" <mai...@dmitry-kazakov.de> wrote in message
news:1tzmth5camkrp.dc82q58olxqa$.dlg@40tude.net...
> On Thu, 1 May 2014 17:04:22 +0100, BartC wrote:
>
>> "Dmitry A. Kazakov" <mai...@dmitry-kazakov.de> wrote in message
>> news:yryqqrizlv6f$.brqhfwfl79vg.dlg@40tude.net...
>>> On Thu, 1 May 2014 15:12:34 +0100, BartC wrote:
>>
>>>> Because 7-bits isn't a likely memory-width size.
>>>
>>> 1-bit of Boolean isn't either. So what?
>>
>> OK, if we extend it a little to include sub-byte types, then in the
>> sequence
>> 1, 2, 4, 8, 16, 32, 64 bits, 8 or 16 are still the best choices.
>
> No, they are not. Bit size is pretty much irrelevant for wast majority of
> programming problems.

Bit size is everywhere. Even OSes are marketed as 16-, 32- and 64-bit. IP
addresses are 32 or 128 bits. Processors are generally 8 to 64 bits. Unix
date stamps are 64-bits. Pointers are 32 or 64 bits. UTF-8/16/32 use
8/16/32-bit strings. Files sizes will be 32 or 64 bits. Audio quality is 8
or 16 bits. Digital video is 8-bits per channel.

So everyone is aware of this stuff, even the general public, yet you seem
insistent on keeping programmers away from knowing all these technical
details?

>> Thanks. When I first delved into this, I didn't have the internet. But
>> notice that the sizes, when given, are in terms of bits, and whether
>> signed
>> or unsigned. It would be simplest if the language to be used for
>> interfacing
>> to it could also define its own types the same way. In the language
>> /you're/
>> proposing, it would be difficult.
>
> Why should it be difficult? I didn't say that memory layout should not be
> controllable in some cases. But defining types in terms of layout is
> rubbish.
>
> You must *always* specify the type in terms of the semantics of its
> values,
> e.g. range, if we consider ranged integer types.

OK so, you have that 16-bit WORD type (unsigned not signed as I'd thought).
You need it in the middle of a struct so it's got to be the right width.
Have would *you* define such a type, in whatever language idiom you like?
(But using a range restraint such as 0 to 65535 might not work, as this is
not guaranteed to be 16-bits, nor offset as you'd expect.)

>> (BTW what /is/ the largest value that can be represented in IEEE 754
>> 64-bit
>> floating point, which is not Inf?)
>
> The largest value is ( 2 - 1 / 2**52 ) * 2**1023

So just shy of 2**1024. And around 1.7e308, pretty much what C's DBL_MAX is
reported as on my x86 machine, and what my 'real.max' will tell me.

Why were you saying, if I understood you correctly, that this is
meaningless? With regard to complex types, then each component would have
the same limit.

--
Bartc

Kaz Kylheku

unread,
May 1, 2014, 10:49:05 PM5/1/14
to
On 2014-05-01, Rod Pemberton <dont_us...@xnothavet.cqm> wrote:
> On Thu, 01 May 2014 14:26:14 -0400, Kaz Kylheku <k...@kylheku.com> wrote:
>
>> C specifies minimum sizes for certain types. The CHAR_BIT preprocessor
>> constant gives how many bits are in a signed or unsigned char (and
>> therefore byte). It is at least eight but doesn't have to be. Example:
>> IBM mainframes with 9 bit bytes, and 36 bit words.
>
> Upon first read, I took the "doesn't have to be" to mean it could be
> 7-bits or 6-bits etc. C would work with that. However, the C
> specifications
> requires 8-bits or more. So, to be clear:
>
> s/doesn't have to be/or more/

A C dialect could have 7 bit bytes; it just wouldn't be conforming to ISO C.

Some programs would work, some wouldn't.

Dmitry A. Kazakov

unread,
May 2, 2014, 2:59:13 AM5/2/14
to
On Thu, 1 May 2014 23:24:26 +0100, BartC wrote:

> "Dmitry A. Kazakov" <mai...@dmitry-kazakov.de> wrote in message
> news:1tzmth5camkrp.dc82q58olxqa$.dlg@40tude.net...
>> On Thu, 1 May 2014 17:04:22 +0100, BartC wrote:
>>
>>> "Dmitry A. Kazakov" <mai...@dmitry-kazakov.de> wrote in message
>>> news:yryqqrizlv6f$.brqhfwfl79vg.dlg@40tude.net...
>>>> On Thu, 1 May 2014 15:12:34 +0100, BartC wrote:
>>>
>>>>> Because 7-bits isn't a likely memory-width size.
>>>>
>>>> 1-bit of Boolean isn't either. So what?
>>>
>>> OK, if we extend it a little to include sub-byte types, then in the
>>> sequence 1, 2, 4, 8, 16, 32, 64 bits, 8 or 16 are still the best choices.
>>
>> No, they are not. Bit size is pretty much irrelevant for wast majority of
>> programming problems.
>
> Bit size is everywhere.
[...]
> So everyone is aware of this stuff, even the general public, yet you seem
> insistent on keeping programmers away from knowing all these technical
> details?

Knowing? I had an impression that you wanted making programmers *dependent*
on these irrelevant details. Why should my program be *semantically* (sic!)
dependent on the width of the memory bus?

>>> Thanks. When I first delved into this, I didn't have the internet. But
>>> notice that the sizes, when given, are in terms of bits, and whether signed
>>> or unsigned. It would be simplest if the language to be used for interfacing
>>> to it could also define its own types the same way. In the language /you're/
>>> proposing, it would be difficult.
>>
>> Why should it be difficult? I didn't say that memory layout should not be
>> controllable in some cases. But defining types in terms of layout is
>> rubbish.
>>
>> You must *always* specify the type in terms of the semantics of its values,
>> e.g. range, if we consider ranged integer types.
>
> OK so, you have that 16-bit WORD type (unsigned not signed as I'd thought).
> You need it in the middle of a struct so it's got to be the right width.
> Have would *you* define such a type, in whatever language idiom you like?

WORD is a modular type of 2**16 modulo. How the compiler represents it, I
don't care 99% of the time, if there is no requirement regarding this.

> (But using a range restraint such as 0 to 65535 might not work, as this is
> not guaranteed to be 16-bits, nor offset as you'd expect.)

Of course it does. Here is an example in Ada, which deals with these issues
right:

type WORD is mod 2**16;

This defines type semantics, most people stop here.

But for Windows API, specifically, add:

for WORD'Size use 16;

This does not change the type semantics, it puts a *representation*
constraint on its implementation. This also makes the program non-portable
for the machines where this constraint cannot be satisfied. Such machines
exist, e.g. DSP where memory unit size is 32. But I don't care here,
because there is no Windows on DSP.

Note, a fundamental language design principle:

Separation of implementation and interface, representation and semantics

>>> (BTW what /is/ the largest value that can be represented in IEEE 754
>>> 64-bit floating point, which is not Inf?)
>>
>> The largest value is ( 2 - 1 / 2**52 ) * 2**1023
>
> So just shy of 2**1024. And around 1.7e308, pretty much what C's DBL_MAX is
> reported as on my x86 machine, and what my 'real.max' will tell me.
>
> Why were you saying, if I understood you correctly, that this is
> meaningless?

I didn't say it is. I said it is ambiguous. When you clarified, that you
wanted a number of the following properties:

1. Real number (+Inf is not a real number)
2. Maximal number (there is no maximal real number)
3. Representable number (which makes 2 working, because IEEE double
precision values set is finite)

then I gave you the answer.

Now, forget all this, and imagine a programmer reading F'Max in the
program. How does he know is it 1+2+3 or only 2+3?

> With regard to complex types, then each component would have
> the same limit.

Huh, let it be polar Complex numbers: (r, f) = r * exp (j * Pi * f). There
is no limit of f in the sense r had.

BartC

unread,
May 2, 2014, 4:53:20 AM5/2/14
to
"Dmitry A. Kazakov" <mai...@dmitry-kazakov.de> wrote in message
news:1gmyk53pswewo$.1b5zpy5w0ksc4$.dlg@40tude.net...
> On Thu, 1 May 2014 23:24:26 +0100, BartC wrote:

>> OK so, you have that 16-bit WORD type (unsigned not signed as I'd
>> thought).
>> You need it in the middle of a struct so it's got to be the right width.
>> Have would *you* define such a type, in whatever language idiom you like?
>
> WORD is a modular type of 2**16 modulo. How the compiler represents it, I
> don't care 99% of the time, if there is no requirement regarding this.
>
>> (But using a range restraint such as 0 to 65535 might not work, as this
>> is
>> not guaranteed to be 16-bits, nor offset as you'd expect.)
>
> Of course it does. Here is an example in Ada, which deals with these
> issues
> right:
>
> type WORD is mod 2**16;
>
> This defines type semantics, most people stop here.
>
> But for Windows API, specifically, add:
>
> for WORD'Size use 16;
>
> This does not change the type semantics, it puts a *representation*
> constraint on its implementation. This also makes the program non-portable
> for the machines where this constraint cannot be satisfied. Such machines
> exist, e.g. DSP where memory unit size is 32. But I don't care here,
> because there is no Windows on DSP.

OK so in the end, it ends up specifying the same thing: unsigned (mod),
width 16 ('Size 16). In addition you have the ability to specify 'mod'
behaviour independently of what happens naturally in the hardware (so long
as 'Size is sufficient); in this case you've made them equivalent.

I just don't have the luxury (in the kind of C-class language I'm talking
about) of having a totally separate type model from that I would generally
expect to be provided in the hardware. At least not for primitive numeric
types. I start off with the expected set of hardware-provided numeric types,
perhaps extend them in either direction a little (shorter and longer) and
use largely the behaviours they are already expected to have, again extended
a little.

Maybe in another language I can do that (actually I do have a higher level
language, a dynamic one, but that just concerns itself a lot less with such
matters (unless it has to talk to Win32 again...); it's not interested in
having a type-system which can define different classes of numeric types. In
fact it deliberately prohibits defining new numeric types for the sake of
simplicity.)

All it comes down to, is some of us choose not to program in Ada. (It's a
good thing that some people do, to end up with robust, safe software which
necessarily has had a lot of thought go into it, but some people want to be
able to program more informally and with smaller, simpler tools.)

Also some of us are not mathematicians. (Clearly you would prefer that only
mathematicians ought to be allowed to program.)

--
Bartc

Dmitry A. Kazakov

unread,
May 2, 2014, 5:22:09 AM5/2/14
to
Yup, this is what we wanted it to be.

> In addition you have the ability to specify 'mod'
> behaviour independently of what happens naturally in the hardware (so long
> as 'Size is sufficient); in this case you've made them equivalent.

No, I first specify mod (type semantics), and, then, very, extremely
rarely, constrain the Size of its instances.

> I start off with the expected set of hardware-provided numeric types,
> perhaps extend them in either direction a little (shorter and longer) and
> use largely the behaviours they are already expected to have, again extended
> a little.

And the point was that this was a language design fault.

BTW, C tried to avoid this by introducing types blind types int, char, etc.
This by no means was a cure, because it replaced arbitrary semantics of
INTEGER*4 (in FORTRAN-IV) with ill-defined one of int.

I don't know what is worse, programming in terms of machine-specific types
or in terms of ill-defined types. Both is wrong.

> All it comes down to, is some of us choose not to program in Ada.

No. It is about language design principles.

> Also some of us are not mathematicians. (Clearly you would prefer that only
> mathematicians ought to be allowed to program.)

Not at all. On the contrary, it is a mystery to me why people who are
trying to bend virtually everything into a number, at the same time don't
want to know what numbers are.

If you don't want only mathematicians programming your language, then give
people something beyond numbers. But you say who needs a type system,
user-defined abstract types? Everything is a number...

James Harris

unread,
May 2, 2014, 6:11:27 AM5/2/14
to
"BartC" <b...@freeuk.com> wrote in message
news:Nsq8v.316223$%n2.1...@fx30.am4...
If "to" always meant "upto" and there was a separate "downto" the direction
issue is resolved. Of course, the word "to" doesn't sound like it is always
ascending and IIRC a Basic allowed "to" to step downwards as in

for P = 10 to 1 step -1

But if "to" can mean either direction depending on the use of "by" that
sounds a little complicated!

>> When the step is a signed variable or an expression that could be
>> positive
>> or negative and when the semantics of the language state that the sign of
>> the step controls the direction of iteration how can the compiler
>> generate
>> code for the loop termination test? It needs to know the direction so
>> that
>> it knows whether to code the loop test as, say, <= or >=.
>
> This is easy. You just don't worry about it. Or prohibit it when the
> compiler can't figure out what to do.

Umm, not sure about that. Consider

S = function_call();
for P = Q to R step S;

Can the compiler figure out what to do? Probably not. Now compare that with

S = -1;
for P = Q to R step S;

Can the compiler figure out here what to do? Probably yes but only if it
does data flow analysis. Yet the statement in question is the same in each
case. I think your idea of defining the direction by a keyword is *much*
better than stating that the step controls the direction.

>> Alternatively if the language design is that the direction of the loop is
>> to be controlled by the relative values of A and B rather than the step
>> the compiler still has the same problem. It doesn't know whether X should
>> ascend or descend and, hence, it doesn't know whether to go on while X <=
>> B or to go on while X >= B. Poor compiler! I think it would have no
>> choice
>> but to write code for both tests and select between them at run time. Am
>> I
>> wrong?
>
> (Have you ever looked at the code you've written, and counted how many
> times
> you've used 'for', and what proportion use simple +1 or -1 iteration, and
> what proportion used anything more complex?

Sorry, I cannot say I have. So ... I have pulled out the following from the
only significant piece of C I have worked on recently.

$ cat sformat.c | grep "^ *for"
for (; padding_reqd-- > 0;) *p++ = pad_char;
for (i = 0; i < qspaces; i++) *dest++ = ' ';
for (i = 0; i < qzeroes; i++) *dest++ = '0';
for (i = 0; i < qdigits; i++) *dest++ = *p++;
for (i = 0; i < qspaces; i++) *dest++ = ' ';
for (i = 0; i < qzeroes; i++) *dest++ = '0';
for (i = 0; i < qdigits; i++) *dest++ = *p++;
for (i = 0; i < qspaces; i++) *dest++ = ' ';
for (i = 0; i < qzeroes; i++) *dest++ = '0';
for (i = 0; i < qdigits; i++) *dest++ = *p++;
for (; (ch = *f++);)
for (more = 1; more;)
for (;;)
for (;;)
for (more = 1; more;)

You can see a mixture in there. Some use your standard up paramaters, one
counts down, one loops until it reaches a zero byte, two use a "more" flag
and two others simply loop.

If you wanted to see a 90+% run of standard up or down parameters I bet you
are disappointed! ;-) In reality this is just a sample piece of code and is
not meant to be typical. I might use the standard up or down loops a lot
more overall. The above forms just suited the code I was writing at the
time.

As programmers we get in to the mindset of writing code in a certain way and
tend to adapt the problem to the way our minds work. You maybe use the form
you do so much because you have become accustomed to thinking in that way.
Similarly, I expect I use C's for mechanism in the way I do because I have
got used to that approach.

We started this subthread because you expressed surprise that few languages
had added anything simpler to C's for loop. I have tried to explain why I
think that C's approach is so good that it doesn't need the addition you
would like, and why that addition can bring with it a lot of unwanted
baggage.

My own loop preference is not C's but I still think C's form brilliantly
simplifies some of these long-standing issues. Because of that and because
it subsumes the type you prefer I am not surprised that other langages have
copied C and not added another form.

> You might be overestimating the number of times you need a more complex
> loop.)

When programming in C I don't think of the C for loop as being complex; it
seems quite natural to use.

In Python, however, I often write things like

for record in records:

...

Thanks for your comments on my nextof call (snipped).

James


BartC

unread,
May 2, 2014, 8:32:27 AM5/2/14
to
"James Harris" <james.h...@gmail.com> wrote in message
news:ljvr0j$cgl$1...@dont-email.me...
> "BartC" <b...@freeuk.com> wrote in message

>>I use:
>>
>> for i:=A to B do Step +1
>> for i:=A downto B do Step -1
>> for i:=A to B by C do
>> for i:=A downto B by C do
>>
>> With the 'by' forms expecting C to be a constant (either positive or
>> negative; it will make 'to' into 'downto' as needed). (If not, it is
>> assumed
>> to be positive or negative respectively).
>>
>> (BTW the 'downto' method is from Pascal, which I thought was a good
>> simplification in forcing a loop direction to be known at compile-time.)
>
> If "to" always meant "upto" and there was a separate "downto" the
> direction issue is resolved. Of course, the word "to" doesn't sound like
> it is always ascending and IIRC a Basic allowed "to" to step downwards as
> in
>
> for P = 10 to 1 step -1
>
> But if "to" can mean either direction depending on the use of "by" that
> sounds a little complicated!

Lua just uses "," in place of "to". In that sense, "," defines both
directions, but needs an explicit -1 step for a downward loop. So the idea
was that "to" could be used in the same way, if the user wants to:

for i:=a to b by 1
for i:=a to b by -1

The "downto" form is an easy and obvious alternative to the -1 step, however
an explicit step size here is more ambiguous:

for i:=a downto b by 1
for i:=a downto b by -1

Do these both count downwards? Perhaps the compiler apply -abs() to the step
which is added to at each iteration.

>> This is easy. You just don't worry about it. Or prohibit it when the
>> compiler can't figure out what to do.
>
> Umm, not sure about that. Consider
>
> S = function_call();
> for P = Q to R step S;
>
> Can the compiler figure out what to do? Probably not. Now compare that
> with
>
> S = -1;
> for P = Q to R step S;
>
> Can the compiler figure out here what to do?

But what about:

for P = Q to R step function_call();

Here the loop could be oscillating backwards and forwards! The sensible
thing here is calculate the step only at the start then have it invariant
(if it isn't already so).

A loop which is always counts up or down, but which it is is not known until
runtime, a compiler can just about deal with (but will be inefficient as
this check needs to be done per iteration, unless you duplicate the loop
body). One that constantly change direction would be too messy though, and
too odd for a compiler to spend too much time supporting.

My decision (and Pascal's) is that a loop direction must be determinable at
compile time.
But in this sample:

* There are 15 for-loops, as written
* 2 of those are infinite loops, which I wouldn't have written as for (but
as do .... end)
* 4 of them look like they'd be happier as while-loops

That leaves 9, all of which appear to be simple iterations (all upwards and
with a step of 1). They are also all 0 to N-1 loops, however .... done of
those appear to use the loop index, socould have been written as 1..N, or
even with loop index at all, as what I call 'to' loops.

So this is inconclusive, except to show that you like using for(a;b;c) loops
for all sorts of purposes other than actual iteration! So more sample data
is needed.

However, this is what the 15 loops look when rewritten using what I consider
the most apt loop statement (I appreciate that C will not have the 'do' and
'to' forms unless you create a macro version). (I've taken the liberty of
switching syntax):

while padding_reqd-- >0 do ...
to qspaces do dest++^:=' ' end
to qzeroes do ...
to qdigits do ...
to qspaces do ...
to qzeroes do ...
to qdigits do ...
to qspaces do ...
to qzeroes do ...
to qdigits do ...
while (ch:=f++^) do ...
more:=1; while more do ...
do ...
do ...
more:=1; while more do ...

> We started this subthread because you expressed surprise that few
> languages had added anything simpler to C's for loop. I have tried to
> explain why I think that C's approach is so good that it doesn't need the
> addition you would like, and why that addition can bring with it a lot of
> unwanted baggage.

Well, OK. I think (for most of the above examples) having to introduce a
variable i, initialise it, increment it, and compare it to N, is also quite
a bit of baggage compared with just writing N!

--
Bartc

James Harris

unread,
May 2, 2014, 11:42:10 AM5/2/14
to
"BartC" <b...@freeuk.com> wrote in message
news:EfM8v.147725$vM2....@fx18.am4...
> "James Harris" <james.h...@gmail.com> wrote in message
> news:ljvr0j$cgl$1...@dont-email.me...
>> "BartC" <b...@freeuk.com> wrote in message
>
>>>I use:
>>>
>>> for i:=A to B do Step +1
>>> for i:=A downto B do Step -1
>>> for i:=A to B by C do
>>> for i:=A downto B by C do
>>>
>>> With the 'by' forms expecting C to be a constant (either positive or
>>> negative; it will make 'to' into 'downto' as needed). (If not, it is
>>> assumed
>>> to be positive or negative respectively).

I've just read that again and it still seems complicated. Have I got the
following right?

for i := A to B by C do (i.e. using *to*)
- if C is a constant and positive the loop will count up
- if C is a constant and negative the loop will count down
- if C is a variable the loop will count up

for i := A downto B by C do (i.e. using *downto*)
- if C is a constant and positive the loop will count down (?)
- if C is a constant and negative the loop will count down
- if C is a variable the loop will count down

>>> (BTW the 'downto' method is from Pascal, which I thought was a good
>>> simplification in forcing a loop direction to be known at compile-time.)
>>
>> If "to" always meant "upto" and there was a separate "downto" the
>> direction issue is resolved. Of course, the word "to" doesn't sound like
>> it is always ascending and IIRC a Basic allowed "to" to step downwards as
>> in
>>
>> for P = 10 to 1 step -1
>>
>> But if "to" can mean either direction depending on the use of "by" that
>> sounds a little complicated!
>
> Lua just uses "," in place of "to". In that sense, "," defines both
> directions, but needs an explicit -1 step for a downward loop. So the idea
> was that "to" could be used in the same way, if the user wants to:
>
> for i:=a to b by 1
> for i:=a to b by -1
>
> The "downto" form is an easy and obvious alternative to the -1 step,
> however
> an explicit step size here is more ambiguous:
>
> for i:=a downto b by 1
> for i:=a downto b by -1
>
> Do these both count downwards? Perhaps the compiler apply -abs() to the
> step
> which is added to at each iteration.

I'm not sure if you are saying your favoured loop works that way or not but
none of those issues need to arise. With C the questions don't need to be
asked. Nor do the answers need to be remembered.

>>> This is easy. You just don't worry about it. Or prohibit it when the
>>> compiler can't figure out what to do.
>>
>> Umm, not sure about that. Consider
>>
>> S = function_call();
>> for P = Q to R step S;
>>
>> Can the compiler figure out what to do? Probably not. Now compare that
>> with
>>
>> S = -1;
>> for P = Q to R step S;
>>
>> Can the compiler figure out here what to do?
>
> But what about:
>
> for P = Q to R step function_call();
>
> Here the loop could be oscillating backwards and forwards! The sensible
> thing here is calculate the step only at the start then have it invariant
> (if it isn't already so).

That depends on whether the step is resolved once before the loop starts or
at the beginning of each iteration. And it is not apparent from the syntax
(as discussed in previous posts).

> A loop which is always counts up or down, but which it is is not known
> until
> runtime, a compiler can just about deal with (but will be inefficient as
> this check needs to be done per iteration, unless you duplicate the loop
> body). One that constantly change direction would be too messy though, and
> too odd for a compiler to spend too much time supporting.
>
> My decision (and Pascal's) is that a loop direction must be determinable
> at
> compile time.

Going a bit off topic here but if you want to use that loop form why not
just have upto and downto keywords? Then the loop direction is always
immediately clear.

...

>> If you wanted to see a 90+% run of standard up or down parameters I bet
>> you are disappointed! ;-) In reality this is just a sample piece of code
>> and is not meant to be typical.
>
> But in this sample:

I did say this was not representative so you should not read too much in to
it. But I can see from your reply that you think of these loops as different
sorts. That's your preference.

My own language goes even further than C and reduces down to one loop type.
After all a loop is a loop. You would love it. ;-)

...

>> We started this subthread because you expressed surprise that few
>> languages had added anything simpler to C's for loop. I have tried to
>> explain why I think that C's approach is so good that it doesn't need the
>> addition you would like, and why that addition can bring with it a lot of
>> unwanted baggage.
>
> Well, OK. I think (for most of the above examples) having to introduce a
> variable i, initialise it, increment it, and compare it to N, is also
> quite a bit of baggage compared with just writing N!

By baggage I meant the issues and questions that are associated with those
kinds of loops but are not apparent in the syntax, i.e. all the questions we
have discussed and for which there is no universally accepted model so that
different languages use different choices.

Having said that, I should add that I could work with a language which had a
simplified X to Y loop - as long as I could remember the answers to all the
questions, that is. ;-)

James


BartC

unread,
May 2, 2014, 12:54:14 PM5/2/14
to
"James Harris" <james.h...@gmail.com> wrote in message
news:lk0ecl$ihg$1...@dont-email.me...

>>>> for i:=A to B do Step +1
>>>> for i:=A downto B do Step -1
>>>> for i:=A to B by C do
>>>> for i:=A downto B by C do
>>>>
>>>> With the 'by' forms expecting C to be a constant (either positive or
>>>> negative; it will make 'to' into 'downto' as needed). (If not, it is
>>>> assumed
>>>> to be positive or negative respectively).
>
> I've just read that again and it still seems complicated. Have I got the
> following right?

You're right, it's too complicated! It shouldn't be necessary to think twice
about a construction like this.

(TBH I haven't used 'for' with 'by' or 'step' yet; I'm not even sure if I've
implemented it!)

So I will revise those forms of the statements to be:

for i:=a to b by c do # always counts upwards
for i:=a downto b by c do # always counts downwards

With perhaps abs() applied to c by the compiler to ensure the right
behaviour with downto.

> I'm not sure if you are saying your favoured loop works that way or not
> but none of those issues need to arise. With C the questions don't need to
> be asked. Nor do the answers need to be remembered.

There are some ambiguities with the C construct too (I think someone already
pointed this out):

for (i=a; i>=b; i-=c;) ....

This works as expected only when c is positive. (Or c is negative and you do
i+=c.)

(But my problem with it isn't so much that, it's this; when I first typed
this example, I mistyped it as 'for (i=a; i>=b; ++c)'. It's a lot easier to
write nonsense, but still have a legal program that gets past the compiler.)

> My own language goes even further than C and reduces down to one loop
> type. After all a loop is a loop. You would love it. ;-)

Maybe C's 'for' should have been named 'loop' since it's more general.

--
Bartc

George Neuner

unread,
May 3, 2014, 1:29:10 AM5/3/14
to
On Fri, 02 May 2014 08:30:49 +1200, Ian Collins <ian-...@hotmail.com>
wrote:
Rod is correct that C defines 'byte' as a minimal addressable unit and
defines characters as data which fits into a byte. Packing multiple
characters into a single 'byte' is non-compliant - but that doesn't
stop compilers for (wide-byte) word oriented machines [typically DSPs]
from doing so.


From the C99 standard:

3.6
byte
addressable unit of data storage large enough to hold any member of
the basic character set of the execution environment
NOTE 1 It is possible to express the address of each individual
byte of an object uniquely.
NOTE 2 A byte is composed of a contiguous sequence of bits, the
number of which is implementation-defined. The least
significant bit is called the low-order bit; the most
significant bit is called the high-order bit.

3.7
character
< abstract > member of a set of elements used for the
organization, control, or representation of data

3.7.1
character
single-byte character
< C > bit representation that fits in a byte


See also: 5.2.1 - Character sets [too long to copy]

See also: 5.2.4.2.1 Sizes of integer types <limits.h>

— number of bits for smallest object that is not a bit-field (byte)
CHAR_BIT >= 8 [per 5.2.1]


The language in the C89/90 standard is not as clear, but the semantics
it describes are equivalent to above. Unfortunately I don't have my
copy of C89/90 handy to provide exact cites.

George

Rod Pemberton

unread,
May 3, 2014, 2:37:54 AM5/3/14
to
On Sat, 03 May 2014 01:29:10 -0400, George Neuner <gneu...@comcast.net>
wrote:
> On Fri, 02 May 2014 08:30:49 +1200, Ian Collins <ian-...@hotmail.com>
> wrote:
>> Rod Pemberton wrote:
>>> On Thu, 01 May 2014 14:30:17 -0400, Kaz Kylheku <k...@kylheku.com>
>>> wrote:
>>>> On 2014-05-01, BartC <b...@freeuk.com> wrote:
>>>>> "Dmitry A. Kazakov" <mai...@dmitry-kazakov.de> wrote in message
>>>>> news:yryqqrizlv6f$.brqhfwfl79vg.dlg@40tude.net...
>>>>>> On Thu, 1 May 2014 15:12:34 +0100, BartC wrote:

>>>>>>> That machines generally work in powers-of-two bitwidths is
>>>>>>> well-known.
>>>>>>
>>>>>> And those that don't, you program in another language... Right?
>>>>>
>>>>> Yes, exactly. C# supports 8, 16, 32 and (I assume) 64-bit data types,
>>>>> and so does Java.
>>>>
>>>> These languages support *only* these types.
>>>
>>> By "these languages", I'm assuming you mean C/C++ and derivatives.
>>
>> Your understanding is arse about face.
>
> Rod is correct that C defines 'byte' as a minimal addressable unit and
> defines characters as data which fits into a byte.

Oh, I thought Ian was saying I made the wrong assumption on which
languages were being discussed. I thought C, C++, and variations
were under discussion. So, I was going to go back and check what
languages were being discussed, but didn't.

Before that, I thought Kaz was saying C didn't support sizes other
than 8, 16, 32, 64, which it can. Standardized microprocessor
architecture is what lends itself to 8-bits and multiples.
Central processing units (cpu), used on mainframes and such,
had widely varying architectures, some of which had C on them.


Rod Pemberton

George Neuner

unread,
May 3, 2014, 3:39:17 PM5/3/14
to
On Sat, 03 May 2014 02:37:54 -0400, "Rod Pemberton"
<dont_us...@xnothavet.cqm> wrote:

>On Sat, 03 May 2014 01:29:10 -0400, George Neuner <gneu...@comcast.net>
>wrote:
>>
>> Rod is correct that C defines 'byte' as a minimal addressable unit and
>> defines characters as data which fits into a byte.
>
>Oh, I thought Ian was saying I made the wrong assumption on which
>languages were being discussed. I thought C, C++, and variations
>were under discussion. So, I was going to go back and check what
>languages were being discussed, but didn't.
>
>Before that, I thought Kaz was saying C didn't support sizes other
>than 8, 16, 32, 64, which it can. Standardized microprocessor
>architecture is what lends itself to 8-bits and multiples.

I haven't seen the whole thread, but ISTM Kaz [will correct me I'm
sure] is arguing that C doesn't have mechanism to semantically define
new numeric types (or subtypes), so programmers are de facto
constrained to those types that C provides.

Which is true with the minor exception that you can abuse bitfields to
create a restricted width integer. It doesn't buy you very much
because bitfields are restricted to register width [or less!] and the
result still is just a C integer with the same semantics only having a
smaller +/- range and maybe slower access.

E.g., there is no way to define your new integer type to have
different semantics such as arbitrary range, or a range with gaps, or
saturation vs wrap-around arithmetic, or overflow signaling, etc.


>Central processing units (cpu), used on mainframes and such,
>had widely varying architectures, some of which had C on them.

Yes, though many of them predate C standardization. Most of the early
machines would not be standard compliant due to restricted (6 or 7
bit) character sets and/or lack of individual character addressing.

The issue was not the size of their memory 'word', but if multiple
characters packed into a word could be individually addressed. On
most mainframes that was not true - packed characters had to be
loaded/stored together and instructions manipulating them in a
register had to specify which character(s) to change by field selector
or mask. [This still is true of many DSPs today.]

Recall that the C standard didn't emerge until 1989 [for ANSI, ISO
ratified a year later] and so it was colored more by exposure to
hardware of the late 70's and 80's than by anything that came before.
CPU design already had settled on power of 2 widths and the standard
effectively was software rubber stamping hardware.

George

Rod Pemberton

unread,
May 3, 2014, 5:30:07 PM5/3/14
to
On Sat, 03 May 2014 15:39:17 -0400, George Neuner <gneu...@comcast.net>
wrote:
> On Sat, 03 May 2014 02:37:54 -0400, "Rod Pemberton"
> <dont_us...@xnothavet.cqm> wrote:
>> On Sat, 03 May 2014 01:29:10 -0400, George Neuner <gneu...@comcast.net>
>> wrote:

>>> Rod is correct that C defines 'byte' as a minimal addressable unit and
>>> defines characters as data which fits into a byte.
>>
>> Oh, I thought Ian was saying I made the wrong assumption on which
>> languages were being discussed. I thought C, C++, and variations
>> were under discussion. So, I was going to go back and check what
>> languages were being discussed, but didn't.
>>
>> Before that, I thought Kaz was saying C didn't support sizes other
>> than 8, 16, 32, 64, which it can. Standardized microprocessor
>> architecture is what lends itself to 8-bits and multiples.
>
> I haven't seen the whole thread, but ISTM Kaz [will correct me I'm
> sure] is arguing that C doesn't have mechanism to semantically define
> new numeric types (or subtypes), so programmers are de facto
> constrained to those types that C provides.
>

True.

Oh, wow, okay, maybe *I* should re-read the entire thread ... ;-)

> Which is true with the minor exception that you can abuse bitfields to
> create a restricted width integer. It doesn't buy you very much
> because bitfields are restricted to register width [or less!] and the
> result still is just a C integer with the same semantics only having a
> smaller +/- range and maybe slower access.

Yeah, I always thought the problem was that C doesn't have a carry
flag even though most microprocessors do. In assembly, you can use
the carry flag to construct larger integers from smaller ones. In C,
the code to do that is a bit of a mess.

> E.g., there is no way to define your new integer type to have
> different semantics such as arbitrary range, or a range with gaps, or
> saturation vs wrap-around arithmetic, or overflow signaling, etc.

True.

You're limited to what C provides, or whatever you can concoct.
There is no formal method to extend the language proper.


Rod Pemberton

Ian Collins

unread,
May 4, 2014, 4:05:11 AM5/4/14
to
George Neuner wrote:
> On Fri, 02 May 2014 08:30:49 +1200, Ian Collins <ian-...@hotmail.com>
> wrote:
>
>> Rod Pemberton wrote:
>>> On Thu, 01 May 2014 14:30:17 -0400, Kaz Kylheku <k...@kylheku.com> wrote:
>>>> On 2014-05-01, BartC <b...@freeuk.com> wrote:
>>>>> "Dmitry A. Kazakov" <mai...@dmitry-kazakov.de> wrote in message
>>>>> news:yryqqrizlv6f$.brqhfwfl79vg.dlg@40tude.net...
>>>>>> On Thu, 1 May 2014 15:12:34 +0100, BartC wrote:
>>>
>>>>>>> That machines generally work in powers-of-two bitwidths is well-known.
>>>>>>
>>>>>> And those that don't, you program in another language... Right?
>>>>>
>>>>> Yes, exactly. C# supports 8, 16, 32 and (I assume) 64-bit data types,
>>>>> and so> does Java.
>>>>
>>>> These languages support *only* these types.
>>>>
>>>
>>> By "these languages", I'm assuming you mean C/C++ and derivatives.
>>
>> Your understanding is arse about face.
>
> Rod is correct ...

I was referring to the By "these languages" in reply to "C# supports 8,
16, 32 and (I assume) 64-bit data types, and so does Java.".

--
Ian Collins

George Neuner

unread,
May 4, 2014, 1:28:39 PM5/4/14
to
On Sun, 04 May 2014 20:05:11 +1200, Ian Collins <ian-...@hotmail.com>
Regardless, you could have said it more nicely. ;-)


Both C# and Java are C derived [at least in part], their numerics have
*similar* semantics to C numerics, and they share C's inability to
define new numeric types/subtypes with differing behavior.

IMO the respective numeric behaviors of C, C++, C# and Java all can
legitimately be lumped together under the heading "C-like". YMMV.

Before you respond, let me say that defining a new object that
encapsulates and manipulates a value is not the same as defining a new
type of value. It is ad hoc, error prone and, because none of these
languages [that phrase again 8-)] define their numeric tower in terms
of objects, correct substitution use of your new "type" can't be
verified in all situations.

George

Ian Collins

unread,
May 4, 2014, 3:40:16 PM5/4/14
to
George Neuner wrote:
> On Sun, 04 May 2014 20:05:11 +1200, Ian Collins <ian-...@hotmail.com>
> wrote:
>
>> George Neuner wrote:
>>> On Fri, 02 May 2014 08:30:49 +1200, Ian Collins <ian-...@hotmail.com>
>>> wrote:
>>>
>>>> Rod Pemberton wrote:
>>>>> On Thu, 01 May 2014 14:30:17 -0400, Kaz Kylheku <k...@kylheku.com> wrote:
>>>>>> On 2014-05-01, BartC <b...@freeuk.com> wrote:
>>>>>>> "Dmitry A. Kazakov" <mai...@dmitry-kazakov.de> wrote in message
>>>>>>> news:yryqqrizlv6f$.brqhfwfl79vg.dlg@40tude.net...
>>>>>>>> On Thu, 1 May 2014 15:12:34 +0100, BartC wrote:
>>>>>
>>>>>>>>> That machines generally work in powers-of-two bitwidths is well-known.
>>>>>>>>
>>>>>>>> And those that don't, you program in another language... Right?
>>>>>>>
>>>>>>> Yes, exactly. C# supports 8, 16, 32 and (I assume) 64-bit data types,
>>>>>>> and so> does Java.
>>>>>>
>>>>>> These languages support *only* these types.
>>>>>>
>>>>>
>>>>> By "these languages", I'm assuming you mean C/C++ and derivatives.
>>>>
>>>> Your understanding is arse about face.
>>>
>>> Rod is correct ...
>>
>> I was referring to the By "these languages" in reply to "C# supports 8,
>> 16, 32 and (I assume) 64-bit data types, and so does Java.".
>
> Regardless, you could have said it more nicely. ;-)

Where I come from, my reply would have been considered polite!

> Both C# and Java are C derived [at least in part], their numerics have
> *similar* semantics to C numerics, and they share C's inability to
> define new numeric types/subtypes with differing behavior.
>
> IMO the respective numeric behaviors of C, C++, C# and Java all can
> legitimately be lumped together under the heading "C-like". YMMV.
>
> Before you respond, let me say that defining a new object that
> encapsulates and manipulates a value is not the same as defining a new
> type of value. It is ad hoc, error prone and, because none of these
> languages [that phrase again 8-)] define their numeric tower in terms
> of objects, correct substitution use of your new "type" can't be
> verified in all situations.

I wouldn't lump C++ in with those (!) languages, given one of the
language design goals is to enable user defined objects to behave as a
built in type. The use of a class template for complex numbers is a
good example of this put to use.

--
Ian Collins

BartC

unread,
Jul 25, 2014, 6:53:52 PM7/25/14
to
"BartC" <b...@freeuk.com> wrote in message
news:3SQ7v.155346$AI5....@fx32.am4...

[List of things I didn't like about C]

> Well, I put together my list. About 115 things listed actually. Too long
> to
> show here so is at: http://pastebin.com/vUVpF1uA (will be edited later).

[Link now expired]

> I didn't specifically set out to find faults with C, but a lot of this is
> how I'm used to doing things, and wondered why C used its own unique
> approach.
>
> And as promised, little of this actually results in a particularly higher
> level language (no OOP, no templates, no dynamic datatypes, no exceptions,
> no threading, nothing about the runtime library (actually that can be item
> #
> 116...).) It just makes more sense.

I've been working on a development of my own static, compiled language
(mainly, trying to get it up to speed, but given up on that aspect).

I only really use it for a limited number of projects (mainly interpreters)
so have not attempted to create a complete, well-rounded language. Even so,
I've gone through my list, and over 75% of my points have been covered, or
do not apply to my language (the rest are largely to do with suggested types
or features that aren't in C either, but which are not worth adding as I'm
now unlikely to use them).

It wasn't very hard either. So, creating a viable, less annoying alternative
to C is quite possible! (And the problem with performance can be got around
by using existing, optimising compiler 'back-ends', although that is not my
style.)

--
Bartc

Rod Pemberton

unread,
Jul 26, 2014, 5:38:46 AM7/26/14
to
On Fri, 25 Jul 2014 18:53:52 -0400, BartC <b...@freeuk.com> wrote:

> I've been working on a development of my own static, compiled language

What do you mean by "static" in this case?
E.g., not a dynamically typed language?

> (mainly, trying to get it up to speed, but given up on that aspect).

All projects just get set aside for the future ...

> I only really use it for a limited number of projects (mainly
> interpreters) so have not attempted to create a complete,
> well-rounded language.

I think that's actually a very interesting point. :-)

If a language does what's needed of it, why must it
be complete, and well-rounded?

C functions superbly with numerous flaws and issues.
I.e., a language which is broken in some or many ways
may result in improved effective of the language.
Do you agree? Or, am I just being the Devil's advocate?

> It wasn't very hard either. So, creating a viable, less annoying
> alternative to C is quite possible!

I agree with:

1) viable
2) alternative to C
3) simple (unmentioned, perhaps not...)

... since I've done that for my own language. But, as for
"less annoying", I'm not sure about that one. Mine might
be more annoying ... ;-) It definately has issues that
need to be "pounded on" for a while. Simplicity of
implementation was a key detail. That may have resulted in
some annoyance.

> (And the problem with performance can be got around by
> using existing, optimising compiler 'back-ends', although that is not my
> style.)

Does this matter for a one off language?


Rod Pemberton
P.S. Posts I should to reply to here are piling up. Sorry guys.

BartC

unread,
Jul 26, 2014, 8:51:17 AM7/26/14
to
"Rod Pemberton" <dont_us...@xnothavet.cqm> wrote in message
news:op.xjlmewoe6zenlw@localhost...
> On Fri, 25 Jul 2014 18:53:52 -0400, BartC <b...@freeuk.com> wrote:
>
>> I've been working on a development of my own static, compiled language
>
> What do you mean by "static" in this case?
> E.g., not a dynamically typed language?

Yes, statically typed and compiled to native code, versus dynamically typed
and using interpreted byte-code (the two main language categories I'm
interested in).

>> I only really use it for a limited number of projects (mainly
>> interpreters) so have not attempted to create a complete,
>> well-rounded language.
>
> I think that's actually a very interesting point. :-)
>
> If a language does what's needed of it, why must it
> be complete, and well-rounded?

I'm being a little harsh on my own language; as it is, it can tackle most
things C can. But it doesn't quite meet my specification of what a C
replacement ought to be.

> C functions superbly with numerous flaws and issues.
> I.e., a language which is broken in some or many ways
> may result in improved effective of the language.
> Do you agree? Or, am I just being the Devil's advocate?

Sure, C works, but can be a bit of pain. But as an example I'm of what I on
about, see this link recently posted in comp.lang.c:

https://software.intel.com/sites/landingpage/IntrinsicsGuide/

(about ways to directly code SSE and other x86-specific stuff from C). Click
on any of the functions, and you will see the descriptions use an Algol-like
pseudo-code language, uncannily similar to mine, not a C-like syntax with
braces!

Pseudo-code often uses syntax like this, because it's clearer and not
cluttered with irrelevant details. So why don't actual languages uses
similar syntax? Well, mine do! C syntax is the main thing I have against the
language; it's also the easiest to do something about.

>> It wasn't very hard either. So, creating a viable, less annoying
>> alternative to C is quite possible!
>
> I agree with:
>
> 1) viable
> 2) alternative to C
> 3) simple (unmentioned, perhaps not...)
>
> ... since I've done that for my own language. But, as for
> "less annoying", I'm not sure about that one. Mine might
> be more annoying ... ;-)

If that's the one that you posted examples of some time back, then I agree
it can be annoying!

>> (And the problem with performance can be got around by
>> using existing, optimising compiler 'back-ends', although that is not my
>> style.)
>
> Does this matter for a one off language?

In my case, because the main application is an interpreter, performance is
crucial. But not actually so critical that it's in the language because it's
easy to throw in some assembly code. Then outperforming even highly
optimised C is child's play.

Outside the main core, however, this is not practical to do everywhere so
any extra performance is always welcome.

--
Bartc

rick.c...@gmail.com

unread,
Oct 25, 2014, 7:48:27 AM10/25/14
to
On Saturday, July 26, 2014 8:51:17 AM UTC-4, Bart wrote:
> Sure, C works, but can be a bit of pain. But as an example I'm of what
> I on about, see this link recently posted in comp.lang.c:
>
> https://software.intel.com/sites/landingpage/IntrinsicsGuide/
>
> (about ways to directly code SSE and other x86-specific stuff from C). Click
> on any of the functions, and you will see the descriptions use an Algol-like
> pseudo-code language, uncannily similar to mine, not a C-like syntax with
> braces!
>
> Pseudo-code often uses syntax like this, because it's clearer and not
> cluttered with irrelevant details. So why don't actual languages uses
> similar syntax? Well, mine do! C syntax is the main thing I have against the
> language; it's also the easiest to do something about.

I intend on introducing types which relate 1:1 with their architectural
counterparts for items like mmxN, xmmN, and so on. They will be defined
primitives with built-in structural components, such as a packed _xmm0
type holding _xmm.f321, _xmm.f322..., and _xmm.f641, _xmm.f642, and so
on to access their f32 and f64 (float and double) sub-components, along
with integer portions.

These will be used in code as:

_xmm data1, data2, data3;
// Code goes here to manipulate them in C or assembly
printf("%f\n", _xmm.f322); // 2nd float in this structure

Intel shipped over 100M units per quarter for the first time in Q3 2014.
Other architectures share many of the same features (ARM, for example,
supports SIMD with similar bit sizes and patterns).

I think the language itself should support the hardware it resides upon,
making it a closely coupled construct at the C level. Above C you are
free to get into all manner of "grander" concepts, but I would even
argue at that point that such concepts should be then translated down
into C for easier debugging, which is translated down into assembly for
final debugging.

Ultimately a person should be able to write their software in comments.
Those comments translate into something like a flowchart. That
flowchart then translates into something like the actual code to conduct
the work. That code is at whatever level it's at, in whatever language
it's at, which is then translated down to C (a language designed to be
very close to hardware, yet expressible in human terms). And that C is
then translated down to assembly, which is translated into machine code.

An app can then be debugged at any one of those levels to find out the
underlying components which need to be fixed, and the fixes can occur
at any of those levels, all with full edit-and-continue abilities.

Prayerfully that is... :-)

Best regards,
Rick C. Hodgin

Rick C. Hodgin

unread,
Oct 25, 2014, 7:50:43 AM10/25/14
to
Should be:

_xmm data1, data2, data3;
// Code goes here to manipulate them in C or assembly
printf("%f\n", data1.f322); // 2nd float in this structure
0 new messages