Discussion:
Command Languages Versus Programming Languages
Add Reply
Lawrence D'Oliveiro
2024-03-29 01:14:18 UTC
Reply
Permalink
At one time, we distinguished between “scripting” languages and
“programming” languages. To begin with, the “scripting” languages were
somehow more limited in functionality than full-fledged “programming”
languages. Or they were slower, because they were interpreted.

Then languages like Perl and Java came along: both were compiled to a
bytecode, a sort of pseudo-machine-language, which was interpreted by
software, not CPU hardware. Were they “scripting” or “programming”
languages? Some might have classed Perl as a “scripting” language to
begin with, but given it is must as powerful as Java, then why
shouldn’t Java also be considered a “scripting” rather than
“programming” language? And before these two, there was UCSD Pascal,
which was probably the pioneer of this compile-to-bytecode idea.

So that terminology for distinguishing between classes of programming
languages became largely obsolete.

But there is one distinction that I think is still relevant, and that
is the one between shell/command languages and programming languages.

In a shell language, everything you type is assumed to be a literal
string, unless you use special substitution sequences. E.g. in a POSIX
shell:

ls -l thingy

“give me information about the file/directory named ‘thingy’”, vs.

ls -l $thingy

“give me information about the files/directories whose names are in
the value of the variable ‘thingy’”.

Whereas in a programming language, everything is assumed to be a
language construct, and every unadorned name is assumed to reference
some value/object, so you need quote marks to demarcate literal
strings, e.g. in Python:

os.listdir(thingy)

“return a list of the contents of the directory whose name is in the
variable ‘thingy’”, vs.

os.listdir("thingy")

“return a list of the contents of the directory named ‘thingy’”.

This difference in design has to do with their typical usage: most of
the use of a shell/command language is in typing a single command at a
time, for immediate execution. Whereas a programming language is
typically used to construct sequences consisting of multiple lines of
code before they are executed.

This difference is also why attempts to use programming languages as
though they were shell/command languages, entering and executing a
single line of code at a time, tend to end up being more trouble than
they are worth.

Conversely, using shell/command languages as programming languages, by
collecting multiple lines of code into shell scripts, does work, but
only up to a point. The concept of variable substitution via string
substitution tends to lead to trouble when trying to do more advanced
data manipulations.

So, in short, while there is some overlap in their applicable usage
areas, they are still very much oriented to different application
scenarios.
candycanearter07
2024-03-29 03:10:12 UTC
Reply
Permalink
Post by Lawrence D'Oliveiro
At one time, we distinguished between “scripting” languages and
“programming” languages. To begin with, the “scripting” languages were
somehow more limited in functionality than full-fledged “programming”
languages. Or they were slower, because they were interpreted.
Then languages like Perl and Java came along: both were compiled to a
bytecode, a sort of pseudo-machine-language, which was interpreted by
software, not CPU hardware. Were they “scripting” or “programming”
languages? Some might have classed Perl as a “scripting” language to
begin with, but given it is must as powerful as Java, then why
shouldn’t Java also be considered a “scripting” rather than
“programming” language? And before these two, there was UCSD Pascal,
which was probably the pioneer of this compile-to-bytecode idea.
So that terminology for distinguishing between classes of programming
languages became largely obsolete.
But there is one distinction that I think is still relevant, and that
is the one between shell/command languages and programming languages.
In a shell language, everything you type is assumed to be a literal
string, unless you use special substitution sequences. E.g. in a POSIX
ls -l thingy
“give me information about the file/directory named ‘thingy’”, vs.
ls -l $thingy
“give me information about the files/directories whose names are in
the value of the variable ‘thingy’”.
Whereas in a programming language, everything is assumed to be a
language construct, and every unadorned name is assumed to reference
some value/object, so you need quote marks to demarcate literal
os.listdir(thingy)
“return a list of the contents of the directory whose name is in the
variable ‘thingy’”, vs.
os.listdir("thingy")
“return a list of the contents of the directory named ‘thingy’”.
This difference in design has to do with their typical usage: most of
the use of a shell/command language is in typing a single command at a
time, for immediate execution. Whereas a programming language is
typically used to construct sequences consisting of multiple lines of
code before they are executed.
This difference is also why attempts to use programming languages as
though they were shell/command languages, entering and executing a
single line of code at a time, tend to end up being more trouble than
they are worth.
Conversely, using shell/command languages as programming languages, by
collecting multiple lines of code into shell scripts, does work, but
only up to a point. The concept of variable substitution via string
substitution tends to lead to trouble when trying to do more advanced
data manipulations.
So, in short, while there is some overlap in their applicable usage
areas, they are still very much oriented to different application
scenarios.
Interesting, I never thought of it like that.
--
user <candycane> is generated from /dev/urandom
M***@dastardlyhq.com
2024-03-29 09:55:33 UTC
Reply
Permalink
On Fri, 29 Mar 2024 01:14:18 -0000 (UTC)
At one time, we distinguished between “scripting” languages and
“programming” languages. To begin with, the “scripting” languages were
somehow more limited in functionality than full-fledged “programming”
languages. Or they were slower, because they were interpreted.
Then languages like Perl and Java came along: both were compiled to a
bytecode, a sort of pseudo-machine-language, which was interpreted by
software, not CPU hardware. Were they “scripting” or “programming”
languages? Some might have classed Perl as a “scripting” language to
My rule of thimb is that a scripting language is one whereby the source code
can be run immediately by the interpreter, eg perl, python, regardless of
what happens internally. A full fledged programming language is one that
requires a compile/debug/link step first with the compiler and runtime (if
required) being seperate. eg Java, C
Josef Möllers
2024-03-29 11:10:20 UTC
Reply
Permalink
Post by M***@dastardlyhq.com
On Fri, 29 Mar 2024 01:14:18 -0000 (UTC)
Post by Lawrence D'Oliveiro
At one time, we distinguished between “scripting” languages and
“programming” languages. To begin with, the “scripting” languages were
somehow more limited in functionality than full-fledged “programming”
languages. Or they were slower, because they were interpreted.
Then languages like Perl and Java came along: both were compiled to a
bytecode, a sort of pseudo-machine-language, which was interpreted by
software, not CPU hardware. Were they “scripting” or “programming”
languages? Some might have classed Perl as a “scripting” language to
My rule of thimb is that a scripting language is one whereby the source code
can be run immediately by the interpreter, eg perl, python, regardless of
what happens internally. A full fledged programming language is one that
requires a compile/debug/link step first with the compiler and runtime (if
required) being seperate. eg Java, C
I second that.

My 2€cts,
Josef
Richard Kettlewell
2024-03-29 11:40:03 UTC
Reply
Permalink
Post by M***@dastardlyhq.com
My rule of thimb is that a scripting language is one whereby the source code
can be run immediately by the interpreter, eg perl, python, regardless of
what happens internally. A full fledged programming language is one that
requires a compile/debug/link step first with the compiler and runtime (if
required) being seperate. eg Java, C
C can be a scripting language by that rule:

$ cat t.c
#!/usr/bin/tcc -run
#include <stdio.h>

int main(void) {
return printf("Hello, world\n");
}
$ ./t.c
Hello, world
--
https://www.greenend.org.uk/rjk/
M***@dastardlyhq.com
2024-03-29 12:02:34 UTC
Reply
Permalink
On Fri, 29 Mar 2024 11:40:03 +0000
Post by M***@dastardlyhq.com
My rule of thimb is that a scripting language is one whereby the source code
can be run immediately by the interpreter, eg perl, python, regardless of
what happens internally. A full fledged programming language is one that
requires a compile/debug/link step first with the compiler and runtime (if
required) being seperate. eg Java, C
No definition is perfect in this case, its all shades of grey.
Kaz Kylheku
2024-03-29 17:09:56 UTC
Reply
Permalink
Post by M***@dastardlyhq.com
On Fri, 29 Mar 2024 11:40:03 +0000
Post by M***@dastardlyhq.com
My rule of thimb is that a scripting language is one whereby the source code
can be run immediately by the interpreter, eg perl, python, regardless of
what happens internally. A full fledged programming language is one that
requires a compile/debug/link step first with the compiler and runtime (if
required) being seperate. eg Java, C
No definition is perfect in this case, its all shades of grey.
Yes, a definition can be close to perfet here:

Scripting is an activity, a use case, not a language.

Scripting refers to executing commands which are so high level that they
are entire applications or functional blocks within an application.
Scripting automates applications or groups of applications.

A language can /support/ scripting (and other paradigms).

If a language only supports scripting well, and nothing else, then it's
a scripting language. That's exactly the same as that a language can be
functional, or multi-paradigm with support for functional programming.

Scripting tend to have the attribute that they would never be used (and
possibly could not be used) to write the functional building blocks
which their commands execute. It's possible for an application to be
written in a language in which it is scripted, but then that's almost
certainly not a scripting language.

Yes, an aspect of scripting is that scripts are taken as-is, in the
representation in which they are written. Or at least, can be. If there
is a compiling step, it is either optional, or hidden by the
implementation. The requirement for some ahead-of-time compilation
ritual to prepare the script for execution by translating it to a
different file in a different format is anti-scripting, in a sense.

The ordinary meaning of the word "script" refers to a dialog followed by
an actor, in the same form in which it was written. The programming
word was almost certainly coined in reference to that.
--
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
Mastodon: @***@mstdn.ca
M***@dastardlyhq.com
2024-03-29 17:18:23 UTC
Reply
Permalink
On Fri, 29 Mar 2024 17:09:56 -0000 (UTC)
Post by Kaz Kylheku
Post by M***@dastardlyhq.com
On Fri, 29 Mar 2024 11:40:03 +0000
Post by M***@dastardlyhq.com
My rule of thimb is that a scripting language is one whereby the source
code
Post by M***@dastardlyhq.com
Post by M***@dastardlyhq.com
can be run immediately by the interpreter, eg perl, python, regardless of
what happens internally. A full fledged programming language is one that
requires a compile/debug/link step first with the compiler and runtime (if
required) being seperate. eg Java, C
No definition is perfect in this case, its all shades of grey.
Define perfect. Yours isn't.
Post by Kaz Kylheku
Scripting is an activity, a use case, not a language.
So if I write a program to for example process some files in a directory by
your argument its a script whether I write it in shell, python, C++ or
assembler.

Umm, no, try again.
Kaz Kylheku
2024-03-29 17:25:18 UTC
Reply
Permalink
Post by M***@dastardlyhq.com
On Fri, 29 Mar 2024 17:09:56 -0000 (UTC)
Post by Kaz Kylheku
Post by M***@dastardlyhq.com
On Fri, 29 Mar 2024 11:40:03 +0000
Post by M***@dastardlyhq.com
My rule of thimb is that a scripting language is one whereby the source
code
Post by M***@dastardlyhq.com
Post by M***@dastardlyhq.com
can be run immediately by the interpreter, eg perl, python, regardless of
what happens internally. A full fledged programming language is one that
requires a compile/debug/link step first with the compiler and runtime (if
required) being seperate. eg Java, C
No definition is perfect in this case, its all shades of grey.
Define perfect. Yours isn't.
Post by Kaz Kylheku
Scripting is an activity, a use case, not a language.
So if I write a program to for example process some files in a directory by
your argument its a script whether I write it in shell, python, C++ or
assembler.
I also wrote: "Scripting refers to executing commands which are so high
level that they are entire applications or functional blocks within an
application."

If you write the program in assembler, are the instructions
"commands which are so high level that they are entire applications
or functional blocks within an application?"

In the assembly language program, mulitiple instructions, irrelevant
to the file processing task, are required just to correctly set up a
function call with parameters and return from it.

You're just being deliberately obtuse, not to mention snippy with the
scissors.
--
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
Mastodon: @***@mstdn.ca
M***@dastardlyhq.com
2024-03-30 10:16:33 UTC
Reply
Permalink
On Fri, 29 Mar 2024 17:25:18 -0000 (UTC)
Post by Kaz Kylheku
Post by M***@dastardlyhq.com
Post by Kaz Kylheku
Scripting is an activity, a use case, not a language.
So if I write a program to for example process some files in a directory by
your argument its a script whether I write it in shell, python, C++ or
assembler.
I also wrote: "Scripting refers to executing commands which are so high
level that they are entire applications or functional blocks within an
application."
So if I write:

