# Re: Estimate: How man Forth-LOCs (line of code) for 10000 C-LOCs ?

48 views

### none albert

Jun 7, 2023, 10:40:26 AMJun 7
to
Brian Fox <bria...@brianfox.ca> wrote:
>On Saturday, May 27, 2023 at 1:00:02 PM UTC-4, Andreas Neuner wrote:
>> Because FORTH Code is far more condensed and efficient, how many lines
>of FORTH Code would I need to recode a 10000 LOC C application?
>> Only as a raw estimation. I'm sure people there are people around here
>who have recoded some C apps.
>>
>> Thank you
>> Best Wishes
>> Andreas
>
>This may be of some use to compare C to Forth in a real project.
>Here is an exercise to make a LISP interpreter in many languages.
>
>https://github.com/kanaka/mal/tree/master/impls
>
>I was surprised to see a GForth implementation there.
>
>The wild card is that these LISPs are built to a recipe for the course
>and so might not fully use idiomatic methods that take advantage
>of the implementation language's features. (?)
>

I'm easily going to step3 a calculator implemented in this way.

Then I stumble upon this gem
"

Add the quasiquote function. The quasiquote function takes a parameter ast and has the following conditional.

If ast is a list starting with the "unquote" symbol, return its second element.

If ast is a list failing previous test, the result will be a list populated by the following process.

The result is initially an empty list. Iterate over each element elt of ast in reverse order:
If elt is a list starting with the "splice-unquote" symbol, replace the current result with a list containing: the "concat" symbol, the second element of elt, then the previous result.
Else replace the current result with a list containing: the "cons" symbol, the result of calling quasiquote with elt as argument, then the previous result.

This process can also be described recursively:
If ast is empty return it unchanged. else let elt be its first element.
If elt is a list starting with the "splice-unquote" symbol, return a list containing: the "concat" symbol, the second element of elt, then the result of processing the rest of ast.
Else return a list containing: the "cons" symbol, the result of calling quasiquote with elt as argument, then the result of processing the rest of ast.

If ast is a map or a symbol, return a list containing: the "quote" symbol, then ast.

Else return ast unchanged. Such forms are not affected by evaluation, so you may quote them as in the previous case if implementation is easier.

"
If a language needs such things I doubt its usefulness.

I suspect this has to do with the decision that a list
(a b c ) requires that a is a function (prohibiting a simple list
denotation as "(1 2 3)" ) and that b and c are "evaluated".
In this example "b" cannot be a symbol (no evaluation possible)
but has to be contrived to be a variable via a key-value hash map,
then it has to replaced by the value.

The mal quote continues :
"sets the stage for the next very exciting step: macros."

I come to suspect that macro's are in fact immediate words,
but more difficult to use.
We are experiencing a surge in artificial intelligence.
It is because of neural nets, not computer languages.

Groetjes Albert
--
Don't praise the day before the evening. One swallow doesn't make spring.
You must not say "hey" before you have crossed the bridge. Don't sell the
hide of the bear until you shot it. Better one bird in the hand than ten in
the air. First gain is a cat spinning. - the Wise from Antrim -

### Kaz Kylheku

Jun 7, 2023, 4:26:08 PMJun 7
to
On 2023-06-07, albert@cherry.(none) (albert) <albert@cherry> wrote:
> We are experiencing a surge in artificial intelligence.
> It is because of neural nets, not computer languages.

Probably since I was a child, I took it for granted that sufficiently
large neural networks will show intelligence: that it's just a number
crunching problem requiring the hardware to have lots of space (and
parallel computing power in order to work in anything resembling real
time).

Not only that, but also that I will likely see this, or the start of it,
well within my lifetime. That dawn is here, pretty much.

I also already decided then that I wasn't interested in massive number
crunching, regardless of its results.

The intelligence that results from it can at most be about as
interesting as people. We've had people for millennia, and only
a few of them have been interesting, so ...

I like my computations to be nice and tight, using a small amount of
resources in order to produce a precise, repeatable result, whose
every aspect can be explained and traced to a piece of code, which
can be traced to a requirement.

> Groetjes Albert

You should open your mind more. Firstly, the MAL ("make a lisp") project
isn't a good way to learn about Lisp. It has a specific educational
goal and focus: to guide people through implementing Lisp-like
evaluation in any programming language, by following a certain recipe.

Production Lisps are not built according to such a recipe.

