A criticism of TB

Hello all!
Some time ago I downloaded and did some experimenting with TB Bronze Demo. I have encountered a number of things I didn't like about the language, its implementation and the way TB is being advocated and merchandised. I intended to post about it here, but I ended up with a much larger text instead which can be found here. I do not mean to offend anyone -- consider it as an observer's opinion, and possibly a feedback to whoever feels interested.
Those who would read it, please bear with my poor English -- it is not my native language.
--Boyko

Comments

Criticsm of TB

I refer to the use of channel #0 in your criticm. Channel #0 is not a legal channel number for users. Channel numbers must be in the range 1 to 1000. Attempting to open a channel outside this range should produce an invalid channel error depending on whether the error is fatal or not.

Big John

Channel # 0

Channel # 0 has always been a legal channel number. You don't OPEN it, it's always open. It's the default TB output window.

Channel #0

I meant that Channel #0 is illegal in the sense that it reserved for the default output window and cannot be used for anything else.

Big John

It is actually used for both

It is actually used for both input and output. Whether that window is called "output" or otherwise I cannot tell (for lack of documentation); in any case, it is quite obvious that the window hosts both "standard input" and "standard output".

In the text, I refer precisely to this usage of channel #0, and not anything else. Therefore, I do not refer to channel #0 in any illegal sense.

In particular, there is no mention of "opening channel #0" in my text. In fact I quite clearly say that it is "considered to be always open", which is exactly the opposite!

Channel #0

Channel #0 is always open because it is the default logical graphical window which occupies the working area of the default physical window. The physical window (with blue title band and borders) can contain any number of logical windows.

PRINT #0: "text" will print text in this default logical window whether the physical window is visible or not.
PRINT "text" will print text in the logical window associated with the current target physical window.
LINE INPUT #0: text$ will accept input from the keyboard whether the default physical window is visible or not.
LINE INPUT text$ will do the same.

If the current target physical window is not the default window then you will see nothing if you use PRINT #0: "text" whereas you will see something if you use PRINT "text". PRINT is therefore the "standard" way to display text because it works regardless of which window happens to be the target.

Regardless of which window is target, active or visible, LINE INPUT #0: text$ or LINE INPUT text$ will both derive input from the keyboard.

LINE INPUT will accept unlimited input from the keyboard, including punctuation until a RETURN character is received. LINE INPUT is terminated by the RETURN charcater and not by CTRL-Z.

You cannot use channel #0 for any other purpose other than the default logical graphical window otherwise you will get error message 7001.

Channel #0 cannot be used in OPEN or CLOSE statements otherwise you will get the error message 7002 (non fatal)

Big John

RETURN and Ctrl-Z are very different concepts

LINE INPUT will accept unlimited input from the keyboard, including punctuation until a RETURN character is received. LINE INPUT is terminated by the RETURN charcater and not by CTRL-Z.

