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

    From Spiros Bousbouras@21:1/5 to Kaz Kylheku on Thu Jun 8 08:45:33 2023
    On Wed, 7 Jun 2023 20:26:03 -0000 (UTC)
    Kaz Kylheku <864-117-4973@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.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kaz Kylheku@21:1/5 to Spiros Bousbouras on Thu Jun 8 17:37:40 2023
    On 2023-06-08, Spiros Bousbouras <spibou@gmail.com> wrote:
    On Wed, 7 Jun 2023 20:26:03 -0000 (UTC)
    Kaz Kylheku <864-117-4973@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,
    it helps with the readability.

    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: @Kazinator@mstdn.ca

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From none) (albert@21:1/5 to spibou@gmail.com on Mon Jun 19 11:41:44 2023
    In article <nzRJAvWCQBiyNSZoM@bongo-ra.co>,
    Spiros Bousbouras <spibou@gmail.com> wrote:
    On Wed, 7 Jun 2023 20:26:03 -0000 (UTC)
    Kaz Kylheku <864-117-4973@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.

    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
    ] .... x add-a-duplicate ...
    } : do-something

    Is that idea related?

    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 -

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Spiros Bousbouras@21:1/5 to albert@cherry. on Tue Jun 20 19:44:43 2023
    On Mon, 19 Jun 2023 11:41:44 +0200
    albert@cherry.(none) (albert) wrote:
    In article <nzRJAvWCQBiyNSZoM@bongo-ra.co>,
    Spiros Bousbouras <spibou@gmail.com> wrote:
    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.

    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
    ] .... x add-a-duplicate ...
    } : do-something

    Is that idea related?

    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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kaz Kylheku@21:1/5 to Spiros Bousbouras on Tue Jun 20 23:06:20 2023
    On 2023-06-20, Spiros Bousbouras <spibou@gmail.com> wrote:
    On Mon, 19 Jun 2023 11:41:44 +0200
    albert@cherry.(none) (albert) wrote:
    In article <nzRJAvWCQBiyNSZoM@bongo-ra.co>,
    Spiros Bousbouras <spibou@gmail.com> wrote:
    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.

    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
    ] .... x add-a-duplicate ...
    } : do-something

    Is that idea related?

    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 .

    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.

    (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.


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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From none) (albert@21:1/5 to spibou@gmail.com on Wed Jun 21 13:42:51 2023
    In article <isMgDLLnFWYAwAbcn@bongo-ra.co>,
    Spiros Bousbouras <spibou@gmail.com> wrote:
    On Mon, 19 Jun 2023 11:41:44 +0200
    albert@cherry.(none) (albert) wrote:
    In article <nzRJAvWCQBiyNSZoM@bongo-ra.co>,
    Spiros Bousbouras <spibou@gmail.com> wrote:
    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.

    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
    ] .... x add-a-duplicate ...
    } : do-something

    Is that idea related?

    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.

    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

    You can do "blink" or "blink blink blink"
    eternal blinking: {| blink |}
    ten times blinking: 1 10 'blink do

    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 -

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)