Tuesday, December 29, 2020

For readability, BASIC was the best

One language stands alone in terms of readability.

That language is BASIC.

BASIC -- the old, pre-Visual Basic of the 1980s -- has a unique characteristic: a single line can be read and understood.

One may think that a line from any programming language can be read and understood. After all, we read and understand programs all the time, don't we? That's true, but we read entire programs, or large sections of programs. Those large fragments of programs contain information that defines the classes, functions, and variables in the programs, and we use that information to understand the code. But if we strip away that extra information, if we limit ourselves to a single line, then we cannot read and completely understand the code.

Let's look at an example line of code:

a = b * 5

Can you tell what this code does? For certain? I cannot.

A naive assessment is that the code retrieves the value of variable 'b', multiplies it by 5, and stores the result in the variable 'a'. It is easy to assume that the variables 'a' and 'b' are numeric. Yet we don't know that -- we only assume it.

If I tell you that the code is Python code, and that 'b' refers to a string object, then our understanding of this code changes. The code still performs a 'multiply' operation, but 'multiply' for a string object is very different from 'multiply' for a numeric object.

Instead, if I tell you that the code is C++, then we must identify the type for 'b' (which is not provided in the single line of code) and we must know if the class for 'b' defines the '*' operator. That operation could do anything, from casting b's contents to a number and multiplying 5 to sending some text to 'cout'.

We like to think we understand the code, but instead we are constantly making assumptions about the code and building an interpretation that is consistent with those assumptions.

But the language BASIC is different.

In BASIC, the line

a = b * 5

or, if you prefer

100 LET A = B * 5

is completely defined. We know that the variable B contains a numeric value. (The syntax and grammar rules for BASIC require that a variable with no trailing sigil is a numeric variable.) We also know that the value of B is defined. (Variables are always defined. If not initialized in our code, that have the value 0.) We know the behavior of the '*' operator -- it cannot be overridden or changed. We know that the variable 'A' is numeric, and that it can receive the results of the multiply operation.

We know these things. We do not need other parts of the program to identify the type for a variable, or a possible redefinition of an operator.

This property of BASIC means that BASIC is readable in a way that other programming languages are not. Other programming languages require knowledge of declarations. All of the C-based languages (C, Objective-C, C++, C#, and even Java) require this. Perl, Python, and Ruby don't have variables; they have names that can refer to any type of object. The only other programming language that comes close is FORTRAN II. It might have had the same readability; it had rules for names of variables and functions.

BASIC's readability is possible because it requires the data type of a variable to be encoded in the name of the variable. This is completely at odds with every modern language, which allow variables to be named with no special markings for type. BASIC used static typing; not only static typing, but overt typing -- the type was expressed in the name.

Static, overt typing was possible in BASIC because BASIC used a limited number of types (numeric, integer, single-precision floating point, double-precision floating point, and string) each of which could be represented by a single punctuation character. Each variable name had a sigil for the type. (Or no sigil, in which case the type was numeric.)

Those sigils were so useful that programmers who switched to Visual Basic kept the idea, through the use of programming style conventions that asked for prefixes for each variable. That effort become unwieldy, as there were many types (Visual Basic used many libraries for Windows functions and classes) and there was no all-encompassing standard and no was to enforce a standard.

Overt typing is possible with a language that has a limited number of types. It won't work (or it hasn't worked) for object-oriented languages. Those languages are designed for large systems with large code bases. They have built-in types and allow for user-defined types, with no support to indicate the type in the name of the variable. And as we saw with Visual Basic, expressing the different types is complicated.

But that doesn't mean the idea is useless. Overt typing worked for BASIC, a language that was designed for small programs. (BASIC was meant to be a language for teaching the skills of programming. The name was an acronym: Beginner's All-Purpose Symbolic Instruction Code.) Overt typing might be helpful for a small language, one designed for small programs.

It strikes me that cloud computing is the place for small languages. Cloud computing uses multiple processors to perform calculations, and split code bases. A well-designed cloud application consists of lots of small programs. Those small programs don't have to be built with object-oriented programming languages. I expect to see new programming languages for cloud-based computing, programming languages that are designed for small programs.

I'm not recommending that we switch from our current set of programming languages to BASIC. But I do think that the readability of BASIC deserves some attention.

Because programs, large or small, are easier to understand when they are readable.

Monday, December 21, 2020

Measuring the success of .NET

