freenode/#lisp - IRC Chatlog
Search
21:20:44
aeth
I mean, I normally do (setf *print-case* :downcase) in the REPL when I'm doing a lot of macroexpand so I can actually read the macros
21:24:20
aeth
vms14: You shouldn't be doing FORMAT *buffer*, though. You really want to only work with streams, and then when you call it, in the caller, do (with-output-to-string (output) (process-html-list list output))
21:25:07
aeth
Even if buffer is more efficient for format, (1) being a special variable instead of a lexical variable is probably going to kill absolutely all of the efficiency gains (and it doesn't even know if it's a buffer or a stream or the symbol nil) and (2) it makes it much harder and less abstract for this particular problem
21:26:57
aeth
You don't want a default value here because you're going to be using it for its side effect, recursively. If you want to add a default value, write a wrapper function where it's optional instead of making it be optional everywhere
21:27:24
aeth
You want to keep things as simple as possible. Nice to have features can be added later.
21:29:08
Shinmera
Phew, me and my two friends finished our Ludum Dare game jam entry just now! Three days to make a game, and of course we used lisp. https://ldjam.com/events/ludum-dare/45/outsider
21:30:51
aeth
vms14: Arrays can be faster, but if you wanted to really use arrays to their full potential you would have to do some really strange things. First, you'd have to give it a maximum size so there's no bounds checking. Second, you'd want to directly write UTF-8 bytes instead of characters to strings. Third, you'd have to use DECLARE on every function. This isn't really worth it unless you need the performance.
21:31:36
aeth
And after all that I'm not sure it would actually be that much faster, since you'd have to use something like babel instead of the implementation's potentially very optimized character writer. It would use less memory, though
21:31:57
vms14
(defun make-text-buffer () (make-array 0 :adjustable t :fill-pointer t :element-type 'character))
21:32:43
aeth
vms14: Anyway, as long as you only use FORMAT, your buffer code should be identical to stream-using code because there's no difference at all (unless you wanted to enforce your choice of using a buffer via a type check or type declaration)
21:33:28
aeth
You might want to check that it's not NIL, though, since format nil will only work as expected on one FORMAT statement.
21:33:52
aeth
(although technically speaking you could do it in one format statement and use ~/foo/ to do your recursion, unless that's disallowed by FORMAT)
21:38:03
aeth
vms14: (defun foo (list &optional (format-destination *standard-output*)) (format format-destination "~A~%" list)) (foo (list 1 2 3))
21:39:01
aeth
vms14: That basic form will give you something that will work with anything that format works with (except NIL as soon as you have more than one FORMAT, so maybe check for that and error) and if the user doesn't provide anything, then it just goes to *standard-output*, which can be rebound locally since it's a special (dynamic) variable
21:41:22
aeth
vms14: The next thing that you should do is that you should change your syntax. (foo :bar 42 "Hello!") is actually really difficult and advanced because you have to parse it to know where the plist ends and the body begins. Try using (foo (:bar 42) "Hello!") instead. This syntax is regular. Then, if you come across a list you can parse it with destructuring-bind.
21:41:48
aeth
vms14: That syntax is then just (destructuring-bind (tag attribute-plist &body body) ...)
21:42:39
aeth
vms14: Then you can handle attributes as their own special case and call them with (process-html-attributes list format-destination) without having to worry about process-html-list having to know at all about attributes
21:44:24
aeth
vms14: If you want to have tiny little functions for everything in parse-html-list, you can use FLET and put them at the top of PROCESS-HTML-LIST and then you don't have to pass format-destination and you don't have to make a global *buffer* because it's creating a closure. So (flet ((start-tag (tag) (format format-destination "<~a" tag)) ...
21:46:06
aeth
vms14: This is what is required to do (title :color red "hi") instead of (title (:color red) "hi) : https://gitlab.com/mbabich/cl-documents/blob/873268445cd2508e59ada0eb651e0c78d42b68d8/write-html.lisp#L26-69
21:47:11
aeth
vms14: That's the wrong thing to think about at this point. At this point you want a direct representation of HTML in s-expressions translated directly to an HTML string (or character buffer)
21:47:28
aeth
vms14: Once it's in s-expressions, you can preprocess it using list processing stuff later on as an earlier stage in your generation
21:48:00
aeth
vms14: the only thing special I do is insert "<!DOCTYPE html>" in front of "<html>" when that tag comes up because it's kind of important not to leave out
21:49:52
aeth
vms14: You are writing a function that writes HTML strings when given HTML in s-expression form, so that's all it should do (I kind of break this rule myself to allow support for some very simple things, but that's mainly because I couldn't find a better way to do it)
21:50:08
aeth
vms14: So you shouldn't be thinking about "so for :color red I should have a class .red and create it if not exists"
21:51:29
aeth
vms14: Yes, but you will probably never finish if you make your functions do too many things at once... if you make them too smart.
21:52:52
aeth
vms14: JS is much harder than the rest, and isn't really critical for the basic task, so you should ignore that for now. And when you do write JS, you should write JS in a direct s-expression representation of JS, rather than trying to do anything fancy, because it's much easier to do fancy things as s-expression->s-expression
21:56:56
aeth
vms14: Anyway, no matter how much you hate the source language and think that it can be improved upon, you can't do that in the function that calls FORMAT because then you'll add too much logic by the time you're done. What you'll want to eventually do is (generate-html (c (b (a your-awesome-language))) buffer)
22:02:05
vms14
the problem is the only way to have a lisp language instead of html+css is making a transpiler
22:04:50
aeth
vms14: Yes, but you were looking at the s-expression problem incorrectly. If you use the syntax (foo (:bar 42) "Hello!") then there are only two cases at the top level. Either it is a list or it is not a list. If it is not a list, then it's in the body and should be an escaped string (to escape stuff like <). If it is in a list, then it has the regular structure (destructuring-bind (tag attribute-plist &body body) item ...)
22:06:05
aeth
In all recursive calls, pass format-destination even though you want to make it a keyword argument and optional for the caller. Then, you don't need *buffer* as a global, since buffer is passed each time
22:07:56
vms14
then how would be your syntax for a lisp language like (title "hi" :color "red" :onclick #'dosomething)
22:10:06
aeth
vms14: That's a separate problem. There, you turn (title "hi" :color "red" :onclick #'dosomething) into (title (:color "red" :onclick "dosomething()") "hi") which is regular and simple and known, and can then be written by the writing function that I described
22:16:47
aeth
vms14: you don't even need to do the writing function if what you really want to do is the fancy part, since the writing function has been done a dozen times before (sometimes with the syntax (:foo :key "value" "body1" "body2") and sometimes with the syntax (:foo (:key "value") "body1" "body2") and sometimes with other syntax, but none of that matters if you're processing it anyway)
22:17:47
aeth
the writing part isn't as easy as it seems because you have to escape <, >, and &, and if in an attribute you also have to escape "
22:35:08
thijso
Shinmera: looks interesting, but it's way past my bedtime here. I'll try to remember to look at it tomorrow. Or remind me...
23:01:13
no-defun-allowed
w.r.t update-instance-for-redefined-class, if I redefine a class A to A', then A' to A'', does the function have to be called twice or can the function "jump" from A to A''?
23:13:35
Bike
"Updating such an instance occurs at an implementation-dependent time, but no later than the next time a slot of that instance is read or written."
6:07:41
yoeljacobsen
Is there a way to see every bound variables in SLDB with SBCL (like CCL's default behavior when entering a frame)?
6:27:00
Shinmera
yoeljacobsen: If they're not there they have been optimised out. You can try compiling your function with debug 3 (C-u C-c C-c) to retain them, but if they're not used at all they still won't show up even then.
6:54:06
nwoob
Not exactly a lisp question but I want to seek some guidance. I am not a smart person, i can't come up to solutions quickly. So what can I do to become a good programmer like people here
6:57:42
nwoob
So it is possible to counted as a good programmer even when a person is not smart to be start with
6:59:25
nwoob
I read all those fairy tales like stuff about lisp that it is magical and will open your mind and all that stuff, maybe I'm looking at it wrong
7:00:43
Shinmera
Lisp offers different perspectives on writing programs. These perspectives can be valuable and useful to building good software.
7:01:24
Shinmera
There's plenty of languages out there that are very different, and each come with their own perspectives. Ideally you learn them all.
7:15:45
beach
nwoob: His research shows that expertise is the result of hard work and not of any sort of intrinsic concept of intelligence.
7:30:35
scymtym
when i install screamer via quicklisp, i get screamer-20190710-git. however, looking at https://github.com/quicklisp/quicklisp-projects/blob/master/projects/screamer/source.txt and https://github.com/nikodemus/screamer , it seems the most recent change was in 2015. does anybody know why that is?
8:06:30
leedleLoo
I recently read richard gabriel's paper here where he distinguishes between languages and systems: https://www.dreamsongs.com/Files/Incommensurability.pdf. Is there other reading making this distinction? When folks have asked why I prefer CL, especially over other lisps, I've always pointed out that the environment exposed through lisp/slime is unparalleled and I feel that the paper kinda touches on this
8:18:21
Lycurgus
u need to set the heap size it won't grow beyond the configed limit, though the hang being a loop is suspect
9:09:12
leedleLoo
beach: I'm not sure which section in the wiki is relevant to the lang vs system distinction
9:12:56
beach
leedleLoo: A language is "just" a (usually infinite) set of phrases. By "system", I assume that Gabriel meant some kind of software.
9:14:04
schweers
As I have no idea what portacle does, I’m afraid I can’t tell you where portacle gets its configuration. Does it start an emacs instance?