Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.forth > #135571 > unrolled thread
| Started by | Hans Bezemer <the.beez.speaks@gmail.com> |
|---|---|
| First post | 2026-09-05 19:55 +0200 |
| Last post | 2026-09-08 17:18 +0200 |
| Articles | 20 on this page of 36 — 9 participants |
Back to article view | Back to comp.lang.forth
Postscript in 4tH Hans Bezemer <the.beez.speaks@gmail.com> - 2026-09-05 19:55 +0200
Re: Postscript in 4tH Paul Rubin <no.email@nospam.invalid> - 2026-09-05 15:54 -0700
Re: Postscript in 4tH albert@spenarnc.xs4all.nl - 2026-09-06 11:08 +0200
Re: Postscript in 4tH Paul Rubin <no.email@nospam.invalid> - 2026-09-07 09:24 -0700
Re: Postscript in 4tH albert@spenarnc.xs4all.nl - 2026-09-07 23:47 +0200
Re: Postscript in 4tH Kragen Javier Sitaker <kragen@canonical.org> - 2026-09-08 02:09 -0300
Re: Postscript in 4tH Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-09-08 20:34 +0000
Re: Postscript in 4tH Kragen Javier Sitaker <kragen@canonical.org> - 2026-09-08 22:38 -0300
Re: Postscript in 4tH Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-09-09 03:05 +0000
XML in Pythong (was: Re: Postscript in 4tH) Johann 'Myrkraverk' Oskarsson <johann@myrkraverk.invalid> - 2026-09-09 15:00 +0800
Re: Postscript in 4tH Kragen Javier Sitaker <kragen@canonical.org> - 2026-09-10 01:06 -0300
Re: Postscript in 4tH Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-09-10 07:38 +0000
Re: Postscript in 4tH Peter Flass <Peter@Iron-Spring.com> - 2026-09-10 07:39 -0700
Re: Postscript in 4tH antispam@fricas.org (Waldek Hebisch) - 2026-09-15 16:04 +0000
Re: Postscript in 4tH Paul Rubin <no.email@nospam.invalid> - 2026-09-15 09:24 -0700
Re: Postscript in 4tH Johann 'Myrkraverk' Oskarsson <johann@myrkraverk.invalid> - 2026-09-09 15:15 +0800
Re: Postscript in 4tH Kragen Javier Sitaker <kragen@canonical.org> - 2026-09-10 01:11 -0300
Re: Postscript in 4tH anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2026-09-09 07:35 +0000
Re: Postscript in 4tH Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-09-09 08:10 +0000
Re: Postscript in 4tH Hans Bezemer <the.beez.speaks@gmail.com> - 2026-09-10 17:58 +0200
Re: Postscript in 4tH Kragen Javier Sitaker <kragen@canonical.org> - 2026-09-10 01:44 -0300
Re: Postscript in 4tH Paul Rubin <no.email@nospam.invalid> - 2026-09-09 03:01 -0700
Re: Postscript in 4tH albert@spenarnc.xs4all.nl - 2026-09-09 14:05 +0200
Re: Postscript in 4tH anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2026-09-09 06:42 +0000
Re: Postscript in 4tH Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-09-09 08:28 +0000
Re: Postscript in 4tH anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2026-09-09 10:03 +0000
Re: Postscript in 4tH Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-09-09 22:17 +0000
Re: Postscript in 4tH albert@spenarnc.xs4all.nl - 2026-09-09 14:42 +0200
Re: Postscript in 4tH antispam@fricas.org (Waldek Hebisch) - 2026-09-09 19:17 +0000
Re: Postscript in 4tH albert@spenarnc.xs4all.nl - 2026-09-10 12:22 +0200
Re: Postscript in 4tH Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-09-09 21:54 +0000
Re: Postscript in 4tH Paul Rubin <no.email@nospam.invalid> - 2026-09-09 22:14 -0700
Re: Postscript in 4tH albert@spenarnc.xs4all.nl - 2026-09-10 12:30 +0200
Re: Postscript in 4tH albert@spenarnc.xs4all.nl - 2026-09-09 14:36 +0200
Re: Postscript in 4tH Hans Bezemer <the.beez.speaks@gmail.com> - 2026-09-06 14:27 +0200
Re: Postscript in 4tH Hans Bezemer <the.beez.speaks@gmail.com> - 2026-09-08 17:18 +0200
Page 1 of 2 [1] 2 Next page →
| From | Hans Bezemer <the.beez.speaks@gmail.com> |
|---|---|
| Date | 2026-09-05 19:55 +0200 |
| Subject | Postscript in 4tH |
| Message-ID | <117hl2n$1ne4b$1@dont-email.me> |
Both raster graphics as well as SVG vector graphics have been available in 4tH for some time now. However, people have expressed a need for Postscript graphics. The next release of 4tH will contain a set of libraries that cover every single functionality of the already available SVG libraries. Note that existing SVG programs can easily be converted to Postscript by simply including the correct libraries and replace "SVGopen" by "PSopen" and "SVGclose" by "PSclose". No other changes are required. Hans Bezemer
[toc] | [next] | [standalone]
| From | Paul Rubin <no.email@nospam.invalid> |
|---|---|
| Date | 2026-09-05 15:54 -0700 |
| Message-ID | <871pb7l36f.fsf@nightsong.com> |
| In reply to | #135571 |
Hans Bezemer <the.beez.speaks@gmail.com> writes: > Note that existing SVG programs can easily be converted to Postscript > by simply including the correct libraries and replace "SVGopen" by > "PSopen" and "SVGclose" by "PSclose". That's interesting as Postscript itself is a rather broken version of Forth. Do you mean with SVG calls you can do all the usual Postscript stuff including text rendering? I just wrote some Postscript code recently and hit some ridiculous snags due to dumb stuff in the language. They were fixable but "traps for the unwary" as it were.
[toc] | [prev] | [next] | [standalone]
| From | albert@spenarnc.xs4all.nl |
|---|---|
| Date | 2026-09-06 11:08 +0200 |
| Message-ID | <nnd$47db062e$781955bb@280ad1e4adf8c230> |
| In reply to | #135573 |
In article <871pb7l36f.fsf@nightsong.com>, Paul Rubin <no.email@nospam.invalid> wrote: >Hans Bezemer <the.beez.speaks@gmail.com> writes: >> Note that existing SVG programs can easily be converted to Postscript >> by simply including the correct libraries and replace "SVGopen" by >> "PSopen" and "SVGclose" by "PSclose". > >That's interesting as Postscript itself is a rather broken version of >Forth. Do you mean with SVG calls you can do all the usual Postscript >stuff including text rendering? > >I just wrote some Postscript code recently and hit some ridiculous snags >due to dumb stuff in the language. They were fixable but "traps for the >unwary" as it were. Maybe you weren't fully embracing the language. Don't expect it to be Forth. I have generated graphics as charts for an evacuation plan for the Dutch Harbour in case of calamities. It was easy to incorporate the whole map for the harbour in this, that were originally given in an other svg language. Generating PostScript from C. Also my assembler package includes generating instruction tables from the assembler itself. Generating PostScript from Forth. I experienced no "ridiculous snags". Actually the language is kind of nice and safer than Forth. Groetjes Albert -- The Chinese government is satisfied with its military superiority over USA. The next 5 year plan has as primary goal to advance life expectancy over 80 years, like Western Europe.
[toc] | [prev] | [next] | [standalone]
| From | Paul Rubin <no.email@nospam.invalid> |
|---|---|
| Date | 2026-09-07 09:24 -0700 |
| Message-ID | <87wlsxjah1.fsf@nightsong.com> |
| In reply to | #135581 |
albert@spenarnc.xs4all.nl writes: > I experienced no "ridiculous snags". Actually the language is > kind of nice and safer than Forth. One thing that bit me was that "def" creates or modifies an essentially global variable. I had expected from the tutorial that I read that it was more like a local, or a LET binding in Lisp terms. So I had to puzzle out that calling a function that set "x" to something, changed the value in the caller. The fix is to create a new dictionary and push it on the stack. This was a pain to figure out because of the near-total absence of a debugging environment. Another annoying thing was that instead of "30 x !" you say "/x 30 def" and that means, to save function args in variables, you have to use "/x exch def" instead of "def". But that was better documented so it mostly only caused a bit of code clutter. I wrote some Postscript a long time ago and it went ok at the time. For this more recent thing, I had forgotten everything about it and had to start from scratch. You are probably right that it gets more comfortable when you use it more. You're right that I didn't "fully embrace" it. I basically puzzled out the minimum amount to get my immediate thing done. Of course PS is safer than Forth since it's garbage collected and doesn't have raw pointers. That has the corresponding performance and memory cost but that's fine. OTOH it still seems designed for fairly low resource environments. I think the original host for it was the Apple LaserWriter with a 68000 cpu and around 1MB of memory but I guess most of the memory was used for fonts and stuff. I remember that the Adobe manuals were pretty good but I didn't use them this time. If I had to do something more serious in Postscript I'd probably read through the Adobe manuals again first.
[toc] | [prev] | [next] | [standalone]
| From | albert@spenarnc.xs4all.nl |
|---|---|
| Date | 2026-09-07 23:47 +0200 |
| Message-ID | <nnd$540c69b5$1efceca9@1fb86dd69acdc7a9> |
| In reply to | #135592 |
In article <87wlsxjah1.fsf@nightsong.com>, Paul Rubin <no.email@nospam.invalid> wrote: >I remember that the Adobe manuals were pretty good but I didn't use them >this time. If I had to do something more serious in Postscript I'd >probably read through the Adobe manuals again first. I had the benefit of the original Adobe manual. It helped me a lot, but the Dutch translation was awful. For instance "set and reset" was translated by the Dutch equivalent of "set and set again". (but it cost f5 say 2.5 euro's, and it got reimbursed by the client.) Groetjes Albert -- The Chinese government is satisfied with its military superiority over USA. The next 5 year plan has as primary goal to advance life expectancy over 80 years, like Western Europe.
[toc] | [prev] | [next] | [standalone]
| From | Kragen Javier Sitaker <kragen@canonical.org> |
|---|---|
| Date | 2026-09-08 02:09 -0300 |
| Message-ID | <875x0gib1k.fsf@debian> |
| In reply to | #135581 |
albert@spenarnc.xs4all.nl writes: > In article <871pb7l36f.fsf@nightsong.com>, > Paul Rubin <no.email@nospam.invalid> wrote: >>That's interesting as Postscript itself is a rather broken version of >>Forth. Do you mean with SVG calls you can do all the usual Postscript >>stuff including text rendering? >> >>I just wrote some Postscript code recently and hit some ridiculous snags >>due to dumb stuff in the language. They were fixable but "traps for the >>unwary" as it were. > > Maybe you weren't fully embracing the language. Don't expect it > to be Forth. I think of PostScript as being Lisp, more or less, but with quasi-Forth syntax, and using arrays where Lisp uses linked lists. Maybe Lua or Python is a closer analogy: PostScript has separate array and dictionary types, like Python. But it’s extensible like Lisp or Forth. Aside from the Adobe manual, Paul Bourke has a great tutorial and reference at <https://paulbourke.net/dataformats/postscript/>. Nathan Laredo has an amazing collection of PostScript code at <https://postscriptcode.com/>, which is worth browsing through, and of course Don Lancaster has lots of interesting stuff at <https://www.tinaja.com/pssamp1.shtml> and nearby. Mitch Bradley wrote a Forth *in* PostScript: <https://dl.acm.org/doi/pdf/10.1145/122630.127247> Kragen
[toc] | [prev] | [next] | [standalone]
| From | Lawrence D’Oliveiro <ldo@nz.invalid> |
|---|---|
| Date | 2026-09-08 20:34 +0000 |
| Message-ID | <117prfv$gq7e$3@dont-email.me> |
| In reply to | #135599 |
On Tue, 08 Sep 2026 02:09:43 -0300, Kragen Javier Sitaker wrote: > I think of PostScript as being Lisp, more or less, but with > quasi-Forth syntax ... PostScript is homoiconic, but the resemblance to Lisp ends there. Lisp has macros, PostScript doesn’t. Lisp needs macros, because it also has “special forms” for syntactic constructs that implement things like control constructs, declarations etc. PostScript doesn’t have “special forms”, since all these concepts are implemented as built-in functions. Which is also why it doesn’t need macros. Also, Forth never heard of homoiconicity ...
[toc] | [prev] | [next] | [standalone]
| From | Kragen Javier Sitaker <kragen@canonical.org> |
|---|---|
| Date | 2026-09-08 22:38 -0300 |
| Message-ID | <87o6e7cifh.fsf@debian> |
| In reply to | #135611 |
(Please forgive in advance the LLM-like wording of what follows. I
wrote it entirely by hand, including reading the documents I linked, but
I’ve been coaxing
Lawrence D’Oliveiro <ldo@nz.invalid> writes:
> On Tue, 08 Sep 2026 02:09:43 -0300, Kragen Javier Sitaker wrote:
>> I think of PostScript as being Lisp, more or less, but with
>> quasi-Forth syntax ...
>
> PostScript is homoiconic, but the resemblance to Lisp ends there. Lisp
> has macros, PostScript doesn’t. Lisp needs macros,
At the time that PostScript was designed, most Lisps did not have
macros; they still had fexprs. Some Lisps did have macros, most notably
MACLISP, but they had not yet become central to language style the way
they are today. Remember that PostScript first shipped in 01982, when
the world was dominated by BASIC, FORTRAN, and COBOL.
PostScript does in fact have something like readmacros; in particular,
readhexstring was the recommended way to handle image data, so that the
image data didn’t have to be loaded into a PostScript object by way of
the PostScript parser. But, for the most part, like Smalltalk,
PostScript uses a lightweight lambda syntax for most of the things you
would use macros for in Lisp.
PostScript has several other key similarities to Lisp. Referencing Paul
Graham’s “What Made Lisp Different” <https://paulgraham.com/diff.html>:
1. Conditionals. Yes, but all languages had conditionals by 01982.
2. A function type. “In Lisp, functions are first class objects--
they’re a data type just like integers, strings, etc, and have a literal
representation, can be stored in variables, can be passed as arguments,
and so on.” Yes; PostScript goes even harder here than Lisp, because
there’s actually no way to define a named function in PostScript. You
have to define an anonymous function and pass it as an argument to /bind
in order to give it a name. This is somewhat related to homoiconicity
but is not the same thing.
3. Recursion. Yes, but only FORTRAN lacked recursion by then. COBOL
and BASIC lacked local variables, though, which generally made recursion
impractical.
4. A new concept of variables. “In Lisp, all variables are effectively
pointers. Values are what have types, not variables, and assigning or
binding variables means copying pointers, not what they point to.”
PostScript does work this way, as does Smalltalk (not coincidentally,
from the same lab, which was also heavily into Lisp). It’s easy to
forget how unusual this was, because now languages more or less like
this dominate the scene: Python, JS, Ruby, PHP, Lua, and to some extent,
even Java and C#. But none of the other popular languages of the day
worked that way. Not conventional assembly (untyped, and variables are
memory addresses), not BASIC, not C, not Pascal, not awk, not the Bourne
shell, not the C shell, not Forth, not BLISS, not FOCAL, not Mesa, not
ML, not Algol, not PL/I, not Ada.
Moreover, in both Lisp and in PostScript, this extends to not just
regular variables, but any item of any data structure. In BASIC, C,
FORTRAN, or Pascal, you might have arrays of strings, or arrays of
integers, or in some cases arrays of 3-element arrays of integers, but
you couldn’t have an array of arbitrary-type values. PostScript arrays
contain arbitrary-type values, as do the most common type of vectors in
Common Lisp, and lists in any Lisp.
5. Garbage-collection. Yes.
6. Programs composed of expressions. Not really, but closer than any of
the currently popular languages.
7. A symbol type. Yes, PostScript distinguishes /names from strings,
which is arguably the feature of all of these that is most distinctive
to Lisp (the only other languages that do this are Ruby, Smalltalk, and,
in a way, JS), and PostScript shares it.
8. A notation for code using trees of symbols. Yes. The only
difference is that in conventional Lisp they’re binary trees, while in
PostScript they’re N-ary ordered trees.
9. “The whole language always available”, i.e., arbitrarily overlapping
compile time and runtime. Yes.
Given that PostScript clearly hits 8 out of 9 of these criteria, and
arguably all 9, while no then-popular language other than Lisp came
anywhere close, I think it’s pretty clear that it mostly belongs to the
Lisp family. Its resemblance to Lisp is much deeper than just being
homoiconic.
Forth hits #1, #3, and #9.
****
If you’re not familiar with PostScript, you might be puzzled by #8.
Let’s define a new function that tells us the sign of a number and bind
it to the symbol `sign`:
GS>/sign {dup 0 gt {pop /positive} {0 lt {/negative} {/zero} ifelse} ifelse} def
GS>3 sign = 0 sign = -53 sign =
positive
zero
negative
We can use `load` on the quoted symbol to find the current definition of
`sign` without executing it:
GS>/sign load ===
{dup 0 gt {pop /positive} {0 lt {/negative} {/zero} ifelse} ifelse}
It turns out that’s an array of length 3:
GS>/sign load type =
arraytype
GS>/sign load length =
6
We can fetch things from it:
GS>/sign load 0 get === /sign load 3 get ===
dup
{pop /positive}
See, the zeroth thing in the array is `dup`. Which is a “name”, not a
string, which PostScript also has:
GS>/sign load 0 get type = (hello, world) type =
nametype
stringtype
We can even modify the array in place to modify the code, although we
can’t lengthen it:
GS>/sign load 0 /pop cvx put
GS>/sign load ===
{pop 0 gt {pop /positive} {0 lt {/negative} {/zero} ifelse} ifelse}
Now it crashes because `pop` drops the operand `gt` wants to compare:
GS>3 sign =
Error: /stackunderflow in --gt--
You can define a regular, non-executable array and turn it into a
function with regular programming operators:
GS>/square 2 array def
GS>square ===
[null null]
GS>square 0 /dup cvx put square ===
[dup null]
GS>square 1 /mul cvx put square ===
[dup mul]
GS>/square square cvx def 3 square ===
9
GS>/square load ===
{dup mul}
If you’re familiar with old Lisp systems, almost all of this will seem
very familiar, but the syntax will seem backwards, and you’ll wonder why
code is stored in arrays instead of lists.
You can also define a function that uses the PostScript reader `token`
to consume input, similar to `word` in Forth but much more similar to
`read` in Lisp:
GS>/typeof {currentfile token pop type} def
GS>typeof dup ===
nametype
GS>typeof 34 ===
integertype
GS>typeof (hello, world) ===
stringtype
Where `token` diverges radically from Forth is that it will read an
entire nested expression (without executing it), not just a token as the
term is normally understood:
GS>typeof {dup mul dup add} ===
arraytype
(Note that this *doesn't* work for [3 4], because `[` and `]` are
operators, so [3 4] isn’t an expression!)
Given that you can parse expressions from the input stream at compile
time and generate code at runtime, you can obviously implement Lisp-like
macros in PostScript. It just isn’t an established practice.
The one very non-Lispy weird thing, which doesn't have a similar feature
in any other language I know of, is that the executable bit set by `cvx`
is an attribute of references, not objects. So `{dup mul}` and `[dup
mul]` can be the same object as seen through two different references.
That’s why making `square` executable required calling `def` again
rather than just `cvx`.
****
To get a feel for what 01982 was like, check out the October 01982 issue
of the CACM <https://dl.acm.org/toc/cacm/1982/25/10> or of Byte
<https://archive.org/details/BYTE_Vol_07-10_1982-10_Computers_in_Business>.
The languages mentioned in the CACM issue are Fortran (in the table of
contents); COBOL, PL/I, and APL (in the data administration article);
Algol 60 and Macsyma but not Lisp (in the “microanalysis” (profiling)
paper, which also included some Algol as pseudocode); Lisp as the
pseudocode, though without naming it (in Kornfield’s paper about
“combinatorially implosive” algorithms); none (in the geometric
algorithm paper); Fortran (in the gamma-deviate-generation comment); and
Ada (in the “ACM Forum” letters column.) It’s a total head trip.
In Byte, the languages mentioned are 68000 assembler, FORTRAN 77,
Pascal, BASIC, COBOL, and C (in the Cromemco ad); Visicalc, BASIC,
Pascal, FORTH, and BASIC again (in the table of contents); Pascal
(though it’s really talking about the UCSD Pascal OS) and FORTRAN (in
the editorial); BASIC, COBOL, BASIC again, and LISP (in the Letters);
Visicalc and something called Microfinesse (in the Visicalc article);
etc.
That’s just the first 41 pages; I’ll leave the other 490 pages to you.
Kragen
[toc] | [prev] | [next] | [standalone]
| From | Lawrence D’Oliveiro <ldo@nz.invalid> |
|---|---|
| Date | 2026-09-09 03:05 +0000 |
| Message-ID | <117qido$ng8h$3@dont-email.me> |
| In reply to | #135613 |
On Tue, 08 Sep 2026 22:38:58 -0300, Kragen Javier Sitaker wrote:
> PostScript does in fact have something like readmacros; in particular,
> readhexstring was the recommended way to handle image data, so that the
> image data didn’t have to be loaded into a PostScript object by way of
> the PostScript parser.
It’s just a function. It’s like saying Python has “readmacros” because
the JSON and XML library modules have functions for reading input
streams and returning language-object representations of those
structures.
> 2. A function type. “In Lisp, functions are first class objects--
> they’re a data type just like integers, strings, etc, and have a
> literal representation, can be stored in variables, can be passed as
> arguments, and so on.” Yes; PostScript goes even harder here than
> Lisp, because there’s actually no way to define a named function in
> PostScript. You have to define an anonymous function and pass it as
> an argument to /bind in order to give it a name. This is somewhat
> related to homoiconicity but is not the same thing.
Homoiconicity comes in because the function body is stored in an array
object, which is a PostScript language type, and its contents are also
objects of various PostScript language types.
Where PostScript is lacking is in missing support for lexical binding.
Anybody who has done much PostScript programming knows how awkward it
is to simulate anything resembling local variables.
> 4. A new concept of variables. “In Lisp, all variables are
> effectively pointers. Values are what have types, not variables, and
> assigning or binding variables means copying pointers, not what they
> point to.”
>
> PostScript does work this way, as does Smalltalk (not
> coincidentally, from the same lab, which was also heavily into
> Lisp). It’s easy to forget how unusual this was, because now
> languages more or less like this dominate the scene: Python, JS,
> Ruby, PHP, Lua, and to some extent, even Java and C#. But none of
> the other popular languages of the day worked that way.
Fair enough.
> 5. Garbage-collection. Yes.
Note that this was only added in PostScript level 2. In the original
language implementation, memory management had to be done in (I think
it’s called) mark-release style, using explicit calls to the “save”
and “restore” functions.
> 6. Programs composed of expressions. Not really, but closer than any
> of the currently popular languages.
No distinction between “statements” and “expressions”.
> 7. A symbol type. Yes, PostScript distinguishes /names from strings,
> which is arguably the feature of all of these that is most
> distinctive to Lisp (the only other languages that do this are Ruby,
> Smalltalk, and, in a way, JS), and PostScript shares it.
True enough.
Java has the option for “interned” strings, which is a way of having a
symbol type without having a symbol type, if you like.
> 8. A notation for code using trees of symbols. Yes. The only
> difference is that in conventional Lisp they’re binary trees, while
> in PostScript they’re N-ary ordered trees.
In Lisp, the tree structure is apparent in the static syntax. In
PostScript, the tree structure (such as it is) gets largely
constructed dynamically at run time, and need not correspond to static
syntax at all.
> 9. “The whole language always available”, i.e., arbitrarily
> overlapping compile time and runtime. Yes.
Yes.
> Given that PostScript clearly hits 8 out of 9 of these criteria, and
> arguably all 9, while no then-popular language other than Lisp came
> anywhere close, I think it’s pretty clear that it mostly belongs to
> the Lisp family.
Only insofar as every dynamic language “mostly belongs to the Lisp
family”.
> Its resemblance to Lisp is much deeper than just being homoiconic.
As you pointed out, other dynamic languages had their own versions
of these features.
Paul Graham’s list is misleading, because it misses out things that
make Lisp distinctive -- perhaps because they were not so well
appreciated in the days before other dynamic languages became popular.
> Forth hits #1, #3, and #9.
Leaves out homoiconicity, which is such a fundamental thing.
> Given that you can parse expressions from the input stream at
> compile time and generate code at runtime, you can obviously
> implement Lisp-like macros in PostScript. It just isn’t an
> established practice.
Unnecessary, because it just doesn’t buy you much in functionality,
the way it does in Lisp.
This should be a clue as to how PostScript is very much different
from Lisp-like languages.
> The one very non-Lispy weird thing, which doesn't have a similar
> feature in any other language I know of, is that the executable bit
> set by `cvx` is an attribute of references, not objects. So `{dup
> mul}` and `[dup mul]` can be the same object as seen through two
> different references. That’s why making `square` executable required
> calling `def` again rather than just `cvx`.
The same is true of read and write access bits -- except for
dictionaries.
I remember doing some experiments with an Apple LaserWriter and a
Macintosh II back in the late 1980s. Someone had cracked the
encryption of the “eexec” operator, and we used this to discover that
there was this other thing called “cexec” (only allowed within
encrypted “eexec” execution, which is why you never saw it in public
code) that let you load MC68000 machine code into the printer and hook
into an API provided by the PostScript interpreter to manipulate
PostScript objects and make function calls.
This effort was triggered by the existence of an app called
“LaserTalk”, which did something truly magical and supposedly
impossible: you could use it to send PostScript code to the printer,
and get back the high-resolution rendered image as a file.
The Macintosh compilers already generated MC68000 machine code, and I
was able to whip up build scripts to link that code into the right
format, with appropriately-set-up header fields, so that the printer
would load and execute it.
All this cexec/eexec stuff went away in PostScript level 2 and later
-- along with the dependency on Motorola-68K-family processors.
[toc] | [prev] | [next] | [standalone]
| From | Johann 'Myrkraverk' Oskarsson <johann@myrkraverk.invalid> |
|---|---|
| Date | 2026-09-09 15:00 +0800 |
| Subject | XML in Pythong (was: Re: Postscript in 4tH) |
| Message-ID | <iu7oS.240010$4yM7.67254@fx08.ams4> |
| In reply to | #135615 |
On 09/09/2026 11:05 AM, Lawrence D’Oliveiro wrote: > On Tue, 08 Sep 2026 22:38:58 -0300, Kragen Javier Sitaker wrote: > >> PostScript does in fact have something like readmacros; in particular, >> readhexstring was the recommended way to handle image data, so that the >> image data didn’t have to be loaded into a PostScript object by way of >> the PostScript parser. > > It’s just a function. It’s like saying Python has “readmacros” because > the JSON and XML library modules have functions for reading input > streams and returning language-object representations of those > structures. > Dear Lawrence, Ok, so I was tempted to ask why you're bringing up Python in a Post- Script discussion, but then I remembered you're a /Pythong influencer/, and can not help yourself. Now, why are there only two library modules in Python for this task? In C, we have -- I believe -- several, but I've only used Expat precisely because it doesn't create language-objects for me. Do you not have a stream oriented XML parser in Pythong? Is Python that much inferiour to C? The same question can be asked of JSON, because sometimes we don't want to download the whole payload before starting the parse process. After all, why not just shut down the network connection when we detect garb- age, like the one Lawrence is constantly spewing all over Usenet? Best wishes, and happy XML, JSON parsing in alt.folklore.computers! I've set the follow-up to: alt.folklore.computers, comp.lang.python, comp.lang.xml, borland.public.xml in that order. Please remove alt.folklore.computers if you think it's not relevant anymore. -- Johann | email: invalid -> com | http://www.myrkraverk.com/blog/ I'm not from the Internet, I just work there. | via Easynews.com https://bsky.app/profile/myrkraverk.bsky.social | for ( ;; ) _:;
[toc] | [prev] | [next] | [standalone]
| From | Kragen Javier Sitaker <kragen@canonical.org> |
|---|---|
| Date | 2026-09-10 01:06 -0300 |
| Message-ID | <87h5jxagx6.fsf@debian> |
| In reply to | #135615 |
(Apologies if this sounds like AI slop; I’ve been interacting with
Claude Opus 5 a lot today, and although I didn’t use any LLM to write
any of this, its voice may be leaking into mine.)
Lawrence D’Oliveiro <ldo@nz.invalid> writes:
> On Tue, 08 Sep 2026 22:38:58 -0300, Kragen Javier Sitaker wrote:
>> PostScript does in fact have something like readmacros; in particular,
>> readhexstring was the recommended way to handle image data, so that the
>> image data didn’t have to be loaded into a PostScript object by way of
>> the PostScript parser.
>
> It’s just a function. It’s like saying Python has “readmacros” because
> the JSON and XML library modules have functions for reading input
It’s a function that runs while the PostScript source code is being
read, which means that it can change the interpretation of that source
code. That’s a way that PostScript is like Lisp and unlike Python.
Python’s JSON and XML library modules’ functions are different from Lisp
readmacros because they cannot read from the Python input stream; the
Python parser finishes running before any Python code runs. There’s no
way to do the equivalent of this readmacro-like example from my post in
Python:
GS>/typeof {currentfile token pop type} def
GS>typeof dup ===
nametype
To sharpen this, note that it doesn’t matter that `dup` is defined:
GS>typeof oagjijgw ===
nametype
You’d have to be able to write something in Python which gave you a
session like this:
$ python3
Python 3.11.2 (main, Aug 26 2024, 07:20:54) [GCC 12.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from somemodule import typeof
>>> typeof(oagjijgw) # or ideally even without the parentheses
<ast.Name object at 0x7f52bb870130>
I claim that this `typeof` function is impossible to write in Python,
because the parser throws a NameError before `typeof` has a chance to
run, given that I haven’t defined `oagjijgw` previously.
That is how PostScript’s `token` (and `readstring`, `readhexstring`,
etc.) are more like Lisp readmacros than they are like any function in
any possible Python module.
>> 2. A function type. “In Lisp, functions are first class objects-- [...]
>
> Homoiconicity comes in because the function body is stored in an array
> object, which is a PostScript language type, and its contents are also
> objects of various PostScript language types.
The analogous statements were true of most Lisps in 01982, because
`lambda` was basically implemented as `quote` when it was the argument
of a function (or subr), but they are true of almost no other
programming languages except assembly language, so this is another
similarity between PostScript and Lisp.
However, the analogous statements are not true of most current Lisps,
which have adopted the position that lambda-expressions are lists, and
functions are not lists. SBCL, for example:
* (type-of 3)
(INTEGER 0 4611686018427387903)
* (type-of (lambda () 3))
COMPILED-FUNCTION
* (type-of '(lambda () 3))
CONS
Or Racket:
> (pair? (lambda () 3))
#f
> (pair? '(lambda () 3))
#t
> (procedure? (lambda () 3))
#t
> (procedure? '(lambda () 3))
#f
Perhaps you would argue that PostScript is homoiconic and SBCL and
Racket are not. However, most people who know the word do consider them
to be homoiconic, because, even though the *runtime representation* of
functions does not contain objects of various Lisp language types, the
*source code* is just a Lisp list, so building Lisp code in Lisp is
easy:
> (eval (cons 'lambda (cons '() (cons 3 '()))))
#<procedure>
> ((eval (cons 'lambda (cons '() (cons 3 '())))))
3
Unfortunately, this definition of homoiconicity suggests that any
language compiled from sequences of characters is “homoiconic” unless
for some reason it lacks the ability to manipulate sequences of
characters. So “homoiconic languages” is no longer a logically
well-defined category; it’s more a sliding scale of what programmers
find easy or difficult.
But, look again at PG’s explanation of what he means by “a function
type”:
>> “In Lisp, functions are first class objects-- they’re a data type
>> just like integers, strings, etc, and have a literal representation,
>> can be stored in variables, can be passed as arguments, and so on.”
The only one of these that plausibly relates to homoiconicity is “have a
literal representation”. In old Lisps you could just print out the
definition of any function as an S-expression, but, as we see above with
Racket, that is not currently the case; we get something like
`#<FUNCTION (LAMBDA ()) {534960EB}>` or `#<procedure>`. But that’s
still a string representation! And *most* languages don't have the
ability to print out, for example, struct literals.
What makes a “string literal” or “integer literal” a *literal* is that
you can put it in your source code without having to give it a name.
C since C99 has “compound literals” for structs and arrays
<https://en.cppreference.com/c/language/compound_literal>, which look
like `(struct foo){3, "hi"}`, and evaluate to a value of that type
without having to bind it to a name. Older versions of ANSI C treated
structs the way C still treats functions; instead of writing
return (struct point){x + dx, y + dy};
you had to write
struct point p = {x + dx, y + dy};
return p;
Golang struct literals are the same thing
<https://go.dev/tour/moretypes/5>: “A struct literal denotes a newly
allocated struct value by listing the values of its fields.”
JS has “array literals”
<https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Array#array_literal_notation>
for which the example given is `["Apple", "Banana"]`.
So the most plausible gloss of PG’s “has a literal representation” is
that there are Lisp expressions which create new functions when
evaluated, which is just as true of modern Common Lisp and Scheme as it
was of Franz Lisp in 01982. And it’s obviously true of PostScript, but
not of C, Pascal, BASIC, etc.
> Where PostScript is lacking is in missing support for lexical binding.
> Anybody who has done much PostScript programming knows how awkward it
> is to simulate anything resembling local variables.
This is another similarity between PostScript and the then-popular
Lisps, which almost entirely used dynamic scope like PostScript, rather
than lexical scope like almost all other programming languages.
However, it is true that the facility is more convenient to use in Lisp.
Here’s a slightly reformatted interactive session showing how awkward it
is to simulate anything resembling local variables, in case anyone is
curious:
GS>/! {exch def} def
GS>/printbuf ( ) def /. {printbuf cvs print} def
GS>/hanoi {
4 dict begin
/n ! /dest ! /storage ! /src !
n 0 gt {
src dest storage n 1 sub hanoi
n . ( from ) print src . ( to ) print dest =
storage src dest n 1 sub hanoi
} if
end
} def
GS>/A /B /C 3 hanoi
1 from A to C
2 from A to B
1 from C to B
3 from A to C
1 from B to A
2 from B to C
1 from A to C
This is definitely more awkward than in most languages, but it doesn’t
seem prohibitive to me.
One major annoyance for interactive use is that, if execution aborts with
an error, all those local variable scopes are left on the stack. Might
be useful for debugging, I guess, but you can end up redefining things
in the wrong dictionary.
>> 5. Garbage-collection. Yes.
>
> Note that this was only added in PostScript level 2. In the original
> language implementation, memory management had to be done in (I think
> it’s called) mark-release style, using explicit calls to the “save”
> and “restore” functions.
Really? I had no idea! I always wondered why they thought `save` and
`restore` were worth incorporating. So that’s a way in which the
original PostScript was actually more like Forth, where you use `marker`
(or `forget`) to deallocate a chunk of the dictionary.
>> 6. Programs composed of expressions. Not really, but closer than any
>> of the currently popular languages.
>
> No distinction between “statements” and “expressions”.
Yes, that’s true, PostScript doesn’t have a statement/expression
distinction. But in that case we should award this Lispiness point to
Forth as well.
>> 7. A symbol type. [...]
>
> True enough.
>
> Java has the option for “interned” strings, which is a way of having a
> symbol type without having a symbol type, if you like.
That’s true, and in particular that’s useful if you’re implementing some
kind of language parser or interpreter in Java. Python has this too.
>> 8. A notation for code using trees of symbols. Yes. The only
>> difference is that in conventional Lisp they’re binary trees, while
>> in PostScript they’re N-ary ordered trees.
>
> In Lisp, the tree structure is apparent in the static syntax. In
> PostScript, the tree structure (such as it is) gets largely
> constructed dynamically at run time, and need not correspond to static
> syntax at all.
I’m not sure I agree. Here’s my example of tree-structured code in
PostScript, from the previous post:
GS>/sign {dup 0 gt {pop /positive} {0 lt {/negative} {/zero} ifelse} ifelse} def
This is an executable array of six things, the fourth of which is `{pop
/positive}`. To me, that’s *more* apparent from the static syntax than
the fact that in `(lambda (x y) (sqrt (+ (* x x) (* y y))))` the car of
the car of the cdr of the cdr is `sqrt`. The Lisp structure is a binary
tree, but the static syntax is formatted as an N-ary ordered tree. In
PostScript, the N-ary ordered tree of the static syntax corresponds to
the N-ary ordered tree in the PostScript data model.
(Note that this is another way in which PostScript is like Lisp but
unlike Forth: in Forths that expose their representation of threaded
code, it’s an array of xts, not a tree.)
There are *other* structures that get constructed dynamically at run
time in PostScript, such as the implicit gsave/grestore tree, the
call/return tree, the implicit begin/end tree, the implicit save/restore
tree — basically anything with a stack could be said to dynamically
construct a sort of tree structure at run time.
>> Given that PostScript clearly hits 8 out of 9 of these criteria, and
>> arguably all 9, while no then-popular language other than Lisp came
>> anywhere close, I think it’s pretty clear that it mostly belongs to
>> the Lisp family.
>
> Only insofar as every dynamic language “mostly belongs to the Lisp
> family”.
PostScript is a lot insofarther, I think. For example, Python, JS, and
Lua hit #1-5, but not #6-9, although they do have `eval`, so you can
compile code at runtime. None of them let you run code at compile time
or at read time. Perl4 is usually considered a dynamic language and
doesn’t have references at all, so we lose #4; Perl5 has references, but
distinguishes between the reference and the thing it refers to, so that
you can take references to references, so we still lose #4, but we gain
#9 because you can write things like Perligata. Tcl not only doesn’t
have references, it doesn’t even have dynamic typing; everything is a
string, but it sort of has #8 except that it doesn’t have a symbol type.
> [...]
>> the executable bit set by `cvx` is an attribute of references, not
>> objects.
>
> The same is true of read and write access bits -- except for
> dictionaries.
I had no idea!
> I remember doing some experiments with an Apple LaserWriter and a
> Macintosh II back in the late 1980s. Someone had cracked the
> encryption of the “eexec” operator, and we used this to discover that
> there was this other thing called “cexec” (only allowed within
> encrypted “eexec” execution, which is why you never saw it in public
> code) that let you load MC68000 machine code into the printer and hook
> into an API provided by the PostScript interpreter to manipulate
> PostScript objects and make function calls.
Wow, that’s amazing! I only ever knew that there was some controversy
about extracting fonts. Maybe this is how it was done?
> [...] The Macintosh compilers already generated MC68000 machine code,
> and I was able to whip up build scripts to link that code into the
> right format, with appropriately-set-up header fields, so that the
> printer would load and execute it.
What a great feeling!
Kragen
[toc] | [prev] | [next] | [standalone]
| From | Lawrence D’Oliveiro <ldo@nz.invalid> |
|---|---|
| Date | 2026-09-10 07:38 +0000 |
| Message-ID | <117tmpa$1ov1u$1@dont-email.me> |
| In reply to | #135638 |
On Thu, 10 Sep 2026 01:06:45 -0300, Kragen Javier Sitaker wrote:
> Lawrence D’Oliveiro <ldo@nz.invalid> writes:
>>
>> On Tue, 08 Sep 2026 22:38:58 -0300, Kragen Javier Sitaker wrote:
>>>
>>> PostScript does in fact have something like readmacros; in
>>> particular, readhexstring was the recommended way to handle image
>>> data, so that the image data didn’t have to be loaded into a
>>> PostScript object by way of the PostScript parser. >> >> It’s just
>>> a function. It’s like saying Python has “readmacros” because >>
>>> the JSON and XML library modules have functions for reading input
>
> It’s a function that runs while the PostScript source code is being
> read, which means that it can change the interpretation of that
> source code.
>
> You’d have to be able to write something in Python which gave you a
> session like this:
>
> $ python3
> Python 3.11.2 (main, Aug 26 2024, 07:20:54) [GCC 12.2.0] on linux
> Type "help", "copyright", "credits" or "license" for more information.
> >>> from somemodule import typeof
> >>> typeof(oagjijgw) # or ideally even without the parentheses
> <ast.Name object at 0x7f52bb870130>
>
> I claim that this `typeof` function is impossible to write in
> Python, because the parser throws a NameError before `typeof` has a
> chance to run, given that I haven’t defined `oagjijgw` previously.
How about this little program:
import code
import ast
class TypeofExpander(ast.NodeTransformer) :
def visit_Call(self, node) :
result = node
if isinstance(node.func, ast.Name) and node.func.id == "typeof" :
result = ast.Constant(value = type(node.args[0]).__name__)
else :
result = type(node) \
(
func = node.func,
args = list(self.visit(a) for a in node.args),
keywords = list((a.arg, self.visit(a.value)) for a in node.keywords)
)
#end if
return result
#end visit_Call
def visit_Expr(self, node) :
return type(node)(self.visit(node.value))
#end visit_Expr
#end TypeofExpander
console = code.InteractiveConsole()
while True :
line = input("? ")
syntax_in = ast.parse(line, mode = "single")
syntax_out = TypeofExpander().visit(syntax_in)
ast.fix_missing_locations(syntax_out)
code = compile(syntax_out, filename = "<console>", mode = "single")
console.runcode(code)
#end while
Example run:
ldo@theon:python_try> ./readmacro_fakeit
? 2 + 2
4
? import math
? math.log
<built-in function log>
? typeof(oagjijgw)
'Name'
? print("typeof(", oagjijgw, ") is", typeof(oagjijgw))
Traceback (most recent call last):
File "<console>", line 1, in <module>
NameError: name 'oagjijgw' is not defined
? print("typeof(oagjijgw) is", typeof(oagjijgw))
typeof(oagjijgw) is Name
? print("typeof(", math.log, ") is", typeof(math.log))
typeof( <built-in function log> ) is Attribute
>> Homoiconicity comes in because the function body is stored in an
>> array object, which is a PostScript language type, and its contents
>> are also objects of various PostScript language types.
>
> The analogous statements were true of most Lisps in 01982, because
> `lambda` was basically implemented as `quote` when it was the
> argument of a function (or subr), but they are true of almost no
> other programming languages except assembly language, so this is
> another similarity between PostScript and Lisp.
Except that ...
> However, the analogous statements are not true of most current
> Lisps, which have adopted the position that lambda-expressions are
> lists, and functions are not lists.
So this is no longer a similarity between PostScript and Lisp.
> Perhaps you would argue that PostScript is homoiconic and SBCL and
> Racket are not. However, most people who know the word do consider
> them to be homoiconic, because, even though the *runtime
> representation* of functions does not contain objects of various
> Lisp language types, the *source code* is just a Lisp list, so
> building Lisp code in Lisp is easy:
OK, so the definition of “homoiconic” becomes “the AST *can* be
represented in terms of language objects”, not “the AST *is*
represented in terms of language objects”. I can accept that.
> Unfortunately, this definition of homoiconicity suggests that any
> language compiled from sequences of characters is “homoiconic”
> unless for some reason it lacks the ability to manipulate sequences
> of characters.
I don’t see why that should be “unfortunate” for the definition (for
the language -- that’s another matter). But I think a sequence of text
characters is too low-level and unstructured a representation to be
worthy of the name “homoiconic”, anyway. It definitely has to involve
the AST level in some way.
> But, look again at PG’s explanation of what he means by “a function
> type”:
>
>>> “In Lisp, functions are first class objects-- they’re a data type
>>> just like integers, strings, etc, and have a literal
>>> representation, can be stored in variables, can be passed as
>>> arguments, and so on.”
>
> The only one of these that plausibly relates to homoiconicity is
> “have a literal representation”. In old Lisps you could just print
> out the definition of any function as an S-expression, but, as we
> see above with Racket, that is not currently the case; we get
> something like `#<FUNCTION (LAMBDA ()) {534960EB}>` or
> `#<procedure>`. But that’s still a string representation! And *most*
> languages don't have the ability to print out, for example, struct
> literals.
Python can. If your class defines a method called “__repr__”, it will
be called by the built-in repr() function, and is expected to return
some string representation that should be usable to reconstruct the object.
Then there is also the “__str__” method and and corresponding built-in
str() function, which is just expected to return some convenient,
reasonably descriptive string.
>> Where PostScript is lacking is in missing support for lexical
>> binding. Anybody who has done much PostScript programming knows how
>> awkward it is to simulate anything resembling local variables.
>
> This is another similarity between PostScript and the then-popular
> Lisps, which almost entirely used dynamic scope like PostScript,
> rather than lexical scope like almost all other programming
> languages. However, it is true that the facility is more convenient
> to use in Lisp.
>
> Here’s a slightly reformatted interactive session showing how
> awkward it is to simulate anything resembling local variables, in
> case anyone is curious:
>
> ...
>
> This is definitely more awkward than in most languages, but it
> doesn’t seem prohibitive to me.
For comparison, here’s an example from my PostScript-alike:
/Count 99 ddef
/metatry
{ # provides context for nonlocals
dup
/Name exch ldef
/Count 0 ldef
{ # actual proc
/Count dup lload 1 add lstore
/Count dup dload 1 add dstore
Name =
(local Count = ) print /Count lload =
(global Count = ) print /Count dload =
(whichever Count = ) print Count =
}
}
ddef
/try1 metatry ddef
/try2 metatry ddef
try1
try2
try1
try2
Note the use of ldef/lload/store for lexical binding, and
ddef/dload/dstore for dynamic binding, in place of simple
def/load/store in old PostScript. As a result, functions now actually
become useful as first-class objects. The output is:
try1
local Count = 1
global Count = 100
whichever Count = 1
try2
local Count = 1
global Count = 101
whichever Count = 1
try1
local Count = 2
global Count = 102
whichever Count = 2
try2
local Count = 2
global Count = 103
whichever Count = 2
>>> 7. A symbol type. [...]
>>
>> True enough.
>>
>> Java has the option for “interned” strings, which is a way of having a
>> symbol type without having a symbol type, if you like.
>
> That’s true, and in particular that’s useful if you’re implementing some
> kind of language parser or interpreter in Java. Python has this too.
Python doesn’t need it, because simple “==” equality comparison works
anyway, whereas it doesn’t in Java.
>>> 8. A notation for code using trees of symbols. Yes. The only
>>> difference is that in conventional Lisp they’re binary trees, while
>>> in PostScript they’re N-ary ordered trees.
>>
>> In Lisp, the tree structure is apparent in the static syntax. In
>> PostScript, the tree structure (such as it is) gets largely
>> constructed dynamically at run time, and need not correspond to
>> static syntax at all.
>
> I’m not sure I agree. Here’s my example of tree-structured code in
> PostScript, from the previous post:
>
> GS>/sign {dup 0 gt {pop /positive} {0 lt {/negative} {/zero} ifelse} ifelse} def
>
> This is an executable array of six things, the fourth of which is `{pop
> /positive}`. To me, that’s *more* apparent from the static syntax than
> the fact that in `(lambda (x y) (sqrt (+ (* x x) (* y y))))` the car of
> the car of the cdr of the cdr is `sqrt`.
I said “need not correspond”, not “does not correspond”. Just because
you can write structures statically in PostScript doesn’t mean you
have to.
>> I remember doing some experiments with an Apple LaserWriter and a
>> Macintosh II back in the late 1980s. Someone had cracked the
>> encryption of the “eexec” operator, and we used this to discover
>> that there was this other thing called “cexec” (only allowed within
>> encrypted “eexec” execution, which is why you never saw it in
>> public code) that let you load MC68000 machine code into the
>> printer and hook into an API provided by the PostScript interpreter
>> to manipulate PostScript objects and make function calls.
>
> Wow, that’s amazing! I only ever knew that there was some
> controversy about extracting fonts. Maybe this is how it was done?
There are PostScript functions called “charpath” and “pathforall”. The
former lets you add a piece of text as outlines to the current path,
instead of directly rendering it. Then you can create special effects
with the usual filling and stroking operators. “pathforall” is a way
to traverse the current elements of the path, invoking suitable
callbacks for each. In PostScript level 1, the path was locked against
traversal if it contained any outlines generated from Adobe’s
proprietary Type 1 fonts.
This restriction was (mostly) lifted in PostScript level 2.
[toc] | [prev] | [next] | [standalone]
| From | Peter Flass <Peter@Iron-Spring.com> |
|---|---|
| Date | 2026-09-10 07:39 -0700 |
| Message-ID | <117ufeq$22ksp$1@dont-email.me> |
| In reply to | #135638 |
On 9/9/26 21:06, Kragen Javier Sitaker wrote: > (Apologies if this sounds like AI slop; I’ve been interacting with > Claude Opus 5 a lot today, and although I didn’t use any LLM to write > any of this, its voice may be leaking into mine.) You are being assimilated. Resistance is futile.
[toc] | [prev] | [next] | [standalone]
| From | antispam@fricas.org (Waldek Hebisch) |
|---|---|
| Date | 2026-09-15 16:04 +0000 |
| Message-ID | <118bq9e$1m4ng$2@paganini.bofh.team> |
| In reply to | #135638 |
In comp.lang.forth Kragen Javier Sitaker <kragen@canonical.org> wrote:
> Lawrence D’Oliveiro <ldo@nz.invalid> writes:
>> On Tue, 08 Sep 2026 22:38:58 -0300, Kragen Javier Sitaker wrote:
<snip>
>>> 2. A function type. “In Lisp, functions are first class objects-- [...]
<snip>
> But, look again at PG’s explanation of what he means by “a function
> type”:
>
>>> “In Lisp, functions are first class objects-- they’re a data type
>>> just like integers, strings, etc, and have a literal representation,
>>> can be stored in variables, can be passed as arguments, and so on.”
>
> The only one of these that plausibly relates to homoiconicity is “have a
> literal representation”. In old Lisps you could just print out the
> definition of any function as an S-expression, but, as we see above with
> Racket, that is not currently the case; we get something like
> `#<FUNCTION (LAMBDA ()) {534960EB}>` or `#<procedure>`. But that’s
> still a string representation! And *most* languages don't have the
> ability to print out, for example, struct literals.
>
> What makes a “string literal” or “integer literal” a *literal* is that
> you can put it in your source code without having to give it a name.
I think that this argument about literals or homoiconicity is very
shallow. When people talk about "first class function" they mean
that one can easily create new functions at runtime. And in fact,
they usualy means that language supports closures. Closures may
look as rather restictive way of creating functions, but properly
implemented they are rather cheap and allow many interesting uses.
AFAICS interpretive languages frequently support 'eval' and general
'eval' allow definiting new functions at runtime. This is rather
heavy-weight way of creating new functions. But instead of saying
that 'eval' is too heavy-weight theoreticians prefer to give
abstract conditions which admit closures, but exclude 'eval'.
But AFAICS this boils down to simple thing: there is no way to
make 'eval' as efficient as closures. Add to that that eval
essentially implies dynamic type checking (or untyped language),
while closures can be statically type checked and you see that
for purpose of creating new functions closures have huge advantage
over 'eval'.
In PG writing things are presented in specific way because of
his agenda: he wants to show that Lisp is a "top point" of
developement of programming languages. And while Lisp has
a lot of merits, PG aims made him ignore aspects where
other languages got ahead of Lisp or made different but equally
good choice.
> So the most plausible gloss of PG’s “has a literal representation” is
> that there are Lisp expressions which create new functions when
> evaluated, which is just as true of modern Common Lisp and Scheme as it
> was of Franz Lisp in 01982. And it’s obviously true of PostScript, but
> not of C, Pascal, BASIC, etc.
AFAICS "literal representation" really means that you do not need
a name for the thing. For example in Common Lisp package must be
created with a name, so in this sense there are no package literals
in Common Lisp, while in most other cases one can easiliy create
anonymous objects.
In more restrictive meaning "literal" may mean special syntax.
With such meaning
(cons 1 nil)
is not considered to be list literal. But in Lisp users may extend
syntax so that special syntax expand to expression above and at
runtime there is limited difference (Common Lisp disallows modification
to lists defined using standard syntax for list constants, but allow
modification for list defined as above). So I think that in PG
writing lack of name is more important than special syntax. Also
I think that PG valued convenience and compact source code, so
for example
procedure(x); x; endprocedure
while satisfies formal criteria (creates new anonymous function),
would be deemed too verbose by PG.
--
Waldek Hebisch
[toc] | [prev] | [next] | [standalone]
| From | Paul Rubin <no.email@nospam.invalid> |
|---|---|
| Date | 2026-09-15 09:24 -0700 |
| Message-ID | <878q52jxd8.fsf@nightsong.com> |
| In reply to | #135712 |
antispam@fricas.org (Waldek Hebisch) writes: > In PG writing things are presented in specific way because of his > agenda: he wants to show that Lisp is a "top point" of developement of > programming languages. I remember thinking Lisp really is what you call a top point. The math term for that sort of top point is "limit ordinal". So my thought about that Blub essay was that PG didn't seem to realize that once you reach a limit ordinal, you can keep right on going, and eventually reach larger limit ordinals that have much different properties than the first one you reached.
[toc] | [prev] | [next] | [standalone]
| From | Johann 'Myrkraverk' Oskarsson <johann@myrkraverk.invalid> |
|---|---|
| Date | 2026-09-09 15:15 +0800 |
| Message-ID | <dI7oS.388329$9H1.151671@fx01.ams4> |
| In reply to | #135613 |
On 09/09/2026 9:38 AM, Kragen Javier Sitaker wrote: > (Please forgive in advance the LLM-like wording of what follows. I > wrote it entirely by hand, including reading the documents I linked, but > I’ve been coaxing > Thank you for that wonderful exposition of PostScript, I'm almost tempt- ed to write my very own P.S. interpreter, but that's going to have to wait a better time, as I already have n+1 projects. And don't worry about sounding like an L.L.M. After all, they were trained on the best of us, and sound like us -- good writers -- more than we sound like them. That's how time works. I take it you've been coaxing Lawrence, but that's a waste of time, just fire away and forget about it; I don't care, and Lawrence doesn't care either. Best wishes, and happy coaxing Lawrence! -- Johann | email: invalid -> com | http://www.myrkraverk.com/blog/ I'm not from the Internet, I just work there. | via Easynews.com https://bsky.app/profile/myrkraverk.bsky.social | for ( ;; ) _:;
[toc] | [prev] | [next] | [standalone]
| From | Kragen Javier Sitaker <kragen@canonical.org> |
|---|---|
| Date | 2026-09-10 01:11 -0300 |
| Message-ID | <87cxulagp3.fsf@debian> |
| In reply to | #135618 |
Johann 'Myrkraverk' Oskarsson <johann@myrkraverk.invalid> writes: > Thank you for that wonderful exposition of PostScript, I'm almost tempt- > ed to write my very own P.S. interpreter, but that's going to have to > wait a better time, as I already have n+1 projects. Maybe you can coax an LLM to do it. > Best wishes, and happy coaxing Lawrence! I choose to interpret this as “Happy coaxing, Lawrence!”, as an aside to him in a message to me, hoping that he is successful in coaxing whoever he needs to coax. Kragen
[toc] | [prev] | [next] | [standalone]
| From | anton@mips.complang.tuwien.ac.at (Anton Ertl) |
|---|---|
| Date | 2026-09-09 07:35 +0000 |
| Message-ID | <2026Sep9.093521@mips.complang.tuwien.ac.at> |
| In reply to | #135613 |
Kragen Javier Sitaker <kragen@canonical.org> writes:
>PostScript has several other key similarities to Lisp. Referencing Paul
>Graham's "What Made Lisp Different" <https://paulgraham.com/diff.html>:
Given your claim below that Forth has only #1, #3, #9, let's look at
the others:
>2. A function type. "In Lisp, functions are first class objects--
>they're a data type just like integers, strings, etc, and have a literal
>representation, can be stored in variables, can be passed as arguments,
>and so on."
Forth has execution tokens.
>4. A new concept of variables. "In Lisp, all variables are effectively
>pointers. Values are what have types, not variables, and assigning or
>binding variables means copying pointers, not what they point to."
In Forth, neither variables nor values have types that are known to
the Forth system. The way to use that is that the programmer must
know the type, and that typically means always storing the same type
into a variable.
>5. Garbage-collection.
Not built into Forth.
>6. Programs composed of expressions. Not really, but closer than any of
>the currently popular languages.
Forth is like Postscript here: Programs composed of words (operators
in Postscript), which work on values on the stack.
>7. A symbol type. Yes, PostScript distinguishes /names from strings,
Forth distinguishes name tokens from strings, but they do not play the
role they play in Lisp or Postscript; in particular, you have to
create new named words outside a colon definitions, and if you use a
named word to get a unique value, you tend to use its body address,
not it's name token.
>8. A notation for code using trees of symbols. Yes. The only
>difference is that in conventional Lisp they're binary trees, while in
>PostScript they're N-ary ordered trees.
As mentioned in <2026Sep9.084205@mips.complang.tuwien.ac.at>, one
might consider the indirect-threaded code representation and its
modern equivalents for inlining to be such a notation, but in Forth
many control structures become branches, whereas in Postscript the
controlled stuff is a procedure (in Forth terminology, a quotation).
>Forth hits #1, #3, and #9.
And also #2, and partially #6, #7, and #8.
Followups reduced to comp.lang.forth. Add some other groups if you
really have to.
- anton
--
M. Anton Ertl http://www.complang.tuwien.ac.at/anton/home.html
comp.lang.forth FAQs: http://www.complang.tuwien.ac.at/forth/faq/toc.html
New standard: https://forth-standard.org/
EuroForth 2026 CFP: http://www.euroforth.org/ef26/cfp.html
[toc] | [prev] | [next] | [standalone]
| From | Lawrence D’Oliveiro <ldo@nz.invalid> |
|---|---|
| Date | 2026-09-09 08:10 +0000 |
| Message-ID | <117r496$u52n$3@dont-email.me> |
| In reply to | #135620 |
On Wed, 09 Sep 2026 07:35:21 GMT, Anton Ertl wrote: > In Forth, neither variables nor values have types that are known to > the Forth system. The way to use that is that the programmer must > know the type, and that typically means always storing the same type > into a variable. Forth is not strongly-typed. I’m not aware of any high-level dynamic language that is not strongly-typed. At a bare minimum, you need to know what value is a pointer and what isn’t, otherwise memory management is not going to be a happy business. >> 6. Programs composed of expressions. Not really, but closer than any of >> the currently popular languages. > > Forth is like Postscript here: Programs composed of words (operators > in Postscript), which work on values on the stack. Note that procedures are also executable entities in PostScript. They exist apart from any name that might be referencing them (aka “lambdas”). And they can be constructed dynamically at run-time.
[toc] | [prev] | [next] | [standalone]
| From | Hans Bezemer <the.beez.speaks@gmail.com> |
|---|---|
| Date | 2026-09-10 17:58 +0200 |
| Message-ID | <117uk38$24gs6$1@dont-email.me> |
| In reply to | #135621 |
On 09-09-2026 10:10, Lawrence D’Oliveiro wrote: > Forth is not strongly-typed. I’m not aware of any high-level dynamic > language that is not strongly-typed. At a bare minimum, you need to > know what value is a pointer and what isn’t, otherwise memory > management is not going to be a happy business. If you created that pointer -- and then forgot it was a pointer -- man, I'd be visiting a doctor.. :-) Or at least learn to use another commenting style. Gee, I do OOP without any safety net -- and I'm still breathing. Hans Bezemer
[toc] | [prev] | [next] | [standalone]
Page 1 of 2 [1] 2 Next page →
Back to top | Article view | comp.lang.forth
csiph-web