Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.misc > #2067 > unrolled thread
| Started by | "BartC" <bc@freeuk.com> |
|---|---|
| First post | 2014-04-29 17:57 +0100 |
| Last post | 2014-10-25 04:50 -0700 |
| Articles | 20 on this page of 58 — 10 participants |
Back to article view | Back to comp.lang.misc
C: 100 Things "BartC" <bc@freeuk.com> - 2014-04-29 17:57 +0100
Re: 100 Things "James Harris" <james.harris.1@gmail.com> - 2014-04-30 07:40 +0100
Re: 100 Things "BartC" <bc@freeuk.com> - 2014-04-30 12:16 +0100
Re: 100 Things "James Harris" <james.harris.1@gmail.com> - 2014-04-30 13:54 +0100
Re: 100 Things "BartC" <bc@freeuk.com> - 2014-04-30 14:39 +0100
Re: 100 Things "James Harris" <james.harris.1@gmail.com> - 2014-04-30 20:18 +0100
Re: 100 Things "BartC" <bc@freeuk.com> - 2014-04-30 22:40 +0100
Re: 100 Things Kaz Kylheku <kaz@kylheku.com> - 2014-04-30 22:09 +0000
Re: 100 Things "BartC" <bc@freeuk.com> - 2014-04-30 23:36 +0100
Re: 100 Things Ian Collins <ian-news@hotmail.com> - 2014-05-01 11:03 +1200
Re: 100 Things "BartC" <bc@freeuk.com> - 2014-05-01 09:47 +0100
Re: 100 Things "James Harris" <james.harris.1@gmail.com> - 2014-05-01 00:35 +0100
Re: 100 Things Andy Walker <news@cuboid.co.uk> - 2014-05-01 11:03 +0100
Re: 100 Things "BartC" <bc@freeuk.com> - 2014-05-01 20:16 +0100
Re: 100 Things "BartC" <bc@freeuk.com> - 2014-05-01 12:44 +0100
Re: 100 Things "James Harris" <james.harris.1@gmail.com> - 2014-05-02 11:11 +0100
Re: 100 Things "BartC" <bc@freeuk.com> - 2014-05-02 13:32 +0100
Re: 100 Things "James Harris" <james.harris.1@gmail.com> - 2014-05-02 16:42 +0100
Re: 100 Things "BartC" <bc@freeuk.com> - 2014-05-02 17:54 +0100
Re: 100 Things Ian Collins <ian-news@hotmail.com> - 2014-05-01 11:01 +1200
Re: 100 Things "Rod Pemberton" <dont_use_email@xnothavet.cqm> - 2014-04-30 21:13 -0400
Re: 100 Things "BartC" <bc@freeuk.com> - 2014-05-01 09:26 +0100
Re: 100 Things "Rod Pemberton" <dont_use_email@xnothavet.cqm> - 2014-05-01 16:08 -0400
Re: 100 Things Ian Collins <ian-news@hotmail.com> - 2014-05-01 13:42 +1200
Re: 100 Things "BartC" <bc@freeuk.com> - 2014-05-01 09:35 +0100
Re: 100 Things Ian Collins <ian-news@hotmail.com> - 2014-05-01 21:02 +1200
Re: 100 Things "BartC" <bc@freeuk.com> - 2014-05-01 10:40 +0100
Re: 100 Things Ian Collins <ian-news@hotmail.com> - 2014-05-01 22:06 +1200
Re: 100 Things "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> - 2014-05-01 11:08 +0200
Re: 100 Things "BartC" <bc@freeuk.com> - 2014-05-01 11:02 +0100
Re: 100 Things "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> - 2014-05-01 13:57 +0200
Re: 100 Things "BartC" <bc@freeuk.com> - 2014-05-01 15:12 +0100
Re: 100 Things "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> - 2014-05-01 17:18 +0200
Re: 100 Things "BartC" <bc@freeuk.com> - 2014-05-01 17:04 +0100
Re: 100 Things Kaz Kylheku <kaz@kylheku.com> - 2014-05-01 18:30 +0000
Re: 100 Things "Rod Pemberton" <dont_use_email@xnothavet.cqm> - 2014-05-01 16:08 -0400
Re: 100 Things Ian Collins <ian-news@hotmail.com> - 2014-05-02 08:30 +1200
Re: 100 Things George Neuner <gneuner2@comcast.net> - 2014-05-03 01:29 -0400
Re: 100 Things "Rod Pemberton" <dont_use_email@xnothavet.cqm> - 2014-05-03 02:37 -0400
Re: 100 Things George Neuner <gneuner2@comcast.net> - 2014-05-03 15:39 -0400
Re: 100 Things "Rod Pemberton" <dont_use_email@xnothavet.cqm> - 2014-05-03 17:30 -0400
Re: 100 Things Ian Collins <ian-news@hotmail.com> - 2014-05-04 20:05 +1200
Re: 100 Things George Neuner <gneuner2@comcast.net> - 2014-05-04 13:28 -0400
Re: 100 Things Ian Collins <ian-news@hotmail.com> - 2014-05-05 07:40 +1200
Re: 100 Things "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> - 2014-05-01 22:00 +0200
Re: 100 Things "BartC" <bc@freeuk.com> - 2014-05-01 23:24 +0100
Re: 100 Things "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> - 2014-05-02 08:59 +0200
Re: 100 Things "BartC" <bc@freeuk.com> - 2014-05-02 09:53 +0100
Re: 100 Things "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> - 2014-05-02 11:22 +0200
Re: 100 Things Kaz Kylheku <kaz@kylheku.com> - 2014-05-01 18:26 +0000
Re: 100 Things "Rod Pemberton" <dont_use_email@xnothavet.cqm> - 2014-05-01 16:08 -0400
Re: 100 Things Kaz Kylheku <kaz@kylheku.com> - 2014-05-02 02:49 +0000
Re: C: 100 Things "Rod Pemberton" <dont_use_email@xnothavet.cqm> - 2014-04-30 22:08 -0400
Re: C: 100 Things "BartC" <bc@freeuk.com> - 2014-07-25 23:53 +0100
Re: C: 100 Things "Rod Pemberton" <dont_use_email@xnothavet.cqm> - 2014-07-26 05:38 -0400
Re: C: 100 Things "BartC" <bc@freeuk.com> - 2014-07-26 13:51 +0100
Re: C: 100 Things rick.c.hodgin@gmail.com - 2014-10-25 04:48 -0700
Re: C: 100 Things "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2014-10-25 04:50 -0700
Page 1 of 3 [1] 2 3 Next page →
| From | "BartC" <bc@freeuk.com> |
|---|---|
| Date | 2014-04-29 17:57 +0100 |
| Subject | C: 100 Things |
| Message-ID | <3SQ7v.155346$AI5.24849@fx32.am4> |
"BartC" <bc@freeuk.com> wrote in message news:94y7v.153301$AI5.43400@fx32.am4... > "Kaz Kylheku" <kaz@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" <bc@freeuk.com> wrote in message news:57B7v.161805$Qm2.151455@fx16.am4... > "James Harris" <james.harris.1@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
[toc] | [next] | [standalone]
| From | "James Harris" <james.harris.1@gmail.com> |
|---|---|
| Date | 2014-04-30 07:40 +0100 |
| Subject | Re: 100 Things |
| Message-ID | <ljq5sv$coh$1@dont-email.me> |
| In reply to | #2067 |
"BartC" <bc@freeuk.com> wrote in message news:3SQ7v.155346$AI5.24849@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
[toc] | [prev] | [next] | [standalone]
| From | "BartC" <bc@freeuk.com> |
|---|---|
| Date | 2014-04-30 12:16 +0100 |
| Subject | Re: 100 Things |
| Message-ID | <kY48v.181432$Ey6.180503@fx24.am4> |
| In reply to | #2071 |
"James Harris" <james.harris.1@gmail.com> wrote in message news:ljq5sv$coh$1@dont-email.me... > "BartC" <bc@freeuk.com> wrote in message > news:3SQ7v.155346$AI5.24849@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
[toc] | [prev] | [next] | [standalone]
| From | "James Harris" <james.harris.1@gmail.com> |
|---|---|
| Date | 2014-04-30 13:54 +0100 |
| Subject | Re: 100 Things |
| Message-ID | <ljqrp2$pli$1@dont-email.me> |
| In reply to | #2074 |
"BartC" <bc@freeuk.com> wrote in message news:kY48v.181432$Ey6.180503@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
[toc] | [prev] | [next] | [standalone]
| From | "BartC" <bc@freeuk.com> |
|---|---|
| Date | 2014-04-30 14:39 +0100 |
| Subject | Re: 100 Things |
| Message-ID | <K278v.218753$vB1.137675@fx36.am4> |
| In reply to | #2076 |
"James Harris" <james.harris.1@gmail.com> wrote in message news:ljqrp2$pli$1@dont-email.me... > "BartC" <bc@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
[toc] | [prev] | [next] | [standalone]
| From | "James Harris" <james.harris.1@gmail.com> |
|---|---|
| Date | 2014-04-30 20:18 +0100 |
| Subject | Re: 100 Things |
| Message-ID | <ljria6$8ka$1@dont-email.me> |
| In reply to | #2077 |
"BartC" <bc@freeuk.com> wrote in message news:K278v.218753$vB1.137675@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
[toc] | [prev] | [next] | [standalone]
| From | "BartC" <bc@freeuk.com> |
|---|---|
| Date | 2014-04-30 22:40 +0100 |
| Subject | Re: 100 Things |
| Message-ID | <85e8v.227832$gV7.159905@fx21.am4> |
| In reply to | #2081 |
"James Harris" <james.harris.1@gmail.com> wrote in message news:ljria6$8ka$1@dont-email.me... > "BartC" <bc@freeuk.com> wrote in message > news:K278v.218753$vB1.137675@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
[toc] | [prev] | [next] | [standalone]
| From | Kaz Kylheku <kaz@kylheku.com> |
|---|---|
| Date | 2014-04-30 22:09 +0000 |
| Subject | Re: 100 Things |
| Message-ID | <20140430150416.549@kylheku.com> |
| In reply to | #2082 |
On 2014-04-30, BartC <bc@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.
[toc] | [prev] | [next] | [standalone]
| From | "BartC" <bc@freeuk.com> |
|---|---|
| Date | 2014-04-30 23:36 +0100 |
| Subject | Re: 100 Things |
| Message-ID | <BWe8v.380788$H82.192335@fx23.am4> |
| In reply to | #2083 |
"Kaz Kylheku" <kaz@kylheku.com> wrote in message
news:20140430150416.549@kylheku.com...
> On 2014-04-30, BartC <bc@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.
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
[toc] | [prev] | [next] | [standalone]
| From | Ian Collins <ian-news@hotmail.com> |
|---|---|
| Date | 2014-05-01 11:03 +1200 |
| Subject | Re: 100 Things |
| Message-ID | <bsddq3Fd2otU2@mid.individual.net> |
| In reply to | #2084 |
BartC wrote: > "Kaz Kylheku" <kaz@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
[toc] | [prev] | [next] | [standalone]
| From | "BartC" <bc@freeuk.com> |
|---|---|
| Date | 2014-05-01 09:47 +0100 |
| Subject | Re: 100 Things |
| Message-ID | <hTn8v.204521$q95.152789@fx22.am4> |
| In reply to | #2086 |
"Ian Collins" <ian-news@hotmail.com> wrote in message news:bsddq3Fd2otU2@mid.individual.net... > BartC wrote: >> "Kaz Kylheku" <kaz@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. 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
[toc] | [prev] | [next] | [standalone]
| From | "James Harris" <james.harris.1@gmail.com> |
|---|---|
| Date | 2014-05-01 00:35 +0100 |
| Subject | Re: 100 Things |
| Message-ID | <ljs1cm$kig$1@dont-email.me> |
| In reply to | #2082 |
"BartC" <bc@freeuk.com> wrote in message
news:85e8v.227832$gV7.159905@fx21.am4...
>
>
> "James Harris" <james.harris.1@gmail.com> wrote in message
> news:ljria6$8ka$1@dont-email.me...
>> "BartC" <bc@freeuk.com> wrote in message
>> news:K278v.218753$vB1.137675@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?
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
[toc] | [prev] | [next] | [standalone]
| From | Andy Walker <news@cuboid.co.uk> |
|---|---|
| Date | 2014-05-01 11:03 +0100 |
| Subject | Re: 100 Things |
| Message-ID | <JZo8v.62500$FD6.39366@fx10.fr7> |
| In reply to | #2087 |
On 01/05/14 00:35, James Harris wrote:
> "BartC" <bc@freeuk.com> wrote in message
> news:85e8v.227832$gV7.159905@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.
[toc] | [prev] | [next] | [standalone]
| From | "BartC" <bc@freeuk.com> |
|---|---|
| Date | 2014-05-01 20:16 +0100 |
| Subject | Re: 100 Things |
| Message-ID | <z4x8v.236209$hB4.223271@fx20.am4> |
| In reply to | #2102 |
"Andy Walker" <news@cuboid.co.uk> wrote in message
news:JZo8v.62500$FD6.39366@fx10.fr7...
> On 01/05/14 00:35, James Harris wrote:
>> "BartC" <bc@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
[toc] | [prev] | [next] | [standalone]
| From | "BartC" <bc@freeuk.com> |
|---|---|
| Date | 2014-05-01 12:44 +0100 |
| Subject | Re: 100 Things |
| Message-ID | <Nsq8v.316223$%n2.142416@fx30.am4> |
| In reply to | #2087 |
"James Harris" <james.harris.1@gmail.com> wrote in message news:ljs1cm$kig$1@dont-email.me... > "BartC" <bc@freeuk.com> wrote in message > news:85e8v.227832$gV7.159905@fx21.am4... >> "James Harris" <james.harris.1@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
[toc] | [prev] | [next] | [standalone]
| From | "James Harris" <james.harris.1@gmail.com> |
|---|---|
| Date | 2014-05-02 11:11 +0100 |
| Subject | Re: 100 Things |
| Message-ID | <ljvr0j$cgl$1@dont-email.me> |
| In reply to | #2105 |
"BartC" <bc@freeuk.com> wrote in message
news:Nsq8v.316223$%n2.142416@fx30.am4...
> "James Harris" <james.harris.1@gmail.com> wrote in message
> news:ljs1cm$kig$1@dont-email.me...
>> "BartC" <bc@freeuk.com> wrote in message
>> news:85e8v.227832$gV7.159905@fx21.am4...
>>> "James Harris" <james.harris.1@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.)
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
[toc] | [prev] | [next] | [standalone]
| From | "BartC" <bc@freeuk.com> |
|---|---|
| Date | 2014-05-02 13:32 +0100 |
| Subject | Re: 100 Things |
| Message-ID | <EfM8v.147725$vM2.40475@fx18.am4> |
| In reply to | #2140 |
"James Harris" <james.harris.1@gmail.com> wrote in message news:ljvr0j$cgl$1@dont-email.me... > "BartC" <bc@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. >> (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. 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
[toc] | [prev] | [next] | [standalone]
| From | "James Harris" <james.harris.1@gmail.com> |
|---|---|
| Date | 2014-05-02 16:42 +0100 |
| Subject | Re: 100 Things |
| Message-ID | <lk0ecl$ihg$1@dont-email.me> |
| In reply to | #2142 |
"BartC" <bc@freeuk.com> wrote in message news:EfM8v.147725$vM2.40475@fx18.am4... > "James Harris" <james.harris.1@gmail.com> wrote in message > news:ljvr0j$cgl$1@dont-email.me... >> "BartC" <bc@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
[toc] | [prev] | [next] | [standalone]
| From | "BartC" <bc@freeuk.com> |
|---|---|
| Date | 2014-05-02 17:54 +0100 |
| Subject | Re: 100 Things |
| Message-ID | <%4Q8v.396809$H82.95203@fx23.am4> |
| In reply to | #2143 |
"James Harris" <james.harris.1@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
[toc] | [prev] | [next] | [standalone]
| From | Ian Collins <ian-news@hotmail.com> |
|---|---|
| Date | 2014-05-01 11:01 +1200 |
| Subject | Re: 100 Things |
| Message-ID | <bsddmvFd2otU1@mid.individual.net> |
| In reply to | #2077 |
BartC wrote: > "James Harris" <james.harris.1@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
[toc] | [prev] | [next] | [standalone]
Page 1 of 3 [1] 2 3 Next page →
Back to top | Article view | comp.lang.misc
csiph-web