Best programming language for beginners?

Once you learn how to use BASIC you'll never use it again.

Nonsense!!!

I have a Toshiba T1200 laptop with an LCD screen from about 1988 that runs QBASIC in DOS 3.3.

I still use it to collect data for my weather station. A 720K floppy disk holds months of data, and the laptop runs for hours on 6xAA batteries if the power goes out!

Also keeps a nice plot of the last ~20 hours of average wind speed and gusts on the screen.

For the BASIC aficionados among you, here is the wind gauge code:

REM read wind gauge and store statistics on disk.

REM circular buffer push and pull
DECLARE SUB gbuf (array!(), v!, nsp%, nsmax%)
DECLARE SUB pbuf (array!(), v!, ns%, nsp%, nsmax%)

REM plot wind speed data in box 1-600 on x, 0-99 on y, lower screen
DIM t0(600), t1(600)
DEFINT I-N
DEFSNG K

nsec = 300 'sample save interval in seconds

SCREEN 2 '640x200
'
' VIEW defines graphics viewport in absolute screen coords, subsequent
' pixel coords are relative to view window
'
' VIEW SCREEN  (ditto) but subsequent pixel coords are absolute
' Order of coordinate pairs is immaterial!
'
VIEW (21, 98)-(620, 198), , 1: REM view won't frame extreme edges
WINDOW (1, 0)-(600, 99): REM logical coords 1-600 on x, 0-99 on y
CLS

OPEN "com1:4800,n,8,1,cs0,ds0,cd0" FOR INPUT AS #1

LOCATE 1, 1: PRINT "Starting wind monitor at: "; DATE$; " "; TIME$
LOCATE 2, 1
INPUT "Output file name: ", n$
OPEN n$ FOR OUTPUT AS #2

PRINT #2, DATE$; " "; TIME$; " sample:"; nsec

r% = 0
REM number of points in graph, buffer pointers
n0m = 300: n0 = 0: n0p = 1
n1m = 300: n1 = 0: n1p = 1

REM get version #

'ON ERROR GOTO handler

LINE INPUT #1, a$
LOCATE 3, 1: PRINT "Version and time: "; a$
LOCATE 4, 1: PRINT "Hit Esc to exit..."

nsamp = 0: wmaxt0 = 0: avgt0 = 0: vart0 = 0

ON TIMER(nsec) GOSUB 5000
TIMER ON

10 LINE INPUT #1, a$: LOCATE 9, 33: PRINT a$; "     "
	nc = INSTR(a$, ","): a$ = MID$(a$, nc + 1)
	nc = INSTR(a$, ","): a$ = MID$(a$, nc + 1)
    
15      temp0 = VAL(a$) / 22.6
	nc = INSTR(a$, ",")
20      temp1 = VAL(MID$(a$, nc + 1)) / 22.6: REM max reported by sensor
       
	IF (wmaxt0 < temp1) THEN wmaxt0 = temp1
	avgt0 = avgt0 + temp0
	vart0 = vart0 + temp0 * temp0
	nsamp = nsamp + 1

	LOCATE 11, 26

PRINT USING "& Avg: ### Max: ### mph"; LEFT$(TIME$, 5); temp0; temp1;

	IF INKEY$ <> CHR$(27) THEN GOTO 10

REM escape key hit, all done

GOSUB 5000
CLOSE #2
STOP

5000 r% = r% + 1: REM write record: average, max and s.d. this interval
avgt0 = avgt0 / nsamp
vart0 = vart0 / nsamp - avgt0 * avgt0
vart0 = SQR(ABS(vart0))
PRINT #2, USING "###.#,###.#,###.#"; avgt0; wmaxt0; vart0
CALL pbuf(t0(), avgt0, n0, n0p, n0m)
CALL pbuf(t1(), wmaxt0, n1, n1p, n1m)
nsamp = 0: avgt0 = 0: wmaxt0 = 0: vart0 = 0

REM plot data

CLS 1

' dotted gridlines
FOR i = 1 TO 600 STEP 4
PSET (i, 30): LOCATE 21, 4: PRINT "10";
PSET (i, 60): LOCATE 17, 4: PRINT "20";
PSET (i, 90): LOCATE 13, 4: PRINT "30";
NEXT i

' pull out most recent temp0 and max measurements

nsp = n0p
FOR i = n0 TO 1 STEP -1
CALL gbuf(t0(), v, nsp, n0m)
v = 3 * v: i2 = 2 * i
PSET (i2, v): PSET (i2, v + 1): PSET (i2, v - 1): PSET (i2 + 1, v): PSET (i2 - 1, v)
NEXT i

RETURN

handler:
LOCATE 3, 30
PRINT "error "; ERR; " at line "; ERL; TIME$; " "; DATE$;
LOCATE 4, 30
PRINT a$
RESUME NEXT

DEFINT K
SUB gbuf (array!(), v!, nsp%, nsmax%)
DEFINT I-N
REM NO check for buffer underflow
v = array(nsp)
nsp = nsp - 1
IF nsp < 1 THEN nsp = nsmax
END SUB

SUB pbuf (array!(), v!, ns%, nsp%, nsmax%)
DEFINT I-N

REM returns ns%, number of values pushed
array(nsp) = v
nsp = nsp + 1: ns = ns + 1
IF nsp > nsmax THEN nsp = 1
IF ns > nsmax THEN ns = nsmax
END SUB