Sure, pressing the RETURN key terminates the line I am currently entering (using whatever of LINE INPUT or LINE INPUT #0). The problem – and this is what I have been bringing your attention to, all this time – is how you tell the program that there are no more lines to read at all. Ctrl-Z (or Ctrl-D, or whatever else a certain system has for that purpose) has been devised for exactly this – to end the input as a whole, not a particular line. But TB neither listens to Ctrl-Z, nor provides any other means in its place. Consequently, there is no way to distinguish, programmatically, between having and not having more lines to read; in fact, there always will be, as the keyboard input cannot be terminated! (Please refer to my main text for more on this.)

You cannot use channel #0 for any other purpose other than the default logical graphical window otherwise you will get error message 7001. Channel #0 cannot be used in OPEN or CLOSE statements otherwise you will get the error message 7002 (non fatal)

I understand that, I have always understood, and I say again: I have never considered or discussed using channel #0 “for any purpose other than the default logical graphical window”, and I have never considered or discussed using channel #0 “in OPEN or CLOSE statements”. This is all irrelevant.

What I am discussing in the text is the uselesness of writing WHILE MORE #0 to detect end of input from keyboard. That construct is clearly acceptable to TB's syntax and runtime system – no error is generated because of this use of #0 – and it is very reasonable to expect that this should be the way for a program to know when its (keyboard) input stream ends, just as WHILE MORE #n works for any n>0 (i.e. for a disk file). However, TB renders the construct WHILE MORE #0 useless by lacking means to effectuate the end of keyboard input. This is a disappointing omission of TB which leads to the inability to solve straightforwardly a large class of programming problems in it, and to developing ill programming practices meant to circumvent the omission (again, please refer to my main text).

Channel #0

You say:

I have never considered or discussed using channel #0 “for any purpose other than the default logical graphical window”

and yet a few lines later you say:

because of this use of #0 – and it is very reasonable to expect that this should be the way for a program to know when its (keyboard) input stream ends

No, it is not at all reasonable to expect that MORE #0 has anything to do with input from the keyboard. I repeat again, channel #0 is a window not the keyboard.

The manual is quite clear on this matter (Chapter 17 Page 9):
MORE #n is a logical expression.
MORE #n is true when #n refers to a file and the file pointer is not at the end of the file.
MORE #n is true when #n refers to a window.
MORE #n is false when #n refers to a file and the file pointer is at the end of the file.

DO WHILE MORE #n is therefore a legal and legitimate statement even when n=0 and will not produce an error.

Your assumption, that because no error is produced means that channel #0 has suddenly and magically changed from being a window to being the keyboard, is misguided.

If you wish to determine the end of an indeterminate number of LINE INPUTs using a key sequence such as CTRL-D then the following code will work:

DO
LINE INPUT line$
LOOP WHILE line$<>chr$(4)

You do of course have to signify the termination of each line input with the return key INCLUDING CTRL-D. If you wish to avoid using the return key then:

DO
GET KEY keynumber
LOOP WHILE keynumber<>4

I hope this clears up the matter once and for all.

Big John

Sorry, but I am not convinced

…channel #0 is a window not the keyboard.

So be it. So far I just did not – when it comes to entering data via keyboard – make difference between “default logical graphical window” (was it not “default output window” before?), on the one hand, and “keyboard”, on the other.

But if there must be difference, then from the following quote of yours:
Regardless of which window is target, active or visible, LINE INPUT #0: text$ or LINE INPUT text$ will both derive input from the keyboard.
I'd deduce that #0 refers to the keyboard not a window – quite the opposite to the meaning of #0 that you insist on!

So, in LINE INPUT #0, #0 is the keyboard but in MORE #0 it is a window? Doesn't seem very consistent to me.

You say:

…it is not at all reasonable to expect that MORE #0 has anything to do with input from the keyboard.

Question: If not the keyboard, what is it that MORE #0 has to do with at all?
Another question: Why bother define MORE #0 at all if it always yields true?

That #0 is such a complicated thing to explain is itself a bad indication – after all, we are talking of plain old keyboard input, and BASIC is supposed to be easy to comprehend – but I really don't care much about all this #0 business. For me, the important issue is the inability of TB to detect end of keyboard input properly. You say:

If you wish to determine the end of an indeterminate number of LINE INPUTs using a key sequence such as CTRL-D then the following code will work:

DO
LINE INPUT line$
LOOP WHILE line$<>chr$(4)

This is admittedly better than having to determine the number of lines in advance or asking for continuation/termination after each line, but is still inferior to the hypothetical (assuming that MORE #0 does check for end of input, and that TB reacts to Ctrl-Z or an equivalent signal):

DO WHILE MORE #0
LINE INPUT #0: S$

LOOP

This is for several reasons:

  • Using chr$(4) or whatever else means explicitly introducing and adhering to a convention in the program. Moreover, you have to now that ASCII 4 is the code of Ctrl-D, in your example. In contrast, Ctrl-Z in DOS/Windows, or Ctrl-D in Unices, is a convention of the operating system, of which the program knows nothing: MORE #0 or whatever else in some other language is an abstraction free of any conventions about how to actually signal end of keyboard input to the program.
  • Not all possible conventions of this kind work. Ctrl-Z doesn't: in TB, if you change your program to wait for chr$(26) instead of chr$(4), pressing Ctrl-Z (whose ASCII code is 26) will have no effect – the result is an infinite loop.
  • Adopting a convention such as in your example bounds one to read text (strings). What if we need a similar program but reading numeric data? An abstract mechanism of checking for end of input (such as really working MORE #0) is independent of the type of data that is being read.
  • MORE #0, the way it should work, would have made reading the keyboard consistent with reading a file (MORE #n where n>0).

As I said several times, lacking a mechanism for properly checking for end of input (including a way to effectuate the actual end) is an omission in TB. Ad hoc workarounds are possible but they suffer serious disadvantages.

serious disadvantages?

You said: "lacking a mechanism for properly checking for end of input (including a way to effectuate the actual end) is an omission in TB. Ad hoc workarounds are possible but they suffer serious disadvantages."

Specifically what are these SERIOUS DISADVANTAGES about which you are so distraught? No computer and no program can POSSIBLY know when the user is "FINISHED INPUTTING" until the user pushes SOME KEY or key combination. What difference does it make how this is implemented?

Now, I am not some computer program expert geek, but I used BASIC when it became available on CEIR teletype machines in about 1967-8, on HP 9830's and 9845's back before PC's, and now True Basic since that has been out. In all that time doing lots of mechanical engineering stuff I can't ever recall any such problems as you allude to manifesting themselves. So what if you have to write a line or two of code like "hit escape key when done" or add a click button labeled "OK" or "DONE". So what??

Cheers,
Mike C.

>>

I am sorry for answering your posts after such a long time …

Mike C.:

Specifically what are these SERIOUS DISADVANTAGES …?

I listed some in my previous post (a bulleted list). Others I mention in the text I wrote about TB. I do find them serious, but of course you are free to differ with me on this.

No computer and no program can POSSIBLY know when the user is "FINISHED INPUTTING" until the user pushes SOME KEY or key combination. What difference does it make how this is implemented?

Sure, some termination method is needed. But when that is defined in the o.s., the program (and, in fact, the programming language!) knows nothing about the implementation. This does make a difference, and a very important one: thousands of programs in heavy every-day use rely on this single abstraction. The implementation of the standard-input termination is done once for an operating system. This is clearly easier to do than having to establish, programmatically maintain, communicate to the user (or negotiate with it), and abide by a termination convention on a program-wise basis.

In all that time … I can't ever recall any such problems as you allude to manifesting themselves.

How about reading a list of numbers (say, weights)? Or of coordinate pairs (say, of a polygon)? Or of names (of people, cities etc)? You can find such examples in any programming tutorial, let alone in the ‘real world’. In Unices, as well as in other o.s., the notions of filter, redirection and piping — known to be extremely useful — are impossible without a standardised, language-independent (let alone program-independent) method of ending the input.

Big John:

… you still have to tell the user which "key" to press to signify that they are done, because most users are unaware of the EOF keystrokes CTRL-Z or CTRL-D. In this context you could tell them to press any key …
Even if the program does know what the operating system is, you still have to tell the user what to type to signify the end of data input.

My point is that the program should not need to know what the o.s. is. The user, on the other hand, does need to know what to type in order to signify the end of data input, but it is easier to learn this once and use it wherever applicable within the o.s. (not only when dealing with BASIC), rather than having to use different keys for each program. It is also easier for the programmer to write programs that do not depend on the specifics of the o.s. or a particular programming system. If I, say, write a program that sums up a (not known in advance) amount of numbers, I would like to use it without a change on all systems where it makes sense.

Regards,
Boyko

Input termination

Hi,

You say that:
Sure, some termination method is needed. But when that is defined in the o.s., the program (and, in fact, the programming language!) knows nothing about the implementation. This does make a difference, and a very important one: thousands of programs in heavy every-day use rely on this single abstraction.

I have been using and writing programs since 1961 and I have never come across nor had need to terminate indeterminate input in this way. Despite the fact that you say thousands of programs rely on this, there are obviously thousands that don't - in particular the ones I have used. The Internet is full of examples of how to terminate indeterminate input - by clicking a "NEXT" or "DONE" button. This is what I would do, and I am sure the general public would expect and prefer this.

Since you agree that you have to tell the user which key to press to terminate input (because most users have little or no knowledge of the operating system) - then it doesn't matter which key or keys you use. Pressing the "END" key seems simpler and more intuitive than CTRL-Z.

Big John

>>

I have been using and writing programs since 1961 and I have never come across nor had need to terminate indeterminate input in this way.

So you have never used any kind of Unix o.s., where even the command shell works in this way, along with many other programs?
And you have never come across such things like redirection or piping of programs (in Unix of all brands, or in DOS or Windows) — which are not possible without o.s.-defined data input termination method?

Despite the fact that you say thousands of programs rely on this …

I say? Don't take my word on that, check for yourself.

… there are obviously thousands that don't …

How does this disprove my point? Many people don't drink wine either — but many others do and so wine keeps being produced.

Since you agree that you have to tell the user which key to press … then it doesn't matter which key or keys you use. Pressing the "END" key seems simpler and more intuitive than CTRL-Z.

First, there is no place for ‘since’ here: the fact that you have to tell them doesn't mean that all choices are of equal value. I have been explaining, and indeed several times, why sticking to an o.s.-defined convention is much preferable.

Second, and even more important: as of now, no support is provided in TB for whatever of Ctrl-Z, END etc as a standard, within the language, method of data input termination. Consequentially, it is impossible to write the kind of program under discussion without program-specific assumptions for termination. That I consider really annoying.

Now, it seems that I am not going to convince you whatever arguments I use, and from this point on I can only repeat myself …

Regards,
Boyko

Channel #0

Dealing with the points you raised:

(1) The default output window is the physical window you see on screen. This window has an ID but not a channel number. Inside the borders of the physical window there is the default logical window which has the channel number zero. Normally when you send output to the default output window you will see the results on screen, however, it is possible to relocate the logical window so you may not see what you type on screen. I just wanted to make sure we all understood which window we were referring to when we use #0.

(2) It is regrettable that LINE INPUT #0 escapes the error detection system, but since it current does, then LINE INPUT #0 and LINE INPUT both act in the same way.

(3) Channel #0 is very definitely the default window and not the keyboard.

(4) MORE #n is always "true" when #n refers to a window

(5) I agree that if the keyboard had a specific channel number (x), then it would be consistent and logical for:
DO WHILE MORE #x
to react to an end of iput keystroke in the same way that it reacts to EOF when reading files. However, from a practical point of view if a user is attempting to input an inderterminate number of data items, you still have to tell the user which "key" to press to signify that they are done, because most users are unaware of the EOF keystrokes CTRL-Z or CTRL-D. In this context you could tell them to press any key, e.g. the "END" key would seem most appropriate.

(6) Although you say that the program knows nothing about the operating system, in TB it is possible to "ask" what the operating system is. Even if the program does know what the operating system is, you still have to tell the user what to type to signify the end of data input.

(7) Again it is regrettable that the Windows version of TB absorbs CTRL-Z. The earlier DOS version was more consistent in this respect and did recognize CTRL-Z.

Big John

Criticism of TB

A very well thought out piece! You do seem to have a fixation on Booleans, though. Some of your criticisms concern the way ANSI (ISO) BASIC works. Since TB tries to follow the ANSI standard and since the ANSI Standards committee has been disbanded, there will be no future changes to the standard and, therefore, probably not to the TB language implementation, either. One thing you mentioned with which I totally disagree, however, is calling the fact that uninitialized variables will contain zero (or the null string for string variables) a bug. This is NOT a bug, nor wrong behavior. It's the way BASIC has been defined right from 1964 on. It's a well-defined behavior and exists in almost all implemetations of BASIC. BASIC was designed for quick and dirty programming while seated at the terminal and taking away the ability to use new variables on the fly takes away that freedom. It's possible to flowchart (does anyone actually do that anymore?) a BASIC program before typing it in but BASIC really wasn't meant for that.

Thanks

A very well thought out piece!

Thank you!

You do seem to have a fixation on Booleans, though.

Boolean values are immensely useful. All other programming languages and all other BASIC dialects that I know of do have Booleans -- this itself is an indication of their importance. I have discussed the subject at length in hope to provide evidence of this importance myself, rather than just refer to the availability of Booleans elsewhere.

... there will be no future changes to the standard and, therefore, probably not to the TB language implementation, either.

It would be regrettable if TB abstains from changing. All languages evolve. The TB designers, rather than sticking to the formal standard (which has never been effective anyway), are in the unique position to define a standard BASIC themselves! Why not take the opportunity?

One thing you mentioned with which I totally disagree, however, is calling the fact that uninitialized variables will contain zero (or the null string for string variables) a bug. This is NOT a bug, nor wrong behavior. It's the way BASIC has been defined right from 1964 on. ...taking away the ability to use new variables on the fly takes away that freedom...

I do understand that this was a deliberate decision. I do, however, believe that it is much better to not allow, or at least warn about, using the value of a variable that wasn't explicitly given one -- this is what I propose.
This does not prevent a programmer from picking variable names on the fly, just from doing arithmetic or whatever with a value he did not provide himself. Does it not make sense?
This kind of checking was perhaps prohibitively complex or time-consuming for a run-time system of the 1960-s but not now, and should be very helpful especially to novices and non-professional programmers.