freenode/#lisp - IRC Chatlog
Search
20:12:27
aeth
Lycurgus: The question was for a distro without one, though. Also relevant for e.g. people making the binary for the distro
20:14:43
aeth
Hmm... Can Lisp-as-a-.SO greatly reduce memory consumption when more than one Lisp image is running at the same time from that Lisp? Does this exist in practice in e.g. ECL?
20:24:48
stacksmith
aeth: I doubt it makes much of a difference, since most of the memory is used as a GC'd object space, not code.. I can't imagine multiple OS-level instances sharing the same object space...
20:27:27
aeth
I was just thinking that e.g. if you had stumpwm, a CL-based Emacs, and an inferior-lisp (the third is not necessary, unlike in GNU Emacs, but it would still be nice not to crash the editor if you had a serious bug) then that's 3 CLs running at once.
20:31:30
aeth
So we're fine until someone has a CL web browser and a CL terminal and a CL POSIX shell and a CL...
20:33:21
aeth
Actually, though, I think 2-3 is all you need to run simultaneously. CL desktop applications could probably use a common CL daemon sort of like Emacs Server.
20:45:07
PuercoPop
aeth: but then you loose the advantage of being able to communicate by passing CL values around and are back to using serializations like in unix-land
20:49:57
aeth
PuercoPop: You do want at least 2 CLs running no matter what if you're doing development since you can easily crash a CL, e.g. through CFFI stuff. inferior-lisp is a feature, even with a CLemacs.
20:50:10
PuercoPop
aeth: if you have everything in the same image calling the 'editor' would be akin to a function call
20:51:00
jackdaniel
shared objects mostly reduce module duplication (and eventual inconsistency), I don't think they do much to memory consumption
20:51:01
PuercoPop
so for example, the way slime/swank communicate is by passing around s-exps as strings, not as the values in the running image
20:52:19
aeth
PuercoPop: Right, but if developing something in the editor brings down everything from the window manager on up, that's basically the Windows 95/98 experience all over again.
20:54:02
jackdaniel
common lisp has elaborate condition handling facilities, so unless there are hidden issues in the implementation it should be possible to wrap each application in handler-case and *not* bring everything down
20:54:47
jackdaniel
it is like saying that editor may crash kernel and everything goes down. sure, if you manage to segfault linux then you bring down x11
20:59:12
PuercoPop
aeth: I do understand the importance of what you are saying and I agree that it is probably the way to go. I just wanted to note the isolation is not without a cost. Like f/e writing a dmenu clone in Lisp. I would prefer if it could call it from inside StumpWM w/o shelling out
21:00:56
pfdietz
To debug the macro, try using macroexpand on a form that uses the macro: (macroexpand '(when (foo) (bar))) ==> the code with the WHEN macro expanded
21:51:43
dmiles
shka__: oh i see, i thought you were telling me about a list datatype yesterday.. you meant the trail
21:56:18
dmiles
using arrays in the case of a thing that resizes millions of times per operation is funny premature optimization i never understood :P
22:06:01
dmiles
the reason for use of arrays in some prolog impls is that the bindings can be undone by just moving a fill pointer
22:07:17
dmiles
but in the case of undo closures that even have to be ran tun undo/unwind the arrays dont make as much sense
22:07:50
dmiles
but in the case of undo closures that even have to be ran to enact a undo/unwind the arrays dont make sense
22:11:29
dmiles
in 1998 i merged a the OCKB Lisp impl (written in Java) and Tarau's KeneralProlog (and written in Java) .. And found this Zen in making the lisp env and prolog trail work together
22:12:58
dmiles
but it sucks that in real life (not doing this from the backend language) it is not beautifull as it should be
22:15:43
dmiles
if i had help porting CYC back into Lisp (instead of translated Lisp) I'd spend the time wuth jackdaniel's trying to revive ECL's WAM engine
22:18:48
pjb
seok: you could, if you passed an object to render-page, instead of a symbol or a sexp.
22:23:53
pjb
read https://github.com/informatimago/lisp/blob/master/common-lisp/html-generator/html-generators-in-lisp.txt
22:31:10
pjb
Macros are functions that work on programs, not on data. They will take program chunks, such as variable names, or expressions, and generate a new expression from them. And they work during compilation TIME. Data is known at run TIME, and you will have functions working on the data. But this run TIME can occur THOUSANDS of YEARS after the compilation!
22:32:52
pjb
Of course, there may be some confusion here, since data is program and program is data. Of course, the variable name, or the expression are lisp data (symbols, lists, etc). And you can also consider any data as program that a macro can interpret and use to generate the lisp expression. But the problem is that those data will have to be known at compilation TIME (remember THOUSANDS of YEARS before run-TIME).
22:33:17
pjb
So it can work only on universal constants data, or old, historic data. Not on new data processed at run-TIME.
23:49:23
pjb
seok: there's what we call the arrow of time, and it cannot loop back (without a time machine).
23:50:24
pjb
seok: so it cannot be first, and therefore we cannot use the value resuting from this evaluation BEFORE, in the macro.
23:51:43
pjb
seok: now, there are different theories of time. In some case, time machines don't project you just "back in time", but actually will fork a new universe from that time in the past. In a way, it makes a copy of the old universe for you to use now. It's not really time travelling, it's universe copying and forwarding.
23:54:09
pjb
(defmacro double (x) `(list ,x ,x)) (defun compute-value-and-double-it () (eval (list 'double (random 10)))) (compute-value-and-double-it) #| --> (4 4) |#
23:55:04
pjb
Notice that (double (random 10)) #| --> (8 4) |# we cannot send back in time the result of the evaluation of (random 10) (which was 8 the first time). Here the macro expands to (list (random 10) (random 10)) and this is evaluated at run-time.
23:55:46
pjb
so instead we compute (random 10) in compute-value-and-double-it, and use it to build an expression such as (double 3) and call eval to copy the universe and fork out to a new evaluation!
23:57:02
pjb
In this simple case, we could write the macro as (defmacro double (x) (let ((vx (gensym))) `(let ((,vx ,x)) (list ,vx ,vx)))) and use (double (random 10)) but x would still have been bound to (random 10), not to 3 or 5, and when you write such macro, it's a strong hint that you should have written a function (as I already told you a lot!). (defun double (x) (list x x)).
23:57:56
pjb
Now, if you have a (real) time machine, just tell us, and we will interface it with a CL system so you can do what you want!
0:10:49
aeth
pjb: (1) alexandria has some macros to simplify that and (2) I think Common Lisp can run on a real time machine
0:11:59
dialectic
seok: Helpful hint. Only write your program using functions. When you find yourself repeating the same thing over and over, then you can reach for defmacro.
4:04:05
vsync
dialectic: though I find it handy to (partly) write in the language I wish I had... or is that an advanced technique?
4:06:04
vsync
and I would say as well, when you do write macros, write them in terms of functions as much as possible... that tripped me up earlier on when I first got really into macros
4:08:26
vsync
problems I ran into were: 1) doing too much restructuring or especially building of code constructs "inline" in the macro rather than factoring out; 2) having all the generated code be inline even when it could be factored out into a function call
4:09:13
vsync
helps debugging to have my macro call functions to do its work and the generated code sometimes call functions to do its work... and found the resulting code clearer as well
4:09:31
aeth
Basically never write macros. Eventually you'll find some boilerplate that will frustrate you enough that you'll break that rule. Some exceptions could be made for ones that fit established patterns like define-foo, with-foo, and do-foo
4:10:51
aeth
And, yes, if you're writing functions, put most of the generation work into functions or at least LET variable bindings and have the actual quasiquoted macro look like this: `(let ,(generate-bindings foo bar) ,@(pre-body bar baz) ,@body ,@post-body)
4:11:17
vsync
aeth: would you support those constructs being recognized as first-class things with language support, e.g., DEFDEFINER, DEFWITHER?
4:12:19
aeth
A define-define that covers 90% of the cases when you want to make a defun or global defparameter/defvar/defconstant, as well as a define-with that covers the basic with-pattern of unwind-protect, would help a lot
4:12:36
aeth
define-do would be harder since you could base your do-foo on loop, do, tagbody/go, or even higher order functions like map
4:14:16
aeth
vsync: DO is structurally an extremely simple TAGBODY with GO and a LET binding around it
4:15:00
aeth
vsync: You can just use the implicit tagbody in DO and confuse people (and probably tools like Emacs)
4:15:23
aeth
dialectic: people only hate DO because they never use it... you can do amazing things with it
4:15:56
aeth
the thing DO gets you is the ability to MACROEXPAND-1 it and see how it is implemented, and how it is probably implemented with only a few differences in other implementations
4:16:26
dialectic
I am an open minded person. I let DO into my life. DO let me down. I no longer use DO.
4:16:56
dialectic
Any macro which makes me commit to memory a totally arbitrary syntax is a design failure.
4:17:12
aeth
The best DOs are zero-body DOs. If you have a body (that's more than just declarations) you're probably doing something that would be clearer with some other iteration form (or defining your own)
4:18:28
dialectic
A DO that has no body is almost always clearer as a LOOP anyway. And in a loop I have the option of splitting the initialization and iteration.
4:19:14
dialectic
And... I can also throw in arbitrary body forms, interspersed with the iteration code. It is just so much more readable, but I get this is preference.
4:19:35
aeth
dialectic: A DO is only clearer as a LOOP if you don't think that you should use the simplest iteration that accomplishes the task
4:20:19
aeth
LdBeth: map/mapcar is extremely clear... if the thing you're iterating with is a function, like (mapcar #'first list)
4:22:02
aeth
dialectic: the only simple iteration that works fine in DO that I think is clearer in LOOP is something like where you're reading because there you have (foo (read-whatever ...) (read-whatever ...)) vs. :for foo := (read-whatever ...)
4:23:19
aeth
LOOP could give you a deleting unreachable code note/warning if the ":for foo := (read-whatever ...)" is only run once since it's technically generating two things, too.
4:24:29
aeth
dialectic: because I want my editor to highlight it like a keyword, and, as an added benefit, I get a pseudo-Pascal :=
4:25:30
aeth
LOOP is a mini-ALGOL-like language where e.g. "for" is a keyword (in non-Lisp terms) but by making it ":for" it's also a keyword in Lisp terms and is highlighted specially
4:26:41
aeth
dialectic: and besides, the first time I used the LOOP example with keywords, I didn't put "s around it or otherwise distinguish it, but it was immediately clear that the "for" wasn't prose
4:32:45
aeth
LdBeth: I love messing with lots of parentheses, and as much as I've gotten used to LOOP, I don't like that it's :for foo :in bar instead of (:for foo :in bar)
4:41:44
aeth
LdBeth: which is why it would use a plist... it would be mostly loop compatible but order wouldn't matter
4:46:11
aeth
There might be some LOOP forms where it can't be represented as unique keys, though. Not sure.
4:47:00
aeth
The only reason I haven't done this yet is because reimplementing LOOP would be a lot of work, even if I might be able to get away with implementing a lot of it IN loop
4:47:29
aeth
stylewarning: I don't dislike LOOP, I literally just want LOOP with parentheses for more Lispiness, and ITERATE fans pitch it as that, but it's not
4:48:06
aeth
my biggest loops have been implementing numeric algorithms, and the :of-type double-float all over the place doesn't help keep it brief
4:50:21
aeth
stylewarning: that probably counts too since it's the same principle just a different domain (translating massive algorithms)
4:51:30
stylewarning
Lots of loops here https://github.com/rigetti/quilc/blob/master/src/addresser/temporal-addresser.lisp
4:52:24
stylewarning
phat loop here https://github.com/rigetti/quilc/blob/master/src/addresser/astar-rewiring-search.lisp