Nп/п : 60 из 93
 От   : Spiros Bousbouras                   2:5075/128        01 сен 23 14:27:19
 К    : none) (albert                                         01 сен 23 17:29:02
 Тема : Re: What does (gensym) generate?
----------------------------------------------------------------------------------
                                                                                 
@MSGID: <8GRTwaqPt+TSAYagO@bongo-ra.co> 6bfd103b
@REPLY:
0085e4af
@REPLYADDR Spiros Bousbouras <spibou@gmail.com>
@REPLYTO 2:5075/128 Spiros Bousbouras
@CHRS: CP866 2
@RFC: 1 0
@RFC-Message-ID: <8GRTwaqPt+TSAYagO@bongo-ra.co>
@RFC-References:
<20230831104914.534@kylheku.com>

@TZUTC: -0000
@TID: FIDOGATE-5.12-ge4e8b94
On Fri, 01 Sep 2023 14:23:21 +0200
albert@cherry.(none) (albert) wrote:
> In article <20230831104914.534@kylheku.com>,
> Kaz Kylheku  <864-117-4973@kylheku.com> wrote:
> >On 2023-08-31, albert@cherry.(none) (albert)  wrote:

[...]

> >> However subsequently you see
> >> (let*   (aaa (rest whatever)) ... )
> >> What is disturbing to me is that let* only allows symbols into the
> >> position of aaa and normally the coupling of aaa hides previous usage.
> >
> >It`s a variable binding construct, so it only allows variable names,
> >which are symbols.
> Huh?

let  binds variables ; so in something like

    (let  (( value) ...))

the    has to be a variable name which means a Lisp object of
type symbol.

[...]

> >>         (let* (condvar (gensym))
> >>           `(let* (~condvar ~(first xs))
> >>              (if ~condvar ~condvar (or ~@(rest xs)))))))))
> >
> >So here condvar is a generated, unique symbol.
> >
> >It is interpolated into the backquote template.
> >
> >~convar says, insert the value of condvar here. The value is
> >a symbol, which is what we want there.

> Can we conclude that the only time to worry is inside
> quasiquote? That helps a lot. There is a moment in time
> where we expand, and the

There is no special worry involved but more on this below.

> >The macro is generating code in which there is a local variable boudd
> >using let*, and that variable`s name is machine generated.
> >
> >This the same as what you see in any compiler: machine generated
> >temporaries, jump labels and so on.

> The big question how to parse
>     (let (aaa  )  ...
> In the abstract structure tree `let and `aaa are symbols
> that are manipulated during evaluation.
> The spec`s of let  is that aaa is a symbol that is bound to object.
> This cannot be the whole story. For instance there is no notice
> to evaluate aaa , the previous binding is lost.
> That are the spec`s of `let , or so I thought.
> Comes gensym . If I previously encountered `` (aaa (gensym)) ``
> everything changes. But how can I even know that the previous
> binding was this weird contraption?

(let ((aaa (foo))))   binds  aaa  to whatever  (foo)  returns. As
far as this goes there is nothing special with something like
(let ((aaa (gensym)))) . aaa  gets bound to whatever  (gensym)
returned much like  (let ((aaa (+ 1 1))))  binds  aaa  to whatever
(+ 1 1)  returns which is 2.

(gensym)  returns a symbol with the special property that it is
uninterned. So the only reference to the symbol returned is through
aaa .There is nothing you can type on the REPL to get the same
symbol {although you can get a symbol with the same name} and every
other call to  gensym  will also return a different symbol.

> I have 256 Gbyte RAM and MAL is a toy implementation, so bear with me:
> each object has 7 64 bit fields.
> All objects are uniform and have a tag giving its type:
> pointer to code, pointer to data, a flag field (containing tags),
> a link field, a name field, a source field (not used) and
> one spare.

I don`t think such low level details are helpful but anyway.

> It is related to the following implementation choice I made.
> All objects have a place to set a name.

The first problem here is that you are using what is standard Lisp
terminology , or at least Common Lisp terminology , for something
which seems to be different. In Common Lisp a symbol has a name
which is a string. So the name of the symbol  aaa  is the string
"aaa" .But a symbol is a different thing than its name ; it`s a
different datatype and a different object.

> All object have some data and possibly no name (e.g. numbers, lists
> functions, strings)
> Symbols have a name and all other fields are free.
> Binding a symbol : fill the name of the symbol in the object
> and possibly link it into an environment (linkfield is the hook for that).
> Sometime we have to clone the whole object, if it previously had a name
> and were linked to some environment.
> For example an anonymous lambda looks like this:
> code pointer : forth interpreter
> data pointer : forth code to be interpreted
> flag : contains either #func or #special or-ed with possibly Forty flags.
> link , name : empty.

So if you have something like  (let ((aaa 19)))  what value are the
various things you mention going to have ?

> The contradiction caused by (gensym) is that you have symbols with
> two names, where the only property of a symbol is that it has
> a name that identifies itself. Or so I thought.

What identifies a symbol is its location in memory. You don`t have
direct access to that location {i.e. you can`t get the address} but
in that location there will be stored {in an appropriate layout known
to the Lisp implementation} the various properties of the symbol
which include the following :

A symbol has a name {meaning a string , as I explained above} and
whether it is bound to a value and whether it is interned or not. For
simplicity lets assume that "interned" is a binary property although
in Common Lisp it isn`t , if a symbol is interned then it is interned
in some package. With something like

    (let ((aaa (gensym))))  

the symbol  aaa  has the following properties :

- it has the name  "aaa"  which is a string.

- it is interned because you typed it into the REPL or read it from source
  code in some file.

- it is bound to the value returned by  (gensym) .By the definition of
  gensym  this value will have the following properties :

  - it will be a symbol therefore it will also have a name which will also
    be a string. In Common Lisp you can even control what that string will be
    and you can even make it to be  "aaa" .But even if you make the name
    to be  "aaa" , the symbol returned by  (gensym)  will be distinct
    from  aaa  which you typed on the REPL ; "distinct" meaning it will be
    stored at a different place in memory and its various properties
    can be different than the properties of  aaa  and that includes whether
    it is bound to a value and which value.

  - it will be uninterned.

These facts are unrelated to quasiquoting although often are used in combination
with quasiquoting. But note that your code

     (let* (condvar (gensym))
       `(let* (~condvar ~(first xs))
          (if ~condvar ~condvar (or ~@(rest xs)))))))))

could be written as

(defun or-function (list-of-clauses)
    (if     list-of-clauses
        (let*   ((condvar (gensym)))
            (list `let* (list (list condvar (first list-of-clauses)))
                  (list `if condvar condvar
                        (or-function (rest list-of-clauses)))))
        nil))

.Obviously this is a lot less readable but I hope it illustrates the
point that  gensym  is not based on quasiquoting nor the other way
around.

-- 
vlaho.ninja/prog
--- FIDOGATE 5.12-ge4e8b94
 * Origin: To protect and to server (2:5075/128)
SEEN-BY: 5001/100 5005/49 5015/255 5019/40 5020/715
848 1042 4441 12000
SEEN-BY: 5030/49 1081 5058/104 5075/128
@PATH: 5075/128 5020/1042 4441



   GoldED+ VK   │                                                 │   09:55:30    
                                                                                
В этой области больше нет сообщений.

Остаться здесь
Перейти к списку сообщений
Перейти к списку эх