int main()
{
system("ls | wc -l");
return 0;
}

Thats a script? No? What if I use popen() or execve() then? Where do you
draw the line?
Post by Kaz Kylheku
You're just being deliberately obtuse, not to mention snippy with the
scissors.
I'm not being obtuse. There is no hard dividing line between scripts and
programs - as I said, its shades of grey.
Janis Papanagnou
2024-03-30 10:35:55 UTC
Reply
Permalink
Post by M***@dastardlyhq.com
I'm not being obtuse. There is no hard dividing line between scripts and
programs - as I said, its shades of grey.
The terms "script" and "scripting languages" are very fuzzy and
just trying to be descriptive, but are effectively meaningless,
the terms don't serve any practical purpose (in my book).

Janis
Kaz Kylheku
2024-03-30 18:10:36 UTC
Reply
Permalink
Post by M***@dastardlyhq.com
On Fri, 29 Mar 2024 17:25:18 -0000 (UTC)
Post by Kaz Kylheku
Post by M***@dastardlyhq.com
Post by Kaz Kylheku
Scripting is an activity, a use case, not a language.
So if I write a program to for example process some files in a directory by
your argument its a script whether I write it in shell, python, C++ or
assembler.
I also wrote: "Scripting refers to executing commands which are so high
level that they are entire applications or functional blocks within an
application."
int main()
{
system("ls | wc -l");
return 0;
}
Thats a script?
The "ls | wc -l" part is a script, passed off for execution to a
language that mainly supports scripting.

Note the non-scripting features here like "int main",
which doesn't /do/ anything, and typically the need to compile
and link this in order to run it.

system() itself also isn't quite "command which is so high level that
it's an inter application or functional block within an application";
it's a shim whose argument might be such a command.
Post by M***@dastardlyhq.com
No? What if I use popen() or execve() then? Where do you
draw the line?
If you use popen and execve, you're using more systems programming
functional blocks that are not scripting commands.
Post by M***@dastardlyhq.com
Post by Kaz Kylheku
You're just being deliberately obtuse, not to mention snippy with the
scissors.
I'm not being obtuse. There is no hard dividing line between scripts and
Right now you're doubling down on obtusity, by my estimate.
Post by M***@dastardlyhq.com
programs - as I said, its shades of grey.
Would you say, fifty shades?
--
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
Mastodon: @***@mstdn.ca
M***@dastardlyhq.com
2024-04-01 08:31:17 UTC
Reply
Permalink
On Sat, 30 Mar 2024 18:10:36 -0000 (UTC)
Post by Kaz Kylheku
Post by M***@dastardlyhq.com
Post by Kaz Kylheku
I also wrote: "Scripting refers to executing commands which are so high
level that they are entire applications or functional blocks within an
application."
int main()
{
system("ls | wc -l");
return 0;
}
Thats a script?
The "ls | wc -l" part is a script, passed off for execution to a
language that mainly supports scripting.
So its not a script.
Post by Kaz Kylheku
Note the non-scripting features here like "int main",
which doesn't /do/ anything, and typically the need to compile
and link this in order to run it.
There may be plenty of surrounding code that does do something.
Post by Kaz Kylheku
Post by M***@dastardlyhq.com
No? What if I use popen() or execve() then? Where do you
draw the line?
If you use popen and execve, you're using more systems programming
functional blocks that are not scripting commands.
They both call high level commands so is it scripting or programming?
Post by Kaz Kylheku
Post by M***@dastardlyhq.com
I'm not being obtuse. There is no hard dividing line between scripts and
Right now you're doubling down on obtusity, by my estimate.
Perhaps you don't understand what being obtuse actually means.
Scott Lurndal
2024-03-30 19:27:05 UTC
Reply
Permalink
Post by M***@dastardlyhq.com
On Fri, 29 Mar 2024 17:25:18 -0000 (UTC)
Post by Kaz Kylheku
Post by M***@dastardlyhq.com
Post by Kaz Kylheku
Scripting is an activity, a use case, not a language.
So if I write a program to for example process some files in a directory by
your argument its a script whether I write it in shell, python, C++ or
assembler.
I also wrote: "Scripting refers to executing commands which are so high
level that they are entire applications or functional blocks within an
application."
int main()
{
system("ls | wc -l");
return 0;
}
Thats a script? No? What if I use popen() or execve() then? Where do you
draw the line?
Technically, only the 'ls | wc -l' is a script. One that is passed
to the default SHELL.
John Ames
2024-03-29 15:44:54 UTC
Reply
Permalink
On Fri, 29 Mar 2024 09:55:33 -0000 (UTC)
Post by M***@dastardlyhq.com
My rule of thimb is that a scripting language is one whereby the
source code can be run immediately by the interpreter, eg perl,
python, regardless of what happens internally. A full fledged
programming language is one that requires a compile/debug/link step
first with the compiler and runtime (if required) being seperate. eg
Java, C
By *that* logic, even Lisp and Forth don't count as "full-fledged
programming languages" o_O Johanne's definition of a "scripting
language" as a DSL designed for directing the actions of the operating
system makes much more sense, IMHO.
M***@dastardlyhq.com
2024-03-29 16:02:13 UTC
Reply
Permalink
On Fri, 29 Mar 2024 08:44:54 -0700
Post by John Ames
On Fri, 29 Mar 2024 09:55:33 -0000 (UTC)
Post by M***@dastardlyhq.com
My rule of thimb is that a scripting language is one whereby the
source code can be run immediately by the interpreter, eg perl,
python, regardless of what happens internally. A full fledged
programming language is one that requires a compile/debug/link step
first with the compiler and runtime (if required) being seperate. eg
Java, C
By *that* logic, even Lisp and Forth don't count as "full-fledged
programming languages" o_O Johanne's definition of a "scripting
As a counter point, good luck writing a device driver in lisp. Forth maybe,
no idea.
John Ames
2024-03-29 16:10:01 UTC
Reply
Permalink
On Fri, 29 Mar 2024 16:02:13 -0000 (UTC)
Post by M***@dastardlyhq.com
On Fri, 29 Mar 2024 08:44:54 -0700
Post by John Ames
By *that* logic, even Lisp and Forth don't count as "full-fledged
programming languages" o_O Johanne's definition of a "scripting
As a counter point, good luck writing a device driver in lisp. Forth
maybe, no idea.
Well, suffice to say that Forth is bare-metal enough to serve as the
foundation for OpenFirmware systems... ;P
Kaz Kylheku
2024-03-29 17:13:47 UTC
Reply
Permalink
Post by M***@dastardlyhq.com
On Fri, 29 Mar 2024 08:44:54 -0700
Post by John Ames
On Fri, 29 Mar 2024 09:55:33 -0000 (UTC)
Post by M***@dastardlyhq.com
My rule of thimb is that a scripting language is one whereby the
source code can be run immediately by the interpreter, eg perl,
python, regardless of what happens internally. A full fledged
programming language is one that requires a compile/debug/link step
first with the compiler and runtime (if required) being seperate. eg
Java, C
By *that* logic, even Lisp and Forth don't count as "full-fledged
programming languages" o_O Johanne's definition of a "scripting
As a counter point, good luck writing a device driver in lisp.
The Lisp machines had operating systems and device drivers written in
Lisp, interrupt-driven and all. Where do you perceive the difficulty?
--
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
Mastodon: @***@mstdn.ca
M***@dastardlyhq.com
2024-03-29 17:20:49 UTC
Reply
Permalink
On Fri, 29 Mar 2024 17:13:47 -0000 (UTC)
Post by Kaz Kylheku
Post by M***@dastardlyhq.com
On Fri, 29 Mar 2024 08:44:54 -0700
Post by John Ames
On Fri, 29 Mar 2024 09:55:33 -0000 (UTC)
Post by M***@dastardlyhq.com
My rule of thimb is that a scripting language is one whereby the
source code can be run immediately by the interpreter, eg perl,
python, regardless of what happens internally. A full fledged
programming language is one that requires a compile/debug/link step
first with the compiler and runtime (if required) being seperate. eg
Java, C
By *that* logic, even Lisp and Forth don't count as "full-fledged
programming languages" o_O Johanne's definition of a "scripting
As a counter point, good luck writing a device driver in lisp.
The Lisp machines had operating systems and device drivers written in
Lisp, interrupt-driven and all. Where do you perceive the difficulty?
Were the mucky bits actually written in Lisp or was Lisp simply calling some
routines written in assembler? In the same sense that Python doesn't actually
"do" AI, its way too slow, the AI but is done in libraries written in C++ that
Python simply calls.
Kaz Kylheku
2024-03-29 17:58:41 UTC
Reply
Permalink
Post by M***@dastardlyhq.com
On Fri, 29 Mar 2024 17:13:47 -0000 (UTC)
Post by Kaz Kylheku
Post by M***@dastardlyhq.com
On Fri, 29 Mar 2024 08:44:54 -0700
Post by John Ames
On Fri, 29 Mar 2024 09:55:33 -0000 (UTC)
Post by M***@dastardlyhq.com
My rule of thimb is that a scripting language is one whereby the
source code can be run immediately by the interpreter, eg perl,
python, regardless of what happens internally. A full fledged
programming language is one that requires a compile/debug/link step
first with the compiler and runtime (if required) being seperate. eg
Java, C
By *that* logic, even Lisp and Forth don't count as "full-fledged
programming languages" o_O Johanne's definition of a "scripting
As a counter point, good luck writing a device driver in lisp.
The Lisp machines had operating systems and device drivers written in
Lisp, interrupt-driven and all. Where do you perceive the difficulty?
Were the mucky bits actually written in Lisp or was Lisp simply calling some
routines written in assembler?
Sorry, could you demarcate where exactly the goalposts are? Which mucky
bits?

In kernels written in C, there are mucky bits in assembler, like
entry and exit into an trap/interrupt handler. You usually can't save
the machine state in an interrupt handler without some instruction that
is of no use in general code generation, not to mention detailed access
to all the working registers that are not normally manipulated from the
HLL.

Yes, the mucky bits of communicating with the device, like passing
frames to and from an ethernet card, would be written in Lisp.

Assembly routines in Lisps, though not Lisp, can at least be written
in Lisp notation and assembled within Lisp.

In machine-compiled Lisps, there is the possibility of inline code,
like in C or other languages.
--
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
Mastodon: @***@mstdn.ca
David W. Hodgins
2024-03-29 18:51:07 UTC
Reply
Permalink
The distinctions between script and programming languages made sense when
they were first introduced. Later, the ability to compile scripts followed
by the things like java bytecode, and then the use of microcode in to make
"machine language" act like a script have made the distinction murky to
the point of effectively being useless at the technical level.

From the user's point of view, text files the are executed by passing them
to an interpreter are best called scripts, and anything that goes through
some sort of compilation to a binary file that then gets executed are best
called programs.

The terminology will continue to be used, but the distinction does not matter,
except from a speed of processing difference.

Regards, Dave Hodgins
Johanne Fairchild
2024-03-29 19:38:48 UTC
Reply
Permalink
"David W. Hodgins" <***@nomail.afraid.org> writes:

[...]
Post by David W. Hodgins
The terminology will continue to be used, but the distinction does not
matter, except from a speed of processing difference.
Just to share that I, personally, don't use the distinction. For
instance, I say that

"the answer is %.2f\n"

is a program that builds a string given its usual context. I say that

awk '1; { print "" }'

is a program to double-space a file. I haven't said ``script'' in
years.
David W. Hodgins
2024-03-29 22:32:30 UTC
Reply
Permalink
Post by Johanne Fairchild
[...]
Post by David W. Hodgins
The terminology will continue to be used, but the distinction does not
matter, except from a speed of processing difference.
Just to share that I, personally, don't use the distinction. For
instance, I say that
"the answer is %.2f\n"
is a program that builds a string given its usual context. I say that
awk '1; { print "" }'
is a program to double-space a file. I haven't said ``script'' in
years.
I still refer to text files, intended to be run through an interpreter such
as bash, as scripts, while things like c text files that must be compiled to
an object file and then linked to be executable as programs.