Microsoft released .NET (and the language C#) in the early 2000s. With almost 20 years of experience, can we say that NET has been a success?

Microsoft, I am certain, will claim that .NET has been a success and continues to be a success. But they have a vested interest in the success of .NET, so their opinion is possibly biased.

It strikes me that Apple's move to ARM processors has provided us with a measure for the success of .NET. How can that be? Well, let's look at programming languages.

Programming languages come in three flavors: compiled, interpreted, and byte-code. Each has a different way of executing instructions to perform the desired calculations.

Compiled languages convert source code into machine code, and that machine code is directly executable by the processor. In today's world, that means (usually) that the compiler produces code for the Intel x86 processor, although other processors can be the "target". Once compiled, the executable form of the program is usable only on a system with appropriate processor. Code compiled for the Intel x86 runs only on the Intel x86 (or a compatible processor such as one from AMD). Notably, the compiled code cannot be used on a different processor, such as the ARM processors. (Apple can run Intel code on its new ARM processors because it emulates the Intel processor. The emulator pretends to be an Intel processor, and the code doesn't know that it is running on an emulator.)

Interpreted languages take a different approach. Instead of converting the source code to executable code, the interpreter parses each line of source code and executes it directly. The importance of this is that a program written in an interpreted language can be run on any processor, provided you have the interpreter.

BASIC, one of the earliest interpreted languages, ran on different processors, including mainframes, minicomputers, and microcomputers. All of them could run the same program, without changes, thus a BASIC program was quite "portable".

In between compiled languages and interpreted languages are the byte-code languages, which are a little bit of interpreter and little bit compiler. Byte-code languages are compiled, but not to a specific processors. Or rather, they are compiled to an imaginary processor, one that does not exist. The code produced by the compiler (often called "byte code") is interpreted by a small run-time system. The idea is that the run-time system can be created for various processors, and the same byte-code can run on any of them.

Java uses the byte-code approach, as does C#, VB.NET (all the .NET languages, actually), and the languages Python, Ruby, Perl, and Raku (and a bunch more).

The languages C, C++, Objective-C, Go, and Swift are compiled to executable code.

I can think of no programming languages that use the pure interpreted approach, at least not nowadays. The two languages that used an interpreted approach were BASIC and FORTH, and there were some implementations of BASIC that were byte-code and some even were fully compiled. But that's not important in 2020.

What is important in 2020 is that Apple is moving from Intel processors to ARM processors, and Microsoft may be considering a similar move. Of the two companies, Microsoft may be in the better position.

Apple uses the languages Objective-C and Swift for its applications, and encourages third-party developers to use those languages. Both of those languages are compiled, so moving from Intel processors to ARM processors means that programs, originally compiled for Intel processors must recompiled to run on the ARM processors.

Unless, of course, you run the Intel code on an ARM processor with an emulator. Not every application is ready to be recompiled, and not every third-party developer is ready to recompile their applications, so the emulator is an easy way to move applications to the ARM processors. The emulator is important to Apple, and I'm sure that they have spent a lot of time and effort on it. (And probably will spend more time and effort in the next year or two.)

Microsoft, in contrast, uses a large set of languages and encourages third-party developers to use its .NET framework. That puts it in a different position than Apple. While Apple's applications must be recompiled, Microsoft's applications do not. Microsoft can provide an ARM-based Windows and and ARM-based .NET framework, and all of the applications written in .NET will run. (And they will run without an emulator.)

Microsoft has a nice, simple path to move from Intel to ARM. Alas, the world is not so simple, and Microsoft's situation is not so simple.

The migration from Intel to ARM is easy (and low-risk) only for applications that are written completely in .NET. But applications are not always written completely in .NET. Sometimes, applications are written partially in .NET and partially in "native code" (code for the underlying processor). There are two reasons for such an approach: performance and legacy code. Native code tends to run faster than .NET byte-code, so applications that require high performance tend to be written in native code.

