Build:
$ cc /include=mysql055_root:[include.mysql] /names=as_is demo.c
$ link/share=demo_shr.exe demo + sys$input/opt mysql055_root:[lib.alpha]libclientlib/lib
mysql055_root:[lib.alpha]libsql/lib
mysql055_root:[lib.alpha]libmysys/lib
mysql055_root:[lib.alpha]libdbug/lib
mysql055_root:[lib.alpha]libstrings/lib
mysql055_root:[lib.alpha]libvio/lib
mysql055_root:[lib.alpha]libz/lib
mysql055_root:[lib.alpha]ssl_libssl32/lib mysql055_root:[lib.alpha]ssl_libcrypto32/lib
CASE_SENSITIVE=YES
SYMBOL_VECTOR=(demo_init=PROCEDURE, -
demo=PROCEDURE, -
demo_deinit=PROCEDURE)
$
mysql055_root:[lib.alpha]libclientlib/lib
mysql055_root:[lib.alpha]libsql/lib
mysql055_root:[lib.alpha]libmysys/lib
mysql055_root:[lib.alpha]libdbug/lib
mysql055_root:[lib.alpha]libstrings/lib
mysql055_root:[lib.alpha]libvio/lib
mysql055_root:[lib.alpha]libz/lib
mysql055_root:[lib.alpha]ssl_libssl32/lib mysql055_root:[lib.alpha]ssl_libcrypto32/lib
On Tue, 12 Aug 2025 19:08:51 -0400, Arne Vajhøj wrote:
mysql055_root:[lib.alpha]libclientlib/lib
mysql055_root:[lib.alpha]libsql/lib
mysql055_root:[lib.alpha]libmysys/lib
mysql055_root:[lib.alpha]libdbug/lib
mysql055_root:[lib.alpha]libstrings/lib
mysql055_root:[lib.alpha]libvio/lib
mysql055_root:[lib.alpha]libz/lib
mysql055_root:[lib.alpha]ssl_libssl32/lib
mysql055_root:[lib.alpha]ssl_libcrypto32/lib
Is there some equivalent to “-L«dir»” to add a common directory to a linker search path so you can just shorten most of that to something
more like “-lclientlib -lsql -lmysys -ldbug -lstrings -lvio -lz”?
On 8/12/2025 11:09 PM, Lawrence D'Oliveiro wrote:
Is there some equivalent to “-L«dir»” to add a common directory to a >> linker search path so you can just shorten most of that to something
more like “-lclientlib -lsql -lmysys -ldbug -lstrings -lvio -lz”?
VMS is not *nix.
Code:
#include <string.h>
#include <mysql.h>
my_bool demo_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
{
if(args->arg_count == 2 && args->arg_type[0] == STRING_RESULT && args->arg_type[1] == INT_RESULT)
{
return 0;
}
else
{
strcpy(message, "demo function requires two arguments: one
string and one integer");
return 1;
}
}
long long demo(UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned
long *length, unsigned char *is_null, unsigned char *error)
{
const char *sv = args->args[0];
long long iv = *((long long *)args->args[1]);
return strlen(sv) + iv;
}
void demo_deinit(UDF_INIT *initid)
{
}
Build:
$ cc /include=mysql055_root:[include.mysql] /names=as_is demo.c
$ link/share=demo_shr.exe demo + sys$input/opt mysql055_root:[lib.alpha]libclientlib/lib
mysql055_root:[lib.alpha]libsql/lib
mysql055_root:[lib.alpha]libmysys/lib
mysql055_root:[lib.alpha]libdbug/lib
mysql055_root:[lib.alpha]libstrings/lib
mysql055_root:[lib.alpha]libvio/lib
mysql055_root:[lib.alpha]libz/lib
mysql055_root:[lib.alpha]ssl_libssl32/lib mysql055_root:[lib.alpha]ssl_libcrypto32/lib
CASE_SENSITIVE=YES
SYMBOL_VECTOR=(demo_init=PROCEDURE, -
demo=PROCEDURE, -
demo_deinit=PROCEDURE)
$
Install (DCL):
$ copy/log demo_shr.exe mysql055_root:[plugin.alpha]*.*
$ def/sys demo_shr "''f$parse("mysql055_root:[plugin.alpha]demo_shr.exe",,,,"NO_CONCEAL")'"
Install (SQL):
CREATE FUNCTION demo
RETURNS INTEGER
SONAME 'demo_shr';
Demo:
MariaDB [test]> select demo('ABC', 1);
+----------------+
| demo('ABC', 1) |
+----------------+
| 4 |
+----------------+
1 row in set (0.01 sec)
MariaDB [test]> select demo('ABCD', 1);
+-----------------+
| demo('ABCD', 1) |
+-----------------+
| 5 |
+-----------------+
1 row in set (0.00 sec)
MariaDB [test]> select demo('ABC', 2);
+----------------+
| demo('ABC', 2) |
+----------------+
| 5 |
+----------------+
1 row in set (0.00 sec)
MariaDB [test]> SELECT demo();
ERROR 1123 (HY000): Can't initialize function 'demo'; demo function
requires two arguments: one string and one integer
MariaDB [test]> SELECT demo('ABC');
ERROR 1123 (HY000): Can't initialize function 'demo'; demo function
requires two arguments: one string and one integer
MariaDB [test]> SELECT demo('ABC', 'DEF');
ERROR 1123 (HY000): Can't initialize function 'demo'; demo function
requires two arguments: one string and one integer
MariaDB [test]> SELECT demo('ABC', 1, 1);
ERROR 1123 (HY000): Can't initialize function 'demo'; demo function
requires two arguments: one string and one integer
Arne
On 2025-08-12, Arne Vajhøj <[email protected]> wrote:
Code:
#include <string.h>
#include <mysql.h>
my_bool demo_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
{
if(args->arg_count == 2 && args->arg_type[0] == STRING_RESULT &&
args->arg_type[1] == INT_RESULT)
Is it guaranteed that arg_type[] will always have at least elements ?
If not, that's dangerous unless the compiler you are using does
expression short-circuiting.
{
return 0;
}
else
{
strcpy(message, "demo function requires two arguments: one
string and one integer");
return 1;
YUCK!!! :-) Does MySQL provide a maximum error message size field or
constant that you can use with strncpy() instead ?
On 8/15/2025 8:27 AM, Simon Clubley wrote:
On 2025-08-12, Arne Vajhøj <[email protected]> wrote:
Code:
#include <string.h>
#include <mysql.h>
my_bool demo_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
{
if(args->arg_count == 2 && args->arg_type[0] == STRING_RESULT && >>> args->arg_type[1] == INT_RESULT)
Is it guaranteed that arg_type[] will always have at least elements ?
If not, that's dangerous unless the compiler you are using does
expression short-circuiting.
Isn't C required to do short circuiting on && ?
{
return 0;
}
else
{
strcpy(message, "demo function requires two arguments: one
string and one integer");
return 1;
YUCK!!! :-) Does MySQL provide a maximum error message size field or
constant that you can use with strncpy() instead ?
Not that I am aware of.
No such used in the example provided by MySQL/Oracle.
Arne
On 2025-08-12, Arne Vajh�j <[email protected]> wrote:
Code:
#include <string.h>
#include <mysql.h>
my_bool demo_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
{
if(args->arg_count == 2 && args->arg_type[0] == STRING_RESULT &&
args->arg_type[1] == INT_RESULT)
Is it guaranteed that arg_type[] will always have at least elements ?
If not, that's dangerous unless the compiler you are using does
expression short-circuiting.
{
return 0;
}
else
{
strcpy(message, "demo function requires two arguments: one
string and one integer");
return 1;
YUCK!!! :-) Does MySQL provide a maximum error message size field or
constant that you can use with strncpy() instead ?
On 8/15/2025 9:35 AM, Arne Vajhøj wrote:^not> an AND_THEN and OR_ELSE operator much like you find
On 8/15/2025 8:27 AM, Simon Clubley wrote:
On 2025-08-12, Arne Vajhøj <[email protected]> wrote:
Code:
#include <string.h>
#include <mysql.h>
my_bool demo_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
{
if(args->arg_count == 2 && args->arg_type[0] == STRING_RESULT &&
args->arg_type[1] == INT_RESULT)
Is it guaranteed that arg_type[] will always have at least elements ?
If not, that's dangerous unless the compiler you are using does
expression short-circuiting.
Isn't C required to do short circuiting on && ?
Yes, C and C++ short-circuits. Other languages may not. For example, Pascal does promise short-circuit which is why our Pascal also provides
On 15/08/2025 18:33, Simon Clubley wrote:
strncpy() makes more sense when you realise that its original purpose
was to fill fixed-size fields in a record with data and to clear the
rest of the field if the source data was smaller than the field size.
BTW, after using strncpy(), my code always unconditionally places
a 0x00 in the final byte of the buffer "just in case :-)".
That wouldn't be good if you are filling part of a record!
In article <107n93n$13rjm$[email protected]>,
Simon Clubley <clubley@remove_me.eisner.decus.org-Earth.UFP> wrote:
On 2025-08-12, Arne Vajh�j <[email protected]> wrote:
Code:
#include <string.h>
#include <mysql.h>
my_bool demo_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
{
if(args->arg_count == 2 && args->arg_type[0] == STRING_RESULT &&
args->arg_type[1] == INT_RESULT)
Is it guaranteed that arg_type[] will always have at least elements ?
If not, that's dangerous unless the compiler you are using does
expression short-circuiting.
C is well-defined in this regard. Boolean expressions in C,
created by combining logical subexpressions with the `&&` and
`||` operators, are documented to use short-circuiting behavior.
However, I must disagree strongly with the advice to use
`strncpy`, which is poorly understood and has strange semantics:
it will write as much of the source string to the destination as
it can, with or without the NUL terminating byte. If the source
is smaller than the destination buffer, then the remainder of
the buffer will be filled with 0s. If the source is exactly as
long as, or longer, than the destination, then the destination
will not be NUL-terminated. Since it just returns the
destination pointer, there is no way to detect truncation other
than to test the last byte in the destination to see whether it
is zero or not. So it is inefficent in the common case, and
dangerous and awkward in the exceptional case. Moreover, its
behavior is orthogonal to that of `strncat`, which does _not_
have the "write 0s to all bytes in the destination past the end
of the what we copied from the source string", and is also
awkward in how it treats it's length argument: whereas for
`strncpy` the length argument is the size of the entire
destination buffer, for `strncat` it is not: `strncat` will
write up to n+1 bytes into the destination.
On 2025-08-15, Dan Cross <[email protected]> wrote:
In article <107n93n$13rjm$[email protected]>,
Simon Clubley <clubley@remove_me.eisner.decus.org-Earth.UFP> wrote:
On 2025-08-12, Arne Vajhøj <[email protected]> wrote:
Code:
#include <string.h>
#include <mysql.h>
my_bool demo_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
{
if(args->arg_count == 2 && args->arg_type[0] == STRING_RESULT && >>>> args->arg_type[1] == INT_RESULT)
Is it guaranteed that arg_type[] will always have at least elements ?
If not, that's dangerous unless the compiler you are using does
expression short-circuiting.
C is well-defined in this regard. Boolean expressions in C,
created by combining logical subexpressions with the `&&` and
`||` operators, are documented to use short-circuiting behavior.
Thank you.
Unless it's explicit in the language syntax itself, and given that
I write code in multiple languages, I have long written code that
assumes implicit[*] short-circuiting is not available.
As such, whether implicit short-circuiting is available or not is
not really that important to me, but I will admit I didn't realise
C had it.
[*] By implicit short-circuiting I mean something that's only defined
in the language standard or implemented in a compiler, instead of some explicit syntax in the language itself to state short-circuiting is available.
However, I must disagree strongly with the advice to use
`strncpy`, which is poorly understood and has strange semantics:
it will write as much of the source string to the destination as
it can, with or without the NUL terminating byte. If the source
is smaller than the destination buffer, then the remainder of
the buffer will be filled with 0s. If the source is exactly as
long as, or longer, than the destination, then the destination
will not be NUL-terminated. Since it just returns the
destination pointer, there is no way to detect truncation other
than to test the last byte in the destination to see whether it
is zero or not. So it is inefficent in the common case, and
dangerous and awkward in the exceptional case. Moreover, its
behavior is orthogonal to that of `strncat`, which does _not_
have the "write 0s to all bytes in the destination past the end
of the what we copied from the source string", and is also
awkward in how it treats it's length argument: whereas for
`strncpy` the length argument is the size of the entire
destination buffer, for `strncat` it is not: `strncat` will
write up to n+1 bytes into the destination.
strncpy() makes more sense when you realise that its original purpose
was to fill fixed-size fields in a record with data and to clear the
rest of the field if the source data was smaller than the field size.
BTW, after using strncpy(), my code always unconditionally places
a 0x00 in the final byte of the buffer "just in case :-)".
Simon.
But I believe most curly bracket languages inherited from C in this
regard.
In article <107n93n$13rjm$[email protected]>,Ah. There is a constant. Good find.
Simon Clubley <clubley@remove_me.eisner.decus.org-Earth.UFP> wrote:
On 2025-08-12, Arne Vajhøj <[email protected]> wrote:
strcpy(message, "demo function requires two arguments: one
string and one integer");
return 1;
YUCK!!! :-) Does MySQL provide a maximum error message size field or
constant that you can use with strncpy() instead ?
Indeed yuck, and MySQL _does_ provide a constant that gives
the maximum error message size: `MYSQL_ERRMSG_SIZE`. https://dev.mysql.com/doc/extending-mysql/9.4/en/adding-loadable-function.html
On 2025-08-15, Dan Cross <[email protected]> wrote:
In article <107n93n$13rjm$[email protected]>,
Simon Clubley <clubley@remove_me.eisner.decus.org-Earth.UFP> wrote:
On 2025-08-12, Arne Vajhøj <[email protected]> wrote:
if(args->arg_count == 2 && args->arg_type[0] == STRING_RESULT && >>>> args->arg_type[1] == INT_RESULT)
Is it guaranteed that arg_type[] will always have at least elements ?
If not, that's dangerous unless the compiler you are using does
expression short-circuiting.
C is well-defined in this regard. Boolean expressions in C,
created by combining logical subexpressions with the `&&` and
`||` operators, are documented to use short-circuiting behavior.
Unless it's explicit in the language syntax itself, and given that
I write code in multiple languages, I have long written code that
assumes implicit[*] short-circuiting is not available.
As such, whether implicit short-circuiting is available or not is
not really that important to me, but I will admit I didn't realise
C had it.
[*] By implicit short-circuiting I mean something that's only defined
in the language standard or implemented in a compiler, instead of some explicit syntax in the language itself to state short-circuiting is available.
On 8/15/2025 9:40 AM, John Reagan wrote:
On 8/15/2025 9:35 AM, Arne Vajhøj wrote:^not> an AND_THEN and OR_ELSE operator much like you find
On 8/15/2025 8:27 AM, Simon Clubley wrote:
On 2025-08-12, Arne Vajhøj <[email protected]> wrote:
Code:
#include <string.h>
#include <mysql.h>
my_bool demo_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
{
if(args->arg_count == 2 && args->arg_type[0] == STRING_RESULT &&
args->arg_type[1] == INT_RESULT)
Is it guaranteed that arg_type[] will always have at least elements ?
If not, that's dangerous unless the compiler you are using does
expression short-circuiting.
Isn't C required to do short circuiting on && ?
Yes, C and C++ short-circuits. Other languages may not. For example,
Pascal does promise short-circuit which is why our Pascal also provides
in Ada.
VB.NET has AndAlso and OrElse.
But I believe most curly bracket languages inherited from
C in this regard.
Arne
BTW, BLISS does not promise short-circuit. And in the true BLISS
fashion, most of us use the following macros
! AND_THEN(B1,B2,...Bn) returns TRUE if all of Bi are TRUE.
! Evaluates the Bi left to right and stops on the first false one.
!
AND_THEN(B)[]=
%IF %LENGTH EQL 1
%THEN
(B)
%ELSE
(IF (B) THEN AND_THEN(%REMAINING) ELSE FALSE)
%FI %,
! OR_ELSE(B1,B2,...Bn) returns FALSE if all of Bi are FALSE.
! Evaluates the Bi left to right and stops on the first true one.
!
OR_ELSE(B)[]=
%IF %LENGTH EQL 1
%THEN
(B)
%ELSE
(IF (B) THEN TRUE ELSE OR_ELSE(%REMAINING))
%FI %,
On 8/15/2025 1:33 PM, Simon Clubley wrote:
On 2025-08-15, Dan Cross <[email protected]> wrote:
In article <107n93n$13rjm$[email protected]>,
Simon Clubley <clubley@remove_me.eisner.decus.org-Earth.UFP> wrote:
On 2025-08-12, Arne Vajhøj <[email protected]> wrote:
if(args->arg_count == 2 && args->arg_type[0] == STRING_RESULT &&
args->arg_type[1] == INT_RESULT)
Is it guaranteed that arg_type[] will always have at least elements ?
If not, that's dangerous unless the compiler you are using does
expression short-circuiting.
C is well-defined in this regard. Boolean expressions in C,
created by combining logical subexpressions with the `&&` and
`||` operators, are documented to use short-circuiting behavior.
Unless it's explicit in the language syntax itself, and given that
I write code in multiple languages, I have long written code that
assumes implicit[*] short-circuiting is not available.
As such, whether implicit short-circuiting is available or not is
not really that important to me, but I will admit I didn't realise
C had it.
[*] By implicit short-circuiting I mean something that's only defined
in the language standard or implemented in a compiler, instead of some
explicit syntax in the language itself to state short-circuiting is
available.
In general I like the idea of writing code in a way that does
not require the reader to have memorized ten thousand things from
the language spec.
But I do not consider this a matter of remembering the specific
details about an operator - I consider this a matter of remembering
what operator a symbol represent.
I consider "short circuiting AND" and "non short circuiting AND"
to be two different operators.
And in C then && is the first operator not the second operator.
And understanding what operator each symbol represent is not
detail but core. IMHO.
Arne
On 8/15/2025 7:48 PM, Arne Vajhøj wrote:
On 8/15/2025 1:33 PM, Simon Clubley wrote:
On 2025-08-15, Dan Cross <[email protected]> wrote:
In article <107n93n$13rjm$[email protected]>,
Simon Clubley <clubley@remove_me.eisner.decus.org-Earth.UFP> wrote: >>>>> On 2025-08-12, Arne Vajhøj <[email protected]> wrote:
if(args->arg_count == 2 && args->arg_type[0] ==
STRING_RESULT &&
args->arg_type[1] == INT_RESULT)
Is it guaranteed that arg_type[] will always have at least elements ? >>>>> If not, that's dangerous unless the compiler you are using does
expression short-circuiting.
C is well-defined in this regard. Boolean expressions in C,
created by combining logical subexpressions with the `&&` and
`||` operators, are documented to use short-circuiting behavior.
Unless it's explicit in the language syntax itself, and given that
I write code in multiple languages, I have long written code that
assumes implicit[*] short-circuiting is not available.
As such, whether implicit short-circuiting is available or not is
not really that important to me, but I will admit I didn't realise
C had it.
[*] By implicit short-circuiting I mean something that's only defined
in the language standard or implemented in a compiler, instead of some
explicit syntax in the language itself to state short-circuiting is
available.
In general I like the idea of writing code in a way that does
not require the reader to have memorized ten thousand things from
the language spec.
But I do not consider this a matter of remembering the specific
details about an operator - I consider this a matter of remembering
what operator a symbol represent.
I consider "short circuiting AND" and "non short circuiting AND"
to be two different operators.
BTW, while the C frontend always generates the "short-circuiting" AND
and OR intermediate opcodes, the GEM optimizer works to detect if that
is really needed. It is hoping to hoist something from the right-hand
side out of a loop (which happens more than you think) and on Itanium it
can even put both left and right in the same bundle if possible (which doesn't happen all that much)
In general I like the idea of writing code in a way that does not
require the reader to have memorized ten thousand things from the
language spec.
On Fri, 15 Aug 2025 09:55:17 -0400, Arne Vajhøj wrote:
But I believe most curly bracket languages inherited from C in this
regard.
Python took over the C operator hierarchy, with one subtle little
twist. It slightly tweaked the precedence of the bitwise operators
relative to the comparisons, so you don’t need parentheses in
expressions like
(C) («val» & «bitmask») == «testvalue»
(Python) «val» & «bitmask» == «testvalue»
I have asked on comp.lang.c whether any existing C code could be
broken by making the same change in that language. In principle it
could, but nobody could come up with any real-world examples.
On Fri, 15 Aug 2025 19:48:14 -0400, Arne Vajhøj wrote:
In general I like the idea of writing code in a way that does not
require the reader to have memorized ten thousand things from the
language spec.
What language spec has room for ten thousand things in it, anyway?
... oh, Java.
On 8/15/2025 10:22 PM, Lawrence D’Oliveiro wrote:
On Fri, 15 Aug 2025 19:48:14 -0400, Arne Vajhøj wrote:
In general I like the idea of writing code in a way that does not
require the reader to have memorized ten thousand things from the
language spec.
What language spec has room for ten thousand things in it, anyway?
... oh, Java.
Language specs for modern languages tend to be pretty big.
On 8/12/2025 11:09 PM, Lawrence D'Oliveiro wrote:
On Tue, 12 Aug 2025 19:08:51 -0400, Arne Vajhøj wrote:
mysql055_root:[lib.alpha]libclientlib/lib
mysql055_root:[lib.alpha]libsql/lib
mysql055_root:[lib.alpha]libmysys/lib
mysql055_root:[lib.alpha]libdbug/lib
mysql055_root:[lib.alpha]libstrings/lib
mysql055_root:[lib.alpha]libvio/lib
mysql055_root:[lib.alpha]libz/lib
mysql055_root:[lib.alpha]ssl_libssl32/lib
mysql055_root:[lib.alpha]ssl_libcrypto32/lib
Is there some equivalent to “-L«dir»” to add a common directory to a >> linker search path so you can just shorten most of that to something
more like “-lclientlib -lsql -lmysys -ldbug -lstrings -lvio -lz”?
You can omit location on all libraries except the first and
let the sticky default mechanism add it.
(I don't think that is a nice solution)
You can setup default libraries with LNK$LIBRARY* logicals.
You can create shareable images and stuff all of them into
a shareable library.
On 8/15/25 02:33, Arne Vajhøj wrote:
On 8/12/2025 11:09 PM, Lawrence D'Oliveiro wrote:...
On Tue, 12 Aug 2025 19:08:51 -0400, Arne Vajhøj wrote:
mysql055_root:[lib.alpha]libclientlib/lib
mysql055_root:[lib.alpha]libsql/lib
mysql055_root:[lib.alpha]libmysys/lib
mysql055_root:[lib.alpha]libdbug/lib
mysql055_root:[lib.alpha]libstrings/lib
mysql055_root:[lib.alpha]libvio/lib
mysql055_root:[lib.alpha]libz/lib
mysql055_root:[lib.alpha]ssl_libssl32/lib
mysql055_root:[lib.alpha]ssl_libcrypto32/lib
Is there some equivalent to “-L«dir»” to add a common directory to a >>> linker search path so you can just shorten most of that to something
more like “-lclientlib -lsql -lmysys -ldbug -lstrings -lvio -lz”?
You can omit location on all libraries except the first and
let the sticky default mechanism add it.
(I don't think that is a nice solution)
You may not like it, but using the file specification stickiness or RMS related name context processing is the only useful method to avoid
repeating the directory specification. This works on the command line as
well as in option files. And you can have more than one library on a
single option line, anyway.
If you have GNV, you can use its linker wrapper. However, it requires
naming the object libraries in Unix style. Although a "libfoo.olb"
works, there is no way to use an "foo.olb" (and you can't easily get a
full map with cross references). So this will not work for ssl_* in the
shown link command. Yeah, you can create (symbolic) links ...
You can setup default libraries with LNK$LIBRARY* logicals.
In your example you would need 9 logicals: LNK$LIBRARY,
LNK$LIBRARY_1, ..., LNK$LIBRARY_8. There is no _0 and they must all be defined. The suffixes must start with 1 and must not have a gap in
numbering. You can't use a search list. Additionally, the link command
line doesn't show that non-system object libraries are used at all.
You can create shareable images and stuff all of them into
a shareable library.
Then the resulting image or application is no longer "statically"
linked: you need the shareable image at runtime. You have to create a shareable with as many universal symbols, aka symbol vector entries, as global symbols in the libraries - just to avoid specifying a couple of
file paths in the link command.
On 8/17/2025 11:24 AM, hb0815 wrote:
On 8/15/25 02:33, Arne Vajhøj wrote:
On 8/12/2025 11:09 PM, Lawrence D'Oliveiro wrote:...
On Tue, 12 Aug 2025 19:08:51 -0400, Arne Vajhøj wrote:
mysql055_root:[lib.alpha]libclientlib/lib
mysql055_root:[lib.alpha]libsql/lib
mysql055_root:[lib.alpha]libmysys/lib
mysql055_root:[lib.alpha]libdbug/lib
mysql055_root:[lib.alpha]libstrings/lib
mysql055_root:[lib.alpha]libvio/lib
mysql055_root:[lib.alpha]libz/lib
mysql055_root:[lib.alpha]ssl_libssl32/lib
mysql055_root:[lib.alpha]ssl_libcrypto32/lib
Is there some equivalent to “-L«dir»” to add a common directory to a >>>> linker search path so you can just shorten most of that to something
more like “-lclientlib -lsql -lmysys -ldbug -lstrings -lvio -lz”?
You can omit location on all libraries except the first and
let the sticky default mechanism add it.
(I don't think that is a nice solution)
You may not like it, but using the file specification stickiness or
RMS related name context processing is the only useful method to avoid
repeating the directory specification. This works on the command line
as well as in option files. And you can have more than one library on
a single option line, anyway.
It can be used.
But if someone edit the list and either remove libraries or
add libraries, then it is pretty easy to mess up.
If you have GNV, you can use its linker wrapper. However, it requires
naming the object libraries in Unix style. Although a "libfoo.olb"
works, there is no way to use an "foo.olb" (and you can't easily get a
full map with cross references). So this will not work for ssl_* in
the shown link command. Yeah, you can create (symbolic) links ...
I did not even consider GNV.
You can setup default libraries with LNK$LIBRARY* logicals.
In your example you would need 9 logicals: LNK$LIBRARY,
LNK$LIBRARY_1, ..., LNK$LIBRARY_8. There is no _0 and they must all
be defined. The suffixes must start with 1 and must not have a gap in
numbering. You can't use a search list. Additionally, the link command
line doesn't show that non-system object libraries are used at all.
It is an option that I considered relevant for the question on
how to shorten link commands.
I would not use it in this case.
As an old Fortran programmer then I find it quite natural that
it starts with _1 and not _0.
:-)
You can create shareable images and stuff all of them into
a shareable library.
Then the resulting image or application is no longer "statically"
linked: you need the shareable image at runtime. You have to create a
shareable with as many universal symbols, aka symbol vector entries,
as global symbols in the libraries - just to avoid specifying a couple
of file paths in the link command.
There is no free lunch.
It is an option for the question on how to shorten link commands.
I would not use it in this case either.
I don't even think I have ever created such a shareable library. But
everyone is using one (IMAGELIB).
Arne
It is an option for the question on how to shorten link commands.
I would not use it in this case either.
I don't even think I have ever created such a shareable library. But
everyone is using one (IMAGELIB).
Can you not use make, MMK (or equiv) utility?
On 8/15/2025 6:42 PM, Lawrence D?Oliveiro wrote:
On Fri, 15 Aug 2025 09:55:17 -0400, Arne Vajh�j wrote:
But I believe most curly bracket languages inherited from C in this
regard.
Python took over the C operator hierarchy, with one subtle little
twist. It slightly tweaked the precedence of the bitwise operators
relative to the comparisons, so you don?t need parentheses in
expressions like
(C) (�val� & �bitmask�) == �testvalue�
(Python) �val� & �bitmask� == �testvalue�
I have asked on comp.lang.c whether any existing C code could be
broken by making the same change in that language. In principle it
could, but nobody could come up with any real-world examples.
What about:
if(reperr & sys$put(&rab, 0, 0) != RMS$_NORMAL)
{
printf("Houston we have a problem\n");
}
In general I like the idea of writing code in a way that does
not require the reader to have memorized ten thousand things from
the language spec.
But I do not consider this a matter of remembering the specific
details about an operator - I consider this a matter of remembering
what operator a symbol represent.
I consider "short circuiting AND" and "non short circuiting AND"
to be two different operators.
And in C then && is the first operator not the second operator.
And understanding what operator each symbol represent is not
detail but core. IMHO.
On 2025-08-15, Arne Vajhøj <[email protected]> wrote:
In general I like the idea of writing code in a way that does
not require the reader to have memorized ten thousand things from
the language spec.
But I do not consider this a matter of remembering the specific
details about an operator - I consider this a matter of remembering
what operator a symbol represent.
I consider "short circuiting AND" and "non short circuiting AND"
to be two different operators.
They are not. One is a subset of the other and both carry out the
same core operation.
And in C then && is the first operator not the second operator.
And understanding what operator each symbol represent is not
detail but core. IMHO.
I disagree. Strongly. Both operators do exactly the same thing which
is to implement a logical AND. Code written using this operator
generates exactly the same logical AND result regardless of whether
short circuiting is in use or not.
In addition however, a short circuiting compiler generates code to
stop evaluation if the previous logical AND subexpression was false.
This is a feature of the compiler and does not turn logical AND into something which does something other than logical AND.
It is _always_ safe to write code which assumes short circuiting is
not in use and it will work exactly the same even in the presence
of a compiler which generates short circuiting code.
It's all about writing robust code, not clever code. My approach
generates much more robust code, especially when you might translate
the code to another language that does not implement short circuiting
and you don't realise this during the translation.
On 2025-08-16, Arne Vajhøj <[email protected]> wrote:
On 8/15/2025 6:42 PM, Lawrence D?Oliveiro wrote:
On Fri, 15 Aug 2025 09:55:17 -0400, Arne Vajhøj wrote:
But I believe most curly bracket languages inherited from C in this
regard.
Python took over the C operator hierarchy, with one subtle little
twist. It slightly tweaked the precedence of the bitwise operators
relative to the comparisons, so you don?t need parentheses in
expressions like
(C) («val» & «bitmask») == «testvalue»
(Python) «val» & «bitmask» == «testvalue»
I have asked on comp.lang.c whether any existing C code could be
broken by making the same change in that language. In principle it
could, but nobody could come up with any real-world examples.
What about:
if(reperr & sys$put(&rab, 0, 0) != RMS$_NORMAL)
{
printf("Houston we have a problem\n");
}
And it's crap like that which means I tend to ignore operator precedence
and place all subexpressions in brackets (nested if needed).
It avoids stuff like this and makes it _extremely_ clear in the code
what the intention is (and makes it easier to read BTW).
On 8/18/2025 8:37 AM, Simon Clubley wrote:And some languages have both operators.
On 2025-08-15, Arne Vajhøj <[email protected]> wrote:
In general I like the idea of writing code in a way that does
not require the reader to have memorized ten thousand things from
the language spec.
But I do not consider this a matter of remembering the specific
details about an operator - I consider this a matter of remembering
what operator a symbol represent.
I consider "short circuiting AND" and "non short circuiting AND"
to be two different operators.
They are not. One is a subset of the other and both carry out the
same core operation.
And in C then && is the first operator not the second operator.
And understanding what operator each symbol represent is not
detail but core. IMHO.
I disagree. Strongly. Both operators do exactly the same thing which
is to implement a logical AND. Code written using this operator
generates exactly the same logical AND result regardless of whether
short circuiting is in use or not.
In addition however, a short circuiting compiler generates code to
stop evaluation if the previous logical AND subexpression was false.
This is a feature of the compiler and does not turn logical AND into
something which does something other than logical AND.
Considering two operators the same because the functionality of one is
a subset of the functionality of the other seems unlogical to me.
On 8/18/2025 8:37 AM, Simon Clubley wrote:
It is _always_ safe to write code which assumes short circuiting is
not in use and it will work exactly the same even in the presence
of a compiler which generates short circuiting code.
Not true.
Not if the second expression has side effects.
I am sure that you don't want expressions with side effect. But
it happens.
On 2025-08-15, Dan Cross <[email protected]> wrote:
In article <107n93n$13rjm$[email protected]>,
Simon Clubley <clubley@remove_me.eisner.decus.org-Earth.UFP> wrote:
On 2025-08-12, Arne Vajh�j <[email protected]> wrote:
Code:
#include <string.h>
#include <mysql.h>
my_bool demo_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
{
if(args->arg_count == 2 && args->arg_type[0] == STRING_RESULT &&
args->arg_type[1] == INT_RESULT)
Is it guaranteed that arg_type[] will always have at least elements ?
If not, that's dangerous unless the compiler you are using does >>>expression short-circuiting.
C is well-defined in this regard. Boolean expressions in C,
created by combining logical subexpressions with the `&&` and
`||` operators, are documented to use short-circuiting behavior.
Thank you.
Unless it's explicit in the language syntax itself, and given that
I write code in multiple languages, I have long written code that
assumes implicit[*] short-circuiting is not available.
As such, whether implicit short-circuiting is available or not is
not really that important to me, but I will admit I didn't realise
C had it.
[*] By implicit short-circuiting I mean something that's only defined
in the language standard or implemented in a compiler, instead of some >explicit syntax in the language itself to state short-circuiting is >available.
However, I must disagree strongly with the advice to use
`strncpy`, which is poorly understood and has strange semantics:
it will write as much of the source string to the destination as
it can, with or without the NUL terminating byte. If the source
is smaller than the destination buffer, then the remainder of
the buffer will be filled with 0s. If the source is exactly as
long as, or longer, than the destination, then the destination
will not be NUL-terminated. Since it just returns the
destination pointer, there is no way to detect truncation other
than to test the last byte in the destination to see whether it
is zero or not. So it is inefficent in the common case, and
dangerous and awkward in the exceptional case. Moreover, its
behavior is orthogonal to that of `strncat`, which does _not_
have the "write 0s to all bytes in the destination past the end
of the what we copied from the source string", and is also
awkward in how it treats it's length argument: whereas for
`strncpy` the length argument is the size of the entire
destination buffer, for `strncat` it is not: `strncat` will
write up to n+1 bytes into the destination.
strncpy() makes more sense when you realise that its original purpose
was to fill fixed-size fields in a record with data and to clear the
rest of the field if the source data was smaller than the field size.
BTW, after using strncpy(), my code always unconditionally places
a 0x00 in the final byte of the buffer "just in case :-)".
On 8/15/2025 10:22 PM, Lawrence D’Oliveiro wrote:
On Fri, 15 Aug 2025 19:48:14 -0400, Arne Vajhøj wrote:
In general I like the idea of writing code in a way that does not
require the reader to have memorized ten thousand things from the
language spec.
What language spec has room for ten thousand things in it, anyway?
... oh, Java.
Language specs for modern languages tend to be pretty big.
Java 21 is 872 pages (no library)
C 23 is 761 pages (basic library)
C++ 11 is 1334 pages (basic library)
Fortran 2018 is 646 pages (basic library)
Cobol 2014 is 923 pages (basic library)
Ada 2012 is 951 pages (basic library)
C# 6.0 is 639 pages (no library)
On 8/18/2025 8:37 AM, Simon Clubley wrote:
It's all about writing robust code, not clever code. My approach
generates much more robust code, especially when you might translate
the code to another language that does not implement short circuiting
and you don't realise this during the translation.
I agree with the philosophy in general.
But I have little faith in trying to translate from one language
to another language without deep understanding of operators in the
two languages.
Should one use parentheses to specify evaluation explicit instead of
relying on operator precedence?
I do think so.
Even if the operator precedence seems clear to you, it might not be
to others—you shouldn’t assume that other programmers know
precedence as well as you do.
On 8/18/2025 3:42 PM, Arne Vajhøj wrote:
On 8/18/2025 8:37 AM, Simon Clubley wrote:
It's all about writing robust code, not clever code. My approach
generates much more robust code, especially when you might translate
the code to another language that does not implement short circuiting
and you don't realise this during the translation.
I agree with the philosophy in general.
But I have little faith in trying to translate from one language
to another language without deep understanding of operators in the
two languages.
As warning:
$ type op.c
#include <stdio.h>
int main(int argc, char *argv[])
{
int iv = 5;
printf("%d %d\n", iv / 2, iv % 2);
return 0;
}
$ cc op
$ link op
$ run op
2 1
$ type op.pas
program op(input,output);
var
iv : integer;
begin
iv := 5;
writeln(iv / 2, ' ', iv mod 2);
end.
$ pas op
$ lin op
$ run op
2.50000E+00 1
$ type op.for
program op
integer*4 iv
iv = 5
write(*,*) iv / 2, iv mod 2
end
$ for op
$ lin op
$ run op
2 0
In article <68a3b334$0$713$[email protected]>,
Arne Vajhøj <[email protected]> wrote:
On 8/18/2025 3:42 PM, Arne Vajhøj wrote:
On 8/18/2025 8:37 AM, Simon Clubley wrote:
It's all about writing robust code, not clever code. My approach
generates much more robust code, especially when you might translate
the code to another language that does not implement short circuiting
and you don't realise this during the translation.
I agree with the philosophy in general.
But I have little faith in trying to translate from one language
to another language without deep understanding of operators in the
two languages.
As warning:
$ cc op
$ link op
$ run op
2 1
$ pas op
$ lin op
$ run op
2.50000E+00 1
Of course. In pascal, integer division is spelled, `div`, not
`/`. Why would one expect otherwise?
$ for op
$ lin op
$ run op
2 0
Here, FORTRAN has type promotion rules that require one of the
operands of the `/` binary operator to be of a real type before
the operation is performed as a real. iv/2.0 would give the
floating point result, for FORTRAN-77 and later.
And of course, `iv mod 2` should be, `mod(iv, 2)`.
On Mon, 18 Aug 2025 15:21:07 -0400, Arne Vajhøj wrote:
Should one use parentheses to specify evaluation explicit instead of
relying on operator precedence?
I do think so.
Parentheses are best used lightly -- where needed, maybe a little bit more than that, and that’s it.
Otherwise parenthesis clutter introduces its own obstacles to readability.
Even if the operator precedence seems clear to you, it might not be
to others—you shouldn’t assume that other programmers know
precedence as well as you do.
I assume that they are just as able to read the spec as you are.
printf("%d %d\n", iv / 2, iv % 2);
C += vs C =
PHP == vs PHP ===
On Mon, 18 Aug 2025 15:42:49 -0400, Arne Vajhøj wrote:
C += vs C =
Inconsistency: if “==” is equality comparison, and “!” denotes logical
negation, why isn’t the inequality operator “!==”? Because “!=” looks like
it follows the pattern of “a «op»= b” being a short form for “a = a «op»
b”.
PHP == vs PHP ===
Why do PHP and Java need the separate “===” operator in addition to “==”,
when Python does not?
On 8/18/2025 7:45 PM, Lawrence D’Oliveiro wrote:
On Mon, 18 Aug 2025 15:21:07 -0400, Arne Vajhøj wrote:
Should one use parentheses to specify evaluation explicit instead of
relying on operator precedence?
I do think so.
Parentheses are best used lightly -- where needed, maybe a little bit
more than that, and that’s it.
Otherwise parenthesis clutter introduces its own obstacles to
readability.
That is not the mantra among people who try to prevent future errors.
Even if the operator precedence seems clear to you, it might not be to
others—you shouldn’t assume that other programmers know precedence as >>> well as you do.
I assume that they are just as able to read the spec as you are.
able to <> will
On Mon, 18 Aug 2025 19:11:48 -0400, Arne Vajhøj wrote:
printf("%d %d\n", iv / 2, iv % 2);
The interpretation in C of “/” being an integer operation with integer operands, and float otherwise, is generally regarded as a Bad Idea. I
think it caught the infection from Fortran.
Python actually started out following this interpretation, then changed to always returning a float, introducing the additional separate “//” operator for when you explicitly want integer division.
Even PHP, bad as it is in other ways, did not follow the C mistake.
Is it OK for a language to change operator precedence, because the
change would only make a difference for code not following good
style?
I don't think so.
Changing behavior of existing code is not acceptable. Not even
for bad style code.
I know a few languages has made such changes (changing behavior of
existing code - not specifically changing operator precedence).
But I still don't like it.
PS: Yes - both Scala 2.13 and 3.3 runs fine on VMS. For 3.3 source files
must be rfm:stmlf.
I agree that the risk of someone not understanding "division"
ways is much less than the risk of someone not understanding "and" ways.
In article <68a3b980$0$713$[email protected]>,
Arne Vajhøj <[email protected]> wrote:
But point is that one need to know something about the
languages.
Just picking an operator that "looks like" and hope it
has similar semantics is no good.
This seems like a very extreme example. There is a scale of
knowledge when it comes to programming languages, from the basic
ways in which one does various things like write loops or
perform basic arithmetic, to the minutia of specific library or
IO routines, with semantics of specific operators and how they
combine probably somewhere in the middle.
I happen to disagree with Simon's notion of what makes for
robust programming, but to go to such an extreme as to suggest
that writing code as if logical operators don't short-circuit
is the same as not knowing the semantics of division is
specious.
On 8/18/2025 7:27 PM, Dan Cross wrote:
In article <68a3b334$0$713$[email protected]>,
Arne Vajhøj <[email protected]> wrote:
On 8/18/2025 3:42 PM, Arne Vajhøj wrote:
On 8/18/2025 8:37 AM, Simon Clubley wrote:
It's all about writing robust code, not clever code. My approach
generates much more robust code, especially when you might translate >>>>> the code to another language that does not implement short circuiting >>>>> and you don't realise this during the translation.
I agree with the philosophy in general.
But I have little faith in trying to translate from one language
to another language without deep understanding of operators in the
two languages.
As warning:
$ cc op
$ link op
$ run op
2 1
$ pas op
$ lin op
$ run op
2.50000E+00 1
Of course. In pascal, integer division is spelled, `div`, not
`/`. Why would one expect otherwise?
$ for op
$ lin op
$ run op
2 0
Here, FORTRAN has type promotion rules that require one of the
operands of the `/` binary operator to be of a real type before
the operation is performed as a real. iv/2.0 would give the
floating point result, for FORTRAN-77 and later.
And of course, `iv mod 2` should be, `mod(iv, 2)`.
Yes.
But point is that one need to know something about the
languages.
Just picking an operator that "looks like" and hope it
has similar semantics is no good.
On Mon, 18 Aug 2025 19:48:16 -0400, Arne Vajhøj wrote:
On 8/18/2025 7:45 PM, Lawrence D’Oliveiro wrote:
On Mon, 18 Aug 2025 15:21:07 -0400, Arne Vajhøj wrote:
Should one use parentheses to specify evaluation explicit instead of
relying on operator precedence?
I do think so.
Parentheses are best used lightly -- where needed, maybe a little bit
more than that, and that’s it.
Otherwise parenthesis clutter introduces its own obstacles to
readability.
That is not the mantra among people who try to prevent future errors.
There are people who just repeat what they are told, aren’t there, instead of learning from actual experience.
On 8/18/2025 7:59 PM, Lawrence D’Oliveiro wrote:
On Mon, 18 Aug 2025 19:48:16 -0400, Arne Vajhøj wrote:
On 8/18/2025 7:45 PM, Lawrence D’Oliveiro wrote:
Parentheses are best used lightly -- where needed, maybe a little
bit more than that, and that’s it.
Otherwise parenthesis clutter introduces its own obstacles to
readability.
That is not the mantra among people who try to prevent future
errors.
There are people who just repeat what they are told, aren’t there,
instead of learning from actual experience.
It is the recommendation from people with actual experience.
One book that recommend it is "The Practice of Programming".
Brian Kernighan and Rob Pike.
On 8/18/2025 8:48 PM, Dan Cross wrote:
In article <68a3b980$0$713$[email protected]>,
Arne Vajhøj <[email protected]> wrote:
But point is that one need to know something about the
languages.
Just picking an operator that "looks like" and hope it
has similar semantics is no good.
This seems like a very extreme example. There is a scale of
knowledge when it comes to programming languages, from the basic
ways in which one does various things like write loops or
perform basic arithmetic, to the minutia of specific library or
IO routines, with semantics of specific operators and how they
combine probably somewhere in the middle.
I happen to disagree with Simon's notion of what makes for
robust programming, but to go to such an extreme as to suggest
that writing code as if logical operators don't short-circuit
is the same as not knowing the semantics of division is
specious.
There are 4 operations:
- short circuiting and
- non short circuiting and
- integer division
- floating point division
Both source and target language has a way of doing those: operator,
function or a more complex expression.
I agree that the risk of someone not understanding "division"
ways is much less than the risk of someone not understanding
"and" ways.
But in the end the team doing the translation need to understand
all operations to do a correct translation.
In article <107nr15$18f8f$[email protected]>,
Simon Clubley <clubley@remove_me.eisner.decus.org-Earth.UFP> wrote:
Unless it's explicit in the language syntax itself, and given that
I write code in multiple languages, I have long written code that
assumes implicit[*] short-circuiting is not available.
Huh, interesting. I suppose my take is that I have an
obligation to learn the idioms of a given language, if I am
writing code in that language, and this feels like one that is
useful to know about.
To each their own, I suppose.
Or, better yet, write less C and use safer languages. :-D
But point is that one need to know something about the
languages.
Just picking an operator that "looks like" and hope it
has similar semantics is no good.
Are there any languages invented the last 20 years that does
not do integer division for two integer operands?
Considering two operators the same because the functionality of one is
a subset of the functionality of the other seems unlogical to me.
C += vs C =
PHP == vs PHP ===
etc.
It is _always_ safe to write code which assumes short circuiting is
not in use and it will work exactly the same even in the presence
of a compiler which generates short circuiting code.
Not true.
Not if the second expression has side effects.
I am sure that you don't want expressions with side effect. But
it happens.
I happen to disagree with Simon's notion of what makes for
robust programming, but to go to such an extreme as to suggest
that writing code as if logical operators don't short-circuit
is the same as not knowing the semantics of division is
specious.
On 8/18/2025 3:42 PM, Arne Vajh�j wrote:
On 8/18/2025 8:37 AM, Simon Clubley wrote:
It is _always_ safe to write code which assumes short circuiting is
not in use and it will work exactly the same even in the presence
of a compiler which generates short circuiting code.
Not true.
Not if the second expression has side effects.
I am sure that you don't want expressions with side effect. But
it happens.
Function calls is a classic example of potential side
effect, but many languages allow assignments in expressions.
Python 3.8 introduced the walrus operator.
On 2025-08-18, Dan Cross <[email protected]> wrote:
I happen to disagree with Simon's notion of what makes for
robust programming, but to go to such an extreme as to suggest
that writing code as if logical operators don't short-circuit
is the same as not knowing the semantics of division is
specious.
That last one is an interesting example. I may not care about
short circuiting, but I am _very_ _very_ aware of the combined
unsigned integers and signed integers issues in C expressions. :-(
It also affects how I look at the same issues in other languages.
I've mentioned this before, but I think languages should give you
unsigned integers by default, and you should have to ask for
a signed integer if you really want one.
On Mon, 18 Aug 2025 21:49:29 -0400, Arne Vajhøj wrote:
On 8/18/2025 7:59 PM, Lawrence D’Oliveiro wrote:
On Mon, 18 Aug 2025 19:48:16 -0400, Arne Vajhøj wrote:
On 8/18/2025 7:45 PM, Lawrence D’Oliveiro wrote:
Parentheses are best used lightly -- where needed, maybe a little
bit more than that, and that’s it.
Otherwise parenthesis clutter introduces its own obstacles to
readability.
That is not the mantra among people who try to prevent future
errors.
There are people who just repeat what they are told, aren’t there,
instead of learning from actual experience.
It is the recommendation from people with actual experience.
One book that recommend it is "The Practice of Programming".
Brian Kernighan and Rob Pike.
One wonders how much experience they really have, across how many
different languages.
On 2025-08-18, Dan Cross <[email protected]> wrote:
In article <107nr15$18f8f$[email protected]>,
Simon Clubley <clubley@remove_me.eisner.decus.org-Earth.UFP> wrote:
Unless it's explicit in the language syntax itself, and given that
I write code in multiple languages, I have long written code that
assumes implicit[*] short-circuiting is not available.
Huh, interesting. I suppose my take is that I have an
obligation to learn the idioms of a given language, if I am
writing code in that language, and this feels like one that is
useful to know about.
To each their own, I suppose.
I write simple to understand code, not clever code, even when the
problem it is solving is complex or has a lot of functionality
built into the problem.
I've found it makes code more robust and easier for others to read, >especially when they may not have the knowledge you have when you
wrote the original code.
I certainly don't feel the need to write job security code or some
"macho" desire to write dense and hard to understand code to order
to try and demonstrate to others just how "smart" I am.
I am not saying you are doing that BTW, but I've seen enough code
written by others which was clearly written with that mindset.
Or, better yet, write less C and use safer languages. :-D
Unfortunately that's not really possible in many cases. I _strongly_
wish a Wirth-style language had become the standard system integration
and low-level language instead of C.
On 2025-08-18, Arne Vajhøj <[email protected]> wrote:
On 8/18/2025 3:42 PM, Arne Vajhøj wrote:
On 8/18/2025 8:37 AM, Simon Clubley wrote:
It is _always_ safe to write code which assumes short circuiting is
not in use and it will work exactly the same even in the presence
of a compiler which generates short circuiting code.
Not true.
Not if the second expression has side effects.
I am sure that you don't want expressions with side effect. But
it happens.
Function calls is a classic example of potential side
effect, but many languages allow assignments in expressions.
Python 3.8 introduced the walrus operator.
Then Python has lost the plot. When you do ugly things like this, then
the easier it is for subtle errors to slip in. Also, you write code once (hopefully), but read it many times.
On 2025-08-18, Dan Cross <[email protected]> wrote:
I happen to disagree with Simon's notion of what makes for
robust programming, but to go to such an extreme as to suggest
that writing code as if logical operators don't short-circuit
is the same as not knowing the semantics of division is
specious.
That last one is an interesting example. I may not care about
short circuiting, but I am _very_ _very_ aware of the combined
unsigned integers and signed integers issues in C expressions. :-(
It also affects how I look at the same issues in other languages.
I've mentioned this before, but I think languages should give you
unsigned integers by default, and you should have to ask for
a signed integer if you really want one.
On 2025-08-18, Arne Vajhøj <[email protected]> wrote:
Are there any languages invented the last 20 years that does
not do integer division for two integer operands?
Javascript's basic number data type is a floating point number. :-(
Make of that what you will and also the mindset of someone who thought
that was a good idea.
Yes, I know Javascript is older than that but it's been through
multiple standards processes.
On 2025-08-18, Arne Vajhøj <[email protected]> wrote:
It is _always_ safe to write code which assumes short circuiting is
not in use and it will work exactly the same even in the presence
of a compiler which generates short circuiting code.
Not true.
Not if the second expression has side effects.
I am sure that you don't want expressions with side effect. But
it happens.
Tell me Arne, given what you now know about me, do you really think
I would ever write code that had expression side effects like that ? :-)
In article <1081sk3$3njqo$[email protected]>,
Simon Clubley <clubley@remove_me.eisner.decus.org-Earth.UFP> wrote:
On 2025-08-18, Dan Cross <[email protected]> wrote:
I happen to disagree with Simon's notion of what makes for
robust programming, but to go to such an extreme as to suggest
that writing code as if logical operators don't short-circuit
is the same as not knowing the semantics of division is
specious.
That last one is an interesting example. I may not care about
short circuiting, but I am _very_ _very_ aware of the combined
unsigned integers and signed integers issues in C expressions. :-(
It also affects how I look at the same issues in other languages.
I've mentioned this before, but I think languages should give you
unsigned integers by default, and you should have to ask for
a signed integer if you really want one.
Whether integers are signed or unsigned by default is not
terribly interesting to me, but I do believe, strongly, that
implicit type conversions as in C are a Bad Idea(TM), and I
think that history has shown that view to be more or less
correct; the only language that seems to get this approximately
right is Haskell, using typeclasses, but that's not implicit
coercion; it takes well-defined, strongly-typed functions that
do explicit conversions internally, from the prelude.
But that's Haskell. For most programming, if one wants to do
arithmetic on operands of differing type, then one should be
required to explicitly convert everything to a single, uniform
type and live with whatever the semantics of that type are.
This needn't be as tedious or verbose as it sounds; with a
little bit of type inference, it can be quite succinct while
still being safe and correct.
On 19/08/2025 16:10, Arne Vajhøj wrote:
On 8/19/2025 10:09 AM, Dan Cross wrote:programmer making an explicit conversion
Whether integers are signed or unsigned by default is not
terribly interesting to me, but I do believe, strongly, that
implicit type conversions as in C are a Bad Idea(TM), and I
think that history has shown that view to be more or less
correct; the only language that seems to get this approximately
right is Haskell, using typeclasses, but that's not implicit
coercion; it takes well-defined, strongly-typed functions that
do explicit conversions internally, from the prelude.
But that's Haskell. For most programming, if one wants to do
arithmetic on operands of differing type, then one should be
required to explicitly convert everything to a single, uniform
type and live with whatever the semantics of that type are.
This needn't be as tedious or verbose as it sounds; with a
little bit of type inference, it can be quite succinct while
still being safe and correct.
Kotlin is rather picky about mixing signed and unsigned.
var v: UInt = 16u
v = v / 2
gives an error.
v = v / 2u
v = v / 2.toUInt()
works.
I consider that rather picky.
Ada as nearly as bad, although that would work, It relies on the
On 8/19/2025 10:09 AM, Dan Cross wrote:
In article <1081sk3$3njqo$[email protected]>,
Simon Clubley <clubley@remove_me.eisner.decus.org-Earth.UFP> wrote:
On 2025-08-18, Dan Cross <[email protected]> wrote:
I happen to disagree with Simon's notion of what makes for
robust programming, but to go to such an extreme as to suggest
that writing code as if logical operators don't short-circuit
is the same as not knowing the semantics of division is
specious.
That last one is an interesting example. I may not care about
short circuiting, but I am _very_ _very_ aware of the combined
unsigned integers and signed integers issues in C expressions. :-(
It also affects how I look at the same issues in other languages.
I've mentioned this before, but I think languages should give you
unsigned integers by default, and you should have to ask for
a signed integer if you really want one.
Whether integers are signed or unsigned by default is not
terribly interesting to me, but I do believe, strongly, that
implicit type conversions as in C are a Bad Idea(TM), and I
think that history has shown that view to be more or less
correct; the only language that seems to get this approximately
right is Haskell, using typeclasses, but that's not implicit
coercion; it takes well-defined, strongly-typed functions that
do explicit conversions internally, from the prelude.
But that's Haskell. For most programming, if one wants to do
arithmetic on operands of differing type, then one should be
required to explicitly convert everything to a single, uniform
type and live with whatever the semantics of that type are.
This needn't be as tedious or verbose as it sounds; with a
little bit of type inference, it can be quite succinct while
still being safe and correct.
Kotlin is rather picky about mixing signed and unsigned.
var v: UInt = 16u
v = v / 2
gives an error.
v = v / 2u
v = v / 2.toUInt()
works.
I consider that rather picky.
Arne
On 8/18/2025 11:00 PM, Lawrence D’Oliveiro wrote:
On Mon, 18 Aug 2025 21:49:29 -0400, Arne Vajhøj wrote:
On 8/18/2025 7:59 PM, Lawrence D’Oliveiro wrote:
On Mon, 18 Aug 2025 19:48:16 -0400, Arne Vajhøj wrote:
On 8/18/2025 7:45 PM, Lawrence D’Oliveiro wrote:
Parentheses are best used lightly -- where needed, maybe a little
bit more than that, and that’s it.
Otherwise parenthesis clutter introduces its own obstacles to
readability.
That is not the mantra among people who try to prevent future
errors.
There are people who just repeat what they are told, aren’t there,
instead of learning from actual experience.
It is the recommendation from people with actual experience.
One book that recommend it is "The Practice of Programming".
Brian Kernighan and Rob Pike.
One wonders how much experience they really have, across how many
different languages.
Brian Kernighan and Rob Pike? A lot! :-)
Kotlin is rather picky about mixing signed and unsigned.
var v: UInt = 16u
v = v / 2
gives an error.
v = v / 2u
v = v / 2.toUInt()
works.
I consider that rather picky.
On 8/19/2025 10:09 AM, Dan Cross wrote:
In article <1081sk3$3njqo$[email protected]>,
Simon Clubley <clubley@remove_me.eisner.decus.org-Earth.UFP> wrote:
On 2025-08-18, Dan Cross <[email protected]> wrote:
I happen to disagree with Simon's notion of what makes for
robust programming, but to go to such an extreme as to suggest
that writing code as if logical operators don't short-circuit
is the same as not knowing the semantics of division is
specious.
That last one is an interesting example. I may not care about
short circuiting, but I am _very_ _very_ aware of the combined
unsigned integers and signed integers issues in C expressions. :-(
It also affects how I look at the same issues in other languages.
I've mentioned this before, but I think languages should give you
unsigned integers by default, and you should have to ask for
a signed integer if you really want one.
Whether integers are signed or unsigned by default is not
terribly interesting to me, but I do believe, strongly, that
implicit type conversions as in C are a Bad Idea(TM), and I
think that history has shown that view to be more or less
correct; the only language that seems to get this approximately
right is Haskell, using typeclasses, but that's not implicit
coercion; it takes well-defined, strongly-typed functions that
do explicit conversions internally, from the prelude.
But that's Haskell. For most programming, if one wants to do
arithmetic on operands of differing type, then one should be
required to explicitly convert everything to a single, uniform
type and live with whatever the semantics of that type are.
This needn't be as tedious or verbose as it sounds; with a
little bit of type inference, it can be quite succinct while
still being safe and correct.
Kotlin is rather picky about mixing signed and unsigned.
var v: UInt = 16u
v = v / 2
gives an error.
v = v / 2u
v = v / 2.toUInt()
works.
I consider that rather picky.
On 8/19/2025 9:01 AM, Simon Clubley wrote:
On 2025-08-18, Dan Cross <[email protected]> wrote:
I happen to disagree with Simon's notion of what makes for
robust programming, but to go to such an extreme as to suggest
that writing code as if logical operators don't short-circuit
is the same as not knowing the semantics of division is
specious.
That last one is an interesting example. I may not care about
short circuiting, but I am _very_ _very_ aware of the combined
unsigned integers and signed integers issues in C expressions. :-(
It also affects how I look at the same issues in other languages.
I've mentioned this before, but I think languages should give you
unsigned integers by default, and you should have to ask for
a signed integer if you really want one.
"by default" sort of imply signedness being an attribute of
same type.
Why not just make it two different types with different names?
Whether we follow tradition and call them integer and cardinal
or more modern style and call them int and uint is less important.
In article <10822mn$3pb8v$[email protected]>,
Arne Vajhøj <[email protected]> wrote:
On 8/18/2025 11:00 PM, Lawrence D’Oliveiro wrote:
On Mon, 18 Aug 2025 21:49:29 -0400, Arne Vajhøj wrote:
On 8/18/2025 7:59 PM, Lawrence D’Oliveiro wrote:
On Mon, 18 Aug 2025 19:48:16 -0400, Arne Vajhøj wrote:
On 8/18/2025 7:45 PM, Lawrence D’Oliveiro wrote:
Parentheses are best used lightly -- where needed, maybe a little >>>>>>> bit more than that, and that’s it.
Otherwise parenthesis clutter introduces its own obstacles to
readability.
That is not the mantra among people who try to prevent future
errors.
There are people who just repeat what they are told, aren’t there, >>>>> instead of learning from actual experience.
It is the recommendation from people with actual experience.
One book that recommend it is "The Practice of Programming".
Brian Kernighan and Rob Pike.
One wonders how much experience they really have, across how many
different languages.
(Wow.)
Brian Kernighan and Rob Pike? A lot! :-)
It may help to read what they actually wrote in TPoP; on page 6:
|_Parenthesize to resolve ambiguity_. Parentheses specify
|grouping and can be used to make the intent clear even when
|they are not required. The inner parentheses in the previous
|example are not necessary, but they don't hurt, either.
|Seasoned programmers might omit them, because the relational
|operators (< <= == != >= >) have higher precedence than the
|logical operators (&& and ||).
|
|When mixing unrelated operators, though, it's a good idea to
|parenthesize. C and its friends present pernicious precedence
|problems, and it's easy to make a mistake.
For reference, the "previous example" they mention here is:
if ((block_id >= actblks) || (block_id < unblocks))
Most C programmers would write this as,
if (block_id >= actblks || block_id < unblocks)
And Kernighan and Pike would be fine with that. It must be
noted that, throughout the rest of TPoP, they rarely
parenthesize as aggressively as they do in that one example.
For example, on page 98, in the discussion of building a CSV
file parser interface, they present a function called,
`advquoted` that contains this line of code:
if (pj] == '"' && p[++j] != '"') {
...
}
(Note this doesn't just omit parenthesis, but also makes use of
the pre-increment operator _and_ boolean short-circuiting.)
Pike is famous for brevity; his 1989 document, "Notes on
Programming in C" is a model here: http://www.literateprogramming.com/pikestyle.pdf
Even now, it's still an interesting read. I like my own code
princples, as well, but of course, I'm biased: https://pub.gajendra.net/2016/03/code_principles
- Dan C.
Two points related to the fact that they have a special operator instead
of just using plain assignment.
On 8/18/2025 11:00 PM, Lawrence D’Oliveiro wrote:
One wonders how much experience they really have, across how many
different languages.
Brian Kernighan and Rob Pike? A lot! :-)
In article <68a493ec$0$710$[email protected]>,
Arne Vajhøj <[email protected]> wrote:
Kotlin is rather picky about mixing signed and unsigned.
var v: UInt = 16u
v = v / 2
gives an error.
v = v / 2u
v = v / 2.toUInt()
works.
I consider that rather picky.
It's kind of annoying that it can't infer to use unsigned for
the '2' in the first example. Rust, for example, does do that
inference which makes most arithmetic very natural.
Even now, it's still an interesting read. I like my own code
princples, as well, but of course, I'm biased: https://pub.gajendra.net/2016/03/code_principles
In article <1081rg2$3njqo$[email protected]>,
Simon Clubley <clubley@remove_me.eisner.decus.org-Earth.UFP> wrote:
I write simple to understand code, not clever code, even when the
problem it is solving is complex or has a lot of functionality
built into the problem.
I've found it makes code more robust and easier for others to read, >>especially when they may not have the knowledge you have when you
wrote the original code.
I'm curious how this expresses itself with respect to e.g. the short-circuiting thing, though. For instance, this might be
common in C:
struct something *p;
...
if (p != NULL && p->ptr != NULL && something(*p->ptr)) {
// Do something here.
}
This, of course, relies on short-circuiting to avoid
dereferncing either `p` or `*p->ptr` if either is NULL. What
is the alternative?
if (p != NULL) {
if (p->ptr != NULL) {
if (something(*p->ptr)) {
// Do something....
}
}
}
If I dare say so, this is strictly worse because the code is now
much more heavily indented.
Ken Thompson used to avoid things like this by writing such code
as:
if (p != NULL)
if (p->ptr != NULL)
if (something(p->ptr)) {
// Do something....
}
Which has a certain elegance to it, but automated code
formatters inevitably don't understand it (and at this point,
one really ought to be using an automated formatter whenever
possible).
AN alternative might be to extract the conditional and put it
into an auxiliary function, and use something similar to
Dijkstra's guarded commands:
void
maybe_do_something(struct something *p)
{
if (p == NULL)
return;
if (p->ptr == NULL)
return;
if (!something(*p->ptr))
return;
// Now do something.
}
I would argue that this is better than the previous example, and
possibly on par with or better than the original: if nothing
else, it gives a name to the operation. This is of course just
a contrived example, so the name here is meaningless, but one
hopes that in a real program a name with some semantic meaning
would be chosen.
On 19/08/2025 17:07, Dan Cross wrote:
In article <10822mn$3pb8v$[email protected]>,
Arne Vajhøj <[email protected]> wrote:
On 8/18/2025 11:00 PM, Lawrence D’Oliveiro wrote:
On Mon, 18 Aug 2025 21:49:29 -0400, Arne Vajhøj wrote:
On 8/18/2025 7:59 PM, Lawrence D’Oliveiro wrote:
On Mon, 18 Aug 2025 19:48:16 -0400, Arne Vajhøj wrote:
On 8/18/2025 7:45 PM, Lawrence D’Oliveiro wrote:
Parentheses are best used lightly -- where needed, maybe a little >>>>>>>> bit more than that, and that’s it.
Otherwise parenthesis clutter introduces its own obstacles to
readability.
That is not the mantra among people who try to prevent future
errors.
There are people who just repeat what they are told, aren’t there, >>>>>> instead of learning from actual experience.
It is the recommendation from people with actual experience.
One book that recommend it is "The Practice of Programming".
Brian Kernighan and Rob Pike.
One wonders how much experience they really have, across how many
different languages.
(Wow.)
Brian Kernighan and Rob Pike? A lot! :-)
It may help to read what they actually wrote in TPoP; on page 6:
|_Parenthesize to resolve ambiguity_. Parentheses specify
|grouping and can be used to make the intent clear even when
|they are not required. The inner parentheses in the previous
|example are not necessary, but they don't hurt, either.
|Seasoned programmers might omit them, because the relational
|operators (< <= == != >= >) have higher precedence than the
|logical operators (&& and ||).
|
|When mixing unrelated operators, though, it's a good idea to
|parenthesize. C and its friends present pernicious precedence
|problems, and it's easy to make a mistake.
For reference, the "previous example" they mention here is:
if ((block_id >= actblks) || (block_id < unblocks))
Most C programmers would write this as,
if (block_id >= actblks || block_id < unblocks)
And Kernighan and Pike would be fine with that. It must be
noted that, throughout the rest of TPoP, they rarely
parenthesize as aggressively as they do in that one example.
For example, on page 98, in the discussion of building a CSV
file parser interface, they present a function called,
`advquoted` that contains this line of code:
if (pj] == '"' && p[++j] != '"') {
...
}
(Note this doesn't just omit parenthesis, but also makes use of
the pre-increment operator _and_ boolean short-circuiting.)
Pike is famous for brevity; his 1989 document, "Notes on
Programming in C" is a model here:
http://www.literateprogramming.com/pikestyle.pdf
Even now, it's still an interesting read. I like my own code
princples, as well, but of course, I'm biased:
https://pub.gajendra.net/2016/03/code_principles
- Dan C.
Interestingly I have just come across an old bit of DEC Basic code:
REPORT.ONLY = W.S4 = "R" ! Global flag
I know what it does, but I would wrapped the knuckles of any programmer
who did that on my shift!
In article <1082lks$3nmtt$[email protected]>,
Chris Townley <[email protected]> wrote:
On 19/08/2025 17:07, Dan Cross wrote:
In article <10822mn$3pb8v$[email protected]>,
Arne Vajhøj <[email protected]> wrote:
On 8/18/2025 11:00 PM, Lawrence D’Oliveiro wrote:
On Mon, 18 Aug 2025 21:49:29 -0400, Arne Vajhøj wrote:
On 8/18/2025 7:59 PM, Lawrence D’Oliveiro wrote:
On Mon, 18 Aug 2025 19:48:16 -0400, Arne Vajhøj wrote:
On 8/18/2025 7:45 PM, Lawrence D’Oliveiro wrote:
Parentheses are best used lightly -- where needed, maybe a little >>>>>>>>> bit more than that, and that’s it.
Otherwise parenthesis clutter introduces its own obstacles to >>>>>>>>> readability.
That is not the mantra among people who try to prevent future
errors.
There are people who just repeat what they are told, aren’t there, >>>>>>> instead of learning from actual experience.
It is the recommendation from people with actual experience.
One book that recommend it is "The Practice of Programming".
Brian Kernighan and Rob Pike.
One wonders how much experience they really have, across how many
different languages.
(Wow.)
Brian Kernighan and Rob Pike? A lot! :-)
It may help to read what they actually wrote in TPoP; on page 6:
|_Parenthesize to resolve ambiguity_. Parentheses specify
|grouping and can be used to make the intent clear even when
|they are not required. The inner parentheses in the previous
|example are not necessary, but they don't hurt, either.
|Seasoned programmers might omit them, because the relational
|operators (< <= == != >= >) have higher precedence than the
|logical operators (&& and ||).
|
|When mixing unrelated operators, though, it's a good idea to
|parenthesize. C and its friends present pernicious precedence
|problems, and it's easy to make a mistake.
For reference, the "previous example" they mention here is:
if ((block_id >= actblks) || (block_id < unblocks))
Most C programmers would write this as,
if (block_id >= actblks || block_id < unblocks)
And Kernighan and Pike would be fine with that. It must be
noted that, throughout the rest of TPoP, they rarely
parenthesize as aggressively as they do in that one example.
For example, on page 98, in the discussion of building a CSV
file parser interface, they present a function called,
`advquoted` that contains this line of code:
if (pj] == '"' && p[++j] != '"') {
...
}
(Note this doesn't just omit parenthesis, but also makes use of
the pre-increment operator _and_ boolean short-circuiting.)
Pike is famous for brevity; his 1989 document, "Notes on
Programming in C" is a model here:
http://www.literateprogramming.com/pikestyle.pdf
Even now, it's still an interesting read. I like my own code
princples, as well, but of course, I'm biased:
https://pub.gajendra.net/2016/03/code_principles
- Dan C.
Interestingly I have just come across an old bit of DEC Basic code:
REPORT.ONLY = W.S4 = "R" ! Global flag
I know what it does, but I would wrapped the knuckles of any programmer
who did that on my shift!
Not knowing DEC BASIC, am I correct in guessing that this
assigns the boolean result of comparing `W.S4` with the string
"R" to `REPORT.ONLY`?
- Dan C.
On 2025-08-19, Dan Cross <[email protected]> wrote:
Even now, it's still an interesting read. I like my own code
princples, as well, but of course, I'm biased:
https://pub.gajendra.net/2016/03/code_principles
I've just read through that document and agree with everything there.
I was especially amused by the write for readability and it will be
read many times comments as I use that wording myself.
I am surprised you are picking me up on some things however, given
the mindset expressed in that document. Perhaps your idea of readability
is different from mine. :-)
On 8/18/2025 8:48 PM, Dan Cross wrote:
In article <68a3b980$0$713$[email protected]>,
Arne Vajhøj <[email protected]> wrote:
But point is that one need to know something about the
languages.
Just picking an operator that "looks like" and hope it
has similar semantics is no good.
This seems like a very extreme example. There is a scale of
knowledge when it comes to programming languages, from the basic
ways in which one does various things like write loops or
perform basic arithmetic, to the minutia of specific library or
IO routines, with semantics of specific operators and how they
combine probably somewhere in the middle.
I happen to disagree with Simon's notion of what makes for
robust programming, but to go to such an extreme as to suggest
that writing code as if logical operators don't short-circuit
is the same as not knowing the semantics of division is
specious.
There are 4 operations:
- short circuiting and
- non short circuiting and
- integer division
- floating point division
Both source and target language has a way of doing those: operator,
function or a more complex expression.
I agree that the risk of someone not understanding "division"
ways is much less than the risk of someone not understanding
"and" ways.
On 2025-08-19, Dan Cross <[email protected]> wrote:
In article <68a493ec$0$710$[email protected]>,
Arne Vajhøj <[email protected]> wrote:
Kotlin is rather picky about mixing signed and unsigned.
var v: UInt = 16u
v = v / 2
gives an error.
v = v / 2u
v = v / 2.toUInt()
works.
I consider that rather picky.
I've not used Kotlin, but I consider that to be the really good type
of picky. :-)
It's kind of annoying that it can't infer to use unsigned for
the '2' in the first example. Rust, for example, does do that
inference which makes most arithmetic very natural.
I actually consider that to be a good thing. The programmer is forced
to think about what they have written and to change it to make those >intentions explicit in the code. I like this.
On 2025-08-19, Dan Cross <[email protected]> wrote:
In article <1081rg2$3njqo$[email protected]>,
Simon Clubley <clubley@remove_me.eisner.decus.org-Earth.UFP> wrote:
I write simple to understand code, not clever code, even when the
problem it is solving is complex or has a lot of functionality
built into the problem.
I've found it makes code more robust and easier for others to read, >>>especially when they may not have the knowledge you have when you
wrote the original code.
I'm curious how this expresses itself with respect to e.g. the
short-circuiting thing, though. For instance, this might be
common in C:
struct something *p;
...
if (p != NULL && p->ptr != NULL && something(*p->ptr)) {
// Do something here.
}
This, of course, relies on short-circuiting to avoid
dereferncing either `p` or `*p->ptr` if either is NULL. What
is the alternative?
if (p != NULL) {
if (p->ptr != NULL) {
if (something(*p->ptr)) {
// Do something....
}
}
}
If I dare say so, this is strictly worse because the code is now
much more heavily indented.
Indented properly (not as in your next example!) I find that very
readable and is mostly how I would write it although I do use code
like your return example when appropriate. This is my variant:
if (p != NULL)
{
if (p->ptr != NULL)
{
if (something(*p->ptr))
{
// Do something....
}
}
}
In case that doesn't survive a NNTP client, it is in Whitesmiths format:
https://en.wikipedia.org/wiki/Indentation_style#Whitesmiths
I like to spread out code vertically as I find it is easier to read.
We are no longer in the era of VT50/52/100 terminals. :-)
Ken Thompson used to avoid things like this by writing such code
as:
if (p != NULL)
if (p->ptr != NULL)
if (something(p->ptr)) {
// Do something....
}
YUCK * 1000!!! That's horrible!!! :-)
Which has a certain elegance to it, but automated code
formatters inevitably don't understand it (and at this point,
one really ought to be using an automated formatter whenever
possible).
AN alternative might be to extract the conditional and put it
into an auxiliary function, and use something similar to
Dijkstra's guarded commands:
void
maybe_do_something(struct something *p)
{
if (p == NULL)
return;
if (p->ptr == NULL)
return;
if (!something(*p->ptr))
return;
// Now do something.
}
I would argue that this is better than the previous example, and
possibly on par with or better than the original: if nothing
else, it gives a name to the operation. This is of course just
a contrived example, so the name here is meaningless, but one
hopes that in a real program a name with some semantic meaning
would be chosen.
There is one difference for me here however. _All_ single conditional >statements as in the above example are placed in braces to help avoid
the possibility of a later editing error.
readable and is mostly how I would write it although I do use code
like your return example when appropriate. This is my variant:
if (p != NULL)
{
if (p->ptr != NULL)
{
if (something(*p->ptr))
{
// Do something....
}
}
}
In case that doesn't survive a NNTP client, it is in Whitesmiths format:
In article <1084fca$afbj$[email protected]>,
Simon Clubley <clubley@remove_me.eisner.decus.org-Earth.UFP> wrote:
On 2025-08-19, Dan Cross <[email protected]> wrote:
Even now, it's still an interesting read. I like my own code
princples, as well, but of course, I'm biased:
https://pub.gajendra.net/2016/03/code_principles
I've just read through that document and agree with everything there.
I was especially amused by the write for readability and it will be
read many times comments as I use that wording myself.
I am surprised you are picking me up on some things however, given
the mindset expressed in that document. Perhaps your idea of readability
is different from mine. :-)
Oh, I hope any criticism I offer doesn't come across as
personal!
On 20/08/2025 16:03, Dan Cross wrote:
In article <1082lks$3nmtt$[email protected]>,
Chris Townley <[email protected]> wrote:
[snip]
Interestingly I have just come across an old bit of DEC Basic code:
REPORT.ONLY = W.S4 = "R" ! Global flag
I know what it does, but I would wrapped the knuckles of any programmer
who did that on my shift!
Not knowing DEC BASIC, am I correct in guessing that this
assigns the boolean result of comparing `W.S4` with the string
"R" to `REPORT.ONLY`?
Correct, but I would have surrounded the comparison with brackets, or
used an IF statement.
Not quite as bad as a colleague who found source code file for a
function, that ended with an UNLESS Z
Z was a global not mentioned in the source file! Try searching a massive >codebase for Z!
On 2025-08-20, Dan Cross <[email protected]> wrote:
In article <1084fca$afbj$[email protected]>,
Simon Clubley <clubley@remove_me.eisner.decus.org-Earth.UFP> wrote:
On 2025-08-19, Dan Cross <[email protected]> wrote:
Even now, it's still an interesting read. I like my own code
princples, as well, but of course, I'm biased:
https://pub.gajendra.net/2016/03/code_principles
I've just read through that document and agree with everything there.
I was especially amused by the write for readability and it will be
read many times comments as I use that wording myself.
I am surprised you are picking me up on some things however, given
the mindset expressed in that document. Perhaps your idea of readability >>>is different from mine. :-)
Oh, I hope any criticism I offer doesn't come across as
personal!
No, it absolutely does _not_ in any way.
For me, it's exactly the same as a colleague noticing something
in another colleague's code or design proposal and commenting on it.
You would have to be extremely fragile to take _that_ personally. :-)
On 20/08/2025 13:27, Simon Clubley wrote:
<big snip>> Indented properly (not as in your next example!) I find that
very
readable and is mostly how I would write it although I do use code
like your return example when appropriate. This is my variant:
if (p != NULL)
{
if (p->ptr != NULL)
{
if (something(*p->ptr))
{
// Do something....
}
}
}
In case that doesn't survive a NNTP client, it is in Whitesmiths format:
<snip>
That is why I don't like Whitesmiths
To me the curly braces should logically align with the preceding statement.
When I first looked at he example, I immediately thought there is a
missing closing brace, which of course there isn't.
I also dislike putting the opening brace at the end of the preceding
line, although I have had to in some cases. Probably a Microsoft invention
On 20/08/2025 16:03, Dan Cross wrote:
In article <1082lks$3nmtt$[email protected]>,
Chris Townley <[email protected]> wrote:
On 19/08/2025 17:07, Dan Cross wrote:
In article <10822mn$3pb8v$[email protected]>,
Arne Vajhøj <[email protected]> wrote:
On 8/18/2025 11:00 PM, Lawrence D’Oliveiro wrote:
On Mon, 18 Aug 2025 21:49:29 -0400, Arne Vajhøj wrote:
On 8/18/2025 7:59 PM, Lawrence D’Oliveiro wrote:
On Mon, 18 Aug 2025 19:48:16 -0400, Arne Vajhøj wrote:
On 8/18/2025 7:45 PM, Lawrence D’Oliveiro wrote:
Parentheses are best used lightly -- where needed, maybe a little >>>>>>>>>> bit more than that, and that’s it.
Otherwise parenthesis clutter introduces its own obstacles to >>>>>>>>>> readability.
That is not the mantra among people who try to prevent future >>>>>>>>> errors.
There are people who just repeat what they are told, aren’t there, >>>>>>>> instead of learning from actual experience.
It is the recommendation from people with actual experience.
One book that recommend it is "The Practice of Programming".
Brian Kernighan and Rob Pike.
One wonders how much experience they really have, across how many
different languages.
(Wow.)
Brian Kernighan and Rob Pike? A lot! :-)
It may help to read what they actually wrote in TPoP; on page 6:
|_Parenthesize to resolve ambiguity_. Parentheses specify
|grouping and can be used to make the intent clear even when
|they are not required. The inner parentheses in the previous
|example are not necessary, but they don't hurt, either.
|Seasoned programmers might omit them, because the relational
|operators (< <= == != >= >) have higher precedence than the
|logical operators (&& and ||).
|
|When mixing unrelated operators, though, it's a good idea to
|parenthesize. C and its friends present pernicious precedence
|problems, and it's easy to make a mistake.
For reference, the "previous example" they mention here is:
if ((block_id >= actblks) || (block_id < unblocks))
Most C programmers would write this as,
if (block_id >= actblks || block_id < unblocks)
And Kernighan and Pike would be fine with that. It must be
noted that, throughout the rest of TPoP, they rarely
parenthesize as aggressively as they do in that one example.
For example, on page 98, in the discussion of building a CSV
file parser interface, they present a function called,
`advquoted` that contains this line of code:
if (pj] == '"' && p[++j] != '"') {
...
}
(Note this doesn't just omit parenthesis, but also makes use of
the pre-increment operator _and_ boolean short-circuiting.)
Pike is famous for brevity; his 1989 document, "Notes on
Programming in C" is a model here:
http://www.literateprogramming.com/pikestyle.pdf
Even now, it's still an interesting read. I like my own code
princples, as well, but of course, I'm biased:
https://pub.gajendra.net/2016/03/code_principles
- Dan C.
Interestingly I have just come across an old bit of DEC Basic code:
REPORT.ONLY = W.S4 = "R" ! Global flag
I know what it does, but I would wrapped the knuckles of any programmer
who did that on my shift!
Not knowing DEC BASIC, am I correct in guessing that this
assigns the boolean result of comparing `W.S4` with the string
"R" to `REPORT.ONLY`?
- Dan C.
Correct, but I would have surrounded the comparison with brackets, or used an IF
statement.
Not quite as bad as a colleague who found source code file for a function, that
ended with an UNLESS Z
Z was a global not mentioned in the source file! Try searching a massive codebase for Z!
On 8/20/2025 11:11 AM, Chris Townley wrote:
On 20/08/2025 16:03, Dan Cross wrote:
In article <1082lks$3nmtt$[email protected]>,
Chris Townley <[email protected]> wrote:
Interestingly I have just come across an old bit of DEC Basic code:
REPORT.ONLY = W.S4 = "R" ! Global flag
I know what it does, but I would wrapped the knuckles of any programmer >>>> who did that on my shift!
Not knowing DEC BASIC, am I correct in guessing that this
assigns the boolean result of comparing `W.S4` with the string
"R" to `REPORT.ONLY`?
Correct, but I would have surrounded the comparison with brackets, or
used an IF
statement.
That statement could make a person think for a while. Not a bad thing, being able to understand something like that. However, I've always been
a big fan of clarity, so go ahead and wack some knuckles.
1) VMS Basic using = for both assignment and equal comparison,
while most other languages use different symbols (= and ==,
:= and =, = and .eq., ...)
But they only apply to non VMS Basic developers.
On 8/20/2025 11:11 AM, Chris Townley wrote:
Not quite as bad as a colleague who found source code file for a
function, that ended with an UNLESS Z
Z was a global not mentioned in the source file! Try searching a
massive codebase for Z!
A good IDE that understand the language syntax can search
for it. But I must admit that I don't know if LSE or VMS IDE
can do it.
For a zero language knowledge search tool, you could have gone
for a regex search, since it must be limited what can come
right before and right after Z in the declaration.
Arne
Not quite as bad as a colleague who found source code file for a
function, that ended with an UNLESS Z
Z was a global not mentioned in the source file! Try searching a massive codebase for Z!
On Tue, 19 Aug 2025 10:54:30 -0400, Arne Vajhøj wrote:
Two points related to the fact that they have a special operator instead
of just using plain assignment.
It’s yet another mechanism for local scoping within an expression. Python doesn’t allow statement blocks within expressions, but it has for- expressions where the for-variables are strictly local to the expression.
To this has been added the walrus. But the walrus is (mostly) unnecessary; you can use a for-expression that iterates over just one value, to get the same effect.
In article <1084drl$afbj$[email protected]>,
Simon Clubley <clubley@remove_me.eisner.decus.org-Earth.UFP> wrote:
On 2025-08-19, Dan Cross <[email protected]> wrote:
In article <68a493ec$0$710$[email protected]>,
Arne Vajhøj <[email protected]> wrote:
Kotlin is rather picky about mixing signed and unsigned.
var v: UInt = 16u
v = v / 2
gives an error.
v = v / 2u
v = v / 2.toUInt()
works.
I consider that rather picky.
I've not used Kotlin, but I consider that to be the really good type
of picky. :-)
It's kind of annoying that it can't infer to use unsigned for
the '2' in the first example. Rust, for example, does do that
inference which makes most arithmetic very natural.
I actually consider that to be a good thing. The programmer is forced
to think about what they have written and to change it to make those
intentions explicit in the code. I like this.
I think the point is, that in cases like this, the compiler
enforces the explicit typing anyway: if the program compiles, it
is well-typed. If it does not, then it is not. In that
context, this level of explicitness adds little, if any,
additional value.
That the literal "2" is a different type than "2u" is
interesting, however, and goes back to what you were saying
earlier about default signedness. As a mathematical object,
"2" is just a positive integer, but programming languages are
not _really_ a mathematical notation, so the need to be explicit
here makes sense from that perspective, I guess.
In Rust, I might write this sequence as:
let mut v = 16u32;
v = v / 2;
And the type inference mechanism would deduce that 2 should be
treated as a `u32`. But I could just as easily write,
let mut v = 16u32;
v = v / 2u32;
Which explicitly calls out that 2 as a `u32`.
Is this really better, though? This is where I'd argue that
matters of idiom come into play: this is not idiomatic usage in
the language, and so it is probably not better, and maybe worse.
And despite the old admonition to make everything a symbolic
constant, things like `2 * pi * r` are perfectly readable, and
I'd argue that `TWO * pi * r` are less so.
In article <10823ei$3pb8v$[email protected]>,
Arne Vajhøj <[email protected]> wrote:
On 8/19/2025 9:01 AM, Simon Clubley wrote:
On 2025-08-18, Dan Cross <[email protected]> wrote:
I happen to disagree with Simon's notion of what makes for
robust programming, but to go to such an extreme as to suggest
that writing code as if logical operators don't short-circuit
is the same as not knowing the semantics of division is
specious.
That last one is an interesting example. I may not care about
short circuiting, but I am _very_ _very_ aware of the combined
unsigned integers and signed integers issues in C expressions. :-(
It also affects how I look at the same issues in other languages.
I've mentioned this before, but I think languages should give you
unsigned integers by default, and you should have to ask for
a signed integer if you really want one.
"by default" sort of imply signedness being an attribute of
same type.
Why not just make it two different types with different names?
Whether we follow tradition and call them integer and cardinal
or more modern style and call them int and uint is less important.
I would argue that, at this point, there's little need for a
generic "int" type anymore, and that types representing integers
as understood by the machine should explicitly include both
signedness and width. An exception may be something like,
`size_t`, which is platform-dependent, but when transferred
externally should be given an explicit size. A lot of the
guesswork and folklore that goes into understanding the
semantics of those things just disappears when you're explicit.
The walrus operator is so much not local.
On 8/19/2025 1:26 PM, Dan Cross wrote:
In article <10823ei$3pb8v$[email protected]>,
Arne Vajhøj <[email protected]> wrote:
On 8/19/2025 9:01 AM, Simon Clubley wrote:
On 2025-08-18, Dan Cross <[email protected]> wrote:
I happen to disagree with Simon's notion of what makes for
robust programming, but to go to such an extreme as to suggest
that writing code as if logical operators don't short-circuit
is the same as not knowing the semantics of division is
specious.
That last one is an interesting example. I may not care about
short circuiting, but I am _very_ _very_ aware of the combined
unsigned integers and signed integers issues in C expressions. :-(
It also affects how I look at the same issues in other languages.
I've mentioned this before, but I think languages should give you
unsigned integers by default, and you should have to ask for
a signed integer if you really want one.
"by default" sort of imply signedness being an attribute of
same type.
Why not just make it two different types with different names?
Whether we follow tradition and call them integer and cardinal
or more modern style and call them int and uint is less important.
I would argue that, at this point, there's little need for a
generic "int" type anymore, and that types representing integers
as understood by the machine should explicitly include both
signedness and width. An exception may be something like,
`size_t`, which is platform-dependent, but when transferred
externally should be given an explicit size. A lot of the
guesswork and folklore that goes into understanding the
semantics of those things just disappears when you're explicit.
The integer types should have well defined width.
And they could also be called int32 and uint32.
That seems to be in fashion in low level languages
competing with C.
Many higher level languages just define that int is 32 bit,
but don't show it in the name.
On 8/20/2025 11:51 AM, Dan Cross wrote:
In article <1084drl$afbj$[email protected]>,
Simon Clubley <clubley@remove_me.eisner.decus.org-Earth.UFP> wrote:
On 2025-08-19, Dan Cross <[email protected]> wrote:
In article <68a493ec$0$710$[email protected]>,
Arne Vajhøj <[email protected]> wrote:
Kotlin is rather picky about mixing signed and unsigned.
var v: UInt = 16u
v = v / 2
gives an error.
v = v / 2u
v = v / 2.toUInt()
works.
I consider that rather picky.
I've not used Kotlin, but I consider that to be the really good type
of picky. :-)
It's kind of annoying that it can't infer to use unsigned for
the '2' in the first example. Rust, for example, does do that
inference which makes most arithmetic very natural.
I actually consider that to be a good thing. The programmer is forced
to think about what they have written and to change it to make those
intentions explicit in the code. I like this.
I think the point is, that in cases like this, the compiler
enforces the explicit typing anyway: if the program compiles, it
is well-typed. If it does not, then it is not. In that
context, this level of explicitness adds little, if any,
additional value.
That the literal "2" is a different type than "2u" is
interesting, however, and goes back to what you were saying
earlier about default signedness. As a mathematical object,
"2" is just a positive integer, but programming languages are
not _really_ a mathematical notation, so the need to be explicit
here makes sense from that perspective, I guess.
In Rust, I might write this sequence as:
let mut v = 16u32;
v = v / 2;
And the type inference mechanism would deduce that 2 should be
treated as a `u32`. But I could just as easily write,
let mut v = 16u32;
v = v / 2u32;
Which explicitly calls out that 2 as a `u32`.
Is this really better, though? This is where I'd argue that
matters of idiom come into play: this is not idiomatic usage in
the language, and so it is probably not better, and maybe worse.
The practical difference for specific code is likely zero.
But there is a difference in language principles and the
confidence the developer can have in it.
A rule that there is never any implicit conversion or
literal inference no matter the context is simple to
understand and gives confidence.
Exceptions even in cases where it does not matter adds
the complexity of understanding when the exceptions apply
and why they do not matter. Complexity that developers
would rather avoid.
On 8/19/2025 1:26 PM, Dan Cross wrote:
And despite the old admonition to make everything a symbolic
constant, things like `2 * pi * r` are perfectly readable, and
I'd argue that `TWO * pi * r` are less so.
I would say that TWO and 2 are the same regarding readability.
The problem with TWO is not readability, but lack of purpose.
There are two good reasons to introduce symbolic names for constants:
1) The name can be more self documenting than a numeric value
2) If the constant is used multiple places, then having a symbolic
name makes it easier to change the value
But neither applies.
TWO does not provide more information than 2.
And it would be very unwise to change the value of TWO
to something different from 2.
In article <108dlq4$2fi6h$[email protected]>,
Arne Vajhøj <[email protected]> wrote:
On 8/19/2025 1:26 PM, Dan Cross wrote:
In article <10823ei$3pb8v$[email protected]>,
Arne Vajhøj <[email protected]> wrote:
Whether we follow tradition and call them integer and cardinal
or more modern style and call them int and uint is less important.
I would argue that, at this point, there's little need for a
generic "int" type anymore, and that types representing integers
as understood by the machine should explicitly include both
signedness and width. An exception may be something like,
`size_t`, which is platform-dependent, but when transferred
externally should be given an explicit size. A lot of the
guesswork and folklore that goes into understanding the
semantics of those things just disappears when you're explicit.
The integer types should have well defined width.
And they could also be called int32 and uint32.
That seems to be in fashion in low level languages
competing with C.
Many higher level languages just define that int is 32 bit,
but don't show it in the name.
If by "many higher level languages" you mean languages in the
JVM and CLR ecosystem, then sure, I guess so. But it's not
universal, and I don't see how it's an improvement.
On Sun, 24 Aug 2025 19:52:52 -0400, Arne Vajhøj wrote:
(... somehow they fucked up longint and made it 32 bit on 32 bit and
64 bit Windows but 64 bit on 64 bit *nix)
It was *Microsoft* that “fucked up longint”, and nobody else. Just to be clear.
On Sun, 24 Aug 2025 19:52:52 -0400, Arne Vajhøj wrote:
(... somehow they fucked up longint and made it 32 bit on 32 bit and
64 bit Windows but 64 bit on 64 bit *nix)
It was *Microsoft* that “fucked up longint”, and nobody else. Just to be clear.
(... somehow they fucked up longint and made it 32 bit on 32 bit and
64 bit Windows but 64 bit on 64 bit *nix)
On Sat, 23 Aug 2025 19:45:19 -0400, Arne Vajhøj wrote:
1) VMS Basic using = for both assignment and equal comparison,
while most other languages use different symbols (= and ==,
:= and =, = and .eq., ...)
But they only apply to non VMS Basic developers.
Nearly all BASICs were like that, including I think Microsoft BASIC.
But note that DEC made half step first: Alpha is 64-bit machine and
DEC made long 32-bit on Alpha.
On Mon, 25 Aug 2025 02:05:37 -0000 (UTC), Waldek Hebisch wrote:
But note that DEC made half step first: Alpha is 64-bit machine and
DEC made long 32-bit on Alpha.
On DEC Unix, as on every other *nix, “int” was 32 bits and “long” was 64
bits. This applied on Alpha, too.
On Sat, 23 Aug 2025 23:49:14 -0000 (UTC), Lawrence D’Oliveiro wrote:
On Sat, 23 Aug 2025 19:45:19 -0400, Arne Vajhøj wrote:
1) VMS Basic using = for both assignment and equal comparison,
while most other languages use different symbols (= and ==,
:= and =, = and .eq., ...)
But they only apply to non VMS Basic developers.
Nearly all BASICs were like that, including I think Microsoft BASIC.
One trick they missed was allowing interval comparisons like this:
if "0" <= ch <= "9" or "a" <= ch <= "f" or "A" <= ch <= "F" :
I think only Python has that.
On 8/24/2025 10:34 PM, Lawrence D?Oliveiro wrote:
One trick they missed was allowing interval comparisons like this:
if "0" <= ch <= "9" or "a" <= ch <= "f" or "A" <= ch <= "F" :
I think only Python has that.
Yes.
But note that the feature is not "interval comparison" but
"chaining comparison operators".
The above example is very readable and makes sense.
But it is less obvious with other operators.
Example:
4 == 4 == True
Most languages (possible all exception Python) evaluate
that to True, because it is treated like:
(4 == 4) == True
But it is False in Python because it is treated like:
(4 == 4) and (4 == True)
Which feels less natural.
On 2025-08-25, Arne Vajhøj <[email protected]> wrote:
On 8/24/2025 10:34 PM, Lawrence D?Oliveiro wrote:
One trick they missed was allowing interval comparisons like this:
if "0" <= ch <= "9" or "a" <= ch <= "f" or "A" <= ch <= "F" :
I think only Python has that.
Yes.
But note that the feature is not "interval comparison" but
"chaining comparison operators".
The above example is very readable and makes sense.
Just don't try getting that code past me without first having used
brackets around the subexpressions. :-)
But it is less obvious with other operators.
Example:
4 == 4 == True
Most languages (possible all exception Python) evaluate
that to True, because it is treated like:
(4 == 4) == True
But it is False in Python because it is treated like:
(4 == 4) and (4 == True)
Which feels less natural.
And _this_ is an example of why Simon's policy of backets around
everything makes it explicitly clear what was intended. :-)
I am all for shoveling lots of parenthesis's all over the code to make
it really obvious.
On 2025-08-25, Arne Vajhøj <[email protected]> wrote:
On 8/24/2025 10:34 PM, Lawrence D?Oliveiro wrote:
One trick they missed was allowing interval comparisons like this:
if "0" <= ch <= "9" or "a" <= ch <= "f" or "A" <= ch <= "F" :
I think only Python has that.
Yes.
But note that the feature is not "interval comparison" but
"chaining comparison operators".
The above example is very readable and makes sense.
Just don't try getting that code past me without first having used
brackets around the subexpressions. :-)
True1 < 3 < 4
False1 < (3 < 4)
On 2025-08-25, Arne Vajh�j <[email protected]> wrote:
On 8/24/2025 10:34 PM, Lawrence D?Oliveiro wrote:
One trick they missed was allowing interval comparisons like this:
if "0" <= ch <= "9" or "a" <= ch <= "f" or "A" <= ch <= "F" :
I think only Python has that.
Yes.
But note that the feature is not "interval comparison" but
"chaining comparison operators".
The above example is very readable and makes sense.
Just don't try getting that code past me without first having used
brackets around the subexpressions. :-)
But it is less obvious with other operators.
Example:
4 == 4 == True
Most languages (possible all exception Python) evaluate
that to True, because it is treated like:
(4 == 4) == True
But it is False in Python because it is treated like:
(4 == 4) and (4 == True)
Which feels less natural.
And _this_ is an example of why Simon's policy of backets around
everything makes it explicitly clear what was intended. :-)
On 8/29/2025 9:11 AM, Dan Cross wrote:
In article <108k9de$1f69$[email protected]>,
Simon Clubley <clubley@remove_me.eisner.decus.org-Earth.UFP> wrote:
On 2025-08-25, Arne Vajhøj <[email protected]> wrote:
[snip]
But it is less obvious with other operators.
Example:
4 == 4 == True
Most languages (possible all exception Python) evaluate
that to True, because it is treated like:
(4 == 4) == True
But it is False in Python because it is treated like:
(4 == 4) and (4 == True)
Which feels less natural.
And _this_ is an example of why Simon's policy of backets around
everything makes it explicitly clear what was intended. :-)
*At some expense for expert users.
Which again, comes back to what I think is _actually_ the
interesting question: who do we write these programs for?
Which is why I always preferred working for people with well defined
local coding (and comment) standards. And, yes, I have worked for both.
On 8/24/2025 7:27 PM, Dan Cross wrote:
In article <108dlq4$2fi6h$[email protected]>,
Arne Vajhøj <[email protected]> wrote:
On 8/19/2025 1:26 PM, Dan Cross wrote:
In article <10823ei$3pb8v$[email protected]>,
Arne Vajhøj <[email protected]> wrote:
Whether we follow tradition and call them integer and cardinal
or more modern style and call them int and uint is less important.
I would argue that, at this point, there's little need for a
generic "int" type anymore, and that types representing integers
as understood by the machine should explicitly include both
signedness and width. An exception may be something like,
`size_t`, which is platform-dependent, but when transferred
externally should be given an explicit size. A lot of the
guesswork and folklore that goes into understanding the
semantics of those things just disappears when you're explicit.
The integer types should have well defined width.
And they could also be called int32 and uint32.
That seems to be in fashion in low level languages
competing with C.
Many higher level languages just define that int is 32 bit,
but don't show it in the name.
If by "many higher level languages" you mean languages in the
JVM and CLR ecosystem, then sure, I guess so. But it's not
universal, and I don't see how it's an improvement.
That are two huge group of languages with a pretty big
market share in business applications.
Delphi provide both flavors. shortint/smallint/integer
and int8/int16/int32, byte/word/cardinal and
uint8/uint16/uint32. I believe the first are the most
widely used.
(64 bit is just int64 and uint64, because somehow they
fucked up longint and made it 32 bit on 32 bit and 64 bit
Windows but 64 bit on 64 bit *nix)
On 8/29/2025 9:24 AM, Dan Cross wrote:
In article <[email protected]>,
bill <[email protected]> wrote:
On 8/29/2025 9:11 AM, Dan Cross wrote:
In article <108k9de$1f69$[email protected]>,
Simon Clubley <clubley@remove_me.eisner.decus.org-Earth.UFP> wrote:
On 2025-08-25, Arne Vajhøj <[email protected]> wrote:
[snip]
But it is less obvious with other operators.
Example:
4 == 4 == True
Most languages (possible all exception Python) evaluate
that to True, because it is treated like:
(4 == 4) == True
But it is False in Python because it is treated like:
(4 == 4) and (4 == True)
Which feels less natural.
And _this_ is an example of why Simon's policy of backets around
everything makes it explicitly clear what was intended. :-)
*At some expense for expert users.
Which again, comes back to what I think is _actually_ the
interesting question: who do we write these programs for?
Which is why I always preferred working for people with well defined
local coding (and comment) standards. And, yes, I have worked for both.
Yup, though this doesn't _really_ address the question.
But yes: having a locally agreed upon style for such things is a
_huge_ boon for maintainability, particularly across a large
codebase. Sure, it's fun to belly up to the virtual bar and
debate the relative merits of different styles on USENET,
complete with contrived examples for or against different
conventions. But the reality is that if one is consistent
within a code base, it doesn't really matter all that much;
competent programmers will absorb the rules in a matter of days
or weeks.
The issue is that someone has to define the style and then
mandate its use, and it has to be enforced through rigorous
review and automated tooling. Given a sufficiently large group
of users, not everyone is going to agree with every rule; the
trick is in getting them to follow those rules regardless.
If you are an employee you either comply, find a new position
or get fired. No real trick at all.
Which again, comes back to what I think is _actually_ the
interesting question: who do we write these programs for?
On 2025-08-29, Dan Cross <[email protected]> wrote:
Which again, comes back to what I think is _actually_ the
interesting question: who do we write these programs for?
You write them for the people who come after you who have to
maintain and extend them. People who have a good understanding
of the language but may have your level of expertise/knowledge/skills.
You write them for the people who understand most of the algorithms
involved, but maybe not at the level you do.
You also write them for yourself a couple of years from now and who
is now looking at this code written a couple of years ago and is now wondering which &*%&^% idiot wrote this code like this in the first
place :-)
On 2025-08-29, Dan Cross <[email protected]> wrote:
Which again, comes back to what I think is _actually_ the
interesting question: who do we write these programs for?
You write them for the people who come after you who have to
maintain and extend them. People who have a good understanding
of the language but may have your level of expertise/knowledge/skills.
You write them for the people who understand most of the algorithms
involved, but maybe not at the level you do.
You also write them for yourself a couple of years from now and who
is now looking at this code written a couple of years ago and is now wondering which &*%&^% idiot wrote this code like this in the first
place :-)
On 2025-08-29, Dan Cross <[email protected]> wrote:
Which again, comes back to what I think is _actually_ the
interesting question: who do we write these programs for?
You write them for the people who come after you who have to
maintain and extend them. People who have a good understanding
of the language but may have your level of expertise/knowledge/skills.
You write them for the people who understand most of the algorithms
involved, but maybe not at the level you do.
You also write them for yourself a couple of years from now and who
is now looking at this code written a couple of years ago and is now >wondering which &*%&^% idiot wrote this code like this in the first
place :-)
In article <108g8kk$33isk$[email protected]>,
Arne Vajhøj <[email protected]> wrote:
On 8/24/2025 7:27 PM, Dan Cross wrote:
In article <108dlq4$2fi6h$[email protected]>,
Arne Vajhøj <[email protected]> wrote:
On 8/19/2025 1:26 PM, Dan Cross wrote:
In article <10823ei$3pb8v$[email protected]>,
Arne Vajhøj <[email protected]> wrote:
Whether we follow tradition and call them integer and cardinal
or more modern style and call them int and uint is less important.
I would argue that, at this point, there's little need for a
generic "int" type anymore, and that types representing integers
as understood by the machine should explicitly include both
signedness and width. An exception may be something like,
`size_t`, which is platform-dependent, but when transferred
externally should be given an explicit size. A lot of the
guesswork and folklore that goes into understanding the
semantics of those things just disappears when you're explicit.
The integer types should have well defined width.
And they could also be called int32 and uint32.
That seems to be in fashion in low level languages
competing with C.
Many higher level languages just define that int is 32 bit,
but don't show it in the name.
If by "many higher level languages" you mean languages in the
JVM and CLR ecosystem, then sure, I guess so. But it's not
universal, and I don't see how it's an improvement.
That are two huge group of languages with a pretty big
market share in business applications.
Market share is not the same as influence, and while the JVM/CLR
languages _do_ have a lot of users, that does not imply that all
are good languages. In fact, only a handful of languages in
each family have any significant adoption, and I don't think PL
designers are mining them for much inspiration these days.
Again, not universal, nor really an improvement over just using
explicitly sized types.
Delphi provide both flavors. shortint/smallint/integer
and int8/int16/int32, byte/word/cardinal and
uint8/uint16/uint32. I believe the first are the most
widely used.
The older names feel like they're very much looking backwards in
time.
(64 bit is just int64 and uint64, because somehow they
fucked up longint and made it 32 bit on 32 bit and 64 bit
Windows but 64 bit on 64 bit *nix)
I'd blame C for that.
In article <108k9de$1f69$[email protected]>,
Simon Clubley <clubley@remove_me.eisner.decus.org-Earth.UFP> wrote:
And _this_ is an example of why Simon's policy of backets around
everything makes it explicitly clear what was intended. :-)
*At some expense for expert users.
On 8/29/2025 9:11 AM, Dan Cross wrote:
In article <108k9de$1f69$[email protected]>,
Simon Clubley <clubley@remove_me.eisner.decus.org-Earth.UFP> wrote:
And _this_ is an example of why Simon's policy of backets around
everything makes it explicitly clear what was intended. :-)
*At some expense for expert users.
I doubt that.
I would expect with parenthesis's:
actually read expression : 2 second
thinking "nice to see good craftmanship" : 1 second
and without:
actually read expression : 1.9 second
thinking "arghh - this code looks written in hast - should I raise an
issue? No - there are probably more important issues!" : 3 seconds
:-)
On 8/29/2025 9:17 AM, Dan Cross wrote:
In article <108g8kk$33isk$[email protected]>,
Arne Vajhøj <[email protected]> wrote:
On 8/24/2025 7:27 PM, Dan Cross wrote:
In article <108dlq4$2fi6h$[email protected]>,
Arne Vajhøj <[email protected]> wrote:
On 8/19/2025 1:26 PM, Dan Cross wrote:
In article <10823ei$3pb8v$[email protected]>,
Arne Vajhøj <[email protected]> wrote:
Whether we follow tradition and call them integer and cardinalI would argue that, at this point, there's little need for a
or more modern style and call them int and uint is less important. >>>>>>
generic "int" type anymore, and that types representing integers
as understood by the machine should explicitly include both
signedness and width. An exception may be something like,
`size_t`, which is platform-dependent, but when transferred
externally should be given an explicit size. A lot of the
guesswork and folklore that goes into understanding the
semantics of those things just disappears when you're explicit.
The integer types should have well defined width.
And they could also be called int32 and uint32.
That seems to be in fashion in low level languages
competing with C.
Many higher level languages just define that int is 32 bit,
but don't show it in the name.
If by "many higher level languages" you mean languages in the
JVM and CLR ecosystem, then sure, I guess so. But it's not
universal, and I don't see how it's an improvement.
That are two huge group of languages with a pretty big
market share in business applications.
Market share is not the same as influence, and while the JVM/CLR
languages _do_ have a lot of users, that does not imply that all
are good languages. In fact, only a handful of languages in
each family have any significant adoption, and I don't think PL
designers are mining them for much inspiration these days.
Again, not universal, nor really an improvement over just using
explicitly sized types.
It is a huge domain that are totally dominated by two approaches:
[snip]
Delphi provide both flavors. shortint/smallint/integer
and int8/int16/int32, byte/word/cardinal and
uint8/uint16/uint32. I believe the first are the most
widely used.
The older names feel like they're very much looking backwards in
time.
Developers tend to like what they know.
(64 bit is just int64 and uint64, because somehow they
fucked up longint and made it 32 bit on 32 bit and 64 bit
Windows but 64 bit on 64 bit *nix)
I'd blame C for that.
Delphi is not C.
In article <68b2087a$0$712$[email protected]>,
Arne Vajhøj <[email protected]> wrote:
On 8/29/2025 9:11 AM, Dan Cross wrote:
In article <108k9de$1f69$[email protected]>,
Simon Clubley <clubley@remove_me.eisner.decus.org-Earth.UFP> wrote:
And _this_ is an example of why Simon's policy of backets around
everything makes it explicitly clear what was intended. :-)
*At some expense for expert users.
I doubt that.
I would expect with parenthesis's:
actually read expression : 2 second
thinking "nice to see good craftmanship" : 1 second
if ((a == 6) || (a == 7)) {
// do the thing...
}
"Huh; I wonder why they parenthesized `a == 6` and `a == 7`....
the operator precedence is obvious, so what am I missing here?
In article <108t0d4$249vm$[email protected]>,
Arne Vajhøj <[email protected]> wrote:
On 8/29/2025 9:17 AM, Dan Cross wrote:
In article <108g8kk$33isk$[email protected]>,
Arne Vajhøj <[email protected]> wrote:
Delphi provide both flavors. shortint/smallint/integer
and int8/int16/int32, byte/word/cardinal and
uint8/uint16/uint32. I believe the first are the most
widely used.
The older names feel like they're very much looking backwards in
time.
Developers tend to like what they know.
(64 bit is just int64 and uint64, because somehow they
fucked up longint and made it 32 bit on 32 bit and 64 bit
Windows but 64 bit on 64 bit *nix)
I'd blame C for that.
Delphi is not C.
Obviously.
But it would be foolish to assume that they weren't influenced
by matters of compatibility with C (or more specifically C++)
here, particularly given the history of Delphi as a language.
Even the name gives it away ("longint").
In article <108t0d4$249vm$[email protected]>,
Arne Vajhøj <[email protected]> wrote:
On 8/29/2025 9:17 AM, Dan Cross wrote:
In article <108g8kk$33isk$[email protected]>,
Arne Vajhøj <[email protected]> wrote:
On 8/24/2025 7:27 PM, Dan Cross wrote:
In article <108dlq4$2fi6h$[email protected]>,
Arne Vajhøj <[email protected]> wrote:
On 8/19/2025 1:26 PM, Dan Cross wrote:
In article <10823ei$3pb8v$[email protected]>,
Arne Vajhøj <[email protected]> wrote:
Whether we follow tradition and call them integer and cardinal >>>>>>>> or more modern style and call them int and uint is less important. >>>>>>>I would argue that, at this point, there's little need for a
generic "int" type anymore, and that types representing integers >>>>>>> as understood by the machine should explicitly include both
signedness and width. An exception may be something like,
`size_t`, which is platform-dependent, but when transferred
externally should be given an explicit size. A lot of the
guesswork and folklore that goes into understanding the
semantics of those things just disappears when you're explicit.
The integer types should have well defined width.
And they could also be called int32 and uint32.
That seems to be in fashion in low level languages
competing with C.
Many higher level languages just define that int is 32 bit,
but don't show it in the name.
If by "many higher level languages" you mean languages in the
JVM and CLR ecosystem, then sure, I guess so. But it's not
universal, and I don't see how it's an improvement.
That are two huge group of languages with a pretty big
market share in business applications.
Market share is not the same as influence, and while the JVM/CLR
languages _do_ have a lot of users, that does not imply that all
are good languages. In fact, only a handful of languages in
each family have any significant adoption, and I don't think PL
designers are mining them for much inspiration these days.
Again, not universal, nor really an improvement over just using
explicitly sized types.
It is a huge domain that are totally dominated by two approaches:
[snip]
So? You referred to "many higher level languages". That is
qualitatively different than "a small number of languages with a
huge share of the market."
"Huh; I wonder why they parenthesized `a == 6` and `a == 7`....
the operator precedence is obvious, so what am I missing here?
Not being an expert.
On Fri, 29 Aug 2025 19:01:21 -0400, Arne Vajhøj wrote:
"Huh; I wonder why they parenthesized `a == 6` and `a == 7`....
the operator precedence is obvious, so what am I missing here?
Not being an expert.
Not knowing how to keep docs handy?
On 8/29/2025 5:44 PM, Dan Cross wrote:
In article <68b2087a$0$712$[email protected]>,
Arne Vajhøj <[email protected]> wrote:
On 8/29/2025 9:11 AM, Dan Cross wrote:
In article <108k9de$1f69$[email protected]>,
Simon Clubley <clubley@remove_me.eisner.decus.org-Earth.UFP> wrote:
And _this_ is an example of why Simon's policy of backets around
everything makes it explicitly clear what was intended. :-)
*At some expense for expert users.
I doubt that.
I would expect with parenthesis's:
actually read expression : 2 second
thinking "nice to see good craftmanship" : 1 second
if ((a == 6) || (a == 7)) {
// do the thing...
}
"Huh; I wonder why they parenthesized `a == 6` and `a == 7`....
the operator precedence is obvious, so what am I missing here?
Not being an expert.
There are experts that like to drizzle parenthesis's out
over the code.
There are experts that do not like to drizzle parenthesis's out
over the code.
There are no experts that has never heard of the practice of
drizzling parenthesis's out over the code.
On 8/29/2025 5:38 PM, Dan Cross wrote:
In article <108t0d4$249vm$[email protected]>,
Arne Vajhøj <[email protected]> wrote:
On 8/29/2025 9:17 AM, Dan Cross wrote:
In article <108g8kk$33isk$[email protected]>,
Arne Vajhøj <[email protected]> wrote:
On 8/24/2025 7:27 PM, Dan Cross wrote:
In article <108dlq4$2fi6h$[email protected]>,
Arne Vajhøj <[email protected]> wrote:
On 8/19/2025 1:26 PM, Dan Cross wrote:
In article <10823ei$3pb8v$[email protected]>,The integer types should have well defined width.
Arne Vajhøj <[email protected]> wrote:
Whether we follow tradition and call them integer and cardinal >>>>>>>>> or more modern style and call them int and uint is less important. >>>>>>>>I would argue that, at this point, there's little need for a
generic "int" type anymore, and that types representing integers >>>>>>>> as understood by the machine should explicitly include both
signedness and width. An exception may be something like,
`size_t`, which is platform-dependent, but when transferred
externally should be given an explicit size. A lot of the
guesswork and folklore that goes into understanding the
semantics of those things just disappears when you're explicit. >>>>>>>
And they could also be called int32 and uint32.
That seems to be in fashion in low level languages
competing with C.
Many higher level languages just define that int is 32 bit,
but don't show it in the name.
If by "many higher level languages" you mean languages in the
JVM and CLR ecosystem, then sure, I guess so. But it's not
universal, and I don't see how it's an improvement.
That are two huge group of languages with a pretty big
market share in business applications.
Market share is not the same as influence, and while the JVM/CLR
languages _do_ have a lot of users, that does not imply that all
are good languages. In fact, only a handful of languages in
each family have any significant adoption, and I don't think PL
designers are mining them for much inspiration these days.
Again, not universal, nor really an improvement over just using
explicitly sized types.
It is a huge domain that are totally dominated by two approaches:
[snip]
So? You referred to "many higher level languages". That is
qualitatively different than "a small number of languages with a
huge share of the market."
Yes - that is two different statements.
But they are both true.
And the second qualifies the first in the sense that the
many are actually some that matter not pure exotic.
On 8/29/2025 5:38 PM, Dan Cross wrote:
In article <108t0d4$249vm$[email protected]>,
Arne Vajhøj <[email protected]> wrote:
On 8/29/2025 9:17 AM, Dan Cross wrote:
In article <108g8kk$33isk$[email protected]>,
Arne Vajhøj <[email protected]> wrote:
Delphi provide both flavors. shortint/smallint/integer
and int8/int16/int32, byte/word/cardinal and
uint8/uint16/uint32. I believe the first are the most
widely used.
The older names feel like they're very much looking backwards in
time.
Developers tend to like what they know.
(64 bit is just int64 and uint64, because somehow they
fucked up longint and made it 32 bit on 32 bit and 64 bit
Windows but 64 bit on 64 bit *nix)
I'd blame C for that.
Delphi is not C.
Obviously.
But it would be foolish to assume that they weren't influenced
by matters of compatibility with C (or more specifically C++)
here, particularly given the history of Delphi as a language.
Even the name gives it away ("longint").
That was also Lawrence's guess.
But the hypothesis that they wanted to follow
C/C++ is obviously not true.
In article <[email protected]>,
bill <[email protected]> wrote:
Which is why I always preferred working for people with well defined
local coding (and comment) standards. And, yes, I have worked for both.
Yup, though this doesn't _really_ address the question.
But yes: having a locally agreed upon style for such things is a
_huge_ boon for maintainability, particularly across a large
codebase. Sure, it's fun to belly up to the virtual bar and
debate the relative merits of different styles on USENET,
complete with contrived examples for or against different
conventions. But the reality is that if one is consistent
within a code base, it doesn't really matter all that much;
competent programmers will absorb the rules in a matter of days
or weeks.
The issue is that someone has to define the style and then
mandate its use, and it has to be enforced through rigorous
review and automated tooling. Given a sufficiently large group
of users, not everyone is going to agree with every rule; the
trick is in getting them to follow those rules regardless.
On 8/29/2025 9:24 AM, Dan Cross wrote:
In article <[email protected]>,
bill <[email protected]> wrote:
Which is why I always preferred working for people with well defined
local coding (and comment) standards. And, yes, I have worked for both.
Yup, though this doesn't _really_ address the question.
But yes: having a locally agreed upon style for such things is a
_huge_ boon for maintainability, particularly across a large
codebase. Sure, it's fun to belly up to the virtual bar and
debate the relative merits of different styles on USENET,
complete with contrived examples for or against different
conventions. But the reality is that if one is consistent
within a code base, it doesn't really matter all that much;
competent programmers will absorb the rules in a matter of days
or weeks.
Yes.
The issue is that someone has to define the style and then
mandate its use, and it has to be enforced through rigorous
review and automated tooling. Given a sufficiently large group
of users, not everyone is going to agree with every rule; the
trick is in getting them to follow those rules regardless.
It does not take that much to get coding conventions
followed.
If >5% of code is reviewed and not following coding
convention get flagged and the guilty get asked to fix
the code *and* other code that has same problem, then
in a few months everyone is following. The risk of
non compliance eventually being detected and the hassle
of doing the fixes makes it easier to do the right
thing the first time.
This is all true. I think one might paraphrase this as meaning
that you write code for the programmer that is slightly below
the median, and only hire engineers at median level or higher.
But this is slightly different than what I meant, which might be
similarly reframed as asking, how does one figure out what
"median" means? What is the base level of competence one might
assume when working on any given project/codebase/etc?
For instance, this demonstrably differs between organizations; I
would argue it often varies across projects within an
organization as well, and probably even within a project as the
project evolves over time. So how does one calibrate the median
point to which one targets ones programming standards, and how
does one ensure that it remains applicable?
So the way that I write software is likely to be far different
between projects/teams and across organizations. If I am
working on a project where excellence is the norm, then
parenthesizing every boolean expression is going to be tedious
and actually slow folks down; if I'm assuming all new-grads,
less so.
On 2025-08-29, Dan Cross <[email protected]> wrote:
This is all true. I think one might paraphrase this as meaning
that you write code for the programmer that is slightly below
the median, and only hire engineers at median level or higher.
But this is slightly different than what I meant, which might be
similarly reframed as asking, how does one figure out what
"median" means? What is the base level of competence one might
assume when working on any given project/codebase/etc?
For instance, this demonstrably differs between organizations; I
would argue it often varies across projects within an
organization as well, and probably even within a project as the
project evolves over time. So how does one calibrate the median
point to which one targets ones programming standards, and how
does one ensure that it remains applicable?
You could always create a "!!!Change_Skills_Required.README" in the
project (or subproject) root directory, stating with specific detail
what skills, knowledge, and experience level, are required before
it is appropriate for someone examining the project to start work
on it. Include references to appropriate papers or tutorial and
background material. Include the actual material in a references/
directory tree if appropriate.
Also include contact details for advice when they get stuck. Try to
list departments or teams instead of specific people if possible.
People change roles much more quickly that the overall team or
department does.
So the way that I write software is likely to be far different
between projects/teams and across organizations. If I am
working on a project where excellence is the norm, then
parenthesizing every boolean expression is going to be tedious
and actually slow folks down; if I'm assuming all new-grads,
less so.
You could also state this initial target audience in the above document.
PS: I'm actually serious about this. _You_, as the original team or
person to create a project, then get to set what is expected before
someone later on starts work on the project.
This stops that future person from having to guess what skills are
required and then finding out the hard way that they are in way over
their heads. It also avoids having to ask the questions you are
asking here.
| Sysop: | Keyop |
|---|---|
| Location: | Huddersfield, West Yorkshire, UK |
| Users: | 715 |
| Nodes: | 16 (2 / 14) |
| Uptime: | 02:06:27 |
| Calls: | 12,098 |
| Calls today: | 6 |
| Files: | 15,003 |
| Messages: | 6,517,869 |