Regards, Dave Hodgins
Janis Papanagnou
2024-03-29 23:14:48 UTC
Reply
Permalink
Post by David W. Hodgins
The distinctions between script and programming languages made sense when
they were first introduced. [...]
I abandoned the term "shell script" as soon as I got aware that
writing a reliable piece of software with "scripts" follows the
same engineering techniques and requires the same quality means
as non-"scripts". (Occasionally I still use the term informally
though I don't see any formal, technical, or practical necessity
for any such distinction between Command and Programming Language
as far as _programming_ is concerned.)

Janis
M***@dastardlyhq.com
2024-03-30 10:19:46 UTC
Reply
Permalink
On Fri, 29 Mar 2024 17:58:41 -0000 (UTC)
Post by Kaz Kylheku
Post by M***@dastardlyhq.com
Were the mucky bits actually written in Lisp or was Lisp simply calling some
routines written in assembler?
Sorry, could you demarcate where exactly the goalposts are? Which mucky
bits?
Oh I dunno, the parts that walk a kernel memory structure for example.
Post by Kaz Kylheku
In kernels written in C, there are mucky bits in assembler, like
entry and exit into an trap/interrupt handler. You usually can't save
Sure, but far less that there would be in a higher level language.
Kaz Kylheku
2024-03-30 18:46:50 UTC
Reply
Permalink
Post by M***@dastardlyhq.com
On Fri, 29 Mar 2024 17:58:41 -0000 (UTC)
Post by Kaz Kylheku
Post by M***@dastardlyhq.com
Were the mucky bits actually written in Lisp or was Lisp simply calling some
routines written in assembler?
Sorry, could you demarcate where exactly the goalposts are? Which mucky
bits?
Oh I dunno, the parts that walk a kernel memory structure for example.
Well, since the kernel is written in Lisp, of course Lisp walks its own
data structures.

In a kernel, there often occur externally imposed memory structures,
like for instance lists of entries in a DMA buffer ring above an
ethernet device. Or banks of registers.

The kernel-writing Lisp dialect would have provisions for dealing
with binary structures like that.

The following example is not from a Lisp operating system, or a Lisp
that is known for operating system work. It's from my own application.

It shows how in CCL (Clozure Common Lisp) (note: note the Z, not Clojure
with a J) we can obtain a linked list C data structure and walk it,
using some CCL-specific concepts; CCL provides #> notations for C
types, and offsets into C structures and such.

The GetAdaptersInfo Win32 API is called, filling the list into a
stack-allocated buffer, with the help of CCL's %stack-block operator.
We get a list of adapters, each of which is a list consisting of
a list of the mac bytes, IP address list, name and description.

(The information is then encrypted, hashed and tied to a software license,
along with other bits of system info.)

