freenode/#lisp - IRC Chatlog
Search
7:10:57
beach
scymtym: For Second Climacs, I want the reader to return parse-results, or as I call them in Second Climacs "wad"s. A wad is a nested data structure that contains source positions corresponding to the start and the end of the thing that was read, and also a list of children, which are also wads. And the children are represented as a list of wads in the order that they were read.
7:13:29
beach
2. Add the possibility for Eclector to return wads, just the way it can now return CSTs.
7:14:13
beach
The thing is complicated by the fact that in Second Climacs I ultimately want CSTs as well.
7:15:03
beach
So then, for solution 1 I can convert wads to CSTs. Just drop the non-expressions and apply a similar technique that Eclector itself uses to construct a CST from a bunch of children.
7:16:33
beach
2.2 Use solution 2, and factor the code so that there is no duplication, i.e. build the CSTs from the wads.
7:19:07
beach
The thing is complicated by the fact that, for Second Climacs, I want to make the parser incremental. I guess I need to think about the interaction between the cache manager and the reader. It is entirely possible that it can not be turned incremental with solution 2.
7:20:30
phoe
beach: for an incomplete expression, is it possible that you return a "special" wad at the end of each list of children that is used as a mark that this expression is incomplete?
7:21:10
phoe
I imagine that for an incomplete expression "(1 2 3" it could be a list resembling (#<WAD 1> #<WAD 2> #<WAD 3> #<EOF-WAD>) or something similar.
7:21:34
phoe
If a list contains an EOF-WAD, then the expression is incomplete, but you can nonetheless return the parse result.
7:22:02
phoe
And if you can return a parse result, then you should be able to make your parser incremental nonetheless.
7:25:39
beach
The reason I am asking all this is that such a wad reader could be useful in situations other than Second Climacs, and if so, it ought to be in a separate system.
7:45:36
beach
I see. Well, PARSE-RESULT turned out to be too long, so I had to choose something shorter.
10:56:26
scymtym
beach: i will have to think about this more, but i have an initial impression. i mentioned before that i would like to turn the eclector-concrete-syntax-tree code into two parts: 1) a protocol for constructing parse results 2) a client of that protocol that constructs CSTs. my impression is that such a protocol (modulo omissions that become apparent when it is used) would be sufficient for the three clients i am aware of: 1) the CST
15:10:38
Ukari
is there any consensus or principle about function api design? There are two ways and which is better ? multiple returned values, or (list (cons :key1 xx) (cons :key2 xx) (cons: key3 xx))
15:11:24
White_Flame
now, if those keys are optional, then you might want to return that and descructure
15:22:37
jackdaniel
if function returns multiple values use multiple values, that way you don't cons unnecessarily
15:26:53
Bike
this isn't even more efficient, you cons up three closures, whereas you only need zero closures
15:27:55
jackdaniel
well, in your situation (if you really need these lambdas inside), just do (defun hash () (let (storage) (values #'(…) #'(…) #'(…))))
15:28:23
Xof
I am having difficulty building an implementation of case using a jump table without consing at runtime (and, worse, doing O(n) initialization at runtime). I wonder if I'm missing something or if that is indeed the best I can do
15:29:05
Ukari
in values #'(...)... way, if i want to call :set or :get, the code need to provide a exact position
15:29:59
jackdaniel
Ukari: whenever you remember that first is init, second is set and third is get, or that you remember that there is assoc :init, assoc :set and assoc :get still makes you remember *things* as a programmer
15:31:09
Ukari
jackdaniel, but if i need to add another :setFoo, i must add it to the last position or it will mess up the code before
15:31:50
jackdaniel
Ukari: for me thsi programming style is unreadable anyway, when I want functions I define them with names and provide argument to them
15:31:59
Bike
i mean, an "actual" jump table is like having a GO special operator that evaluates its argument
15:32:24
Xof
the good news is that means I can forget about my case-using-perfect-hashes, at least for now, and move on to find-restart-using-perfect-hashes
15:33:00
jackdaniel
Ukari: eventually (if I really must) I can always define dynamic variable and create dynamic context for these functiosn with let, that way I have only one thing to carry in the application instead of n functions
15:33:48
jackdaniel
Ukari: I admit that these advices are very opinionated, but you have asked about opinions ;)
15:34:54
Ukari
show me the example about `define dynamic variable and create dynamic context for these functiosn with let`, it sounds interesting
15:37:09
jackdaniel
(defvar *foo*) (defun init () (setf *foo* (make-hash-table))) (defun ukari-get () (gethash …)) (ukari-set () (setf (gethash …)))
15:37:53
jackdaniel
in body of this let form *foo* is bound to nil, outside this let form *foo* is not bound at all
15:43:33
jackdaniel
we could go on with improving your hack, but readable solution is to have argument to your set/get functions
15:44:05
pjb
Ukari: I would distinguish inner-loop functions from public API functions. The later, notably if they're intended to be invoked from the REPL, as commands, can have all kinds of sophisticated argument parsing, including &key and others (eg. catching additionnal arguments or list of arguments after the last &key, which is not parsed by default). But for internal functions, it may be better to use more plain lambda-lists, with only
15:44:25
jackdaniel
having dynamic context, or even worse – floating anonymous functions, makes your program hard to analyze
15:44:40
pjb
Ukari: and for results, multiple-values are probably the fastest way to return multiple values, even if you put a lot of NILs there for optional results.