freenode/#lisp - IRC Chatlog
Search
11:29:50
ggole
"Essentials of Compilation" is also worth a look, it iterates through a series of more interesting compilers, culminating in a Scheme-like thing
11:30:32
ggole
And roughly a million other papers on functional languages have ideas that can profitably be applied to Lisp
11:31:39
no-defun-allowed
Is this the Essentials of Compilation you have in mind? https://jeapostrophe.github.io/courses/2017/spring/406/notes/book.pdf
11:33:24
no-defun-allowed
I don't know much about compilation to a low level target so I'm not sure I'd get most of the papers you suggest too.
11:35:00
no-defun-allowed
The preface to EoC seems to suggest they tried to make it easy to get into.
11:39:12
ggole
I would start by writing a compiler for a (much) simpler language before tackling something like Common Lisp
12:52:42
TheWild
the question is about the detail of Lisp design. Between (xxx ...) and (... xxx ...), the xxx not only differs in meaning but also refers to something else. Is that correct?
13:15:49
TheWild
I suspect I can define in Lisp such a function/macro that doesn't have their arguments immediately evaluated, just takes them straight as if they were quoted, right?
13:21:55
pjb
TheWild: the value and the function slots were different. The question is when did it occur to somebody to conflate them like in Scheme. Was Scheme the first one?
13:24:04
LdBeth
Until it supports function pointer/higher order function stuff it doesn’t really matter
13:26:36
pjb
phoe: Algol report was published in 1958, just like AIM-8. Since AIM-8 is from March, chances are it was first.
13:27:40
Bike
algol lets you reference functions. i don't know if they're "first class" exactly, but you can pass them as arguments.
13:28:18
pjb
http://www.softwarepreservation.org/projects/ALGOL/report/Algol58_preliminary_report_CACM.pdf/
13:29:27
pjb
This reports refers in the past to dates up to June 2, 1958, so it was posterior to AIM-8. LISP was first!
13:30:03
pjb
Now, of course, JMC heard about the works on Algol, and because they refused to include COND, he forked out LISP and beat them.
13:41:00
beach
TheWild: when the arguments are not evaluated until they are needed, we call it "lazy evaluation" or "outermost evaluation", and it is what Haskell is doing.
13:51:28
pjb
Before macros, there were FEXPR and EXPR. You could write in LISP 1.5 special FEXPR functions that would get their arguments un-evaluated, and they would decide at run-time what to do with them. Normal functions were SUBR or FSUBR. see https://pastebin.com/pSgKMGeZ
14:59:43
TheWild
In the context of designing an experimental dialect of Lisp, from time to time I take a peek how Lisp does a thing
15:00:18
TheWild
(lambda (x) x). I suspected that lambda itself cannot be evaluated any further, and indeed it was the case. (eval (lambda (x) x))
15:01:09
Bike
symbols and cons are the only types of objects the evaluator deals with. everything else is just returned as-is.
15:01:41
Bike
because in CL the only thing allowed at the head of a form is a symbol or (lambda ...)
15:02:23
Bike
"If the car of the compound form is not a symbol, then that car must be a lambda expression,"
15:06:40
TheWild
*lambda form n.* a [form] that is a [list] and that has a first element which is a [lambda expression] representing a [function] to be called on [arguments] which are the result of evaluating subsequent elements of the [lambda form].
15:08:06
TheWild
okay, don't get anything from it. I only suspect that it's not yet a phase in which *eval* works, that's why that expression wasn't considered a lambda
15:10:53
Bike
all the bit i quoted said is that the only thing allowed at the head of a form is a symbol or (lambda ...)
17:28:59
skidd0
i'm thinking i should add testing to my codebase. how much pain am I in for having only barely every done testing, and having a significant amount of work already invested into the code?
17:30:54
dim
skidd0: just add a couple test where you miss them the most, that's a good starting point
17:31:34
dim
anytime you edit code and you wonder if you're breaking use cases that used to work before, that's where you miss testing
17:33:05
dim
I mostly do RDD, though sometimes I don't write the readme in a file and just have it in my head
17:33:47
dim
yeah, write the README first, as in how are the users going to benefit from any code you wirte
17:37:15
skidd0
Once i have a readme, i'll probably have a good idea of where to start with testing, too
17:47:06
pfdietz
I think fiveam, and then prove and stefil, are the most popular unit testing packages.
17:47:25
pfdietz
But automated testing includes automated test generation, which is a separate thing.
17:50:34
dim
what's hard for me with testing is choosing what to test in a way that makes the tests a good security to feel free to change the implementation while not adding useless work when changing your mind about some implementation choices
17:51:42
pfdietz
Well, you want to test through the public interface(s), which should be less likely to change. Failing that, test at the major internal interfaces, which also should be somewhat stable. Tiny unit tests of low level functions? Arguably not a good idea.
17:53:26
dim
yeah finding the proper boundaries where tests are going to be a net bonus... I'm not good at that
18:09:02
pjb
skidd0: first you have to decide what level of testing you want to do. https://yandex.com/collections/card/5aedac160265c1e2e48c40d5/
18:10:34
pjb
skidd0: in particular, unit-testing can require internal module knowledge and hooks. If the code is not designed to be tested, this will be the most difficult part to implement. On the other hand, if you do bottom-up programming in lisp, testing subexpressions in the repl, etc, it can be rather easy to just save the testing expression into a unit-test file.
18:11:04
pjb
skidd0: component testing should be rather easy and straighforward, unless you defined crazy APIs.
18:11:19
skidd0
i'm reading On Lisp currently to get a better understanding of the lang and bottom-up
18:11:33
pjb
skidd0: system integration testing may require more resources, since you may have to launch servers, test user interfaces, etc.
18:12:40
pfdietz
When evaluating your tests, coverage information is useful. sbcl lets you compile code with coverage enabled and then see which parts are executed by your tests. Anything not executed has not been tested.
18:13:17
pfdietz
Coverage is not a guarantee the tests are sufficient, but lack of coverage means they probably aren't.
18:14:00
pfdietz
I need to get back to work on my mutation testing framework, which is intended to test tests.
18:14:26
skidd0
so sbcl can be made aware of my testing setup (with a library), then report line coverage?
18:15:05
pfdietz
skidd0: if you explore various quicklisp systems, you will find many are sadly lacking in tests. Some are just dead though.
18:15:52
pfdietz
Line coverage requires support of some kind. In general tests just see if the program does the right thing; the tests have no hooks into the source code to do coverage themselves.
18:17:09
pfdietz
sbcl just lets your find out what parts of a program have been executed, line (or branch) by line. It doesn't care whether that execution was in a "test framework".
18:17:49
pfdietz
There's also a public domain implementation-independent coverage package, COVER (in quicklisp now). It has some drawbacks, though.
18:18:34
pjb
And yes, one difficulty with coverage, is to also test it with all implementations and combinations of features, so you're sure you've covered all #+/#- cases.
18:22:51
pjb
in that case you can #-your-implementation (error "~S not implemented yet for ~A" 'name-of-function (lisp-implementation-type))
18:40:54
skidd0
so for testing, i'd want to create a test/ dir with my tests that pulls in my library, and keep the library in it's own src/, right?
18:50:03
pjb
So I can (asdf:oos 'asdf:test-op :<system>) and it will compile and load the <system>.test and run the forms defined in it to run the test.
20:48:36
pjb
anamorphic: (define-condition example-condition (error) ()) #| --> example-condition |# (make-condition 'example-condition) #| --> #<example-condition #x30227DDBE9ED> |# (princ-to-string (make-condition 'example-condition)) #| --> "Error #<example-condition #x30227DE5E9CD>" |#
20:49:12
pjb
anamorphic: some conditions have a format-string and format-argument that they format when asked to be printed, like simple-error.
20:58:35
anamorphic
I see. Similarly for restarts, does one just princ them too and hope for something that makes sense to the user?
22:37:43
Bike
"If multiple iteration clauses are used to control iteration, variable initialization and stepping[1] occur sequentially by default. The and construct can be used to connect two or more iteration clauses when sequential binding and stepping[1] are not necessary. The iteration behavior of clauses joined by and is analogous to the behavior of the macro do with respect to do*. "
22:39:14
dim
I think my fav example of that are the following examples: (loop repeat 10 for a = 1 then b for b = 1 then (+ a b) collect a) and then (loop repeat 10 for a = 1 then b and b = 1 then (+ a b) collect a)
22:40:42
makomo
can anyone else try to indent the top-level form corresponding to this ONCE-ONLY definition https://gitlab.common-lisp.net/alexandria/alexandria/blob/master/macros.lisp#L58 and tell me if anything changes
22:41:13
makomo
and more specifically, regarding its behavior when indenting operators (MAPCAR in this case) that are unquoted
22:41:59
makomo
the 2nd and 3rd arguments to the MAPCAR on line 58 get shifted to the left, under "MAPCAR"
22:44:28
dim
I pushed a clean-up patch to the PR already, and now I'm seeing more that the github UI did hide from me before
22:45:13
dim
the (format nil (sql "some/file/in/the/source/tree/foo.sql") param param param ...) is my poor man's attempt at cl-yesql, because at the time it wasn't ready for this
22:46:41
phoe
sure - formatting queries this way is good as long as you don't care about SQL injections
22:47:05
phoe
and I think if you're doing pgloader, you usually trust your input and output and the pgloader itself.
22:47:07
dim
maybe I could introduce named arguments or stop relying so much on the format string facilities in my SQL templates and use something else instead, but I'm not sure about that
22:47:55
dim
SQL injection on Postgres with postmodern is a non issue, because it uses the parse/bind/execute query protocol
22:48:27
phoe
yes, but here we're creating raw SQL strings with FORMAT - normally that would be an issue
22:48:31
dim
you can't fool Postgres around with some parameters suddenly being interpreted as SQL statement when using parse/bind/execute, becase at PARSE time Postgres didn't receive the parameters yet
22:49:09
phoe
dim: or just create a macro-wrapper around DEFUN and FORMAT, something like (define-query-generator my-query (foo bar baz) "SELECT ~A FROM ~A JOIN ~A" foo bar baz)
22:49:10
dim
I went on with my usual answer without thinking about the exact use case I have under my eyes, not good :/
22:49:30
phoe
this would be a dumb way to create something like (defun my-query (foo bar baz) (format nil "
22:50:08
phoe
it's possible to write a poor man's yesql that uses flat files and FORMAT to create SQL strings
22:51:54
dim
I'm just thinking of doing (defun sql (url &rest args) (apply #'format nil (gethash url *fs*) args)) now
22:53:12
phoe
or use asdf:system-relative-pathname inside the function - I think you already do that
22:55:24
dim
I've been using a hash-table as a proxy for that, the key being an absolute pathname, here for the SQL queries it looks like (sql "/mysql/list-all-columns.sql")
22:55:56
dim
works well enough for my taste; I did that first with static assets for a website that ends up all being into the image, that's a nice delivery then
22:56:48
dim
Xach: https://github.com/dimitri/pgcharts/blob/master/src/resources.lisp might be useful for you then
22:58:55
Xach
still, for functions not directly under your control that expect to work with files/pathnames, would be fun to bundle files along with the image somehow.
22:59:10
dim
the derivative in pgloader is at https://github.com/dimitri/pgloader/blob/master/src/utils/queries.lisp ; same idea, different taste, specialized in load .sql files from the source tree
23:00:17
dim
well then you need to hack things more seriously so that open/close/file-position and many other things just work on top of your image based file system, right?
23:01:12
dim
maybe you can do a logicial pathname translation unit (or something, can't remember the proper terminology) and make it happen that way? I think pjb has implemented something AGPL for that