freenode/#lisp - IRC Chatlog
Search
19:42:10
anamorphic
Would it make much of a difference at runtime if I had compiled all the ASDF systems my code depended on, along with my own code from one, large, concatenated source file?
20:02:36
jasom
anamorphic: the compiler is allowd to inline functions that are defined in the same source file as they are called in without an inline declaration.
20:04:10
jasom
also when you load a file, it rebinds certain dynamic variables, so it's not 100% the same if you are modifying state at load-time.
20:22:03
anamorphic
So I've been looking at some CFFI-based projects, and sometimes the project will defined a file "reload.lisp" which includes only (define-foreign-library ...) and (use-foreign-library) calls and then in a separate file, the project will have all the CFFI (defcfun ...) forms. Is there a reason for the separate "reload.lisp" file?
20:24:01
Bike
i think so that if you load the project and then save image, it's easy for a restored image to dlopen the thing again.
20:47:28
sjl
anyone know of any tricks to have a standalone .lisp file that can be both executed as a script (via a shebang like #!/usr/local/bin/sbcl --script) and LOADed?
20:48:21
sjl
sbcl --script ignores the shebang, but trying to LOAD the file doesn't, and #! isn't a reader macro by default
20:48:27
Shinmera
It's not really possible unless you define a reader macro beforehand that causes the #! to be ignored
20:48:59
Shinmera
I've tried that sorta shenanigan for a while, and typically just end up making a shell wrapper script instead
20:49:42
pjb
sjl: the trick is to have a reader macro for #! as comment, and to use a feature in the repl, so you don't call the main function of the script. I use #-testing-script (main)
20:50:38
sjl
pjb: Yeah, getting the reader macro is the hard part, because the #! has to be the first two bytes of the file for the shebang to work
20:52:28
sjl
Sure, if you load another file first it's trivial. Or even sbcl --eval "(set-dispatch-macro-character #\# #\! #'read-line)" --load scratch.lisp
20:54:12
pjb
Also, you don't have to use #! on linux and other unices. There are kernel modules to interpret files as scripts depending on other things, such as file name or path.
20:54:51
pjb
But since it requires a custom installation of a module or configuration, you couldn't use it for distributed files.
21:01:56
sjl
Yeah, there's lots of ways to do it. I was just hoping there was some magic trick to get it all self-contained in a single file.
21:02:41
aeth
You wouldn't want that because you want the script to call (main) and you would want the loadable file to leave calling (main) to the user.
21:07:31
aeth
I would personally just use: sbcl --noinform --non-interactive --load foobar.lisp --eval "(foo:main)"
21:08:49
aeth
bash will ignore #| as a comment, then you run sbcl (and this way the path isn't hardcoded to sbcl)
21:09:43
pjb
Yes, you can always write bash scripts that call lisp implementations to run pure lisp files.
21:10:59
pjb
This is what I do from Makefile to generate executable images. as bash scripts: #!/bin/bash \n exec ccl --no-init --load "$0".lisp
21:11:10
aeth
I think you need something like exit or something before the CL part? And then you wouldn't need # |# and can just have |#
21:12:46
sjl
there are twenty different ways I could do it, but I don't think any will satisfy my goals of "single standalone file", "executable on its own", "loadable with LOAD" on its own
21:13:20
sjl
Not a big deal, I was just curious. I usually end up dumping binaries for these kinds of things anyway
21:13:49
pjb
your requirement is loadable with load, not loadable with load in an image that has been prevented to load its rc files.
21:14:02
aeth
sjl: Bilingual sh/lisp where the first part is sh that reloads the file as CL meets the requirement!
21:15:23
pjb
Yes, but "executable on its own" doesn't need a reader macro: it's interpreted by the kernel!
21:16:38
sjl
for the script to be executable on its own, it needs "#!" as the first two bytes in the file, barring any extra kernel extensions and such, right?
21:17:43
sjl
For the file to be LOADable, you need a reader macro that knows to ignore that line. But there's nowhere to *put* that reader macro aside from some other file somewhere, because the #! has to come first.
21:20:10
pjb
If you change the requirements in the middle of the problem solving, then I don't play.
21:21:36
sjl
I thought "standalone file" clearly implied "other files aren't allowed". Anything you could do with a non-rc file you could certainly stuff into an rc file instead, so disallowing only other-files-that-arent-rc-files doesn't make much sense.
21:22:44
sjl
I refuse to use clisp for moral reasons -- they chose a name that confuses the heck out of new lispers.
21:23:45
aeth
sjl: That is if I'm remembering the hack properly. I saw something similar to this once
21:27:12
Shinmera
it's not a feature of any kind, it's just using # as a comment, reloading itself as lisp, then exiting before the |# can be read
21:29:26
pjb
hard coding of things in script is not a problem, if you have a Makefile with an install target to do the hard coding.
21:29:52
sjl
> If the execl() function fails due to an error equivalent to the [ENOEXEC] error, the shell shall execute a command equivalent to having a shell invoked with the command name as its first operand, with any remaining arguments passed to the new shell.
21:35:41
aeth
sjl: idk, as someone who plays around with languages and with bilingual files, this is pretty trivial
21:36:12
aeth
It's imo the Wrong Thing™, though. The right thing is to have a separate, trivial .sh file that runs the .lisp file imo.
21:36:46
sjl
I mean the POSIX behavior of "no shebang -> yolo, just pipe whatever this thing is to a shell" is horrifying
21:37:25
sjl
Lisp's multiline comments and bash's comments happening to use the same # character is just a... "lucky" coincidence
21:37:57
anamorphic
How does roswell's scripting differ with cl-launch? (apart from probably finding systems and stuff)
21:38:29
aeth
sjl: Technically, you could do the reader hack in the CL part and have a #! at the top as well
21:39:15
sjl
aeth: Yeah, but if you "do the reader hack" you need a separate file for the reader macro to go in, and if you're gonna have a separate file you may as well just do this all in a more reasonable way
21:40:02
aeth
Shinmera: That's possible, but now you have to have a different implementation for every CL implementation
21:40:20
aeth
Shinmera: Right now, it's pretty clear what to substitute to make it run in ECL or CCL etc.
21:40:34
aeth
Once you start having to do something other than calling main it might not be as portable
21:40:55
Shinmera
sjl: I mean a combination of aeth's trick with a shebang at the top to make it "standard"
21:44:34
sjl
If you do the reader macro in the sbcl args, you don't need aeth's trick, you just use a shebang of sbcl
21:45:34
Shinmera
no, I mean aeth's trich invocation will include the reader macro in /its/ call to sbcl
21:45:41
jasom
you can do it without the args by using a here document as well; that might be able to be made portable (modulo parsing native namestrings).
21:46:12
aeth
sjl: You still need the block comment trick. The block comment trick is for bash, not for SBCL
21:47:02
aeth
Shinmera: I think what you were saying was to include the reader macro definition in the --eval ? I don't think it would work, though, because isn't that run after the load?
21:47:39
aeth
There might be a way to run something before the load but that's probably implementation-specific
21:48:01
aeth
And it would be messy to have non-trivial Lisp in a bash string in a Lisp block comment
21:49:14
aeth
sjl: but yeah, you basically have to write bilingual files by (ab)using coincidences like the #| coincidence.
21:52:25
jasom
https://gist.github.com/jasom/7a02f6f228dcb469845ff1db86537e85 <-- no --eval needed. More changes would be needed to correct the output of course though.
21:54:16
jasom
that's doable by not having the shebang, but then non-posix compliant shells won't run it
21:56:37
aeth
Thanks to uiop:run-program and uiop:launch-program, CL is your shell. So why would you use any other shell?
23:43:45
emaczen
Does the CFFI groveller parse each include file, find the struct definitions and then write the defcstruct forms?
23:47:40
jasom
emaczen: I think it writes a C program to print out size and offsets, then compiles and runs the C program.
23:50:11
emaczen
jasom: I wrote a tiny program to do what you are saying to find constants and the sizes of structs
23:52:02
jasom
emaczen: it can (non-portably, but usually works) be implemented as #define offsetof(st, m) ((size_t)&(((st *)0)->m))
0:12:52
jasom
cl-autowrap actually parses and extracts types and things but I didn't think the groveller did.
0:13:26
jasom
emaczen: C11 lets you do it, but most programs don't target that version yet so may not work in C11 mode.
0:16:19
jasom
emaczen: especially since many APIs define what fields there are and their types, but not their order.
1:09:02
emaczen
Bike: I don't see how sizeof and offsetof could distinguish between types with the same sizes
1:13:57
|3b|
at least i hope people wouldn't make APIs where something is a float sometimes or an int other times
1:16:07
|3b|
i'd expect most actual changes in struct definition per platform to be things like using different sized ints, assuming just taking native int size wasn't good enough
1:19:40
Bike
for the groveler you can specify the types in a struct. dunno if that's required, it's a &key
1:20:08
|3b|
looks like it does https://github.com/sionescu/iolib/blob/master/src/sockets/grovel.lisp#L89
1:23:20
|3b|
and cffi-grovel includes ctype https://common-lisp.net/project/cffi/manual/html_node/Groveller-Syntax.html
1:35:06
emaczen
Bike: I had written my own groveller minus the C structs a few weeks ago, and I just added the C structs
1:35:58
emaczen
I looked at the types of structure members earlier today when I was manually typing defcstruct and I noticed differences
2:38:16
russellw
what's the shortest way to add an entry to an alist? I mean, you can use a pair of cons calls of course, but is there a shorter form?
2:39:37
no-defun-allowed
(push (cons key value) alist) and (setf alist (acons key value alist)) are common
4:47:32
anamorphic
Is it possible to pass multiple values for a (setf foo) form? Something like this (defun (setf foo) (new-value) (multiple-value-bind (x y) new-value (list x y)))?
4:50:11
emaczen
anamorphic: It is also a good idea to write your own macros for when you wish to further customize what you want
5:02:44
aeth
(setf (foo) (values 1 2 3)) is very useful. it composes well with (setf (foo) (foo)) where (foo) is a function that returns multiple values
5:03:09
aeth
You can also do (setf (values x y z) (values 1 2 3)) which makes me wonder why you can't do that in let, which would make multiple-value-bind unnecessary
5:04:34
|3b|
you could add (function x) to that and get rid of flet, add (special x) and get rid of special declarations too :)
5:07:48
anamorphic
I did some reading... apparently there's a setf* in CLIM that does this for output record x/y position
5:09:15
aeth
Actually, I might get rid of define-destructuring-function, actually. It's just like define-function except the first argument is destructured, so (define-destructuring-function foo ((foobar baz) quux) ...) instead of (define-function foo (list quux) (destructuring-bind (foobar baz) list) ...)
5:09:36
aeth
But the whole prefix thing is an interesting idea, and I could just say (destructuring (foobar baz)) or something
5:12:04
aeth
anamorphic: Oh, and when you mix the multiple-value accessors like (setf (foo quux) (bar baz)) with symbol-macrolet/with-accessors you get (setf foo bar)
5:14:08
fiddlerwoaroof
The nice thing about a lisp is that the community generally doesn't have to accept your preferred syntax
5:18:10
aeth
anamorphic: symbol-macrolet is how with-accessors is (probably) implemented and is necessary if you want to use fancier accessors (such as aref)
5:18:33
beach
One major advantage of Common Lisp is that a serious project can choose the language for a long-term project, knowing that the standard will remain as it is, that the language won't evolve according to the whim of some benevolent dictator who is ignorant both when it comes to programming language design and compiler technology.
5:19:16
beach
... and that there are several implementations, free or commercial according to the needs of the project, that implement that standard.
5:19:46
fiddlerwoaroof
Yeah, I really wish more "modern" languages were implemented as compilers to CL
5:20:20
fiddlerwoaroof
ACL2, Shen, etc. show that this is possible and CL is a much nicer target than C or lower-level stuff, if you don't need performance
5:21:10
fiddlerwoaroof
(that is, if you're not in a domain where you need real-time guarantees, etc.
5:21:15
Jachy
That still wouldn't help much though when the younger languages update and make breaking or incompatible changes...
5:21:44
beach
fiddlerwoaroof: There are very few modern "languages", if by "language" you mean an independently published specification of the syntax and semantics of valid phrases, and the consequences of submitting invalid phrases to the compiler.
5:22:46
jackdaniel
Jachy: if your target language of compilation is CL nothing prevents you from putting different language versions in separate packages of the same image
5:23:32
jackdaniel
in that case you'd be able to have (say) python2 and python3 funcitons interoperate
5:23:38
beach
There are, however, plenty of "programming systems" without any attempt at a detailed specification, and certainly no specification of what will remain unchanged in the future and what might change at arbitrary times in arbitrary ways.
5:23:45
Jachy
(Just ran into that last weekend, some code in hip new lang I wrote from 3 years ago didn't run. The language designers put random() into a module.)
5:24:23
Jachy
jackdaniel: by the same logic I can always run an old VM with the old language version, CL as a target not needed.
5:24:47
jackdaniel
Jachy: that's not the same logic, because you don't have two runtimes in the same image
5:25:20
aeth
CL isn't a suitable compilation target for everything that you'd want to have in a language.
5:25:48
jackdaniel
I don't think CL would make a good compilation target, just commenting on Jachy remark
5:27:37
beach
It would probably be a better idea to generate Cleavir ASTs directly from the source language.
5:28:12
beach
A few new ASTs could be introduced where needed, but the bulk of the translation chain would remain the same.
5:28:54
jackdaniel
aren't Cleavir ASTs a subject of the same "beneloved dictator" syndrome you've mentioned before?
5:29:03
beach
That way, you would automatically get source tracking in the source language, and you would not have to debug your code in terms of Common Lisp target code.
5:29:42
beach
jackdaniel: It is not a language, and I don't pretend it is. It is a compiler framework.
5:31:02
jackdaniel
uhm, then why is it better to compile to AST of a single compiler which is designed for another language than to compile to CL which has numerous implementations?
5:31:46
aeth
You could compile to CL by having a series of extensions that the major implementations accepted. beach is right that debugging would be painful, though.
5:32:16
aeth
Afaik there probably aren't *that* many things that couldn't be added as extensions, it's just that it's a niche no one has really catered to.
5:34:20
jackdaniel
I can't be right because I didn't make any statement, just asked a question out of curiosity
5:35:26
fiddlerwoaroof
Racket has done a lot of work to figure out tracking errors in macro expansion to the source the programmer wrote
5:35:46
jackdaniel
compiling to *some* compiler IR is a common thing (LLVM is a common target for instance)
5:40:13
fiddlerwoaroof
I've been writing a lot of Clojure/Scala/Java for $work and not having to explicitly decode/encode values in ffi is the best part of the JVM
5:40:43
aeth
fiddlerwoaroof: notice that JVM languages with the best interop are written specifically for the JVM, though
5:41:15
fiddlerwoaroof
aeth: there's no reason why clojure couldn't be a library + readtable for ABCL
5:42:26
aeth
symbol case sensitivity and a separate nil from false tend to be noticable interoperability issues with other languages and CL
5:43:01
aeth
CL macros would be pretty hard or impossible to interface with from a CLFFI, especially ones like symbol-macrolet
5:44:02
fiddlerwoaroof
I've been doing a lot of work embedding Apple's Objective-C runtime in CL and a couple well-chosen reader macros make dealing with a case-sensitive language pretty painless
5:45:04
fiddlerwoaroof
_using_ macros from other languages would be tricky, but this is true of most of the "advanced" features of JVM languages.
5:48:43
aeth
I've been thinking about Scheme<->CL and I think the best way to handle CL things defined in Scheme is to assume CL is being written case-insensitively with automatic upcasing and downcase it. So if you define a Scheme CONS from CL, turn it into |cons| because it was probably written as cons and then upcased into CONS.
5:49:40
aeth
Going the other way could be trickier. You could just upcase |foo| into FOO but the Scheme could be written with case-sensitivity in mind.
5:51:24
fiddlerwoaroof
https://bitbucket.org/cowan/r7rs-wg1-infra/src/312606b342ba83fd099cc5719ae71fc9ada1890a/RedEdition.md?fileviewer=file-view-default
5:55:17
Jachy
fiddlerwoaroof: If it's so simple for objectitve-c I'm curious why ABCL and then later JSS lib still use strings to identify java method names...
5:55:29
aeth
e.g. doesn't look like this is a SRFI https://bitbucket.org/cowan/r7rs-wg1-infra/src/312606b342ba83fd099cc5719ae71fc9ada1890a/WG1Ballot8.md?at=default&fileviewer=file-view-default
5:59:48
fiddlerwoaroof
Objective-c does have the advantage that it's designed to be embedded into another language
6:00:42
fiddlerwoaroof
https://github.com/fiddlerwoaroof/objc-lisp-bridge#type-directed-objective-c-extractors
6:01:04
aeth
I could probably do Scheme via a reader macro because once there's a reader you just plug the reader into the reader macro
6:01:20
fiddlerwoaroof
I'm planning to eventually get rid of having to specify the type of each argument