Quasiquation is something necessary and useful in Lisp because it's a
language which exhibits nested syntax. Just because you don't
have that in Forth doesn't mean it's nonsense. (Or that Forth is
nonsense due to not having that.)

MAL doesn't properly explain what quasiquotation is; it assumes you
know about it from somewhere else and just want to get it working
by following the steps in MAL.

Quotation allows a Lisp program to refer to a piece of its syntax
as a literal value. For instance whereas (+ 4 4) is an expression
that calculates 8, '(+ 4 4), which means exactly the same thing
as (quote (+ 4 4)) produces the value (+ 4 4): a list of three
elements, those being the + symbol, and the integer 4 appearing twice.

We can produce the same list in another way, for instance by
calling the list function with three arguments, which are evaluated
expressions: (list '+ 4 4). The symbol + is quoted, otherwise
it is treated as the variable + whose value is to be referenced.
The advantage of list is that we can stick in variable material,
for instance

(defun make-funny-list (arg)
(list arg 4 4))

Now we can call (make-funny-list 3) to produce (3 4 4),
or (make-funny-list '-) to produce (- 4 4).

Quasiquotation lets us use a visual template to do the same thing.
Instead of the quote, a different character is used, typically
the backquote.

(defun make-funny-list (arg)
`(,arg 4 4))

Everything in the backquote is literal-like constant material,
except for the parts indicated by the comma unquote, like ,arg.
Those expressions are evaluated and the value is inserted.

The quasiquote is a templating language for creating nested
lists using a notation which looks like those lists, rather
A quasiquote can be nested and it can insert material into
any level of nesting.

This templating notation is heavily used in writing macros,
and other code-to-code transformation situations.
Sometimes it is used in manipulating data which isn't code, too.

Manipulating syntax is an different approach to metaprogramming than
what is going on in Forth; you're only selling yourself short
if you dismiss that casually without learning anything about it.
(And then dismissing it, if you're still inclined.)

--
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
Mastodon: @Kazi...@mstdn.ca

### Spiros Bousbouras

Jun 8, 2023, 4:45:39 AMJun 8
to
On Wed, 7 Jun 2023 20:26:03 -0000 (UTC)
Kaz Kylheku <864-11...@kylheku.com> wrote:
> The quasiquote is a templating language for creating nested
> lists using a notation which looks like those lists, rather
> than hard-to-read nested constructor calls.
> A quasiquote can be nested and it can insert material into
> any level of nesting.
>
> This templating notation is heavily used in writing macros,
> and other code-to-code transformation situations.
> Sometimes it is used in manipulating data which isn't code, too.

For 2 or more levels of nesting , I find it a lot more readable
to use explicit calls instead of nested backquotes. With the
explicit calls , you push all the quoting to the innermost level
and otherwise the usual evaluation rules apply. It usually is
more verbose but I find it more readable.

### Kaz Kylheku

Jun 8, 2023, 1:37:45 PMJun 8
to
On 2023-06-08, Spiros Bousbouras <spi...@gmail.com> wrote:
> On Wed, 7 Jun 2023 20:26:03 -0000 (UTC)
> Kaz Kylheku <864-11...@kylheku.com> wrote:
>> The quasiquote is a templating language for creating nested
>> lists using a notation which looks like those lists, rather
>> than hard-to-read nested constructor calls.
>> A quasiquote can be nested and it can insert material into
>> any level of nesting.
>>
>> This templating notation is heavily used in writing macros,
>> and other code-to-code transformation situations.
>> Sometimes it is used in manipulating data which isn't code, too.
>
> For 2 or more levels of nesting , I find it a lot more readable
> to use explicit calls instead of nested backquotes.

Sure, but I was mostly referring to just nested structure in
one backquote, not nested backquotes, as in:

`(let ((,var ,init) ,@body))

compared to

(list* 'let (list (list var init)) body)

or, worse:

(append '(let) (list (list (list var init))) body)

> With the
> explicit calls , you push all the quoting to the innermost level
> and otherwise the usual evaluation rules apply. It usually is
> more verbose but I find it more readable.

I'm sure it's readable, but you probably can't grok the shape of what is
being built as well.

(defmacro write-another-macro (name arg)
`(defmacro ,name (other-arg)
`(whatever ... ,other-arg ... ,',arg)))

On the other hand, the problem with nested backquotes is that if you
have to do any of the following, then you may have to stare at them and
pick them apart:

- Debug a non-working nested backquote.

- Convince yourself that a suspicious nested backquote is
correct (or not) just by looking at it rather than testing.

- Understand what a backquote is supposed to do in some
undocumented situation.

If these are not issues, the nested backquote does a good
job of conveying the structure of what is being built.

If you're used to a few idioms like ,',outer and whatnot,

I remember that I really stuggled with this defset-expander
function:

which has triple backquoting.

https://www.kylheku.com/cgit/txr/tree/stdlib/defset.tl#n59

However, I don't feel it would have been easier if I tried
to do it without quasiquoting. Even if it were, it would probably
be indecipherable to later scrutiny.

But if you were to change a comma here or there, I wouldn't know by
looking at it.

--
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
M..astodon: @Kazi...@mstdn.ca

### none albert

Jun 9, 2023, 4:46:59 AMJun 9
to
In article <202306071...@kylheku.com>,
Kaz Kylheku <864-11...@kylheku.com> wrote:
>On 2023-06-07, albert@cherry.(none) (albert) <albert@cherry> wrote:
>> We are experiencing a surge in artificial intelligence.
>> It is because of neural nets, not computer languages.
>
>Probably since I was a child, I took it for granted that sufficiently
>large neural networks will show intelligence: that it's just a number
>crunching problem requiring the hardware to have lots of space (and
>parallel computing power in order to work in anything resembling real
>time).
>
>Not only that, but also that I will likely see this, or the start of it,
>well within my lifetime. That dawn is here, pretty much.
I too saw it coming, I've similar idea's but was nowhere near
able to implement it. There were machines in factories, then
machine to build this machines, then computers to design these
machines, and now ai to design factories around this.
The only problems to solve are overpopulation, global warming and
energy.

>
>I also already decided then that I wasn't interested in massive number
>crunching, regardless of its results.
>
>The intelligence that results from it can at most be about as
>interesting as people. We've had people for millennia, and only
>a few of them have been interesting, so ...
What is more interesting is to see an intelligence develop,
say the first 10 years of a child. That is possible in a
smaller time frame, if not overnight.

There is no communication possible with an ai caused by
a speed discrepancy. If you converse with an ai, she can
learn mandarin while you formulate your next thought.

>
>I like my computations to be nice and tight, using a small amount of
>resources in order to produce a precise, repeatable result, whose
>every aspect can be explained and traced to a piece of code, which
>can be traced to a requirement.
>
>> Groetjes Albert
>
>You should open your mind more. Firstly, the MAL ("make a lisp") project
>isn't a good way to learn about Lisp. It has a specific educational
>goal and focus: to guide people through implementing Lisp-like
>evaluation in any programming language, by following a certain recipe.

Rest assured. I use it as a programming challenge only.
Forth is supposed to extend the language. This should mean that
you don't write an interpreter for mal, you should morph Forth
into mal.
For example let ';' be the comment symbol as in mal.
";" now becomes a Forth word, reading to the end of line and

>
>Production Lisps are not built according to such a recipe.
All compilers are based on C, because the chip manufacturers
target c-compilers. I know.

<SMIP >Quasiquation explained>

Thank you. That clears things up, and inspires me to go on
with mal.

>
>This templating notation is heavily used in writing macros,
>and other code-to-code transformation situations.
>Sometimes it is used in manipulating data which isn't code, too.

This reminds me of a trick ^H^H^H^H^H technique I use to
generate classes via a sort of template.
The name is duplicated several times and filled in at the %s.
NAME\$ \$@ 2DUP 2DUP 2DUP
": %s CREATE BUILD-%s ^%s ! DOES> ^%s ! ;" FORMAT&EVAL
Resulting in the source code for class rectangle
: rectangle CREATE BUILD-rectangle ^rectangle ! DOES> ^rectangle ! ;
The %s is similar to quasicode, I guess. 1]
The line is then compiled to add rectangle to the keywords.

>
>Manipulating syntax is an different approach to metaprogramming than
>what is going on in Forth; you're only selling yourself short
>if you dismiss that casually without learning anything about it.
>(And then dismissing it, if you're still inclined.)

Certainly willing to learn from your explanation.

>
Groetjes Albert
1] Looks primitive and it is. The source code for class is
one block 16 lines by 64 chars. It is supported by formatting
that is also one block, but is useful in its own right.

### none albert

Jun 19, 2023, 5:41:50 AMJun 19
to
In article <nzRJAvWC...@bongo-ra.co>,
I have been experimenting with a reverse polish like language.
The main elements are bracket pairs.
{ } is deferred code
{ do something } leaves a token that can be "run".
Normally code is executed, but you can execute code
while in deferred mode by [ ]
So you got
{ [ 1 2 + "addition result:" type . ] "hello world" type }
This types the addition result while the line is entered.
It leaves a token that can be run to type the "hello world| message.
Normally a deferred token is given a name via ':' like so.
{ "hello world" type } : hellow

The idea is that the brackets can be nested indefinitely.
{ [ variable x ] .... x ... }
{
[
variable x
{ 2 * + } : add-a-duplicate
} : do-something

Is that idea related?

### Spiros Bousbouras

Jun 20, 2023, 3:44:48 PMJun 20
to
It is related to the overall discussion but it is kind of the opposite to
what I was saying in my post you are directly replying to. I find it harder
to read where you have nested scopes and , depending on the level of nesting
, the evaluation happens during translation time or later and that's the kind
of thing I aim to avoid. I find your notation better than backquotes and
commas but basically with something like { .... } , you still have to read
deeper to see if there are any [ ... ] and within a [ ... ] deeper to see
if there are any { ... } and so forth ; whereas with Common Lisp's QUOTE ,
you know right away that everything in the scope of QUOTE will be taken as
is. Actually this isn't completely accurate because CL also offers read time
evaluation but I've never used it , I don't think it's a good idea and I turn
it off by setting *READ-EVAL* to NIL .

Apart from that , I find your approach interesting. How far are you planning
to develop your language ? How high level is it going to be ? For example
with CL macros , one of the arguments of the macro often is some user
provided code and the macro produces some code of its own and combines it
with the user code to achieve a desired effect. The analogous for your
language would be to pass some user code on the stack. Perhaps the same
effects can be achieved by passing an execution token on the stack , it
depends on what else the language can do.

--
How did he find her? Quite simple really. He assumed there was only
one place for a foreigner to stay in Ibusuki-the big international hotel.
So he called there and asked to have himself connected to the Dutch woman's
room.
http://www.debito.org/beggarsresults.html

### Kaz Kylheku

Jun 20, 2023, 7:06:26 PMJun 20
to
In TXR Lisp there is a macro-time macro. (Such a macro can easily be
written in ANSI CL.) (macro-time expr) evaluates macro during expansion
and substitutes its result, which is quoted to prevent it being
expanded and evaluated as code.

2> (expand '(list (macro-time (uname).sysname) (uname).sysname))
(list "Linux" (slot (uname) 'sysname))

But I sense this is not the same as in the languagre above.

The main mechanism for deferrment is the lambda expression.
Implementations of cruft like delay or force, or lazily evaluated
sub-languages generate lambdas.

We can imagine a form of lambda expression which is evaluated as normal,
but in whose body you can perform calculations *now*, rather than later.

For instance

(let ((x ...))
(lambda (y)
(+ [* x 2] y)))

Here {* x 2} is evaluated and reduced at the time the lambda is
evaluated, not at the time when it is called. This could be achieved
by a transformation like this:

(let ((x ...))
(let ((#:g0025 (* x 2)))
(lambda () (+ #:g0025 y)))) ;; same gensym

We have exactly what we want: (* x 2) is evaluated at around the same
time as the lambda (just before). Its value is available through a
a hidden variable that is inserted where the {* x 2} expression
appeared.

In ANSI CL we could make some macro, say dlambda, such that

(dlambda () (+ (unlambda * x 2) y))

will expand to the above let construction. Then a reader macro provides
the {...} -> [unlambda ...] sugar.

### none albert

Jun 21, 2023, 7:45:09 AMJun 21
to
In article <isMgDLLn...@bongo-ra.co>,
I keep the language as compact and simple as possible.
Most words are familiar Forth words, meta takes the role of the
CREATE/DOES> construct.

This is all:
{ } [ ] : run reserve meta do ix poke peek bpoke bpeek r r- 0x x. \$.
>r r> . drop dup over nip swap pdup pdrop spswap + - * / < > or and
xor negate invert = <> here , % not << >> >= <= false true data do
variable |{ }|{ }| {| | |} ; lsn clr shw include from: import want

The idea is to provide the user with a simple scripting language,
in competition with python. Almost nobody is programming in python,
everything complicated is relegated to c-libraries.
Likewise classes libraries and such is programmed in the underlying
implementation language Forth and accessed with
include from: import want

A simple example for a blinking led:

WANT MS #output set-function

{ 24 } : led
#output led set-function
{ led gpio-on 100 MS led gpio-off 100 MS } : blink