APL\360

Peter Corlett abuse at cabal.org.uk
Mon Feb 1 07:07:01 CST 2021


On Wed, Jan 20, 2021 at 02:05:37PM -0700, ben via cctalk wrote:
[...]
> I don't see languages in general have improved since the the mid
> 1960's. Hardware and language models don't reflect each other,
> and don't have extendable data sizes and types.
> PL/I seems to have been the best,but too tied to IBM.
> C standard 2131 complex numbers
> C standard 2143 dubble complex numbers
> Every machine I can think of had a carry flag of some type
> yet no language uses that to extend it self.

You're describing a failing in C and similar languages stuck in the 1960s.
Here's a Rust method that does add-exposing-carry:

https://doc.rust-lang.org/nightly/std/primitive.u32.html#method.overflowing_add

The documentation doesn't explicitly say "carry" because Rust is
architecture-neutral and it's down to LLVM to decide how to express it in
machine code, but on x86 (and probably ARM) the boolean return value comes
directly from the carry flag.

> I don't believe in objects because data structures don't have classes, but
> are more similar to each other. A window A structure is like window B but
> details are different. That makes things look portable when they are not.

> Constants still
> seem to be embedded in data structures, rather than abstract.
> -- zero array
> define LIMIT abc
> blah array[LIMIT]
> ...
> i = 0 while i< LIMIT array[i] = 0 i = i + 1 endw
> I would like say
> let LIMIT = abc
> blah array[LIMIT]
> i = 0 while i< array:LIMIT array[i] = 0 i = i + 1 endw

You "don't believe in objects" yet then describe a problem which only exists
due to the lack of them and then present OO pseudocode to solve it. A lot of
OO languages suck of course, but the fundamental idea of encapsulation is
not the bit that sucks. Here's it in Rust, where it takes in an arbitrary
array (pedantically, "slice", a (pointer, element count)-tuple) and
determines its length at runtime:

pub fn clear_indexed(array: &mut [usize]) {
  for index in 0 .. array.len() {
    array[index] = 0;
  }
}

(The code for C-style fixed-length arrays looks broadly similar but has a
bit more boilerplate because they're less useful.)

Iterating over indices is generally discouraged for a number of reasons, not
least being that the index may be out-of-bounds, but also because it can
inhibit vectorisation or parallelisation. You have no choice in broken
languages such as C, but many languages provide some notion of iteration
which guarantees to not go out-of-bounds:

pub fn clear_iterator(array: &mut [usize]) {
  for elem in array {
    *elem = 0;
  }
}

Both code fragments generate equivalent assembly in this trivial example
because the Rust compiler could prove at compile time that the index
variable can't go out-of-bounds. In more complex real-world code it cannot
reliably do so and will insert a run-time check which aborts if the index is
out-of-bounds. Or if it's C, trundle on and corrupt things.

Oddly enough, the state of the art has moved on a bit in the half-century
since C was invented. It's just that quite a lot of programmers haven't yet
noticed.



More information about the cctalk mailing list