freenode/#lisp - IRC Chatlog
Search
11:33:02
jack_rabbit
can someone describe the mechanism by which setf is allowed to be a function with a list name?
11:34:48
jack_rabbit
It's a special case, and implementations are free to define other setf-like functions.
11:36:27
jack_rabbit
Or I guess, given that description, implementations can even define weirder name structures.
14:09:05
phoe
the standard is clear, it's either FOO or (SETF FOO), and the implementations are not allowed to extend it in a portable way
14:54:44
Shinmera
It's not very often that being able to specify the other parts in the resulting list is useful, but it has come in handy at times.
14:56:28
|3b|
ACTION probably should have used something with identity, since a could have 2,3 already too
14:57:51
Shinmera
A specific instance is: for textures you can specify a wrapping, both in x and y. (enlist wrapping wrapping) means that if it's a single keyword, it goes for both x and y.
14:59:04
Shinmera
Another example: when binding the matrix stack locally you can specify which matrices to bind, and how (copy, zero, identity). So (enlist matrix :copy) means the default behaviour is to copy, but if you want to specify further you can do that too.
15:00:13
Shinmera
With things like LOOP where the destructuring that is available is rather poor, this sort of thing is handy though.
15:01:24
|3b|
and most of the things i can think of that would fix my perception of oddness would probably make it verbose enough to no longer be as useful
15:03:08
jackdaniel
I'm not sure if putting so much meaning into lists stored in variables is a good idea either, but it's only an opinion
15:12:31
AeroNotix
oh man, I've been writing lisp on and off for years but never thought to see if that :upcase/:downcase behaviour could be changed. QOL improvement for sure
15:30:29
phoe
Printing a specialized vector of (unsigned-byte 8) gives me #(0 1 2 3) which, when read, is a simple-vector.
15:31:11
pjb
(format t "#.(make-array '~S :element-type '~S :initial-contents '~S)" (array-dimensions a) (array-element-type a) (convert-to-sequence a))
15:33:53
pjb
May not work depending on how the implementation prints the types and how it takes it for coerce.
15:34:53
Bike
phoe: if you use *print-readably* the implementation might figure something out. ECL uses a special form of #a and sbcl adopted that, iirc.
15:47:11
phoe
" In general, however, you can put a value in *print-pprint-dispatch* that makes pretty-printed output look exactly like non-pretty-printed output."
15:49:04
phoe
Inside some dynamic environment, I want to print all non-string vectors as #.(MAKE-ARRAY ... :ELEMENT-TYPE ... :INITIAL-CONTENTS ...) - I guessed that I can do this by hacking the pretty-printer dispatch table and feeding it a function that prints them like this.
15:49:40
phoe
But this means that everything else will be pretty-printed, which is not readable. So I want to tell the pretty-printer dispatch table to print everything in a not-pretty way.
15:54:39
pjb
I consider print and print-object only for debugging purposes. Not for enterprisy serialization.
15:57:36
|3b|
could put a function in pprint-dispatch that just rebind print-pretty to nil and prints again, but don't see any way to get an empty dispatch table or enumerate the contents to be sure you replaced everything in it
15:59:58
|3b|
(possibly with something to detect loops, in case some print-object tries to pprint things)
17:22:33
tfb
it signals en eof error *regardless of eof-error-p* if you hit the end of file while (say) reading a string or list
17:23:24
beach
tfb: That part I understand. But then it seems to require eof-error-p to be non-nil for this situation to be detected.
17:23:27
whoman
i really think it would be better if the hyperspec was more CODE. (same with legal documents)
17:26:29
beach
I think I know how to implement it, but I can't figure out why they say that eof-error-p is non-nil.
17:30:52
tfb
My guess is that if recursive-p is true then you need to signal regardless of eof-error-p since you are in the middle of reading something
17:31:03
random-nick
maybe that means the recursive calls to read when encountering something like ( have recursive-p and eof-error-p non-nil so that the toplevel call to read gets the error
17:32:44
tfb
whoman: but specifications written in some logical formalism are insanely hard to understand (for me)
17:32:52
whoman
well it could be. but i think the CLHS could benefit from some more mathematical/logical descriptions. beyond the useless syntax graphics.
17:32:57
random-nick
I think "This" refers to "if a file does not contain enough right parentheses to balance the left parentheses in it"
17:34:04
beach
random-nick: Yes, when READ is called recursively, it should be called with that flag being true.
17:34:24
whoman
there is a project (forgetting the name, again) which implements CL in an implementation-independant way. like a reference, i guess
17:35:25
jasom
e.g. it's loop implementation will not work unless you have first-class global environments
17:37:15
beach
whoman: Is SICL the project you are thinking of? There is an older project (abandoned I think) that did something simpler than what SICL is attempting.
17:37:30
jasom
"2016-05-30 22:09:47 beach jasom: Currently, in order to use SICL LOOP, you need first-class global environments to avoid the package lock."
17:39:41
beach
I think I did it so that you can create a sicl-loop package and not define the macro itself. That way, you can define package:loop to call the support functions.
17:40:09
jasom
If I wanted to use sicl in a lisp bootstrapped by sbcl, how would I go about doing so?
17:42:00
beach
The SICL Loop macro is very small https://github.com/robert-strandh/SICL/blob/master/Code/Loop/loop-defmacro.lisp
17:42:27
beach
So if you just omit it and define your own replacement in the package of your choice, you can use the full SICL LOOP.
17:43:18
jasom
that makes sense. The implementation I was planning on using it from (jscl) has since gotten loop via a port from Symbolics's implementation
17:43:37
beach
But I fully admit that I still have to come up with a configuration of one or more ASDF system definitions that will work both natively, and when someone wants to try the system in some other implementation without tripping the package lock.
17:45:48
specbot
The RECURSIVE-P argument: http://www.lispworks.com/reference/HyperSpec/Body/23_acb.htm
17:46:35
|3b|
beach: looks like "this" is the specific condition of eof in the middle of an object rather than eof in general
17:47:01
beach
jasom: Most of the code is there, but I am making slow progress on the bootstrapping part.
17:48:04
jasom
beach: so it's not quite at the point where I can make an hir-to-target translator and push a button to bootstrap?
17:48:52
beach
jasom: Well, not quite true. If all you want is a file compiler, then everything is in place.
17:49:41
jasom
beach: that *might* be sufficient for what I'm looking for; but isn't a runtime needed?
18:32:34
jmercouris
I have this for example: (setf (gethash "RETURN" *character-conversion-table*) (char-code #\Return))
18:33:46
jmercouris
okay, so will name-char "Escape" return different values on different implementations?
18:35:48
jmercouris
so, will (char-code #\Return) return a different value in a unicode vs ascii based implementation?
18:41:11
jasom
it started out as an encoding, but they abandoned that once it was clear that the 2**16 wasn't nearly enough
18:42:21
jasom
jmercouris: (char-code #\Return) can return any number whatsoever and still be conforming. In practice all modern implementations will return the unicode code-point
18:43:02
jasom
and the first unicode code-points are identical to iso-8859-1 which is a superset of ascii
18:43:02
jmercouris
when the day comes that a random implementation changes that I'll put a +sbcl :D
18:49:51
shrdlu68
Given all this, how would one collect a range of characters. For example if I wanted #\a to #\z, would
18:51:48
jasom
shrdlu68: actually not; the spec only defines that #\z > #\a , not that there are exactly 26 characters in the range #\a - #\z
18:53:30
sjl
e.g. a Lisp made by an Icelandic person might have (= (char-code #\Ă°) (char-code #\d))
18:54:34
Bike
a lisp made by an icelandic person who hates their language and just collapses all the funny characters to english ones
19:47:54
AeroNotix
I personally am not happy with how browsers currently work and lispki/next scratch that itch
21:08:35
emaczen
How much of a speedup can I expect with SBCL if I declaim and declare my functions/methods
21:09:32
jasom
emaczen: generic function calls are not significantly affected by declarations in sbcl, since you are free to add methods at any time
21:11:14
emaczen
I understand that, but I'm pretty content with the relationships amongst my classes -- I would have to rewrite it all without CLOS to get it to be fast??
21:14:00
Bike
you want general advice for optimizing unknown programs? profile and see if you can think of a smarter algorithm for the slow parts
21:14:35
jasom
a non-generic inlined function with an etypecase that calls the actual implementations is *significantly* faster on sbcl than GF dispatch, so if you have small functions, you will be held back by GF dispatch (but as Bike says, profile first, then optimize)
21:22:59
jasom
self% what fraction of samples were in this one; cumul% what fraction of samples were in this one, or ones above it; total% what fraction of samples were either in this one, or this one was on the call-stack
21:29:00
Bike
this is why i said, find better algorithms, rather than doing stuff like declaring types
21:30:46
pjb
Fastest way to remove elements from a list, is not to add them there in the first place.
21:31:15
Bike
pjb, could you please just say what you mean outright rather than waiting for a confused "are you serious" so you can pontificate
21:36:46
aeth
emaczen: At least ime, it's rarely worth doing type declarations if it's not a sequence or a number.
21:37:30
aeth
Sequences can make a huge difference, especially if the type information you give is a known length rather than * length
21:38:27
aeth
(This is SBCL, other implementations might be further behind, but they'll probably catch up eventually.)
21:39:32
aeth
But that's because sequences and arithmetic functions are a special kind of non-CLOS generic function, where type information is very useful.
21:40:33
pjb
flip214: basically, you would have to duplicate the solar system, move the duplicate 3 years behind (about 25,000 light years behind). Then when you want to go back in time, you would have to travel those 25,000 light years very fast…
21:41:06
flip214
pjb: as light has nearly no width, I can fold it up into a hilbert-curve, so I can easily store 3 light years in a container of, say, 2x2x2 mÂł.
21:41:52
pjb
Sorry, I meant 75,000 light years above. It's incredible, but we're travelling at a speed of 24,194.16 light years each year!
21:43:36
jasom
diffraction effects happen at multiples of the wavelength, and the wavelength of even visible light is on the order of a micron
21:44:52
pjb
Now, it's possible that the orbit of the planets doesn't change plane when we circle around the galaxy center, so the direction depends on the time of the galactic year. I would assume.
21:45:00
jasom
flip214: did you read what that calculation does? It calculates the width of a fluid flowing at a hight of 1 inch, a flow-rate of 8L/min and linear velocity of c
21:46:42
aeth
emaczen: I think the main thing you get from type declarations for most types is type checking at the beginning of the function (in SBCL, actually before the beginning), instead of when you call a function that expects a different type at some point in the middle of the function, e.g. this will prevent "Hello, world!" from showing up: (defun foobar (x) (declare (list x)) (format t "Hello, world!~%") (car x)) (foobar 1)
21:47:47
aeth
(In SBCL the difference with a check-type at the top of a function is that check-type is slightly less efficient, but lets you recover by providing a valid value at runtime)
21:50:50
aeth
emaczen: If you inline things all of the way, with an eventual etypecase or typecase, you will probably see SBCL remove the branches that won't happen (i.e. the other types) automatically. An alternative would be https://github.com/markcox80/specialization-store/ for inline type-based dispatch or https://github.com/guicho271828/inlined-generic-function/ for inline CLOS dispatch
21:51:48
pjb
flip214: there's no sense in giving astronomical distances in other units than light.year. Expressing speeds in light.year/s is also way more meaningful than keeping m/s.
21:53:07
pjb
Actually, even short distances are better expressed relative to light. Eg. your leg is about 3 ns.light long. Way more informative than saying that it's about one yard long.
21:53:33
flip214
pjb: but using the galaxy as zero point is very galacti-centric again. same mistake as, eg., Kopernikus.
21:53:59
pjb
6 ns.light from your feet to your brains means that you cannot feel anything fromr your feet but 6 ns too late.
21:54:23
flip214
pjb: well, within the solar system AE is a nice measure, too. in my youth the parsec was en vogue, but that's changed to light years, yeah.
21:55:47
flip214
pjb: well, you keep your initial system, and I'll use mine. currently I'm at rest, it's nearly 11pm ;)
21:55:58
pjb
Notice also that when parsecs are used, they mostly don't know the radial distances and speed in general. It's a nice unit, but so limited…
21:56:50
pjb
If you want to take it into account, the speed of the Milky Way relative to the Local Group is about 600 km/s.
21:57:11
flip214
what? 1 parsec is defined via the AE, no need for other radial distances or speeds. 1 parsec = 3.262 ly
21:59:05
flip214
pjb: yeah, exactly. but the triangle is defined via the angle 1" and the opposite length of 1 AE.
22:00:16
pjb
For example, sending a modulated laser beam thru space to a reflector. So when you need an old value, you can read it back frmo the beam.
22:00:40
aeth
The #1 performance improvement I can normally get is by preallocating before loops rather than heavily consing during the loops.
22:00:55
rjmacready
is there any common lisp implemented in a common lisp based on the special forms alone? http://www.lispworks.com/documentation/HyperSpec/Body/03_ababa.htm
22:01:02
aeth
e.g. allocating 4 vectors that are constantly overwritten each iteration rather than allocating 4 new vectors each iteration
22:01:22
jasom
rjmacready: that's not possible; how do you implement "print" only in terms of special forms?
22:01:33
pjb
rjmacready: not really. First special operators are not all the primitives of a CL system. Some functions are primitive too!
22:02:07
pjb
rjmacready: otherwise you may have a look at cl-stepper, which redefines special operators as macros to implement a stepper.
22:03:17
rjmacready
jasom: yeah i was looking at that and wondered there was some special form only based implementation
22:04:19
aeth
rjmacready: You can probably implement CL without CLOS and without most of loop. Some of loop really is just too convenient for macros, especially collect but sometimes also append. (Most of loop has alternatives, those don't really.)
22:04:58
jasom
implementing collect and append is fairly easy, you just need to keep track of your tail pointer
22:05:04
aeth
So I just picked two of the easiest complicated parts of the language to remove, and then said you can't remove them. :-p
22:06:59
aeth
jasom: I guess my point is that most of the common useful parts of loop have direct equivalents in dofoo or higher order functions, but not collect and append, you'd essentially have to write something lower-level in do
22:07:09
rjmacready
had this silly idea of plugging an empty executable as inferior lisp to slime and checking what would arrive there
22:07:20
emaczen
I really do need to go back and look through my code, usually I am not too concerned about speed
22:07:21
pjb
Also, the usefulness of most of special operators to implement a language is rather dubious. eg. THE is useless.
22:08:13
Bike
there's also a question of how you're like, implementing this. sbcl and sicl and stuff work on a principle of having an existing lisp just dump compiled files, so it's not like you're bootstrapping up from some limited set of operators
22:08:32
pjb
It can be implemented conformingly as (defmacro the (type expression) (declare (ignore type)) expression)
22:08:39
aeth
pjb: Determine the return type of a function in a compilation unit, and be as specific as possible. Wrap calls to it within that compilation unit with a the (assuming sbcl semantics, which type-checks and uses truly-the for real assumptions)
22:11:36
aeth
(I actually suspect SBCL binaries could be made much more efficient if everything's moved into one compilation unit as the final compilation process, to keep literally all of the program's type information and really put all that inference to work)
22:16:18
aeth
Bike: I suspect the main use for a very restricted Lisp to implement Lisp would be to build something that's useful for building a richer, probably better written Lisp.
22:20:11
aeth
Can you use SBCL to cross-compile SBCL to other architectures? e.g. new architectures?
22:21:01
pjb
The only usefulness in a restricted lisp, would be either you time travel to 1958, or you get lost light years from Earth without a CL implementation.
22:21:40
aeth
I *guess* a restricted Lisp might be more secure, but then you'd probably just want to write a VM and use bytecode, not a subset of Lisp.
22:21:41
pjb
In all other cases, you can get access to a CL implementation faster, and use it to implement faster and easier your new CL.
22:29:00
aeth
I've skimmed through the Lisp Machine Manuals and they're very similar to the HyperSpec
22:31:54
Shinmera
https://en.wikipedia.org/wiki/Kyoto_Common_Lisp "KCL is notable in that it was implemented from scratch, outside of the standard committee, solely on the basis of the specification. It was one of the first Common Lisp implementations ever, and exposed a number of holes and mistakes in the specification that had gone unnoticed."
22:34:48
Bike
well, beach's method has proven to be pretty performant and is conceptually pretty simple, so you could do that.
22:37:21
aeth
White_Flame: I'd assume that the main thing that would matter for the runtime performance of CLOS is dispatch
22:38:13
Bike
the rest of clos is basically just data structures, and some functions you ahve to call sometimes
22:39:02
White_Flame
well, there's also instantiation & registration, updating classes, etc, that can have their own performance impact
22:39:29
aeth
If CLOS generics were as performant when the class is known as the generic functions for arithmetics and sequences are when the types are known, that would completely change how people write fast CL. Although type-dispatch would still be necessary for numbers and sequences a lot of the time.
22:40:07
aeth
Would it be possible to just JIT the dispatch in an otherwise AOT implementation? JIT has big drawbacks, too.
22:41:24
White_Flame
and so because it's a single centralized dispatch function, it can't take advantage of call-site knowledge
22:42:05
aeth
I wonder how hard it would be to unify type dispatch (e.g. specialization-store) and class dispatch. If that's even possible.
22:42:47
aeth
What I like about what specialization-store does with types is... it produces the exact same thing that I'd produce by hand. Except automatically.
22:42:47
Bike
they're the same concept, it's just that clos allows things to be redefined, inhibiting static analysis
22:43:53
White_Flame
yeah, it'd be nice if you could say "bake these things in" at some point, and "unbake back to dynamic, I want to change things"
22:44:28
Bike
it would, but unbaking would require recompiling all call sites in general, which is kind of annoying
22:44:48
aeth
White_Flame: There are, I think, essentially three levels of control. Inline, inline function call (remove the generic dispatch, keep the function), and runtime dispatch. Specialization-store handles all three of these for type-based dispatch.
22:44:54
Bike
i should probably do that, actually, i k now all the bullshit in clos well enough by now
22:45:55
aeth
Although I'm not sure if specialization-store keeps the return type information when there's an inline function call, which would be useful. That information is lost in SBCL if it's outside of the compilation unit (normally the file)
22:51:37
aeth
It looks like speicalization-store does keep the return type information when doing a named specialization. (defspecialization (foo :name %foo/single-float) ((x single-float) (y single-float)) single-float (+ x y)) (defun foobar () (+ 1f0 (foo 2f0 3f0))) ; does not have a generic + in SBCL
22:52:32
aeth
I'd love to see something just as mature for optimizing CLOS, especially if it was compatible.
22:55:27
aeth
One thing that I'm considering doing soon is using structs and CLOS to define custom data structures. In particular, I think typed lists expressed as structs would be very useful, especially for what I'm doing. At the moment, if something's best expressed as a linked list, I have to type check multiple times where a typed data structure would just type check the elements once, when making the list, and then I'd just type check the list itse
22:56:53
aeth
So what I'm considering writing is: a cons cell represented as a struct with a car and a cdr, where the car is some type and the cdr is either null or another of the new type of cons cell
22:57:25
aeth
This is not entirely portable, but where it isn't portable I can add manual type-checking with #+foo for the implementations that don't check on e.g. creation or access
23:10:27
scymtym
pkhuong made (in 2007 no less) a prototype for "sealed" generic functions which would inline dispatch and/or methods and derive call site-specific return types depending on availability of argument type information and declarations
23:13:19
aeth
I'm only aware of https://github.com/markcox80/specialization-store/ for writing +-style and map-style type-generic functions and https://github.com/guicho271828/inlined-generic-function/ for inlining CLOS dispatch, although I haven't tried the latter, and wouldn't be able to use it in my MIT-licensed projects because it's LLGPL, which would complicate using my projects.