The other reason for native code is legacy applications. Large applications written prior to the introduction of .NET (and yes, that is twenty years ago) were written in a language that compiled to Intel code, typically C or C++. Converting that code from C or C++ to a .NET languages (C#, VB.NET, or the not-quite-C++ that was "managed C++") was a large effort, and entailed a large risk. Better to avoid the effort and avoid the risk, and maintain the application in its original language.

With all of that as a prelude (and I admit it is a long prelude), we can now look at the success of .NET.

If Microsoft releases a version of Windows for the ARM processor, we can see how many applications can migrate from Intel-based Windows to ARM-based Windows, and how many applications cannot. The applications that can move will be those applications written completely in .NET. The applications that cannot migrate (or that need an emulator) are those applications that are written all or partially in native code.

The degree of total (or pure) .NET applications can be a measure of the success of .NET. The more applications that use .NET (and no native code), the more success we can attribute to .NET.

The degree of native-code applications (partial or total), on the other hand, indicates a failure of .NET. It indicates choices made to not use .NET and use a different platform (Windows API, MFC, etc.) instead.

That is my measurement of the success of .NET: How many applications can move from Intel to ARM without recompiling. If Microsoft announces Windows for ARM, let's see which applications can move immediately and without the assistance of an emulator.


Tuesday, December 1, 2020

A few minor thoughts on Apple's new M1 processor

Apple has released their new M1 processor and their new Mac and Macbook computer which use the new processor. Apple is quite proud of this achievement (and they have every right to be) and users are impressed with the performance of the M1.

Yet I have some concerns about the new processors.

First, with the new processors and the new Macs, Apple has consistently emphasized performance, but little beyond that. Their demos have featured games and video editing, to show off the performance. The advertising is far from the presentations of yore which listed features and boasted MIPS ratings. (Perhaps video games are the new way to boast processor performance.) Apple's announcement was designed for consumers, not corporate buyers and not technologists and especially not developers. Apple has made their computers faster (and more efficient, so longer battery life) but not necessarily more capable.

Second, Apple's change to proprietary ARM processors (and let's be real, the design is proprietary) fractures the hardware market. Apple equipment is now different from "regular" personal computers. This is not new; Apple used PowerPC processors prior to using Intel processors in 2006. But the new Macs are different enough (and designed with enough security) that other operating systems cannot (and probably will never) be installed on them. Linus Torvalds has commented on the new Macs, and indicated that without Apple's support, Linux will not run on the M1 Macs.

Third, Apple made no announcement of cloud computing. This is not a surprise; Apple has not offered cloud computing and I see nothing to change that in the near future. It is telling that Amazon, not Apple, has announced new offerings of Apple M1 Mac minis in the cloud. Apple seems content to limit their use of cloud computing to iCloud storage, online documents, and Siri. I'm not expecting Apple to offer cloud computing for some time.

Moving beyond Apple, what will other manufacturers (Dell, Lenovo, etc) do? Will they switch to ARM processors?

I expect that they will not -- at least not on their own. Their situation is different. Apple has control over hardware and software. Apple designs the computer (and now, the processor). Apple designs and writes the operating system. Apple builds many of the applications for the Mac. This vertical integration lets Apple switch to a proprietary processor.

Manufacturers for "regular" personal computers rely on Windows, which is designed and written by Microsoft. Microsoft sells some applications, but encourages a large ecosystem of applications. A corresponding shift in the "regular" PC market requires the cooperation Microsoft, hardware manufacturers, and application developers. Such a change is possible, but I think Microsoft has to lead the effort.

Microsoft does provide a hardware specification for running Windows, and they could issue a specification that uses an ARM processor. Such a specification would exist along side the current Intel-based specification, expanding the space for Windows PCs. Microsoft could even design and build their own hardware, much as they did with Surface tablets and laptops.

I expect that Microsoft will support ARM processors (although not Apple's M1 processors) and offer cloud compute services for those processors. They may design a custom ARM processor, as Apple has done, or use a "standard" ARM processor design.

Getting back to Apple, I can see that the new M1 processor gives Apple more control over its market. The "expansion" market of running non-Apple operating systems is, as I see it, terminated with the M1 Macs. Boot Camp is out, Parallels works (but not with virtual machines), and non-Apple operating systems cannot be installed. (Technically that's not quite true. A clever engineer did get the ARM version of Windows to run on an M1 Mac, but only by using QEMU as an intermediary. It wasn't native ARM Windows on the M1 Mac.)

More control may sound good, but it does alienate some folks.

The Linux crowd will move to other hardware. Linux is a small presence in the desktop market, and Apple may not care or notice even. But Linux is a large presence in the developer market, and a decline in developers using Macs may affect Apple.

The Windows crowd has plenty of options for hardware, with more as Microsoft expands Windows to ARM processors. Windows laptops are just as good as Macbooks, and better in some ways, with options for non-glare displays and finger-friendly keyboards. My experience has shown that PC hardware tends to last longer than Apple hardware (especially equipment built after 2010).

I think, in the long run, Apple's move will fragment the market, aligning Apple hardware with Apple operating systems and Apple applications. It will push developers away from Apple hardware, and therefore Apple operating systems and the entire Apple ecosystem. Apple won't die from this, but it will give up some market share. The more noticeable effect will be the separation of processing on Apple and non-Apple platforms. Apple will be in their own world, their own garden of hardware, operating systems, and applications, and they will gradually drift away from mainstream computing.