(defun get-network-interface-list ()
(open-shared-library "iphlpapi.dll")
(let ((blk-size 65536) ;; crude!
(get-adapters-info (foreign-symbol-address "GetAdaptersInfo")))
(if get-adapters-info
(%stack-block ((blk blk-size))
(rlet ((len-inout #>ULONG blk-size))
(if (zerop (ff-call get-adapters-info :address blk
:address len-inout
#>DWORD))
(loop for ptr = blk then (pref ptr #>IP_ADAPTER_INFO.Next)
until (%null-ptr-p ptr)
collecting
(let ((alen (pref ptr #>IP_ADAPTER_INFO.AddressLength))
(addr (pref ptr #>IP_ADAPTER_INFO.Address))
(aname (pref ptr #>IP_ADAPTER_INFO.AdapterName))
(descr (pref ptr #>IP_ADAPTER_INFO.Description))
(iplist (pref ptr #>IP_ADAPTER_INFO.IpAddressList))
(type (pref ptr #>IP_ADAPTER_INFO.Type)))
(list type
(loop for i below alen
collecting (%get-unsigned-byte addr i)
into mac-bytes
finally
(return (mac-bytes-to-string mac-bytes)))
(get-ip-address-list iplist)
(%get-cstring aname)
(%get-cstring descr))))))))))

CCL is compiled; this just turns into a machine language function
poking at stack memory.
--
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
Mastodon: @***@mstdn.ca
M***@dastardlyhq.com
2024-04-01 08:32:48 UTC
Reply
Permalink
On Sat, 30 Mar 2024 18:46:50 -0000 (UTC)
Post by Kaz Kylheku
(defun get-network-interface-list ()
(open-shared-library "iphlpapi.dll")
(let ((blk-size 65536) ;; crude!
(get-adapters-info (foreign-symbol-address "GetAdaptersInfo")))
(if get-adapters-info
(%stack-block ((blk blk-size))
(rlet ((len-inout #>ULONG blk-size))
(if (zerop (ff-call get-adapters-info :address blk
:address len-inout
#>DWORD))
(loop for ptr = blk then (pref ptr #>IP_ADAPTER_INFO.Next)
until (%null-ptr-p ptr)
collecting
(let ((alen (pref ptr #>IP_ADAPTER_INFO.AddressLength))
(addr (pref ptr #>IP_ADAPTER_INFO.Address))
(aname (pref ptr #>IP_ADAPTER_INFO.AdapterName))
(descr (pref ptr #>IP_ADAPTER_INFO.Description))
(iplist (pref ptr #>IP_ADAPTER_INFO.IpAddressList))
(type (pref ptr #>IP_ADAPTER_INFO.Type)))
(list type
(loop for i below alen
collecting (%get-unsigned-byte addr i)
into mac-bytes
finally
(return (mac-bytes-to-string mac-bytes)))
(get-ip-address-list iplist)
(%get-cstring aname)
(%get-cstring descr))))))))))
Ugh. No wonder the language fell out of fashion. Looks like some kind of
hacked up Basic.
Johanne Fairchild
2024-04-01 09:49:48 UTC
Reply
Permalink
Post by M***@dastardlyhq.com
On Sat, 30 Mar 2024 18:46:50 -0000 (UTC)
Post by Kaz Kylheku
(defun get-network-interface-list ()
(open-shared-library "iphlpapi.dll")
(let ((blk-size 65536) ;; crude!
(get-adapters-info (foreign-symbol-address "GetAdaptersInfo")))
(if get-adapters-info
(%stack-block ((blk blk-size))
(rlet ((len-inout #>ULONG blk-size))
(if (zerop (ff-call get-adapters-info :address blk
:address len-inout
#>DWORD))
(loop for ptr = blk then (pref ptr #>IP_ADAPTER_INFO.Next)
until (%null-ptr-p ptr)
collecting
(let ((alen (pref ptr #>IP_ADAPTER_INFO.AddressLength))
(addr (pref ptr #>IP_ADAPTER_INFO.Address))
(aname (pref ptr #>IP_ADAPTER_INFO.AdapterName))
(descr (pref ptr #>IP_ADAPTER_INFO.Description))
(iplist (pref ptr #>IP_ADAPTER_INFO.IpAddressList))
(type (pref ptr #>IP_ADAPTER_INFO.Type)))
(list type
(loop for i below alen
collecting (%get-unsigned-byte addr i)
into mac-bytes
finally
(return (mac-bytes-to-string mac-bytes)))
(get-ip-address-list iplist)
(%get-cstring aname)
(%get-cstring descr))))))))))
Ugh. No wonder the language fell out of fashion. Looks like some kind of
hacked up Basic.
Fashion and intelligence have never been very good friends.
M***@dastardlyhq.com
2024-04-01 14:47:15 UTC
Reply
Permalink
On Mon, 01 Apr 2024 06:49:48 -0300
Post by Kaz Kylheku
Post by M***@dastardlyhq.com
On Sat, 30 Mar 2024 18:46:50 -0000 (UTC)
Post by Kaz Kylheku
(defun get-network-interface-list ()
(open-shared-library "iphlpapi.dll")
(let ((blk-size 65536) ;; crude!
(get-adapters-info (foreign-symbol-address "GetAdaptersInfo")))
(if get-adapters-info
(%stack-block ((blk blk-size))
(rlet ((len-inout #>ULONG blk-size))
(if (zerop (ff-call get-adapters-info :address blk
:address len-inout
#>DWORD))
(loop for ptr = blk then (pref ptr #>IP_ADAPTER_INFO.Next)
until (%null-ptr-p ptr)
collecting
(let ((alen (pref ptr #>IP_ADAPTER_INFO.AddressLength))
(addr (pref ptr #>IP_ADAPTER_INFO.Address))
(aname (pref ptr #>IP_ADAPTER_INFO.AdapterName))
(descr (pref ptr #>IP_ADAPTER_INFO.Description))
(iplist (pref ptr
#>IP_ADAPTER_INFO.IpAddressList))
Post by M***@dastardlyhq.com
Post by Kaz Kylheku
(type (pref ptr #>IP_ADAPTER_INFO.Type)))
(list type
(loop for i below alen
collecting (%get-unsigned-byte addr i)
into mac-bytes
finally
(return (mac-bytes-to-string
mac-bytes)))
Post by M***@dastardlyhq.com
Post by Kaz Kylheku
(get-ip-address-list iplist)
(%get-cstring aname)
(%get-cstring descr))))))))))
Ugh. No wonder the language fell out of fashion. Looks like some kind of
hacked up Basic.
Fashion and intelligence have never been very good friends.
Readability of the flow of control matters. God knows whats going on with
all those nested statements.
Kaz Kylheku
2024-04-01 18:25:54 UTC
Reply
Permalink
Post by M***@dastardlyhq.com
On Mon, 01 Apr 2024 06:49:48 -0300
Post by Kaz Kylheku
Post by M***@dastardlyhq.com
On Sat, 30 Mar 2024 18:46:50 -0000 (UTC)
Post by Kaz Kylheku
(defun get-network-interface-list ()
(open-shared-library "iphlpapi.dll")
(let ((blk-size 65536) ;; crude!
(get-adapters-info (foreign-symbol-address "GetAdaptersInfo")))
(if get-adapters-info
(%stack-block ((blk blk-size))
(rlet ((len-inout #>ULONG blk-size))
(if (zerop (ff-call get-adapters-info :address blk
:address len-inout
#>DWORD))
(loop for ptr = blk then (pref ptr #>IP_ADAPTER_INFO.Next)
until (%null-ptr-p ptr)
collecting
(let ((alen (pref ptr #>IP_ADAPTER_INFO.AddressLength))
(addr (pref ptr #>IP_ADAPTER_INFO.Address))
(aname (pref ptr #>IP_ADAPTER_INFO.AdapterName))
(descr (pref ptr #>IP_ADAPTER_INFO.Description))
(iplist (pref ptr
#>IP_ADAPTER_INFO.IpAddressList))
Post by M***@dastardlyhq.com
Post by Kaz Kylheku
(type (pref ptr #>IP_ADAPTER_INFO.Type)))
(list type
(loop for i below alen
collecting (%get-unsigned-byte addr i)
into mac-bytes
finally
(return (mac-bytes-to-string
mac-bytes)))
Post by M***@dastardlyhq.com
Post by Kaz Kylheku
(get-ip-address-list iplist)
(%get-cstring aname)
(%get-cstring descr))))))))))
Ugh. No wonder the language fell out of fashion. Looks like some kind of
hacked up Basic.
Fashion and intelligence have never been very good friends.
Readability of the flow of control matters. God knows whats going on with
all those nested statements.
I didn't spend a lot of time on that code in the first place, and have
not looked it in over ten years; yet it's trivially easily readable to me.

Anyway, it's in a high level language, yet following a linked list of
structs obtained from a Win32 function, which the code fetches into
a buffer allocated efficiently on the native stack.

The whole thing is compiled into native code.

CCL's primitives for accessing the C stuff aren't pretty, but they are
helpful. It's nice that it has the parsed information about the struct
offsets, like #>IP_ADAPTER_INFO.AdapterName. I didn't have to define
that anywhere. I remember it was pretty easy to figure the primtiies
out from CCL's reference documentation. Easy to write, easy to read
a decade later.
--
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
Mastodon: @***@mstdn.ca
Johanne Fairchild
2024-04-02 00:26:19 UTC
Reply
Permalink
***@dastardlyhq.com writes:

[...]
Post by M***@dastardlyhq.com
Readability of the flow of control matters. God knows whats going on with
all those nested statements.
You don't seem to much of a Lisp writer. Lisp writers have no problem
reading that indentation.
Lawrence D'Oliveiro
2024-04-02 00:57:23 UTC
Reply
Permalink
Post by Johanne Fairchild
reading that indentation.
If indentation is good, more indentation should be better.
Keith Thompson
2024-04-02 01:18:32 UTC
Reply
Permalink
Post by Lawrence D'Oliveiro
Post by Johanne Fairchild
reading that indentation.
If indentation is good, more indentation should be better.
No.
--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+***@gmail.com
Working, but not speaking, for Medtronic
void Void(void) { Void(); } /* The recursive call of the void */
Lawrence D'Oliveiro
2024-04-02 03:01:42 UTC
Reply
Permalink
Post by Lawrence D'Oliveiro
Post by Johanne Fairchild
reading that indentation.
If indentation is good, more indentation should be better.
No.
Don’t quote so deeply, then.
James Kuyper
2024-04-02 09:28:15 UTC
Reply
Permalink
Post by Lawrence D'Oliveiro
Post by Johanne Fairchild
reading that indentation.
If indentation is good, more indentation should be better.
By that same logic, if water is good, more water should be better. Tell
that to someone who is drowning.
For that matter, tell it to my mother who had a dangerous drug
interaction involving a diuretic, while (unknown to her doctor) she was
following a recommendation that she drink 8 glasses of water a day "for
her health". Look up hyponatremia.
Johanne Fairchild
2024-04-02 18:20:06 UTC
Reply
Permalink
Post by Lawrence D'Oliveiro
Post by Johanne Fairchild
reading that indentation.
If indentation is good, more indentation should be better.
Too much of a good thing is a bad thing.
Kenny McCormack
2024-04-02 18:58:01 UTC
Reply
Permalink
Post by Johanne Fairchild
Post by Lawrence D'Oliveiro
Post by Johanne Fairchild
reading that indentation.
If indentation is good, more indentation should be better.
Too much of a good thing is a bad thing.
By definition. Because the definition of "too much" implies having crossed
into the zone of being a bad thing.

I would like to argue that there are things that there is no such thing as
too much of, but I can't think of any examples off hand.
--
First of all, I do not appreciate your playing stupid here at all.

- Thomas 'PointedEars' Lahn -
Scott Lurndal
2024-04-02 18:59:00 UTC
Reply
Permalink
Post by Kenny McCormack
Post by Johanne Fairchild
Post by Lawrence D'Oliveiro
Post by Johanne Fairchild
reading that indentation.
If indentation is good, more indentation should be better.
Too much of a good thing is a bad thing.
By definition. Because the definition of "too much" implies having crossed
into the zone of being a bad thing.
I would like to argue that there are things that there is no such thing as
too much of, but I can't think of any examples off hand.
Money?
Dmitry A. Kazakov
2024-04-02 20:05:18 UTC
Reply
Permalink
Post by Scott Lurndal
Post by Kenny McCormack
Post by Johanne Fairchild
Post by Lawrence D'Oliveiro
Post by Johanne Fairchild
reading that indentation.
If indentation is good, more indentation should be better.
Too much of a good thing is a bad thing.
By definition. Because the definition of "too much" implies having crossed
into the zone of being a bad thing.
I would like to argue that there are things that there is no such thing as
too much of, but I can't think of any examples off hand.
Money?
Inflation.
--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
Kenny McCormack
2024-04-02 20:16:54 UTC
Reply
Permalink
In article <UzYON.154262$***@fx47.iad>,
Scott Lurndal <***@pacbell.net> wrote:
...
Post by Scott Lurndal
Post by Kenny McCormack
By definition. Because the definition of "too much" implies having crossed
into the zone of being a bad thing.
I would like to argue that there are things that there is no such thing as
too much of, but I can't think of any examples off hand.
Money?
Think of all those lottery winners whose lives got totally screwed up by
money.

I'm of the opinion that if I did win the lottery (which I don't play, so
there's no chance of this happening), I'd keep a million or two to live on
(comfortably) and give the rest away (in one fell swoop) to some good
charity. I wouldn't tell anyone about it.

The hard part, in this day and age where everything is a scam, would be
finding an actually good/deserving charity.
--
Prayer has no place in the public schools, just like facts
have no place in organized religion.
-- Superintendent Chalmers
Stefan Ram
2024-04-02 07:56:48 UTC
Reply
Permalink
Post by Johanne Fairchild
You don't seem to much of a Lisp writer. Lisp writers have no problem
reading that indentation.
Well, there is the expression "write-only code", which shows
that a good Lisp writer may not necessarily be a good reader.

This is an example of LISP code:

( SETQ DIFF
( LAMBDA( X )
( COND
( ( ATOMP X )
( COND
( ( = X 'X )
1 )
( T
0 )))
( T
( COND
( ( =( CAR X )'SUM )
( LIST 'SUM( DIFF( CADR X ))( DIFF( CADDR X )))))))))

. For someone who has not learned LISP, this is difficult to read,
/not/ because of the indentation, but because the words used have no
meaning for him. Without the indentation it would be harder to read.

It defines ("SETQ") the name "DIFF" to be a function ("LAMBDA")
of one argument ("X"). When called, the functions tests
("COND") whether X is an atom ("ATOMP X"). In this case,
if X is the letter "X" the result is one, otherwise it's zero.
If X is not a atom, but a sum, we will return the sum of the
DIFFs of the augend and the added. This calls the same function
as the one defined. Yes! In LISP a function may call itself!
Stefan Ram
2024-04-02 08:18:48 UTC
Reply
Permalink
Post by Stefan Ram
( SETQ DIFF
( LAMBDA( X )
( COND
( ( ATOMP X )
( COND
( ( = X 'X )
1 )
( T
0 )))
( T
( COND
( ( =( CAR X )'SUM )
( LIST 'SUM( DIFF( CADR X ))( DIFF( CADDR X )))))))))
In Python:

def diff( x ):
return 1 if x == 'x' else 0 if type( x )is str
else[ 'sum', diff( x[ 1 ]), diff( x[ 2 ])]
if x[ 0 ]== 'sum' else None

. An attempt at indentation:

def diff( x ):
return \
1 if x == 'x' else 0 \
if type( x )is str else \
[ 'sum', diff( x[ 1 ]), diff( x[ 2 ])] \
if x[ 0 ]== 'sum' else None

. In a multiple-returns style:

def diff( x ):
if type( x )is str:
if x == 'x':
return 1
else:
return 0
else:
if x[ 0 ]== 'sum':
return [ 'sum', diff( x[ 1 ]), diff( x[ 2 ])]

.
Stefan Ram
2024-04-02 08:26:14 UTC
Reply
Permalink
Post by Stefan Ram
return 1 if x == 'x' else 0 if type( x )is str
else[ 'sum', diff( x[ 1 ]), diff( x[ 2 ])]
if x[ 0 ]== 'sum' else None
Oops! That was one long line starting with "return";
it was wrapped by the newsreader, but is not correct
Python anymore when wrapped this way.
Kaz Kylheku
2024-04-02 16:33:11 UTC
Reply
Permalink
Post by Stefan Ram
Post by Stefan Ram
( SETQ DIFF
( LAMBDA( X )
( COND
( ( ATOMP X )
( COND
( ( = X 'X )
1 )
( T
0 )))
( T
( COND
( ( =( CAR X )'SUM )
( LIST 'SUM( DIFF( CADR X ))( DIFF( CADDR X )))))))))
return 1 if x == 'x' else 0 if type( x )is str
else[ 'sum', diff( x[ 1 ]), diff( x[ 2 ])]
if x[ 0 ]== 'sum' else None
n TXR Lisp:

(defun-match dif
((sum @left @right) ^(sum ,(dif left) ,(dif right)))
((@op . @args) (error "~s: unrecognized operator: ~s" 'dif op))
(x 1)
(@else 0))

diff is a built in, which we don't want to be redefining without
an exceptionally good reason, so I changed to dif.

If we compile 'dif we get unused variable warnings:

2> (compile 'dif)
** expr-1:1: warning: let*: variable args unused
** expr-1:1: warning: let*: variable else unused
#<vm fun: 0 param + 3 optional + variadic>

To suppress that, we use @nil instead of @args or @else; @nil is a
placeholder pattern that matches any object without binding a variable.

Otherwise we need more verbiage:

((@op . @args) (ignore args) (error ....))
...
(@else (ignore else) 0)
--
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
Mastodon: @***@mstdn.ca
Kaz Kylheku
2024-04-02 16:18:24 UTC
Reply
Permalink
Post by Stefan Ram
Post by Johanne Fairchild
You don't seem to much of a Lisp writer. Lisp writers have no problem
reading that indentation.
Well, there is the expression "write-only code", which shows
that a good Lisp writer may not necessarily be a good reader.
( SETQ DIFF
( LAMBDA( X )
( COND
( ( ATOMP X )
( COND
( ( = X 'X )
1 )
( T
0 )))
( T
( COND
( ( =( CAR X )'SUM )
( LIST 'SUM( DIFF( CADR X ))( DIFF( CADDR X )))))))))
. For someone who has not learned LISP, this is difficult to read,
/not/ because of the indentation, but because the words used have no
meaning for him. Without the indentation it would be harder to read.
I know all the words. It's still hard to read because of the weird
spaces.

This is the way of writing the code that the vast majority of the Lisp
word since gravitated toward:

(SETQ DIFF
(LAMBDA (X)
(COND
((ATOMP X)
(COND
((= X 'X) 1) ;; unnecessary line breaks shored up here
(T 0)))
(T
(COND
((= (CAR X) 'SUM)
(LIST 'SUM (DIFF (CADR X)) (DIFF (CADDR X)))))))))

The code is from just before MacCarthy invented the ternary IF, as a
shorthand for a one clause cond:

(SETQ DIFF
(LAMBDA (X)
(IF (ATOM X)
(IF (= X 'X) 1 0)
(IF (= (CAR X) 'SUM)
(LIST 'SUM (DIFF (CADR X)) (DIFF (CADDR X)))))))

Also, modern cond clauses are not strictly pairs,
which allows the T to be omitted:

(cond (this that) (else)) ;; rather than (t else)

when a cond clause consists of a single expression, then if that
expression is true, cond stops and yields that expression's value.
--
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
Mastodon: @***@mstdn.ca
Lawrence D'Oliveiro
2024-04-01 21:41:56 UTC
Reply
Permalink
Post by M***@dastardlyhq.com
Ugh. No wonder the language fell out of fashion. Looks like some kind of
hacked up Basic.
The BASIC comparison is just ignorant, but a lot of the ugliness comes
from the traditional “parenthesis pileup” layout. I prefer to write my
LISP code in a different way.

One of the key things about LISP is homoiconicity. That is, the language
explicitly includes an AST representation made out of objects defined in
the language itself. This allows for a robust token-based macro facility,
for example. Contrast this with the fiddliness and fragility of #define in
C and C++, for example.
Andreas Eder
2024-04-01 15:11:31 UTC
Reply
Permalink
Post by M***@dastardlyhq.com
On Fri, 29 Mar 2024 17:13:47 -0000 (UTC)
Post by Kaz Kylheku
Post by M***@dastardlyhq.com
On Fri, 29 Mar 2024 08:44:54 -0700
Post by John Ames
On Fri, 29 Mar 2024 09:55:33 -0000 (UTC)
Post by M***@dastardlyhq.com
My rule of thimb is that a scripting language is one whereby the
source code can be run immediately by the interpreter, eg perl,
python, regardless of what happens internally. A full fledged
programming language is one that requires a compile/debug/link step
first with the compiler and runtime (if required) being seperate. eg
Java, C
By *that* logic, even Lisp and Forth don't count as "full-fledged
programming languages" o_O Johanne's definition of a "scripting
As a counter point, good luck writing a device driver in lisp.
The Lisp machines had operating systems and device drivers written in
Lisp, interrupt-driven and all. Where do you perceive the difficulty?
Were the mucky bits actually written in Lisp or was Lisp simply calling some
routines written in assembler? In the same sense that Python doesn't actually
"do" AI, its way too slow, the AI but is done in libraries written in C++ that
Python simply calls.
It was Lisp all the way down. Even the machine langauge was quite lispy
simply because the processor was a lisp chip.
Go read about it - there is lots of info about it on the net and if you
want, you can even run the lisp machines (several implementations) on an
emulator.

'Andreas
--
ceterum censeo redmondinem esse delendam
Christian Weisgerber
2024-03-29 18:12:35 UTC
Reply
Permalink
Post by M***@dastardlyhq.com
As a counter point, good luck writing a device driver in lisp.
Mmh--anybody know whether that was done for Lisp machines?
--
Christian "naddy" Weisgerber ***@mips.inka.de
David Brown
2024-03-30 18:32:05 UTC
Reply
Permalink
Post by M***@dastardlyhq.com
On Fri, 29 Mar 2024 08:44:54 -0700
Post by John Ames
On Fri, 29 Mar 2024 09:55:33 -0000 (UTC)
Post by M***@dastardlyhq.com
My rule of thimb is that a scripting language is one whereby the
source code can be run immediately by the interpreter, eg perl,
python, regardless of what happens internally. A full fledged
programming language is one that requires a compile/debug/link step
first with the compiler and runtime (if required) being seperate. eg
Java, C
By *that* logic, even Lisp and Forth don't count as "full-fledged
programming languages" o_O Johanne's definition of a "scripting
As a counter point, good luck writing a device driver in lisp. Forth maybe,
no idea.
"Open Firmware" is an attempt to have device drivers for PCI cards (and
other hardware) included in flash on the cards, in a processor and
platform independent way. It uses Forth - so the device drivers are
provided as Forth source code or byte-compiled Forth, and can then be
executed with a simple Forth VM on the target system. They can also be
JIT compiled for the target.

<https://en.wikipedia.org/wiki/Open_Firmware>

It didn't really take off very well, but certainly people have written
device drivers in Forth.
Kaz Kylheku
2024-03-30 20:19:25 UTC
Reply
Permalink
Post by David Brown
<https://en.wikipedia.org/wiki/Open_Firmware>
It didn't really take off very well, but certainly people have written
device drivers in Forth.
Unfortunately, the device tree crap from Open Firmware took off.
--
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
Mastodon: @***@mstdn.ca
Kaz Kylheku
2024-03-29 17:12:40 UTC
Reply
Permalink
Post by John Ames
On Fri, 29 Mar 2024 09:55:33 -0000 (UTC)
Post by M***@dastardlyhq.com
My rule of thimb is that a scripting language is one whereby the
source code can be run immediately by the interpreter, eg perl,
python, regardless of what happens internally. A full fledged
programming language is one that requires a compile/debug/link step
first with the compiler and runtime (if required) being seperate. eg
Java, C
By *that* logic, even Lisp and Forth don't count as "full-fledged
programming languages" o_O Johanne's definition of a "scripting
language" as a DSL designed for directing the actions of the operating
system makes much more sense, IMHO.
Common Lisp requires the implementation to be able to read
and execute printed expressions, without having them placed into
a file that must be translated to a compiled file.

The most prominent CL implementations compile every form before
executing it, even at the interactive prompt. It's invisible to the
user.

Scripting doesn't mean that the commands cannot be transparently
translated into antoher language before being executed.
--
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
Mastodon: @***@mstdn.ca
Johanne Fairchild
2024-03-29 11:09:46 UTC
Reply
Permalink
Post by Lawrence D'Oliveiro
At one time, we distinguished between “scripting” languages and
“programming” languages. [...] But there is one distinction that I
think is still relevant, and that is the one between shell/command
languages and programming languages.
[...]

Consider looking at a shell language like a domain-specific programming
language. A shell is a programming language made specifically for
running programs. When you write a shell line, you're specifying the
arguments of execve(2). In other words, a shell is a programming
language made to prepare the memory to be consumed by the system in a
specific way---execve(2). (Of course, the idea evolves and you want to
glue programs, do variable substitution et cetera.)

A scripting language is a programming language made for a hypothetical
machine, not too different from a programming language made for a real
machine, one made of hardware.

You seem to find trouble with using a programming language in a REPL.
It seems to contradict be the overall feeling of so many people who
understand a lot about programming---who made all of these things
actually work (and fun).
Stefan Ram
2024-03-29 20:07:29 UTC
Reply
Permalink
Post by Johanne Fairchild
A scripting language is a programming language made for a hypothetical
machine, not too different from a programming language made for a real
machine, one made of hardware.
C is clearly a programming language, yet its specification
says, "The semantic descriptions in this document describe
the behavior of an abstract machine". And you cannot buy
this abstract C machine as a piece of hardware anywhere!
Johanne Fairchild
2024-03-30 00:17:48 UTC
Reply
Permalink
Post by Stefan Ram
Post by Johanne Fairchild
A scripting language is a programming language made for a hypothetical
machine, not too different from a programming language made for a real
machine, one made of hardware.
C is clearly a programming language, yet its specification
says, "The semantic descriptions in this document describe
the behavior of an abstract machine". And you cannot buy
this abstract C machine as a piece of hardware anywhere!
Of course. :) But we both know what that means. It's abstract because
there are so many real machines for which this abstract one is an
abstraction of. And the real ones are the target of the language.
Stefan Ram
2024-03-30 07:47:14 UTC
Reply
Permalink
Post by Johanne Fairchild
Post by Stefan Ram
Post by Johanne Fairchild
A scripting language is a programming language made for a hypothetical
machine, not too different from a programming language made for a real
machine, one made of hardware.
C is clearly a programming language, yet its specification
says, "The semantic descriptions in this document describe
the behavior of an abstract machine". And you cannot buy
this abstract C machine as a piece of hardware anywhere!
Of course. :) But we both know what that means. It's abstract because
there are so many real machines for which this abstract one is an
abstraction of. And the real ones are the target of the language.
If you want to see it this way ...

But look at Pascal, Java, or Python. They are usually compiled
into an intermediate code (called "p-code" in the case of
Pascal) which is then interpreted (the interpreter is called
"JVM" in the case of Java). Yet, we think of Pascal and Java
as programming languages and of Python as a scripting language.

But this is actually an implementation detail: Java also can
be compiled into machine code.

In any case, we can write a small batch file "execute" which
can be called for source code in any programming language and
will execute it:

execute Main.pas
execute Main.java
execute Main.py
execute main.c
execute main.cpp
execute main.bas
execute main.bat
...

They all will print "Hello World". Whether the execution happens
via translation to machine code or via interpretation by another
program or by a mixture of both is just an implementation
detail of "execute", that usually will not matter much for the
programmer. And often for the same language, one is free to
either compile it to machine language or interpret it via another
program.

Some language, like LISP or Python, have "eval": These languages
still can be compiled, but they require an interpreter at run-
time. Java often is executed by interpretation first, but when
the "Hotspot" interpreter sees that some code is executed often,
it will then decide /at run-time/ to compile it into actual
machine code! (And there are Python implementations that run
on the JVM.)

How can such implementation details matter for the question whether
a language is called a programming language or a scripting language,
when the programmer often does not even need to know about them?

Yes, there also are C interpreters IIRC, but they are rare.
Janis Papanagnou
2024-03-30 10:28:34 UTC
Reply
Permalink
Post by Stefan Ram
But look at Pascal, Java, or Python. They are usually compiled
into an intermediate code (called "p-code" in the case of
Pascal) which is then interpreted (the interpreter is called
"JVM" in the case of Java). Yet, we think of Pascal and Java
as programming languages and of Python as a scripting language.
I never used an interpreted Pascal, nor one that produced p-code.
(As far as memory serves it was the UCSD Pascal dialect that
decided to use intermediate code to be interpreted.) My Pascal
programs have always been compiled.

And there were BASIC compilers on mainframes before the BASIC
interpreters on PCs became popular and widespread.

It's _the same_ language (modulo dialects), and languages are
usually defined by their grammar and semantics and not whether
it is interpreted/compiled or how it is run (VM or else).

I think it's obvious that interpretation vs. compilation or any
intermediate interpreted p-code is not an appropriate criterion
to declare something as a "scripting" language. You can't tell
whether a language, Pascal, BASIC, or any other language, is a
"scripting" language by that criterion. It's also generally a
fuzzy term; literature speaks vaguely about "typical" criteria
but cannot pin them down. - And that term isn't even helpful in
any way! - So why use it at all or religiously dispute about it.

Janis
Post by Stefan Ram
But this is actually an implementation detail: Java also can
be compiled into machine code.
[...]
Christian Weisgerber
2024-03-30 13:37:24 UTC
Reply
Permalink
Post by Stefan Ram
But look at Pascal, Java, or Python. They are usually compiled
into an intermediate code (called "p-code" in the case of
Pascal) which is then interpreted
Pascal is usually compiled to machine code. UCSD Pascal with its
intermediate p-code was an atypical case.
--
Christian "naddy" Weisgerber ***@mips.inka.de
Scott Lurndal
2024-03-30 19:25:58 UTC
Reply
Permalink
Post by Stefan Ram
Post by Johanne Fairchild
Post by Stefan Ram
Post by Johanne Fairchild
A scripting language is a programming language made for a hypothetical
machine, not too different from a programming language made for a real
machine, one made of hardware.
C is clearly a programming language, yet its specification
says, "The semantic descriptions in this document describe
the behavior of an abstract machine". And you cannot buy
this abstract C machine as a piece of hardware anywhere!
Of course. :) But we both know what that means. It's abstract because
there are so many real machines for which this abstract one is an
abstraction of. And the real ones are the target of the language.
If you want to see it this way ...
But look at Pascal, Java, or Python. They are usually compiled
into an intermediate code (called "p-code" in the case of
Pascal) which is then interpreted (the interpreter is called
"JVM" in the case of Java). Yet, we think of Pascal and Java
as programming languages and of Python as a scripting language.
VAX Pascal (1980) was compiled directly to VAX machine code, as was
the Pascal compiler I wrote in the graduate compiler class.

UCSD Pascal used p-code, and IIRC Borland picked up
on that.
Christian Weisgerber
2024-03-30 21:48:11 UTC
Reply
Permalink
Post by Scott Lurndal
VAX Pascal (1980) was compiled directly to VAX machine code, as was
the Pascal compiler I wrote in the graduate compiler class.
UCSD Pascal used p-code, and IIRC Borland picked up
on that.
Borland's Turbo Pascal compiled to machine code.
--
Christian "naddy" Weisgerber ***@mips.inka.de
Lawrence D'Oliveiro
2024-03-29 21:06:58 UTC
Reply
Permalink
Post by Johanne Fairchild
Consider looking at a shell language like a domain-specific programming
language. A shell is a programming language made specifically for
running programs. ... (Of course, the idea evolves and you want to
glue programs, do variable substitution et cetera.)
That’s the thing. The design for a “language made specifically for running
programs” always seems to start with the assumption that what the user
types is to be passed as literal text, unless special markers are present
to indicate that they want to “glue programs, do variable substitution et
cetera”. Notice your use of the term “variable substitution”, which is
characteristic of a shell language: in a programming language, you don’t
call it “substitution”, you call it “evaluation”.
Post by Johanne Fairchild
A scripting language is a programming language made for a hypothetical
machine, not too different from a programming language made for a real
machine, one made of hardware.
In our CS classes we learned to think about “abstract machines”, and
forget the distinction between “software” and “hardware”. Instead, we
build layers of abstract machines, one on top of the other, getting more
and more specialized towards the particular class of problems we want to
solve at any particular time.

Command languages are just another such “abstract machine”, and the
scripts we write in them are another layer on top.

The layering only stops when you get to a GUI; they can’t be used to build
any further “machines” on top.
Post by Johanne Fairchild
You seem to find trouble with using a programming language in a REPL.
I find REPLs annoying and inconvenient. If I want to do “scratchpad”
programming, I do it in a Jupyter notebook.
Johanne Fairchild
2024-03-30 00:24:01 UTC
Reply
Permalink
Post by Lawrence D'Oliveiro
Post by Johanne Fairchild
Consider looking at a shell language like a domain-specific programming
language. A shell is a programming language made specifically for
running programs. ... (Of course, the idea evolves and you want to
glue programs, do variable substitution et cetera.)
That’s the thing. The design for a “language made specifically for running
programs” always seems to start with the assumption that what the user
types is to be passed as literal text, unless special markers are present
to indicate that they want to “glue programs, do variable substitution et
cetera”. Notice your use of the term “variable substitution”, which is
characteristic of a shell language: in a programming language, you don’t
call it “substitution”, you call it “evaluation”.
That's right. Substitution is evaluation; a specific form of.
Post by Lawrence D'Oliveiro
Post by Johanne Fairchild
You seem to find trouble with using a programming language in a REPL.
I find REPLs annoying and inconvenient. If I want to do “scratchpad”
programming, I do it in a Jupyter notebook.
That's something to think about. Your perception is wildly different
from a lot of people who have thought and think very deeply about the
whole craft.

Consider your Lisp writing, which violates the culture of Lisp writing.
Of course you should keep your independence, but maybe there are good
reasons why the culture is as it is---not all culture is fashion.
Lawrence D'Oliveiro
2024-03-30 01:11:31 UTC
Reply
Permalink
Post by Johanne Fairchild
Consider your Lisp writing, which violates the culture of Lisp writing.
Of course you should keep your independence, but maybe there are good
reasons why the culture is as it is---not all culture is fashion.
Let me know what they are. The only reasons I have seen offered so far are
basically just “that’s the way it’s always been done”.
Stefan Ram
2024-04-01 14:16:33 UTC
Reply
Permalink
Post by Johanne Fairchild
A scripting language is a programming language made for a hypothetical
machine, not too different from a programming language made for a real
machine, one made of hardware.
I think of the type system:

In a non-scripting programming language, the types often are
based on hardware, like "16 bit integer", and typing is often
handled in a static and rather strict way. Higher types, like
strings whose size can change at run time, are often missing.

Scripting languages are often less strictly typed, some rely entirely
on strings which are interpreted as integers if necessary. Often
one has no control over the internal represention of data, so one
cannot access a library using the ABI or write a device driver in a
scripting language. Explicit type conversions are rarely required.

Also, resource handling:

Scripting languages handle the memory for you. In a scripting
language, you cannot call "malloc" to obtain the obligation to
free this piece of memory exactly once in the future. They are
garbage collected.
John Ames
2024-04-01 18:15:52 UTC
Reply
Permalink
On 1 Apr 2024 14:16:33 GMT
Post by Stefan Ram
In a non-scripting programming language, the types often are
based on hardware, like "16 bit integer", and typing is often
handled in a static and rather strict way. Higher types, like
strings whose size can change at run time, are often missing.
Notwithstanding the fuzziness granted by the use of "often" here, this
doesn't seem like a terribly accurate assessment. Lots of compiled/
"non-scripting" languages - *however* you define that - have dynamic
strings; even C++ provides that as part of the standard library
(admittedly, not as a basic language construct, but that's C for you -
*every* data structure is essentially pointers in a trenchcoat.) AFAIK
it's much rarer to *lack* that capability; C does, for aforementioned
reasons (although you can certainly roll your own,) O.G. Pascal did (as
a hideous misfeature,) probably a few other current systems languages...
but not many spring to mind.

It's also not terribly true that "non-scripting" languages are pre-
dominantly statically-typed. It's more common, certainly, but there are
still a number of compiled applications languages with some kind of
dynamic support. And while the division of number types into floating-
point and integer is very frequently the case, most language standards
don't specify word sizes that strictly (even in C, stdint.h wasn't
introduced until C99 - which lead to headaches of its own, as anyone
who's tried to run old code that makes assumptions about sizeof(int) on
targets that break those assumptions can attest.) Plenty of "non-
scripting" languages include or can be extended with support for
arbitrary bignum types, as well.
Post by Stefan Ram
Scripting languages handle the memory for you. In a scripting
language, you cannot call "malloc" to obtain the obligation to
free this piece of memory exactly once in the future. They are
garbage collected.
And while this is pretty true of scripting languages, it doesn't make
for a good point-of-contrast with "non-scripting" languages; *piles* of
them include support for automatic memory management, and some (outside
of the C family) don't even include facilities for doing it "by hand."

Overall, this seems like a very narrow and C-centric view of programming
language design - and while C is definitely *my* language-of-choice for
application development,* let's not pretend it's the absolute be-all
and end-all, as if there *could* be such a thing in a field as vast and
diverse as this!

* (Funnily enough, for a lot of "scripting" type jobs, my go-to is
actually a compiled language - FreeBasic.)
Scott Lurndal
2024-04-01 19:42:05 UTC
Reply
Permalink
Post by John Ames
On 1 Apr 2024 14:16:33 GMT
Post by Stefan Ram
Scripting languages handle the memory for you. In a scripting
language, you cannot call "malloc" to obtain the obligation to
free this piece of memory exactly once in the future. They are
garbage collected.
And while this is pretty true of scripting languages, it doesn't make
for a good point-of-contrast with "non-scripting" languages; *piles* of
them include support for automatic memory management, and some (outside
of the C family) don't even include facilities for doing it "by hand."
Indeed, and if you use the set (resources) rather than a member
of the set (memory), even scripting languages allocate resources and
must free them. E.g. temporary files, with some garbage collection
(/tmp cleaners).

Why is it important that there be a distinction between "scripting"
and "non-scripting" languages at all?
John Ames
2024-04-01 20:25:31 UTC
Reply
Permalink
On Mon, 01 Apr 2024 19:42:05 GMT
Post by Scott Lurndal
Why is it important that there be a distinction between "scripting"
and "non-scripting" languages at all?
Oh, it's an interesting question from a general standpoint, and I think
you could make an argument that it'd be "useful" to someone trying to
determine what the right tool for a given job would be.* The problem
seems to be that *A.* we're arguing from several wildly different
definitions of "scripting language" - is it a matter of problem domain?
Implementation details? Both? Phase of the moon? - and nobody seems to
want to budge on their preferred line, and *B.* even with a given
definition, it's not exactly a firm line.

* (Funny story - when I was a young'un first dabbling with computer
programming, I got the impression that a lot of DOS games were written
in Batch, of all things, because that was how you invoked them, and
spent several confused days poring over the MS documentation trying to
figure out how they could've done it!)
Lawrence D'Oliveiro
2024-04-02 00:20:31 UTC
Reply
Permalink
Why is it important that there be a distinction between "scripting" and
"non-scripting" languages at all?
Particularly since the point of this thread is that there isn’t an
important one.
James Kuyper
2024-04-02 09:13:13 UTC
Reply
Permalink
On 4/1/24 15:42, Scott Lurndal wrote:
...
Post by Scott Lurndal
Why is it important that there be a distinction between "scripting"
and "non-scripting" languages at all?
I don't know, which is why this discussion bores me. But when people
aren't in agreement about the definition of a term, it's often useful to
consider what you might want to say using the term - not what you want
to say about the definition, but what you want to say that can be
non-trivially derived from the definition. Then you should carefully
choose a definition for the term so that makes what you want to say
about it both true, and even more important, useful.
John Ames
2024-04-01 20:44:57 UTC
Reply
Permalink
On Mon, 1 Apr 2024 11:15:52 -0700
Post by John Ames
And while this is pretty true of scripting languages, it doesn't make
for a good point-of-contrast with "non-scripting" languages; *piles*
of them include support for automatic memory management, and some
(outside of the C family) don't even include facilities for doing it
"by hand."
And, in fact, C actually does one specific bit of automatic memory
management itself - the stack, which may or may not even *be* a true
hardware stack (depending on the architecture,) and which is handled in
an entirely transparent fashion* by compiler-generated entry/exit code
generated by the compiler for each function.

* (Until you go and pass a pointer to a local variable to some piece of
code that expects it to still be valid later, natch.)
Stefan Ram
2024-04-01 21:13:42 UTC
Reply
Permalink
Post by John Ames
And, in fact, C actually does one specific bit of automatic memory
management itself - the stack, which may or may not even *be* a true
hardware stack (depending on the architecture,) and which is handled in
an entirely transparent fashion* by compiler-generated entry/exit code
generated by the compiler for each function.
This stack "management" is "limited" in C:

|Unfortunately, the notion of stack overflow is not mentioned
|by the standard or the standard’s rationale at all. This is
|very troublesome, as for most actual implementations stack
|overflow is a real problem.
...
|in a real C implementation, a call like f(10000000) will not
|return 10000000, but instead will crash with a message like
|"segmentation fault". Furthermore, stack overflow does not
|necessarily have to result in a crash with a nice error
|message, but might also overwrite non-stack parts of the
|memory (possibly putting the address of virus code there).
|Stack overflow even can occur without function calls. For
|example, the program int main(void) { int a[10000000]; }
...
"Subtleties of the ANSI/ISO C standard" (2012); Robbert
Krebbers, Freek Wiedijk; Radboud University Nijmegen.
John Ames
2024-04-01 21:30:42 UTC
Reply
Permalink
On 1 Apr 2024 21:13:42 GMT
True enough, although as noted that's an implementation issue as much
as it is a limitation of the language spec. (I'm not sure how you could
handle that in a way that's both robust and reasonably C-ish...)
Post by Stefan Ram
|Stack overflow even can occur without function calls. For
|example, the program int main(void) { int a[10000000]; }
But I did have to have a chuckle at this reminder of the days when "try
to allocate < 40 MB on the stack" meant "automatic segfault." A lotta
modern developers should've had to cut their teeth in an environment
like that...!
Scott Lurndal
2024-04-01 22:40:31 UTC
Reply
Permalink
Post by John Ames
On 1 Apr 2024 21:13:42 GMT
True enough, although as noted that's an implementation issue as much
as it is a limitation of the language spec. (I'm not sure how you could
handle that in a way that's both robust and reasonably C-ish...)
Modern (64-bit) linux systems leave large buffer zones (unmapped addresses)
on either side of the stack; a stack overflow or underflow will
immediately fault if the RLIMIT_STACK value is exceeded.
Post by John Ames
Post by Stefan Ram
|Stack overflow even can occur without function calls. For
|example, the program int main(void) { int a[10000000]; }
POSIX and linux systems support limiting the amount of address
space an individual users stack can consume. 8MB is the default
on many linux distributions.
candycanearter07
2024-04-02 15:30:09 UTC
Reply
Permalink
Post by Scott Lurndal
Post by John Ames
On 1 Apr 2024 21:13:42 GMT
True enough, although as noted that's an implementation issue as much
as it is a limitation of the language spec. (I'm not sure how you could
handle that in a way that's both robust and reasonably C-ish...)
Modern (64-bit) linux systems leave large buffer zones (unmapped addresses)
on either side of the stack; a stack overflow or underflow will
immediately fault if the RLIMIT_STACK value is exceeded.
It still protects writing to memory outside that buffer, right?
[snip]
--
user <candycane> is generated from /dev/urandom
John Ames
2024-04-02 15:43:04 UTC
Reply
Permalink
On Tue, 2 Apr 2024 15:30:09 -0000 (UTC)
Post by candycanearter07
It still protects writing to memory outside that buffer, right?
[snip]
"Protecting memory" doesn't mean "no page fault," though, just that it
won't scribble all over some other process's memory. But I am curious
how universally various freenix distributions these days just let the
application segfault vs. using that as a cue to allocate additional
stack space; a quick test with WSL (Debian somethingorother) runs that
test without complaint, but I don't have a genuine *nix box to hand to
try it with.
Scott Lurndal
2024-04-02 16:09:38 UTC
Reply
Permalink
Post by John Ames
On Tue, 2 Apr 2024 15:30:09 -0000 (UTC)
Post by candycanearter07
It still protects writing to memory outside that buffer, right?
[snip]
"Protecting memory" doesn't mean "no page fault," though, just that it
won't scribble all over some other process's memory.
The regions each side of the stack are marked not-present. This supports
automatic stack expansion, within the resource limit for the stack on
one side, and will produce a SIGSEGV or SIGBUS on the other end.
Post by John Ames
But I am curious
how universally various freenix distributions these days just let the
application segfault vs. using that as a cue to allocate additional
stack space; a quick test with WSL (Debian somethingorother) runs that
test without complaint, but I don't have a genuine *nix box to hand to
try it with.
All linux will allocate space, up to the stack resource limit.
candycanearter07
2024-04-02 18:50:11 UTC
Reply
Permalink
Post by Scott Lurndal
Post by John Ames
On Tue, 2 Apr 2024 15:30:09 -0000 (UTC)
Post by candycanearter07
It still protects writing to memory outside that buffer, right?
[snip]
"Protecting memory" doesn't mean "no page fault," though, just that it
won't scribble all over some other process's memory.
The regions each side of the stack are marked not-present. This supports
automatic stack expansion, within the resource limit for the stack on
one side, and will produce a SIGSEGV or SIGBUS on the other end.
Post by John Ames
But I am curious
how universally various freenix distributions these days just let the
application segfault vs. using that as a cue to allocate additional
stack space; a quick test with WSL (Debian somethingorother) runs that
test without complaint, but I don't have a genuine *nix box to hand to
try it with.
All linux will allocate space, up to the stack resource limit.
Interesting.
--
user <candycane> is generated from /dev/urandom
Keith Thompson
2024-04-01 22:56:11 UTC
Reply
Permalink
Post by Stefan Ram
Post by John Ames
And, in fact, C actually does one specific bit of automatic memory
management itself - the stack, which may or may not even *be* a true
hardware stack (depending on the architecture,) and which is handled in
an entirely transparent fashion* by compiler-generated entry/exit code
generated by the compiler for each function.
|Unfortunately, the notion of stack overflow is not mentioned
|by the standard or the standard’s rationale at all. This is
|very troublesome, as for most actual implementations stack
|overflow is a real problem.
...
|in a real C implementation, a call like f(10000000) will not
|return 10000000, but instead will crash with a message like
|"segmentation fault". Furthermore, stack overflow does not
|necessarily have to result in a crash with a nice error
|message, but might also overwrite non-stack parts of the
|memory (possibly putting the address of virus code there).
|Stack overflow even can occur without function calls. For
|example, the program int main(void) { int a[10000000]; }
...
"Subtleties of the ANSI/ISO C standard" (2012); Robbert
Krebbers, Freek Wiedijk; Radboud University Nijmegen.
Available online at :

https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1637.pdf
--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+***@gmail.com
Working, but not speaking, for Medtronic
void Void(void) { Void(); } /* The recursive call of the void */
Lawrence D'Oliveiro
2024-04-02 00:19:44 UTC
Reply
Permalink
... the stack, which may or may not even *be* a true
hardware stack (depending on the architecture,) ...
This reinforces the point I made elsewhere about abstract machines being
layered on top of other abstract machines, such that the line between
“hardware” and “software” really becomes arbitrary.

What constitutes a “true” hardware stack? Does it have to be a reserved
area, like page 1 on the 6502 family? Does the use of a particular
register as a stack pointer have to be defined by the instruction set, or
just by the ABI, as in many RISC architectures?
Lawrence D'Oliveiro
2024-04-01 21:43:23 UTC
Reply
Permalink
Post by Stefan Ram
Scripting languages handle the memory for you.
If I were to link compiled C code against a runtime that includes a
garbage collector, would that turn it into a “scripting” language?
David Brown
2024-03-29 12:47:07 UTC
Reply
Permalink
Post by Lawrence D'Oliveiro
At one time, we distinguished between “scripting” languages and
“programming” languages. To begin with, the “scripting” languages were
somehow more limited in functionality than full-fledged “programming”
languages. Or they were slower, because they were interpreted.
I don't think there has ever been a clear distinction.

A "script" is usually small and often written for a particular task on a
particular system, while a "program" might be bigger and more generic,
runnable on multiple systems by multiple people. But there is no
dividing point in the type of code, and plenty of overlap - even though
the difference is often clear ("This is a script for making backups of
my servers - it uses the rsync program to do the bulk of the work").

Similarly, there are not "scripting languages" and "programming
languages". There are languages that are more suitable for script work,
and languages that are more suitable for programming work, and languages
that are suitable for both.

Then there are "interpreted" languages and "compiled" languages. As you
say, this is not a binary distinction - there are shades between this,
especially with byte compiling. Some languages, such as Python, are
used like interpreted language (you "run" the source code) but are
byte-compiled on the fly. Some, like Java, are used like compiled
languages but generate byte code that is interpreted. Others use some
byte-compiled code along with JIT machine code to blur the lines even more.

It is fair to say that "scripts" are usually written in interpreted
languages (or languages designed to look like they interpreted, by
compiling or byte-compiling on the fly). "Programs" can be written in
interpreted or compiled languages - there is no consensus.
Post by Lawrence D'Oliveiro
Then languages like Perl and Java came along: both were compiled to a
bytecode, a sort of pseudo-machine-language, which was interpreted by
software, not CPU hardware. Were they “scripting” or “programming”
languages? Some might have classed Perl as a “scripting” language to
begin with, but given it is must as powerful as Java, then why
shouldn’t Java also be considered a “scripting” rather than
“programming” language? And before these two, there was UCSD Pascal,
which was probably the pioneer of this compile-to-bytecode idea.
Such classification is just wrong, IMHO. You can write scripts in Perl,
and you can write programs in Perl. "APL" is invariably (AFAIK)
interpreted, and it is for programming rather than scripting - the
acronym stands for "A Programming Language".

And of course there are many computer languages whose prime purpose is
other tasks, even though they can be used for programming - TeX and
Postscript are examples.
Post by Lawrence D'Oliveiro
So that terminology for distinguishing between classes of programming
languages became largely obsolete.
I am not at all convinced it was ever relevant to distinguish between
"scripting languages" and "programming languages". It was useful to
distinguish between "interpreted" and "compiled" languages, and the
overlap and blurring has increased there.
Post by Lawrence D'Oliveiro
But there is one distinction that I think is still relevant, and that
is the one between shell/command languages and programming languages.
In a shell language, everything you type is assumed to be a literal
string, unless you use special substitution sequences. E.g. in a POSIX
ls -l thingy
“give me information about the file/directory named ‘thingy’”, vs.
ls -l $thingy
“give me information about the files/directories whose names are in
the value of the variable ‘thingy’”.
Whereas in a programming language, everything is assumed to be a
language construct, and every unadorned name is assumed to reference
some value/object, so you need quote marks to demarcate literal
os.listdir(thingy)
“return a list of the contents of the directory whose name is in the
variable ‘thingy’”, vs.
os.listdir("thingy")
“return a list of the contents of the directory named ‘thingy’”.
This difference in design has to do with their typical usage: most of
the use of a shell/command language is in typing a single command at a
time, for immediate execution. Whereas a programming language is
typically used to construct sequences consisting of multiple lines of
code before they are executed.
That is arguably a useful distinction in the style of programming
languages, and this difference makes the language more or less suited to
particular tasks (such as typical short scripts).

Again, however, there are exceptions that mean a clear binary
distinction is not possible. Knuth did a lot of work on "literary
programming", where documentation and source is combined along with
executable code, and used such languages and tools for programs like TeX
and Metafont. ("Linux from Scratch" is another example.)

TCL is a language that might be considered half-way between your
categories here.
Post by Lawrence D'Oliveiro
This difference is also why attempts to use programming languages as
though they were shell/command languages, entering and executing a
single line of code at a time, tend to end up being more trouble than
they are worth.
Conversely, using shell/command languages as programming languages, by
collecting multiple lines of code into shell scripts, does work, but
only up to a point. The concept of variable substitution via string
substitution tends to lead to trouble when trying to do more advanced
data manipulations.
So, in short, while there is some overlap in their applicable usage
areas, they are still very much oriented to different application
scenarios.
<https://en.wikipedia.org/wiki/List_of_programming_languages_by_type>
gives something like 40 categories of programming languages, of which
"scripting languages" is one type. I think any attempt at dividing up
programming languages will either be so full of grey areas as to be
almost useless, or have so many categories that it is almost useless.
The best you can do is pick some characteristics of languages, or some
typical use-cases of languages, and ask if any given language fits there.
Lawrence D'Oliveiro
2024-03-29 20:36:52 UTC
Reply
Permalink
Post by David Brown
TCL is a language that might be considered half-way between your
categories here.
TCL is definitely an interesting in-between case. In my limited use, I
recall it was awkward with data structures, just like shell languages. So
maybe that puts it more on the shell side than the programming side.
Lawrence D'Oliveiro
2024-03-29 20:59:02 UTC
Reply
Permalink
Program text is initially text.[*] During parsing (either in
an interpreted or in a compiled language) you split the text
in tokens.
And then, how do you interpret the tokens? In a shell language, you have
the assumption that “everything is literal text until indicated
otherwise”; in a programming language, you have the assumption that
“everything is a program construct until indicated otherwise”.
Janis Papanagnou
2024-03-29 23:14:42 UTC
Reply
Permalink
Post by Lawrence D'Oliveiro
Program text is initially text.[*] During parsing (either in
an interpreted or in a compiled language) you split the text
in tokens.
And then, how do you interpret the tokens?
In an interpreter the tokens are interpreted, in a compiler
they are subject to the parsing. (But you know that I'm sure.)

What I was saying is that there's initially literal program text
that is transformed to tokens in the lexical analysis, and then
further processed.
Post by Lawrence D'Oliveiro
Post by Lawrence D'Oliveiro
In a shell language, everything you type is assumed to be a
literal string, unless you use special substitution sequences.
In a shell language, you have
the assumption that “everything is literal text until indicated
otherwise”;
Who is that "you"? (Not me, for sure.) And where did you get that
from?
Post by Lawrence D'Oliveiro
in a programming language, you have the assumption that
“everything is a program construct until indicated otherwise”.
So what is 'for i in a ; do ... ; done' then in your world?

This is one of many basic shell constructs that I use in shell
programming (not "shell scripting") regularly.

Janis
Janis Papanagnou
2024-03-29 23:45:21 UTC
Reply
Permalink
Post by Janis Papanagnou
Post by Lawrence D'Oliveiro
Program text is initially text.[*] During parsing (either in
an interpreted or in a compiled language) you split the text
in tokens.
And then, how do you interpret the tokens?
In an interpreter the tokens are interpreted, in a compiler
they are subject to the parsing. [...]
Just noticed that this may be misleading. Of course the shell
does also a syntax analysis step and report syntax errors. So
don't get me wrong here.

Janis
Keith Thompson
2024-03-30 00:03:05 UTC
Reply
Permalink
Post by Janis Papanagnou
Post by Janis Papanagnou
Post by Lawrence D'Oliveiro
Program text is initially text.[*] During parsing (either in
an interpreted or in a compiled language) you split the text
in tokens.
And then, how do you interpret the tokens?
In an interpreter the tokens are interpreted, in a compiler
they are subject to the parsing. [...]
Just noticed that this may be misleading. Of course the shell
does also a syntax analysis step and report syntax errors. So
don't get me wrong here.
I did indeed get you wrong here (see my other followup).
--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+***@gmail.com
Working, but not speaking, for Medtronic
void Void(void) { Void(); } /* The recursive call of the void */
Janis Papanagnou
2024-03-30 00:06:35 UTC
Reply
Permalink
Post by Keith Thompson
Post by Janis Papanagnou
Just noticed that this may be misleading. Of course the shell
does also a syntax analysis step and report syntax errors. So
don't get me wrong here.
I did indeed get you wrong here (see my other followup).
Sorry for the inconvenience!

Janis
Lawrence D'Oliveiro
2024-03-29 23:51:02 UTC
Reply
Permalink
Post by Janis Papanagnou
What I was saying is that there's initially literal program text
that is transformed to tokens in the lexical analysis, and then
further processed.
In a shell language, that is “further processed” as literal text, except
for any instances of substitution markers.
Post by Janis Papanagnou
Post by Lawrence D'Oliveiro
in a programming language, you have the assumption that
“everything is a program construct until indicated otherwise”.
So what is 'for i in a ; do ... ; done' then in your world?
“for” is just the name of a command, like any other. In POSIX, this one
happens to be built into the shell; it might not in other shells.
Keith Thompson
2024-03-30 00:08:35 UTC
Reply
Permalink
Post by Lawrence D'Oliveiro
Post by Janis Papanagnou
What I was saying is that there's initially literal program text
that is transformed to tokens in the lexical analysis, and then
further processed.
In a shell language, that is “further processed” as literal text, except
for any instances of substitution markers.
Post by Janis Papanagnou
Post by Lawrence D'Oliveiro
in a programming language, you have the assumption that
“everything is a program construct until indicated otherwise”.
So what is 'for i in a ; do ... ; done' then in your world?
“for” is just the name of a command, like any other. In POSIX, this one
happens to be built into the shell; it might not in other shells.
"for" is not just a command. It's a keyword, part of the shell language
syntax.

By contrast, "echo" is a command that may be built into the shell or
not, and behaves similarly either way. There's no way to implement
"for" as an external command.

(Very early UNIX shells had "goto" as an external command. The
implementation was convoluted.)
--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+***@gmail.com
Working, but not speaking, for Medtronic
void Void(void) { Void(); } /* The recursive call of the void */
Lawrence D'Oliveiro
2024-03-30 01:12:05 UTC
Reply
Permalink
Post by Keith Thompson
"for" is not just a command. It's a keyword, part of the shell language
syntax.
Remember, that’s only true of POSIX shells.
Keith Thompson
2024-03-30 01:15:05 UTC
Reply
Permalink
Post by Lawrence D'Oliveiro
Post by Keith Thompson
"for" is not just a command. It's a keyword, part of the shell language
syntax.
Remember, that’s only true of POSIX shells.
It may well be true of some non-POSIX shells as well (not that it
matters).
--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+***@gmail.com
Working, but not speaking, for Medtronic
void Void(void) { Void(); } /* The recursive call of the void */
Scott Lurndal
2024-03-30 01:21:09 UTC
Reply
Permalink
Post by Keith Thompson
"for" is not just a command. It's a keyword, part of the shell language
syntax.
Remember, that’s only true of POSIX shells
Not necessarily. Bash is not a POSIX shell. It can be,
but without special configuration it is not POSIX.

ksh is as close as one might get to a true POSIX shell,
but even ksh has extensions.

But nitpicking aside, the context of the discussion that
you responded to was about clearly POSIX-like shells.
Janis Papanagnou
2024-03-30 00:30:53 UTC
Reply
Permalink
Post by Lawrence D'Oliveiro
Post by Janis Papanagnou
So what is 'for i in a ; do ... ; done' then in your world?
“for” is just the name of a command, like any other. In POSIX, this one
happens to be built into the shell; it might not in other shells.
'for' is a "reserved word" and part of a "compound command". It's
part of the _shell syntax_! - You get syntax errors like

$ for ; do : ; done
ksh: syntax error: `;' unexpected

And, specifically, "i in a" are *not* arguments of a 'for' command
but also part of the control construct syntax.

But, okay, I see where you're coming from.

Besides the naming, keep in mind that there's a semantical differences
between a "command", a "built-in command", and "shell construct". An
example where you can observe operational differences is:
'/bin/test' and '/bin/['
'test' and '['
'[['
where (for example) the latter does not need quoting.

$ x="Hello world" ; [[ $x == "Hello world" ]] ; echo $?
0
$ x="Hello world" ; [ $x == "Hello world" ] ; echo $?
ksh: [: world: unknown operator
2
$ x="Hello world" ; [ "$x" == "Hello world" ] ; echo $?
0

The distinction is important since there's operational differences
associated with these forms. The same holds for other control constructs
("built-in compound commands"), like 'case', or even simple assignments.

Janis
Lawrence D'Oliveiro
2024-03-30 01:15:29 UTC
Reply
Permalink
Post by Janis Papanagnou
Besides the naming, keep in mind that there's a semantical differences
between a "command", a "built-in command", and "shell construct". An
'/bin/test' and '/bin/['
'test' and '['
'[['
where (for example) the latter does not need quoting.
I know that there are places in POSIX shells where the usual rules for
interpretation of special-substitution markers are altered or suspended.
But those situations are always delimited in some special way (distinctive
syntactic constructs or reserved words). Throughout the entire rest of the
language, the principles I have described still apply.
Keith Thompson
2024-03-30 00:01:45 UTC
Reply
Permalink
Post by Janis Papanagnou
Post by Lawrence D'Oliveiro
Program text is initially text.[*] During parsing (either in
an interpreted or in a compiled language) you split the text
in tokens.
And then, how do you interpret the tokens?
In an interpreter the tokens are interpreted, in a compiler
they are subject to the parsing. (But you know that I'm sure.)
Are you suggesting that interpreters don't parse their input? No doubt
there are interpreters that handle tokens one at a time, but shells
typically don't work that way.

There are a lot of different ways to distinguish between languages like
sh/ksh/bash that are normally interpreted and languages like C that are
normally compiled to machine code:

- Is the language primarily designed for interactive command-line use?
- Is the language normally compiled to machine code?
- Is the language compiled by some kind of byte code that is then
interpreted? Is that byte code *sometimes* translated to machine
code?
- Is foo treated by default as a string or as an identifier?
(Treating it as a string is convenient for interactive use.)
- Does a syntax error on line 10 prevent lines 1-9 from being executed?

I don't think *any* of these distinctions are fundamental.

For example, a Perl or Python program/script is parsed and "compiled"
into some in-memory form before execution begins. A syntax error
prevents the entire script from being executed. In Bourne-line shells,
a syntax error won't be detected until execution reaches that line.
(Things like Perl's BEGIN and eval can complicate things.)

Shells also have to parse their input, though it's done a bit
differently. Typically the entire script isn't parsed as a unit.

[...]
Post by Janis Papanagnou
So what is 'for i in a ; do ... ; done' then in your world?
This is one of many basic shell constructs that I use in shell
programming (not "shell scripting") regularly.
I use it both in shell scripting/programming and interactively.

And the entire construct needs to be processed before the shell can
begin to execute it. Misspelling "done" prevents the whole thing from
running.
--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+***@gmail.com
Working, but not speaking, for Medtronic
void Void(void) { Void(); } /* The recursive call of the void */
Janis Papanagnou
2024-03-30 00:49:20 UTC
Reply
Permalink
Post by Keith Thompson
Post by Janis Papanagnou
So what is 'for i in a ; do ... ; done' then in your world?
This is one of many basic shell constructs that I use in shell
programming (not "shell scripting") regularly.
I use it both in shell scripting/programming and interactively.
So do I. (To me there's no significant difference. Only that larger
projects I do not start to develop in interactive mode, of course.)
Post by Keith Thompson
And the entire construct needs to be processed before the shell can
begin to execute it. Misspelling "done" prevents the whole thing from
running.
Indeed.

From the other posters statements I got the impression that he may
think that control constructs is what makes the difference (between
scripting and programming, or, command interpreters and programming
languages; still not sure what he thinks). In a later post I read
it as if the naming of e.g. 'for' as a "command" leads to his view.
Anyway.

I can see a point where people use for interactive use other shells
than for programming; like tcsh (interactively) and bash (programming),
because of the powerful features tcsh supports. Since the increase of
interactive features supported by the shells that are typically used
for programming I prefer to have the same shell with same syntax and
features for both, and to be able to pass code from one application
context to the other.

Janis
Keith Thompson
2024-03-30 01:00:16 UTC
Reply
Permalink
Janis Papanagnou <janis_papanagnou+***@hotmail.com> writes:
[...]
Post by Janis Papanagnou
I can see a point where people use for interactive use other shells
than for programming; like tcsh (interactively) and bash (programming),
because of the powerful features tcsh supports. Since the increase of
interactive features supported by the shells that are typically used
for programming I prefer to have the same shell with same syntax and
features for both, and to be able to pass code from one application
context to the other.
Indeed. I spent several years using tcsh interactively (because it had
a few interactive features that I found convenient) and bash for writing
scripts (previously I had actually written *gasp* csh and tcsh scripts).
Eventually I found that using a single shell for both was easier, and
that bash's interactive features are about as good as tcsh's. (And I
can write complex nested commands on one line, something I probably
wouldn't have attempted in [t]csh even if it were possible.) I haven't
looked back.

zsh has some nice features, but I haven't learned it well enough to
consider switching.
--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+***@gmail.com
Working, but not speaking, for Medtronic
void Void(void) { Void(); } /* The recursive call of the void */
Lawrence D'Oliveiro
2024-03-31 20:47:29 UTC
Reply
Permalink
Post by Janis Papanagnou
So what is 'for i in a ; do ... ; done' then in your world?
***@theon:~> for i in a b c; do echo i; done
i
i
i

Like I said, in a shell language, you have the assumption that “everything
is literal text until indicated otherwise”.
Dmitry A. Kazakov
2024-03-30 11:44:37 UTC
Reply
Permalink
Post by Lawrence D'Oliveiro
At one time, we distinguished between “scripting” languages and
“programming” languages. To begin with, the “scripting” languages were
somehow more limited in functionality than full-fledged “programming”
languages. Or they were slower, because they were interpreted.
[...]

The key difference is that a program in a scripting language need not to
be complete or known in order to be executed.

The limitations and ugliness of scripting languages is determined by
this requirement, but also easiness of use.
--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
Keith Thompson
2024-03-30 21:28:31 UTC
Reply
Permalink
Post by Dmitry A. Kazakov
Post by Lawrence D'Oliveiro
At one time, we distinguished between “scripting” languages and
“programming” languages. To begin with, the “scripting” languages were
somehow more limited in functionality than full-fledged “programming”
languages. Or they were slower, because they were interpreted.
[...]
The key difference is that a program in a scripting language need not
to be complete or known in order to be executed.
The limitations and ugliness of scripting languages is determined by
this requirement, but also easiness of use.
Perl, Python, and Lua are all considered scripting languages, and for
all of them a syntax error at the end of a script will prevent any of it
from being executed. The distinction is that they're not optimized for
interactive use, as shell languages are (though they all can be used
interactively).

If you want to say that Python isn't a scripting language because of
that, I won't argue, but others will.

There are a lot of dividing lines (compiled to machine code vs. compiled
to byte code (on each execution or just once) vs. interpreted (perhaps
with JIT), interactive vs. batch, strong vs. weak typing, static
vs. dynamic typing, etc.). None of them are rigorously defined, and
none of them particularly need to be.
--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+***@gmail.com
Working, but not speaking, for Medtronic
void Void(void) { Void(); } /* The recursive call of the void */
Dmitry A. Kazakov
2024-03-31 20:06:50 UTC
Reply
Permalink
Post by Keith Thompson
Post by Dmitry A. Kazakov
Post by Lawrence D'Oliveiro
At one time, we distinguished between “scripting” languages and
“programming” languages. To begin with, the “scripting” languages were
somehow more limited in functionality than full-fledged “programming”
languages. Or they were slower, because they were interpreted.
[...]
The key difference is that a program in a scripting language need not
to be complete or known in order to be executed.
The limitations and ugliness of scripting languages is determined by
this requirement, but also easiness of use.
Perl, Python, and Lua are all considered scripting languages, and for
all of them a syntax error at the end of a script will prevent any of it
from being executed. The distinction is that they're not optimized for
interactive use, as shell languages are (though they all can be used
interactively).
I was not talking about [syntactically] incorrect incomplete programs.
In a scripting language an incomplete program can be correct and
executable. E.g. I type in bash:

ls

This is only a part of my program. Because then I inspect the output and
type:

rm foo.bar

After that I turn off the computer. My program is complete now.
--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
Loading...