freenode/lisp - IRC Chatlog
Search
13:50:04
beach
phoe: Are you the one in charge of the streaming for ELS? If so, what is the deadline for uploading the talk?
14:01:36
Josh_2
Was wondering if someone could show me an example in real code where they have used it to get a performance increase
14:02:17
lotuseater
Josh_2: this is something which I still don't get ^^ got to know this after reading the Google Common Lisp style guide
14:04:40
Bike
i mean, honestly, there's not much to it. if you make an object and you know it won't escape you can declare it dynamic-extent to hint to the compiler to stack allocate
14:05:01
pjb
the use of the guard cons cell lets you avoid a special case when you have to insert at the before the first element of the list. However, this cons cell is a temporary cons cell that won't be needed once the function returns.
14:05:12
lotuseater
had the thought it could be useful if you loop many times and create each time new data in a DO clause
14:05:24
pjb
Josh_2: therefore it can be declared dynamic-extend and the implementation could allocate it on the stack instead of the heap.
14:06:26
pjb
It's dangerous to write dynamic-extend declarations, because in maintenance, the status of the object could change! It's better to let the compiler determine it itself, without error.
14:08:23
Nilby
I would only use a dynamic-extent declaration where it was demonstrated to make speed critical code faster.
15:24:40
Bike
hm, dunno. it's a bit of an involved question. for a closure the code will be sort of separate from the closure vector, for example
15:25:42
phoe
beach: I am in charge of streaming; I don't know if we have an established deadline, heisig will know that as the programme chair
15:27:32
Bike
i guess you'd do sb-kernel:fun-code-header, and then look at the... there's a "code-size" and a "text-size". couldn't tell you what they are.
15:31:31
nnni
Bike: I am compiling some data into closures. I want to see the differences b/w (data+runtime functions) and closures implementations.
15:32:27
Bike
well, again, closures aren't stored as one thing. if you have multiple closures of the same function, in basically any implementation they'll all share the same code
15:35:26
Bike
generally speaking closures are represented with a simple vector. there will be an entry for each thing closed over.
15:35:58
Nilby
Perhaps a more portable and comprehensive way is to look at (room) differences under controled conditions, e.g. making sure gc is done.
15:36:22
Bike
i don't think i'm explaining this well, sorry. What I mean is that the code - the executable code I mean - is stored separately from the closure data. That's what I meant by the size of the closure versus the size of the function.
15:39:04
Bike
well it sounds like you're not actually interested in the executable size, since that's a fixed cost, unlike the actual closed over data, which every closure instance will have its own copy of
15:39:42
Bike
i'd say the basic guide here is that you can expect (let ((a x) (b y)) (lambda (n) (if n a b))) and (vector a b) to take up rougly the same amount of space, plus the closure has the fixed space of the code
17:07:30
phoe
During this year's ELS, we will be selling prints and hosting an auction of the original of The Y Combinator Codex, a 42cm x 240cm calligraphy piece.
17:07:37
phoe
All proceeds from the auction and print sales made during the two days of ELS (sans printing and shipping costs) will be split evenly and donated to the following organizations, earmarked as money for promotion and development of the respective Lisp languages and their implementations:
17:07:46
phoe
Free Software Foundation (elisp), Clojurists Together (clojure), Common Lisp Foundation (cl), Software Freedom Conservancy (Racket), and ACM SIGPLAN (earmarked as scholarships for the ICFP Scheme Workshop).
17:07:52
phoe
There's photos: https://www.reddit.com/r/LispMemes/comments/l5f4n9/the_y_combinator_codex_but_its_actually/ and a small-res scan: https://cdn.discordapp.com/attachments/532344856731975690/836296248528732170/y-combinator-codex-micro.jpg
19:40:12
pjb
ChoHag: Well, it's not strictly equivalent to scheme RnRS: there's only One CL ANSI Standard to rule them all, One CL ANSI Standard to find them, One CL ANSI Standard to bring them all, and in the darkness bind them. So if you write a conforming CL program in 1996, it will work the same in 2021, and it will work the same in 2046. On the other hand, with scheme, you'd be hard pressed to locate r3rs implementations, and in 2046,
19:40:12
pjb
won't find any working r5rs implementation, so your programs and libraries will be dusk, rotten bits.
19:40:27
pjb
ChoHag: http://informatimago.com/develop/lisp/com/informatimago/small-cl-pgms/wang.html
19:42:01
pjb
ChoHag: said otherwise, my advice is, if you don't plan to finish the program this year, and become a billionaire selling it by next year, if instead you plan to work on your free time for the next few years, perhaps the next few decades, you should better use Common Lisp to avoid having to rewrite it every year (like, eg. swifth programs for iOS that require maintenance only to stay on the AppStore because of new versions of iO
19:43:45
pjb
Great! And this means that you won't have to change the implementation each year, so you can concentrate on making it better. You may also prefer to collaborate with beach on #sicl ?
19:44:41
Xach
I don't think I've ever come across someone unfamiliar with the CL standard who is writing a new language in which to implement CL
19:44:46
ChoHag
I'm not trying to get anyone to change implementations. I want to stop all that sort of shit.
19:47:34
ChoHag
My focus has been mostly on scheme. I've not touched CL for a few years. I want to re-acquaint myself.
19:54:57
pjb
ChoHag: if you write a CL implementation today, it will still be a CL implementation in 20 or 40 years from now. Actually, until the singularity!
19:55:50
pjb
ChoHag: that said, it is allowed to write implementations of a subset of Common Lisp, or superset (extensions) to CL as long as it's clearly documented.
19:56:14
pjb
ChoHag: nothing prevents you to spend the next 40 years improving on your extensions to the CL language in your implementation.
19:59:32
dieggsy
pjb: 'allowed' in what sense? just like, you can still call this CL by the standard's definition ?
20:03:55
pjb
dieggsy: in the sence that as long as the implementation is a conforming CL implementation, a conforming CL program will produce the same results as on any other conforming CL implementation. Ie. the extensions cannot modify the semantics of the base CL language.
20:05:06
pjb
dieggsy: an implementation can easily provide new functionalities in different packages. Eg. clisp provides a ffi in the FFI package, a interface to regex(3) in the REGEXP package, access to screen and keyboard in the SCREEN and KEYBOARD packages, access to LINUX specific operations in the LINUX package, etc.
20:05:47
pjb
dieggsy: furthermore, functions taking &key arguments, may allow additionnal key arguments for extensions. The standard behavior apply when those additionnal key arguments are not provided.
20:06:29
pjb
dieggsy: some extensions in the class hierarchy are possible when mentionned (intermediate classes, or subclasses could be provided). etc. It's all specified in great detail.
20:06:57
pjb
But the important point: to remain a conforming implementation any extension (or subset of the language) must be clearly documented.
20:07:47
pjb
dieggsy: well, it depends. sbcl has its own extensions, but both have problems. The best is to use all the implementations to validate one's conforming code, and to use the implementation best adapted to the deployment case.
20:09:45
pjb
When you want to write portable programs you would avoid those implementation specific extensions anyways, using preferably portability libraries or conforming libraries. Or using #+/#-, you would make use of the extension only when the specific implementation is used.
20:11:24
Nilby
dieggsy: Sadly clisp isn't as neat as it sounds anymore. It has some problems, which likely won't be resolved, and you can have all that in sbcl, and bunch other stuff which make it very fast.
20:12:55
pjb
dieggsy: for example, sbcl lies to you. It says that call-arguments-limit is 4611686018427387903, but when you try to call (apply f l) with a list L containing 100000 elements, it crashes.
20:13:40
dieggsy
when you're applying a function to that many arguments, one might argue it's more an issu of program design?
20:14:10
pjb
clisp has the best encoding support, notably unicode: it knows the name of all the unicode characters. That's not the case with sbcl or ccl they give you useless names such as #\u12345
20:14:48
pjb
All implementations have problem with pathnames: https://github.com/informatimago/check-pathname
20:15:38
pjb
clisp has a report of 72 lines, while sbcl (some old version) had 338 lines of problems!
20:16:40
_death
pjb: I've had trouble compiling it the last time I tried.. some .d compilation errors
20:31:22
jcowan
Call-arguments-limit is mostly important when applying a function rather than invoking one. (apply + list) really be non-portable when the list has more than 50 elements.
20:35:12
_death
since you can query its value, you can use it to portably apply with more than 50 elements on implementations that support it..
20:49:14
jcowan
So how would you write a function to apply an arbitrary number of list elements to an arbitrary (opaque) function?
20:54:50
phoe
and then do a giant gase of (funcall foo), (funcall foo arg1), (funcall foo arg1 arg2), ..., (funcall foo arg1 arg2 ... argn)
20:55:10
Bike
(defun apply (f &rest args) (multiple-value-call (values-list (butlast args)) (values-list (first (last args))))
20:55:52
Bike
sbcl implements apply in terms of multiple-value-call so that it only needs to optimize one kind of vararg thing
20:56:21
jcowan
My point is that (contra what _death appeared to be claiming), there is no waay to write a portable APPLY* that uses APPLY to accept arbitrarily long lists.
20:56:46
Bike
i think _death just meant that you can do (if (> call-arguments-limit (length args)) (apply f args) (error "implementation sucks too hard, sorry!"))
21:01:20
jcowan
that's a first step, but it doesn't really get you there, because you don't know what to do after grouping them.
21:01:50
Nilby
It's like core Lisp is a system of equations where you can solve in terms of the others.
21:03:43
moon-child
don't remember link sadly. The original site is dead now, though it's on the internet archive
21:05:03
pjb
call-arguments-limit is gigantic, and nthcdr doesn't terminate before having counted down the whole count!
21:06:00
pjb
Anyways, the point is that apply is called with lists that have less elements than call-arguments-limit so it should not crash.
21:07:54
_death
pjb: what I mean is, you are concerned about passing call-arguments-limit to nthcdr, so why fix that only at this location instead of defining pjb-nthcdr that you can always use
21:08:22
pjb
Because the beyond nthcdr, the problem is sbcl lying about call-arguments-limit anyways.
21:12:57
pjb
It could indeed be computed from the control-stack-size parameter, but in any case, it better be conservative as you say, because the stack may be almost full already.
21:15:51
_death
anyway, defining such a conservative constant would avoid the special casing and related code
21:16:07
mfiano
Not sure how much this changed in the 3 years since I posted it: https://gist.github.com/mfiano/1a31ef23cdde03e17843e02ffbffa46f
21:20:13
Nilby
I actually appreciate sbcl's optimism. like for (glob "/**"), but it usually fails because fixed heap :(
21:21:00
_death
if checking for nil on each iteration is too slow, it could split it so that it checks every M iterations
22:02:25
gendl__
Hi, in sbcl, how can I set a global parameter so that its value will be inherited by any newly spawned threads?
22:03:27
gendl__
if i just setq it in some application file, then start the webserver, the server threads don't see the value.
22:04:06
gendl__
it's a standard CL symbol -- but I'm allowed to set it to double-float in my application, aren't I?
22:05:02
_death
gendl: that would be a bad idea... a lot of code assumes 1.0 is a single-float, and contains declarations to this end
22:07:29
_death
gendl: what I mean is that it's useful if you, say, READ something yourself.. if you load arbitrary code, it's likely not a good idea to have it bound to anything but single-float
22:18:10
_death
just my experience.. and imagine that some of that code also turns safety off.. evil stuff
22:19:12
jcowan
As a particular case, if you are reading numeric data generated by something other than CL or Fortran, it is advisable to dynamically bind it to double-float.
22:31:11
jcowan
The usual approach is to say that float values are inexact representations of mathematical numbers, but an alternative view is that float values represent exact numbers, but floating point operations are fast but inexact approximations to mathematical truth.
22:33:10
gendl__
on*... as it is now, it pretty much depends on *read-default-float-format* being bound to ‘double-float. Annoying things will start breaking everywhere if that’s not the case.
22:34:27
gendl__
In order to be a good citizen, it sounds like Gendl has to stop doing that and figure out where to strategically do local dynamic binding.
22:35:08
_death
I guess you could add some asdf-specific code to bind it for certain components.. not tried that though
22:36:10
gendl__
It’s going to take a lot of regression testing, So it will have to happen after our May 1 release. Not enough time to risk it before that.
22:44:20
jcowan
dieggsy: Note that CFFI has multiple implementations, conceptually one for each CL implementation.
22:45:23
jcowan
It doesn't directly, except that if there is no CFFI implementation for the CL you are using, you are out of luck.
22:48:11
jcowan
In particular, some features don't work on some implementations, see https://common-lisp.net/project/cffi/manual/cffi-manual.html#Implementation-Support
23:03:30
dieggsy
hmm, i'm looking for something like CHICKEN's foreign-value? e.g. (foreign-value SOME_C_VAR int)
23:10:07
_death
dieggsy: if you M-. on cffi:defcvar, you may arrive at the conclusion that (cffi:mem-ref (cffi:foreign-symbol-pointer "SOME_C_VAR") :int) may work ;)
23:14:00
dieggsy
_death: ah, it doesn't only because what i'm after is actually a macro in a header file, lol. but cheers
23:15:41
phoe
macros disappear after compilation and cffi works on compiled objects; but see what _death said
23:19:29
jcowan
Anyone know why it's called "the groveler"? "Grovel" in the sense "inspect closely" seems to be computer jargon with no obvious connection to its mundane meanings "be prone", "crawl", etc.
23:21:15
_death
jcowan: in the manual it says "grovels through system headers".. so maybe in the sense of "crawl"
23:22:12
_death
dieggsy: you could look at a project that uses it.. here's a simple one https://github.com/death/monotonic-clock
23:23:43
dieggsy
_death: thanks. still getting used to the whole packaging framework. i guess it has to be used with an asdf declaration, not in code like CFFI itself
23:39:37
kagevf
jcowan: I don't think White_Flame left one? but the basic idea was to create a macro that you could wrap around a defun and the macro would set compiler optimizations, etc
23:42:44
kagevf
if you update a macro you have to re-compile every defun that uses it ... something I didn't know and caused me a lot of confusion ... so FYI anybody who didn't know that hehe
23:43:39
pjb
kagevf: that's why project often have macros in a separate file, so that we may write file dependencies in asdf and have things recompiled automatically.
23:44:56
pjb
phoe: it's the opposite: each major implementation has a custom FFI. Therefore there can be a CFFI backend for them.
23:44:59
no-defun-allowed
Whatever happened to White_Flame? He got a macro that made his ears burn...
23:45:23
White_Flame
(defmacro fast-body (&body body) `(locally (declare (optimize (speed 3) (safety 0) (space 0) (compilation-speed 0))) ,@body))
23:45:53
pjb
moon-child: cmucl may still be used, since it has some differentiating characteristics. For example, it can be compiled with 8-bit characters instead of unicode. That may be useful.
23:51:54
drmeister
Is there a way to get a list of all source files in an asdf system from within Common Lisp?
23:52:56
drmeister
I'm writing a report and I'm taking an inventory of the amount of code that we compile into our runtime.
23:53:42
drmeister
So far: 580,000 lines of C++; 236,000 lines of Common Lisp code; 81 ASDF systems.
23:54:10
drmeister
The last one doesn't mean anything to non-CL people - so I'm trying to get an estimate of the number of lines of CL code that come from ASDF systems.
23:56:33
White_Flame
speaking of dynamic-extent from upstream in the logs, is there a legal way to push to a lexical list var while having all the cells be dynamic-extent?
23:58:04
pjb
White_Flame: of course, you can do whatever you want with the cells. That's the danger of dynamic-extend declarations.
23:58:42
pjb
White_Flame: note that the declaration is on the variable holding the value, not the value, while it applies obviously to the allocated values…
0:00:02
pjb
(let ((list '()) (cell '())) (declare (dynamic-extend cell)) (loop repeat 10 do (setf cell (cons 'a list)) (setf list cell)) (prin1 list) (values)) #| (a a a a a a a a a a) |#
0:00:57
pjb
assuming of course, that prin1 doesn't store the list somewhere for later (this would be dragons out of the nose).
0:01:17
kagevf
pjb: wouldn't asdf:load-system recompile any defuns anyway even if they're in the same file as the defmacros they are using? and even if the macros are in a different system, wouldn't that still be the case? if what I just said is wrong, I'd be very interested in knowing, since that might explain some things I've observed and don't fully understand ...
0:21:21
White_Flame
but, (let ((cell (cons ...))) (declare (dynamic-extent cell)) (push cell list)) might do it, it just leaves the scope of the LET which might make it immediately invalid depending on the compiler
0:21:57
White_Flame
which is the weirdness I hit in terms of dynamically consing up stuff on the stack (which may or may not be possible based on the stack discipline of the compiler as well)
1:27:32
pjb
kagevf: in the same file yes, but not in other files, if they don't depend on the file where the macros are defined.
1:30:06
pjb
kagevf: if you modify a system and reload it, this doesn't make asdf reload the systems that depend on it! You need to load a leaf system to have all the dependencies recompiled and reloaded. So if you have N systems in a project, you could define an artifical N+1 bottom system that would depend on all the N system, and that you could reload when you modify any of the N system, to have it and all its dependents be reloaded.
1:33:23
pjb
White_Flame: well, dynamic-extend doesn't imply stack. An implemented could use a separate heap, managed similarly to the old Pascal heap, which is basically a parallel, data stack, instead of a garbage collected heap.
1:34:21
White_Flame
still, my example exits the lexical scope the var is defined in, while it still keeps it alive, be it the process stack or not
1:34:27
pjb
White_Flame: upon entry in a function the function records the size of this dynamic-extend heap; dynamic-extend objects are allocated there (simply incrementing the size of the heap), and when the function returns, it resets the size of the heap to the saved value.
1:36:27
saturn2
my impression was that in sbcl, dynamic-extent doesn't affect setf assignments at all
1:36:42
pjb
White_Flame: and remember all declarations but special declarations can be ignored by the implementation.
1:37:55
saturn2
you have to do some sort of continuation-passing kind of thing if you want to build a dynamic-extent list a little at a time
1:39:39
pjb
saturn2: not needed. Any new object that is stored in the declared variable is dynamic-extend, you say to the compiler. What you do with this object later is not the problem of the compiler anymore. It's your problem. My code is conforming and produce in list, a variable not declared, a list of cons cells that are dynamic-extent.
1:39:59
White_Flame
(now, it doesn't have to, but at least SBCL doesn't include the stack magic to dynamic-extent + tco)
1:40:48
White_Flame
pjb: the stack says that the declaration declares that the values become inaccessible outside the form
1:40:51
pjb
White_Flame: for an object to be dynamic-extend doesn't imply anything!!! It's up to the implementation to allocate it wherever it wants, and to free it sooner than later!
1:41:23
pjb
Which is indeed all that conforming programs need to know: the fuck don't access the fucking objects outside of the form!
1:42:11
pjb
White_Flame: yes, because the implementation can ignore dynamic extent so it is possible that we may!
1:44:49
White_Flame
when I said "expressibility", that is creating the assertions for this situation. The declarations assert things which may or may not be checked or used by the implementation
1:45:34
White_Flame
however, dynamic-extent does say "for each value ... that vari takes on", which is quite broader
1:46:17
White_Flame
especially since data that has a larger extent than the current form might be placed in there, too, without practical issue