Re: Bart's Language

Liste des GroupesRevenir à cl c 
Sujet : Re: Bart's Language
De : 643-408-1753 (at) *nospam* kylheku.com (Kaz Kylheku)
Groupes : comp.lang.c
Date : 21. Mar 2025, 18:47:24
Autres entêtes
Organisation : A noiseless patient Spider
Message-ID : <20250321101440.282@kylheku.com>
References : 1 2 3 4 5 6 7 8
User-Agent : slrn/pre1.0.4-9 (Linux)
On 2025-03-21, bart <bc@freeuk.com> wrote:
On 20/03/2025 23:45, Kaz Kylheku wrote:
On 2025-03-20, Waldek Hebisch <antispam@fricas.org> wrote:
bart <bc@freeuk.com> wrote:
>
In this case, just write it like that, and only adjust it for the
somewhat different syntax:
>
   func foo:int =
       let int c := c1(10)
       let int b := c + c2(2)
       let int a := b+c3(c)
       bar()
       baz()
       return c
   end
>
   >> In your description you wrote that declarations can be written
"out of order" and compiler will rearrange them in correct
order.  That looked like great opportunity to write obfuscated
code.
 
I made a language feature like that: mlet.
 
https://www.nongnu.org/txr/txr-manpage.html#N-2B3072E9
 
This allows for circular references in order to support
the construction of lazy objects:
 
1> (mlet ((a (lcons 1 b))
           (b (lcons 0 a)))
     (take 20 a))
(1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0)
>
I don't understand what's going on above; the example here is a bit
clearer, other than that z at the end:

What's going on is that

1. A variable that is not accessed is not initialized at all.
   When a variable is used for the first time (dynamically;
   determined at run time as you correcly observe) the
   initializing expression is evaluated then. Here, we don't
   see the (print 42) side effedt in the case where x is not
   used:

     1> (mlet ((x (prinl 42))) x)
     42
     42
     2> (mlet ((x (prinl 42))))
     nil

2. lcons is also a lazy construct; it is not a function but
   a macro operator. It constructs and returns a lazy cons
   cell which is associated with a lambda function that will
   fill the car and cdr of the lazy cons cell when either of
   those fields are accessed for the first time.
   So (lcons 1 b) returns a lazy cons which is uninitialized.
   When we access it, 1 is put into the car, and b is evaluated
   and put into the cdr.

3. The first thing to be evaluated is the body expression (take 20 a).
   This causes (lcons 1 b) to be evaluated and a to take on that
   value. The take function will traverse into that cell, triggering
   b's initializer (lcons 0 a) being evaluated.
   When the take function steps into that second cell, triggering
   its lazy initialization, variable a already has a value,
   pointing to the first cell. So the circular list is closed.
   take then just keeps walking the finished circular list, until
   it obtains 20 items.

   (mlet ((x (+ y 1))
          (y (+ z 1))
          (z (+ x 1)))
     z)
>
But this looks like something that goes on at runtime. In the language
above, it's all dealt with at compile time. If I create a similar example:

Serious functional languages which are single-mindedly dedicated to lazy
semantics will hoist a lot of this kind of processing to compile time.

I could make a non-lazy binding macro which determines the dependencies among
the expressions, detects and diagnoses cycles, and then emits a regular let
based on a topological sort of the dependencies.

The tools are there; there is an API by which a macro can ask what are the free
variable references emanating from a piece of code, so we can know exactly
which of the variables in the circular let construct are being referenced by
which initializing expressions, and build a graph from that.

There is just not use for such a thing. Programs already require us to jump
backwards and forwards to understand the flow due to the presence of functiond
definitions, and looping constructs; we don't need that at the statement level.

mlet allows any order because that's a side effect of handling the mutually
referencing lazy definitions, not because that's the motivating use case.
>
  const x = y + 1,
        y = z + 1,
        z = x + 1
>
then it is the compiler that reports a circular reference.
>
Otherwise, in my dynamic (and non-lazy) language, circular references
are allowed at runtime, but it is object references rather than names:
>
    a ::= (1,2,3)   # create two short lists (::= makes a mutable copy)
    b ::= (4,5,6)
>
    a &:= b         # append each to the other (concatenate is
    b &:= a         # well-behaved)

