On Thursday, August 31, 2023 at 2:11:21 AM UTC-7, none albert wrote:
The explanations about the usage of gensym are clear,
how your are supposed to used them.
The theoretical background however is far from it.
The theoretical background is essentially this:
* For regular symbols, when the reader encounters a symbol, it creates a
symbol object and "interns" it. Interning means creating a mapping from
the symbol name to the symbol object.
* GENSYM will generate an "uninterned" symbol. It creates and returns a
symbol object, but does *not* create a mapping from the (generated)
name to the symbol object. That means that even if you type in the same
as gets internally chosen for this uninterned symbol, it will not be the
same object.
The explanations about the usage of gensym are clear,
how your are supposed to used them.
The theoretical background however is far from it.
(let* (aaa (gensym)) .. aaa .. )
In the context `` .. aaa .. '' `aaa is obviously a symbol.
The interesting question is what value is aaa coupled to due to
the environment (aaa (gensym))?
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.
I have the following lisp type of objects:
symbols lists numbers strings arrays hashes normal-function
special-functions booleans
and more MAL oddballs:
nil key atom
Nothing seems an appropriate type for `aaa.
(let* (condvar (gensym))
`(let* (~condvar ~(first xs))
(if ~condvar ~condvar (or ~@(rest xs)))))))))
The explanations about the usage of gensym are clear,
how your are supposed to used them.
The theoretical background however is far from it.
(let* (aaa (gensym)) .. aaa .. )
In the context `` .. aaa .. '' `aaa is obviously a symbol.
The interesting question is what value is aaa coupled to due to
the environment (aaa (gensym))?
Apparently aaa must be evaluated before it is any use.
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.
I have the following lisp type of objects:
symbols lists numbers strings arrays hashes normal-function special-functions booleans
and more MAL oddballs:
nil key atom
Nothing seems an appropriate type for `aaa.
Example studied:
(defmacro! or
(fn* (& xs)
(if (empty? xs)
nil
(if (= 1 (count xs))
(first xs)
(let* (condvar (gensym))
`(let* (~condvar ~(first xs))
(if ~condvar ~condvar (or ~@(rest xs)))))))))
No , interning means creating an association between a symbol and a package. Different packages can have symbols with the same name. Other relevant facts {for Common Lisp} :
On 2023-08-31, albert@cherry.(none) (albert) <albert@cherry> wrote:
The explanations about the usage of gensym are clear,
how your are supposed to used them.
The theoretical background however is far from it.
(let* (aaa (gensym)) .. aaa .. )
In the context `` .. aaa .. '' `aaa is obviously a symbol.
The interesting question is what value is aaa coupled to due to
the environment (aaa (gensym))?
gensym is an ordinary function which returns an object.
That object is a symbol.
If we replace it with (aaa (list 1 2 3)), then aaa is bound
to list of three elements.
The object returned by gensym is always a newly created symbol,
different from any other symbol in the system that has hitherto existed.
In Common Lisp, gensym returns an uninterned symbol: a symbol which
is not registered in a package. (There are some subtle details to it,
but let that suffice.) Common Lisp prints such symbols with a #:
(hash colon) prefix. E.g. (gensym "ABC-") -> #:ABC-0013 .
The Common Lisp gensym maintains an incrementing counter which it uses
to generate new names, but those names are just for human readability,
not the basis for the uniquenes..
Each time the reader encounters the #: syntax, it creates a new,
uninterned symbol so that (eq '#:abc '#:abc) will be false.
Those are two different symbols, which have the same name.
For interned symbols, that is impossible: only one symbol can
exist in a package under a given name: there can at most be one cl:list
or abc:foo or whatever.
Huh?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.
I have the following lisp type of objects:
symbols lists numbers strings arrays hashes normal-function
special-functions booleans
and more MAL oddballs:
nil key atom
Nothing seems an appropriate type for `aaa.
The obect aaa itself is a symbol. The token aaa appears in your code.
The Lisp reader scans that token, recognizes it as having the
shape of a symbol, and so it interns it: it produces either the
existing symbol that exists under that name, or else produces a new
one and registers it under that name. (If it didn't register it,
the symbol would be uninterned, like the ones from gensym.)
I'm guessing that since you've gone this far in MAL, you must
have that working.
(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.
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.
--
TXR Programming Language: http://nongnu.org/txr
In article <20230831104914.534@kylheku.com>,
Kaz Kylheku <864-117-4973@kylheku.com> wrote:
On 2023-08-31, albert@cherry.(none) (albert) <albert@cherry> 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,Huh?
which are symbols.
(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
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 <object> ) ...
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?
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.
It is related to the following implementation choice I made.
All objects have a place to set a name.
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.
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.
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) <albert@cherry> wrote:
[...]
(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.
let : symbolAll 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 ?
Okay that is what I do.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} andx can be different than the properties of aaa and that includes whether
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
it is bound to a value and which value.
x
- it will be uninterned.
--
ninja
In article <8GRTwaqPt+TSAYagO@bongo-ra.co>,
Spiros Bousbouras <spibou@gmail.com> wrote:
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) <albert@cherry> wrote:
[...]
(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.
Remember that my big question was,what is the type of the value
`aaa is bound to. So apparently that is a symbol that has
uninterned.
Can you please elaborate what uninterned means?
It is clear that you can have a symbol that is floating around
and has not been placed in abstract structure tree or a
hash table. Is that uninterned?
Suppose I use a name for a symbol that is already present in the environment.
I hope that that the new and old symbol are distinct despite having the
same name. Otherwise I seriously misunderstand lisp.
The explanations about the usage of gensym are clear,
how your are supposed to used them.
The theoretical background however is far from it.
(let* (aaa (gensym)) .. aaa .. );; try (let* (,~condvar ~(first xs))
In the context `` .. aaa .. '' `aaa is obviously a symbol.
The interesting question is what value is aaa coupled to due to
the environment (aaa (gensym))?
Apparently aaa must be evaluated before it is any use.
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.
I have the following lisp type of objects:
symbols lists numbers strings arrays hashes normal-function
special-functions booleans
and more MAL oddballs:
nil key atom
Nothing seems an appropriate type for `aaa.
Example studied:
(defmacro! or
(fn* (& xs)
(if (empty? xs)
nil
(if (= 1 (count xs))
(first xs)
(let* (condvar (gensym))
`(let* (~condvar ~(first xs))
(if ~condvar ~condvar (or ~@(rest xs)))))))))
(dostring (chr "hello world")(print chr))
Sysop: | Keyop |
---|---|
Location: | Huddersfield, West Yorkshire, UK |
Users: | 307 |
Nodes: | 16 (2 / 14) |
Uptime: | 95:48:02 |
Calls: | 6,849 |
Files: | 12,352 |
Messages: | 5,414,880 |