freenode/#lisp - IRC Chatlog
Search
13:40:08
jcowan
What are the most common use cases for the syntaxes #n= and #n#, as opposed to the data structures they represent? Is it genuinely common to serialize such things as S-exprssions?
13:40:57
beach
For example, if I have an application with some internal structured data, I use it as a format on disk.
13:41:36
jcowan
beach: thanks. jackdaniel: I didn't mean in code, but that usage is new to me, so I'm glad to see it.
13:41:37
beach
jcowan: Recently, the ASTs produced by the SICL compiler are saved like that, thereby producing FASL files .
13:52:42
beach
jcowan: Here is an example. It is the AST for (defclass t () (:metaclass built-in-class)): http://metamodular.com/SICL/t-defclass.fasl.
14:00:53
beach
In both cases, I use the character `[' as a reader macro. It takes a name of a class and a bunch of initargs, just like the protocol dictates.
14:01:00
phoe
but all that's just a fancy pretty-printed S-expression with *print-circle* being true
14:03:07
beach
It creates a structure that is entirely isomorphic to the original one that was saved.
14:10:10
phoe
how do you map concrete classes to protocol classes? I assume that GSHARP-BUFFER:BUFFER is a protocol class
14:15:03
_death
for example, (defstruct link parent child) the parent link has to refer to the child
14:15:55
_death
you do need forward references for cyclic graphs.. this is the same issue that CL designers solved in make-load-form by having it return a creation form and an initialization form
14:17:35
phoe
I guess that this is because multiple MAKE-LOAD-FORMs do not necessarily depend on the slots of one another, whereas the above is just one big ball of cyclic references printed as a whole
14:21:38
beach
So when it sees #1#, it sticks in some unique temporary object, and enters the correspondence in a table. Then when the entire expression (in this case a single CONS cell) has been read, the graph is traversed, and the temporary object is replaced by what was returned as #1=.
14:24:11
aeth
jcowan: One use is when *print-circle*. A useless example: https://gitlab.com/snippets/1761668
14:26:04
_death
so while the form looks like it supplies initargs, it's actually patching the slots?
14:26:18
beach
I guess this feature (and its power) is little known, hence the question from jcowan. I think it is fantastic and, like I said, I use it all the time.
14:27:28
beach
_death: In my examples, if it sees :some-initarg #n#, it is replaced by :some-initarg <unique>
14:28:02
beach
_death: Then, if it turns out that :some-initarg stores <unique> in a slot, then it is patched later.
14:28:15
phoe
and I assume that all of this patching is done by the reader on the lists, before any MAKE-INSTANCE is even called
14:28:27
TMA
unless #n# is encountered before #n=, there is no need to patch if you can construct the object in some incomplete state (the state between allocate-instance and initialize-instance)
14:29:29
jackdaniel
had there been instances to be serialized, then the reader macro [ wouldn't make sense
14:29:55
jackdaniel
and there is no need to define a method on make-load-form on simple objects, like 3 or :staff
14:30:04
phoe
this means that READ-DELIMITED-LIST must finish operating before MAKE-INSTANCE is called
14:30:35
phoe
which means that the reading (including the patching!) must be complete before MAKE-INSTANCE is called
14:31:57
jcowan
beach: _death is correct, 2.4.8.16 explicitly forbids forward references with #n#, so no patching is necessary.
14:32:08
Bike
reading a standard-object with circular references in it isn't much different from reading a vector with em
14:32:11
phoe
because #1= must happen before #1# - if the reader stores the EQ references in some sort of read-time hash table, it can then directly look up the object and insert it there
14:33:33
phoe
you can't have an instance before calling MAKE-INSTANCE so there is nothing to insert there.
14:33:53
beach
phoe: First (my-class :stuff #1#) is read, but since we don't know #1#, we replace it with <mumble> and then we call (make-instance 'my-class :stuff <mumble>)
14:34:39
beach
Finally, we traverse the graph, find that some instance of my-class has <mumble> in it.
14:36:46
beach
Like I said, [ is a reader macro that does (apply #'make-instance (read-delimited-list ...))
14:37:35
_death
beach: well, what is <mumble>? if the slot has a :type integer it must be an integer or a special value indicated that the slot is unbound
14:39:13
_death
beach: ok.. an alternative design would be to use the two forms from make-load-form..
14:46:02
beach
For each class, I also have to give pairs :initarg reader corresponding to the protocol that the class respects.
14:49:00
beach
I can have a class with a slot AGE but produce initargs :DATE-OF-BIRTH DATE-OF-BIRTH.
14:52:44
beach
_death: The initarg and the reader are part of the protocol and I want the saved file to create a graph using the protocol. That way, I can change the physical structure between save and load.
14:52:58
_death
I guess READing is dangerous because you don't have that much control over the reader
14:53:17
Bike
you don't have much control over the loader either. i don't understand the debate here
14:53:49
Bike
i mean there's no way to allocate an instance without calling allocate-instance, which can have whatever user methods
14:54:25
beach
Bike: If I don't allow external code to be loaded, how do those method come into existence?
14:54:55
_death
I mean dangerous in that it there are arbitrary limits you can't control when invoking the reader
14:56:30
_death
for example the length and depth of lists, symbol names, magnitudes of numbers, etc.
14:58:15
Bike
you're arguing about which of two standard mechanisms to use and both of thos emechanisms are chock full of hooks to do arbitrary things at arbitrary times, so you have to control what files are being loaded or something. both can deal with circular structures and custom object definitions.
14:58:25
_death
beach: this is unrelated to the make-load-form remarks.. I'm just saying READ is "dangerous" too :).. I did not mean to say that the make-load-form design is better or anything, just tried to understand this format
15:05:02
theseb
What is easiest way to implement *global variables* in a common lisp like implementation I wrote?
15:05:23
theseb
What I mean is....I want to set x in a function and then have value OUTSIDE the function be modified
15:08:51
phoe
alternatively you can make some sort of global hashtable whose keys are symbols and whose values are variable values
15:09:06
beach
theseb: Not that I know how your implementation works. I am just telling you what is usually done.
15:10:13
beach
theseb: The advantage of the symbol slot is that the symbol becomes available to the program at read time, so it is just an indirection to set the value.
15:10:42
beach
theseb: The hash table solution is slower, because you need, well, a hash-table access for each operation.
15:11:00
theseb
phoe: if a global table sets variable x to equal variable y...what do you do next? i'm intrigued
15:13:26
theseb
phoe: i understand all that but how will that help me modify *x* or *y* in a function f?
15:13:52
theseb
Bike: intriguing because slots sounded complicated but variable setting is something i can do and understand
15:14:21
Bike
i don't think any of these implementations of global variables is very complicated. neither is the sicl one
15:14:52
Bike
it does get complicated when you start having local specials and thread locality, but for globals, whatever
15:16:17
beach
I am guessing that theseb doesn't know how to get the symbol into the executable code.
15:16:48
theseb
Bike: to give you context.....the reason this came up is i'm implementing a print function by appending to a global variable called output
15:17:08
beach
But then, it all depends on the implementation, and I suspect it is very different from the way Common Lisp and indeed other languages as well, are implemented.
15:18:22
theseb
errr i could modify it anywhere I wanted but the changes would disappear once I left a scope ;)
15:18:55
Bike
i don't think the context matters. it's pretty simple. you have a persistent hash table and you modify that table
15:19:14
Bike
i have no idea what your language targets or anything. maybe it's not image based. in that case you'd be really far off topic for this channel
15:20:11
beach
theseb: Your questions are essentially about how to implement a programming language. That is really too general for #lisp. If you want to know how to implement Common Lisp, we can help you with that, but it is nearly impossible for us to debug a problem in your own implementation of a language that is not Common Lisp.
15:22:58
theseb
What do you think of this...I'm going to open source a project called "Program To Processor"....you start with a minimal Python variant called Snake and convert to AST...then convert the AST to a minimal intermediate Lisp code...then to a simple virtual processor...All the parts are written in python for easy reading
15:23:26
theseb
So basically the entire stack and all code in all layers will be accessible and understandable in python
15:23:36
Bike
i mean i like lisp better than python, which is why i'm in the lisp channel and not the python channel.
15:24:27
jackdaniel
python with all its arbitrary syntactic rules (and oh my god spaces) is not easy to read, at most it is easy to evangelise as easy to read :)
15:26:16
jackdaniel
I think that this is as far from Common Lisp as one could get having parenthesis involved
15:29:10
beach
theseb: You are asking impossible questions, and you don't understand the recommendations, so it is very frustrating.
15:31:52
theseb
beach: sorry i'm slow....i think i understand why a hashtable is the answer now....if you modify e.g. x=4 in a function those changes will disappear when you leave scope but if x = more complex object like a hash table then changes will survive when you leave scope....is that it?
15:32:43
beach
theseb: x is not a hash table. It is a symbol, and it is used as a key in a hash table.
15:34:50
beach
theseb: My hypothesis is that it is time for you to read about compiler design as opposed to guessing how it might be done.
15:37:12
_death
beach: I wrote a bit of code and I think I understand what happens where/when better now.. e.g., https://plaster.tymoon.eu/view/1946#1946
17:47:25
|3b|
ok, CL(sbcl) should be supported for icfp programminng contest :) if anyone intends to participate with CL, might check https://github.com/icfpcontest2020/dockerfiles/tree/master/dockerfiles/commonlisp and (the pull request on) https://github.com/icfpcontest2020/starterkit-commonlisp for anything you think should be improved