So, if you had a category of list cells that are lazy, you could
bring about this circularity without ever perpetrating a mutating
assignment. (Because it's hidden in the implementation: when the lazy
cell is accessed, its fields are de facto assigned then, but in the abstract
semantics, it's understood as not being initialized.)

  1> (let (a b)
       (set a (lcons 1 b))
       (set b (lcons 0 a))
       (take 20 a))
  (1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0)

Here we still have assignments to bring about the circularity, but the
assignments are just of lexical variables, not of the list structure.

The mlet solves the problem of hiding the variable assignments,
in its own way.

There is a cheaper way to solve the problem for the above case;
we can have a "letrec" construct (similar to what exists in Scheme) which
literally does what we did above; i.e. one which takes:

  (letrec ((a (lcons 1 b))
           (b (lcons 0 a))
    ...body...)

and writes, effectively, this code:

  (let (a b)
    (set a (lcons 1 b))
    (set b (lcons 0 a))
    ...body...)

that is to say, the initializing forms have all the variables in scope, and are
evaluated from left to right. An earlier initform evaluating a later variable
will see a nil value. But here the lcons forms are lazy, and so do not evaluate
the variables.  In other words, we don't need the laziness of mlet; lcons is
enough.

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

Date Sujet#  Auteur
18 Mar 25 * Bart's Language57bart
18 Mar 25 `* Re: Bart's Language56Waldek Hebisch
18 Mar 25  `* Re: Bart's Language55bart
18 Mar 25   `* Re: Bart's Language54Waldek Hebisch
18 Mar 25    +* Re: Bart's Language46bart
18 Mar 25    i+* Re: Bart's Language36David Brown
18 Mar 25    ii`* int a = a (Was: Bart's Language)35Kenny McCormack
18 Mar 25    ii +* Re: int a = a (Was: Bart's Language)25Janis Papanagnou
18 Mar 25    ii i+- Re: int a = a (Was: Bart's Language)1Kaz Kylheku
19 Mar 25    ii i`* Re: int a = a (Was: Bart's Language)23David Brown
19 Mar 25    ii i +- Re: int a = a (Was: Bart's Language)1Kaz Kylheku
19 Mar 25    ii i +* Re: int a = a14Keith Thompson
20 Mar 25    ii i i+* Re: int a = a12Tim Rentsch
20 Mar 25    ii i ii`* Re: int a = a11Keith Thompson
20 Mar 25    ii i ii +* Re: int a = a8David Brown
20 Mar 25    ii i ii i`* Re: int a = a7Keith Thompson
21 Mar 25    ii i ii i `* Re: int a = a6David Brown
21 Mar 25    ii i ii i  `* Re: int a = a5Keith Thompson
21 Mar 25    ii i ii i   +- Re: int a = a1David Brown
22 Mar 25    ii i ii i   `* Re: int a = a3Tim Rentsch
22 Mar 25    ii i ii i    `* Re: int a = a2Keith Thompson
28 Apr 25    ii i ii i     `- Re: int a = a1Tim Rentsch
29 Apr 25    ii i ii `* Re: int a = a2Tim Rentsch
29 Apr 25    ii i ii  `- Re: int a = a1Keith Thompson
20 Mar 25    ii i i`- Re: int a = a1David Brown
19 Mar 25    ii i +* Re: int a = a (Was: Bart's Language)5Chris M. Thomasson
20 Mar 25    ii i i`* Re: int a = a (Was: Bart's Language)4David Brown
20 Mar 25    ii i i `* Re: int a = a (Was: Bart's Language)3bart
20 Mar 25    ii i i  `* Re: int a = a (Was: Bart's Language)2David Brown
20 Mar 25    ii i i   `- Re: int a = a (Was: Bart's Language)1wij
20 Mar 25    ii i `* Re: int a = a (Was: Bart's Language)2Tim Rentsch
20 Mar 25    ii i  `- Re: int a = a (Was: Bart's Language)1David Brown
18 Mar 25    ii +* Re: int a = a (Was: Bart's Language)3David Brown
18 Mar 25    ii i`* Re: int a = a (Was: Bart's Language)2Janis Papanagnou
19 Mar 25    ii i `- Re: int a = a (Was: Bart's Language)1David Brown
19 Mar 25    ii `* Re: int a = a (Was: Bart's Language)6Tim Rentsch
19 Mar 25    ii  +* Re: int a = a2Keith Thompson
27 Apr 25    ii  i`- Re: int a = a1Tim Rentsch
19 Mar 25    ii  +- Re: int a = a (Was: Bart's Language)1David Brown
19 Mar 25    ii  `* Re: int a = a (Was: Bart's Language)2Rosario19
20 Mar 25    ii   `- Re: int a = a (Was: Bart's Language)1Tim Rentsch
20 Mar 25    i`* Re: Bart's Language9Waldek Hebisch
21 Mar 25    i `* Re: Bart's Language8Keith Thompson
22 Mar 25    i  +* Re: Bart's Language5Waldek Hebisch
22 Mar 25    i  i`* Re: Bart's Language4James Kuyper
22 Mar 25    i  i +* Re: Bart's Language2Waldek Hebisch
23 Mar 25    i  i i`- Re: Bart's Language1James Kuyper
23 Mar 25    i  i `- By definition... (Was: Bart's Language)1Kenny McCormack
27 Apr 25    i  `* Re: Bart's Language2Tim Rentsch
27 Apr 25    i   `- Re: Bart's Language1Keith Thompson
18 Mar 25    `* Re: Bart's Language7bart
20 Mar 25     `* Re: Bart's Language6Waldek Hebisch
21 Mar 25      +* Re: Bart's Language4Kaz Kylheku
21 Mar 25      i`* Re: Bart's Language3bart
21 Mar 25      i `* Re: Bart's Language2Kaz Kylheku
22 Mar 25      i  `- Re: Bart's Language1Tim Rentsch
21 Mar 25      `- Re: Bart's Language1bart

Haut de la page

Les messages affichés proviennent d'usenet.

NewsPortal