freenode/#lisp - IRC Chatlog
Search
7:08:46
aeth
I actually found a practical (well, the program itself is impractical) use for *print-circle* and the whole #1= thing recently. https://gitlab.com/snippets/1761668
7:09:33
aeth
The best part is that if I coerced that vector into a list once the need for random access is over the return value itself would be n
7:10:03
beach
slightlycyborg: I fully intend to make Second Climacs extremely good for editing Common Lisp code, so I think I will use it myself for that. For other things, it would take some work to get it to become as competent as Emacs.
7:10:40
slightlycyborg
beach: ya, I suppose you don't plan on implementing a cl->el compiler, so all modules will be in cl
7:11:50
aeth
el->cl should be easy (and it has been done at least once before). Common Lisp was literally made so you could port legacy Lisps like Emacs Lisp to it.
7:13:25
oni-on-ion
why would i mention guile randomly, for fun? =) yeh emcascript was a test afaik. a real joke there =)
7:13:34
aeth
Having gone the other direction, and implemented large parts of Scheme on CL, I can say it's not entirely trivial. But Emacs on CL probably could actually be described as trivial.
7:16:19
aeth
oni-on-ion: I'm saying that implementing Emacs Lisp on top of Common Lisp is something you could probably do in a week or less.
7:16:23
oni-on-ion
it has 'languages' like racket does. maybe thats what was not immediately obvious. i dont mean to say that elisp is compatible with guile scheme in the same files.
7:17:03
aeth
And the difference here is that Common Lisp was designed so that you could port "legacy Lisps" (Lisps with classic design decisions like Emacs Lisp choose) to it
7:17:59
aeth
So e.g. the EL:LET macro would just be the LET macro with (declare (special foo)) for every foo bound in the LET
7:18:36
beach
slightlycyborg: No, that would not be practical. Part of the reason for writing it in Common Lisp is to get a better architecture. That goal would be defeated if I had to support Emacs Lisp code without modification.
10:07:13
slightlycyborg
flet on a already defined function, does it work like let on a dynamic variable?
10:09:11
jackdaniel
I think that at one els there was an overview of dynamically scoped functions, but I don't remember which
10:10:18
jackdaniel
also compare (flet ((foo () 4)) (funcall 'foo)) with (flet ((foo () 4)) (funcall #'foo)) and (flet ((foo () 4)) (foo))
10:11:40
slightlycyborg
Ok. That sucks. I want to override a function call somewhere deep in my code
10:12:21
slightlycyborg
I'm tweeting out my completed todos, but I want to test todo completion without tweetng them by overriding a function
10:14:13
jackdaniel
slightlycyborg: easy solution would be binding function to a dynamic variable and calling it with funcall
10:16:10
jackdaniel
then when you call (foo) from whatever, it will automagically resolve to the dynamically bound variable having function
10:20:25
slightlycyborg
this wouldn't be a problem if cl was a lisp1 would it? I could dynamically let the fn name and the eval would operate on it properly.
10:21:53
jackdaniel
I think I'm not qualified enough to explain this topic despite having some understanding of it
10:22:34
jackdaniel
reading is yet another source code processing step and doesn't have much to do with calling functions
10:24:22
_death
it has to do with dynamic and lexical bindings, not with namespaces, so lisp1 is irrelevant
10:26:48
no-defun-allowed
Yep. If your function is in the variable namespace, lisp1/2/n doesn't matter too much.
10:26:58
_death
you could (letf (((fdefinition 'my-function) #'some-other-function)) ...) but it's a drastic measure, will affect other threads, and you'd want to declare the name notinline
10:28:12
trittweiler
slightlycyborg, depending on how your code looks like, but one way to do this is to make that piece of code a generic function, and then in your test code, inherit from the TODO object and specialize on that subclass
10:34:53
slightlycyborg
_death: that letf sounds interesting. if I am not using other threads would it cause problems?
10:39:21
jackdaniel
it is hack which you may find sometimes and it bites in the ass if the whole algorithm depends on it *and* you want to make something work in multiprocessing environment
10:40:52
jackdaniel
I believe that solution suggested by me above (using dynamic variables and a trampoline) is 1) suitable for your purpose, 2) safe
10:41:17
jackdaniel
first thing is: CL doesn't have notion of multiprocessing, so it is all implementation-dependent
10:41:30
jackdaniel
second thing: yes, usually dynamic bindings are per-thread, so they are thread-safe
10:42:17
slightlycyborg
Ya, true. I know from experience with *standard-output* that SBCL rebinds per thread, cause I had to lexically close over a variable like top-level that was let to *standard-output*
10:43:20
jackdaniel
all implementations with threads I've tried behave that way (but there are alternative implementation strategies and it would be still a conforming CL implementation)
11:03:50
slightlycyborg
http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.5.8433&rep=rep1&type=pdf this is a pretty cool link on how to do dflet.
11:32:11
|3b|
i'm guessing it tries to store whole file in ram (possibly a few copies, for example one base-64 or whatever encoded, and then decoded version)
11:33:05
|3b|
might look at your server lib to see if you can get a stream and copy directly from that to file instead of loading whole thing into ram
11:40:22
shka_
https://stackoverflow.com/questions/434937/how-does-one-use-sbcls-sb-sprof-allocation-profiling
11:40:27
heisig
The dynamic space size of SBCL is specified in megabytes, so 1024 is not that much. Have you tried something like 10000?
11:41:40
|3b|
(which actually is worth checking, what does (room) look like after server is running?)
11:44:51
|3b|
so you might end up with a bunch of copies of the upload if it is dumping whole thing to text for every frame it shows up in or something
11:45:10
_death
right, (ERROR "~@<When attempting to ~A, the slot ~S is missing from the ~ object ~S.~@:>" "read the slot's value (slot-value)" VECTOR #<SB-SYS:FD-STREAM for "file /tmp/tmpGHU3ALSW.tmp" {100 1889413}>)
11:46:08
_death
it looks like you have a file stream already.. maybe it's just a matter of renaming a file
11:47:54
jmercouris
so _death I assume you are suggesting take data (from the let), and somehow copy it to the desired location?
11:47:58
|3b|
i think you are getting different types for the file contents depending on size (or maybe upload format, chunked etc)
11:48:02
jdz
You might at least look at the content-length header and not process requests that are too big.
11:48:31
jmercouris
but I want users to be able to upload files of around 10, 20mb, as they will be uploading CAD files
11:48:56
_death
jmercouris: I'm thinking the framework you use already writes it to a file and passes a stream
11:51:05
|3b|
yeah, i don't think file size is directly the problem (beyond it possibly changing how the server lib handles the data)
11:52:01
jmercouris
I remember some warning in the sbcl man page about when it tries to use more virtual memory than is allocated it causes a crash or something
11:52:13
jmercouris
I don't know, I'm just shooting in the dark here, but I figured I'll try the simple thing first
11:53:12
jdz
Just making it less likely to happen, but more likely to happen in most unfortunate moments.
11:53:14
_death
you're assuming the stream is a flexi-stream that has vector storage, but that ain't so
11:54:05
|3b|
but with more ram it might give you a backtrace from that instead of from thje error handler running out of memory
11:55:08
jdz
I had the impression that the heap exhaustion error is first, as a result of which the slot in the instance is not set, which causes problems when generating the backtrace.
11:55:09
|3b|
i think your problem is that you just need to treat the file as a stream, and read parts from it and write to your destination file rather than treating it as a sequence
11:55:56
|3b|
yeah, looks like with big files you get a stream to a temp file instead of an in-memory flexistream
11:57:54
|3b|
(you could also try to detect file streams and move the file, but that risks conflicts with the server trying to delete the temp file or whatever)
11:58:51
jmercouris
jdz: This is a common lisp library, I think you and I both know there is no documentation beyond the readme
12:08:37
jmercouris
it is now a #<SB-SYS:FD-STREAM for "file /private/var/folders/98/plnqpl8j7k51bmshc0c9r60r0000gn/T/tmpJAIDFZTC.tmp" {1002DA7753}
12:09:24
|3b|
right, i think the only thing you can rely on is that it is a stream you can read from
12:13:38
jmercouris
so I should just use (with-open-file ...) and then put "s" as the output stream?
12:13:47
|3b|
just get rid of the DATA variable, and replace write-sequence call with (alexandria:copy-stream (first |file|) s)
12:14:14
jmercouris
ok I already did the first part, I kept it in a let though so it is still (data (first |file|)), just easier for me to understand taht way
12:15:44
_death
and then there's already the fd-stream buffering.. so maybe it's not a big issue.. better profile
12:16:39
jmercouris
so, alexandria copy stream is agnostic of flexi stream or of a sb-sys:fd-stream?
12:16:42
|3b|
(unless you have lots of uploads, performance probably doesn't matter too much, and if you do you might want to keep ram per client down anyway)
12:17:29
|3b|
well, flexistream and fd-stream are implementation details to the streams API in general
12:18:36
|3b|
there is a non-standard but pretty much universally implemented extension called "Gray streams" that lets you make your own stream types that work with the normal stream APIs, flexistreams is an example of that
12:19:23
_death
for a long time I felt uncomfortable with CL streams.. one day it occurred to me that the discomfort comes from Gray streams, which mostly just took the user's interface and adapted it to an extender's interface, resulting in a mess of a protocol.. I looked at Franz' simple-streams, and it's much better.. and SBCL also implements that, although I had to fix a bug there to make it work
12:21:44
|3b|
jmercouris: well, FDs can be pretty much anything streams can... files, TTYs, memory maps, serial ports, etc
12:21:48
shrdlu68
CLHS glossary: "stream n. an object that can be used with an input or output function to identify an appropriate source or sink of characters or bytes for that operation."
12:22:51
jdz
jmercouris: I brought it up because in CL a stream is basically the same thing a file descriptor is in Unix: an opaque object that can be used with some functions (call it a protocol, or an API).
12:24:26
_death
I would say not all sockets fit the stream abstraction.. tcp, yes, because it's a stream oriented protocol.. udp, no, because it's datagram oriented
12:24:40
python476
jmercouris: heh, I hate when I click on simple shit years after the fact, but at the same time, you're now free to roll
12:25:52
python476
there was a new paper from a team that decided to make an OS out of the 'everything is an object' out of curiosity
12:26:08
jmercouris
my question is related to a webserver, I'll be redesigning the static site to be dynamic soon
12:26:59
|3b|
ioctl is a result of "everything is a file, whether file ops make sense for it or not" :/
12:35:53
shka_
jmercouris: you will have to load shorter file because if you out of memory before getting the result, you are not getting the result
12:36:25
jmercouris
now I think it is just maybe web-server issues, or my internet connection, because locally I can load massive files
16:47:00
spm_
Is there an existing mechanism to bind all slots of an object to a local var matching the name of the slot? Thinking along the lines of (with-all-slots (obj) ...) which I know doesn't exist in the spec. I see how I do it via macro, but don't want to recreate the wheel if there is already something there.
16:47:53
Xach
spm_: no. i don't think something like that is a great idea. it leads to code that uses variables that are not visibly bound.
16:49:23
spm_
Xach: so better to list each one specifically? I'm working on some bridge code from lisp to java, and it means I'm translating a lot of fields so was trying to shortcut. I can see the argument for doing it explicitly, but am lazy.
16:52:48
sjl
spm_: I have something fairly horrifying I use for this occasionally https://github.com/sjl/cl-losh/blob/master/src/eldritch-horrors.lisp
16:56:58
pfdietz
spm_: how could one do that, even in principle? Different objects with different slots could be there at run time, and there's no way to know at compile time what the slots will be.
16:58:35
spm_
pfdietz: I was thinking of doing this inside the specific translation method for each distinct type I have to translate. That means I have a priori knowledge of what I'm translating into and therefore was looking to shortcut the binding boilerplate.
16:59:26
pfdietz
One you have the list of slots, you can easily (in a macro) produce the with-slots form. To get the list of slots from the class, that's something MOP lets you do.
17:00:14
spm_
pfdietz: Yes, that's exactly what I was thinking of doing, but thought it might be something that already existed and didn't want to recreate if it did.
17:01:54
spm_
Xach makes a good point that it has the potential to inject non-visible bindings which might not be such a good thing.
17:09:42
ThJ
i've been programming for 26 years. when i switched from pascal to c, i had an epiphany, because it was so powerful. when i learned the new functional syntax in ES6, i had a small epiphany, because that was powerful. just saw this little library and my brain went "BOOF!": https://github.com/fukamachi/sxql
17:10:42
ThJ
that's like JSX for SQL... and unlike JSX, you can do it to *any* language. you're not just stuck with what the language happens to offer
17:11:39
ThJ
it's like the other languages are just giving you slices of lisp, but the whole pie is available if you dare to explore it
17:15:57
ThJ
pjb: well, my personal experience was that C had a far more expressive syntax, and felt far more permissive of bit-banging, and shit, here's direct access to the OS API instead of abstractions/wrappers.
17:17:15
ThJ
pascal had pointers, but they weren't such a central theme in the language, so they felt slightly mysterious to me.
17:17:22
pjb
ThJ: even at that time, Pascal was more powerful, always has been. Several OSes as or more avanced than unix were written in Pascal, including Sol, a unix-like one, pUCSD, MacOS, etc.
17:20:06
pjb
There are too many pitfalls in C, too many implementation and platform dependent behavior.
17:20:28
ThJ
pascal -> c definitely felt like a step up to me, because what i wanted at the time was a *lower* level language.
17:20:53
pjb
For example, can you list by heart the 27 operators precedence levels of C? When I worked with Pascal, I knew the syntax by heart, including all the operators precedence levels.
17:21:26
pjb
Granted, but at that time, you had easy access to assembler, and processors of all kind, for the educational aspect. You didn't need C.
17:23:45
ThJ
having "first-class citizen" access to the operating system APIs was definitely a big part of it, of course.
17:25:43
pjb
ThJ: now, I must confess, that I felt the attraction for C too. The spirit coming from PL/1. But I was never entirely satisfied by it, I explored a lot of programming languages, including Modula-2, Eiffel, Ada, Modula-3. Modula-2 was my favorite for a long time. Until I found Common Lisp.
17:25:47
ThJ
but there was also stuff like the for-loop syntax, operators like += -= *= /= ++ --, etc.
17:25:55
pfdietz
Thj: Some cool things in lisp vs C: being able to load new (or redefined) functions into a running image. Being able to do arbitrary computations in macros, eliminating the need for preprocessors like yacc. Exception handling that doesn't necessarily unwind the stack before invoking handlers. An OO system that dynamically dispatches on all arguments, not just (as in C++ or Java) the first one. Being able to fully control th
17:26:21
ThJ
C definitely felt like a world opening up to me, and nothing can take that feeling away from me.
17:26:57
pjb
Also, there's a difference writing a little program in C, and writing a big application, with error handling, safety, etc.
17:27:35
aeth
You can avoid precedence issue with a code style that mandates parentheses and spaces. ((x * y) / 3) + 4
17:28:37
aeth
Even using s-expressions! Just eval from the function position in the middle instead of the start
17:29:24
ThJ
i'm not saying that C is greater than Lisp, but i've always been a right-tool-for-the-job person, and my interest at the time of learning C was stuff like demo coding, graphics, poking straight into unprotected memory from MS-DOS, talking to a NES controller's shift register via the parallel port, etc...
17:30:17
ThJ
and, well, when you look for documentation on how to do those things, here comes the C examples and C libraries.
17:30:47
pfdietz
Even lisp has the issue of how operations are ordered in multi-fix expressions. Is (+ x y z) (+ (+ x y) z) or (+ x (+ y z))? Either is allowed, as are commutative rearrangements.
17:30:51
aeth
Graphics are totally doable in CL because the performance intensive stuff is mostly in shaders these days
17:31:18
ThJ
aeth: yeah, but this was in the mid-1990s and i was writing my own triangle filling code, haha...
17:31:47
ThJ
and the sort of developer i would've looked up to would be john carmack and linus torvalds.
17:32:08
LdBeth
Seems (setf ccl:arglist) works but I'd like to know how to declare it inside function binding
17:36:06
ThJ
well, yeah. i was always good at containing memory leaks, though... a job made easier by the fact that i wasn't writing production code at the time, just small projects... for a larger multi-developer codebase, it's harder.
17:36:31
_death
pfdietz: I think this can be a (theoretical) advantage.. you could choose an order that minimizes error, or allocations..
17:37:49
ThJ
there was this whole culture surrounding the world i inhabited at the time where you wanted small and fast things and you used bit shifts instead of multiplies, and fixed-point integer instead of floats...
17:38:09
_death
ThJ: I spent very little time with Pascal as well.. but it did have SWAG (and BASIC had ABC).. which were cool
17:39:03
ThJ
now that even an arm device has the sort of power that was once reserved for powerful workstations, all of that stuff isn't so critical anymore.
17:39:24
ThJ
except perhaps for special-domain applications like if you're optimising a H.264 decoder.
17:42:11
ThJ
_death: my progression was GW-BASIC, QBASIC, Turbo Pascal, Delphi, C (DJGPP), Java, C++, and then my career started, so i picked up PHP, classic JavaScript and finally stuff like ES6, ESnext...
17:43:51
ThJ
parallel to this, i was learning linux, opengl, electronics and embedded programming, etc.
17:45:15
ThJ
and i guess all i wanted when i drew the comparison to pascal->C is to express the joy of having a world open up to me again.
17:46:15
_death
ThJ: well, I started with an atari, and LOGO actually, then its basic.. with DOS similar start to yours.. basica/gwbasic/qbasic/quickbasic etc. but x86 assembly too.. then a long chain of C and C++ implementations.. then Windows came... too long and uninteresting to elaborate the history ;)
17:47:14
ThJ
and toyed around with stuff like placing asm programs in the 512-byte boot sector of a floppy drive.
17:52:02
pjb
Both C and Pascal (and Python) share the defect of having statements. vs. only expressions, like in CL or Ruby.
17:52:36
pjb
Having only expressions in the syntax of a language is the first thing that outclasses it.
17:59:09
pfdietz
Pascal's big problem, at the start, was treating each program as a closed world. No external linkage. Fine for a teaching language, not so fine for something used for real things.
18:05:05
pjb
units were introduced very fast, and even before that, that is, at the time you programmed pascal using punched cards, you could write in Pascal a pre-processor similar to the C preprocessor to implement an $include directive to use libraries.
18:09:44
rpg
I've been doing a lot of Python programming lately (machine learning stuff). One thing that I have found helpful is the type annotations and associated checkers, which help me avoid stupid mistakes. Is there anyone working on gradual, optional typing for CL and associated checkers? Drew McDermott made a typed dialect, but it's wrapped in very idiosyncratic style (and it's own system definition framework).
18:16:33
pfdietz
There's nothing stopping any lisp implementation from propagating type declarations and checking them at compile time, when it can. Do you want it to do something more than that?
18:22:53
rpg
pfdietz: That's basically what I want. It seems like SBCL does a bunch of what I want (but I'm not good at using it to do so).
18:24:22
rpg
pfdietz: I really want to catch stupid mistakes earlier. I do enough things that are computationally expensive that it hurts to get a work-losing error. I noticed this very strongly working with python, whose debugger is not that good, making it harder to recover compute results when there's a failure.
18:24:36
pfdietz
My suggestion is use strong testing instead of strong typing. If you have tests that cover the code you will find many errors that static type checking would have found, and you will also find other non-type bugs.
18:25:33
pfdietz
SBCL has a code coverage facility to check your test's coverage; there's also the old COVER package (which has some limitations but is portable.)
18:25:35
rpg
pfdietz: That doesn't scratch the same itch. Lots of testing entails writing lots more code, and it doesn't catch the stupid stuff like passing arguments in the wrong order, etc.
18:25:54
shka_
phoe: anyway, first of you will have to ensure that both superclass and class are instances of your own metaclass
18:28:02
pfdietz
rpg: short of formal verification, there's no way to avoid testing if you want any piece of nontrivial code to work.
18:28:19
rpg
phoe: I'm not sure how far that gets me, but I could try. I don't understand SBCL's type propagation well enough to understand what errors it will and won't find (e.g., will it propagate and reason about disjunctive types?)
18:29:14
rpg
pfdietz: I get it, but testing and static analysis are really just two different tools. It's kind of like me saying I want a saw, and you saying you've got a drill. They are both useful, but they aren't the same thing.
18:29:40
shka_
phoe: yeah, i had something like this, but i was noob back then and i used initialize-instance
18:29:54
pfdietz
rpg: it should, although there are some bugs with CONS types and some hairy situations involving SATISFIES types. I've been annoying Stassats with random tests involving that stuff.
18:31:18
pfdietz
Propagation will give up on hairy satisfies types. However, static type checking won't work with those either.
18:32:24
trittweiler
rpg: SBCL and declaim the ftype of your "API" related functions (i.e. the exported ones) will go a long way. Offending call sites will be highlighted in Slime.
18:33:52
trittweiler
that said, I am not sure how well that actually works with CLOS-heavy code though, which is very runtime-y
18:34:01
rpg
I worry a little about moving this code to other implementations, where type declarations are interpreted as assertions, rather than claims that can be falsified.
18:34:52
pfdietz
So, you're complaining that there exist implementations that don't do compile time type checking?
18:35:01
rpg
I'd just like to catch the low-hanging fruit, like functions that demand a pathname instead of a pathname-designator, or a string pathname designator instead of a pathname, etc.
18:37:26
rpg
pfdietz: That's one way of thinking about my complaint. An alternative would be to say that I'd like toolage that supports typing for me (i.e. haskell style typing) in addition to typing for the compiler (C-style typing). CL typing is advertised as the latter, not the former. I like it that SBCL (mis)uses it for the former, but that's not what it was designed for.
18:41:15
trittweiler
I find that a bold claim. You mean historically declarations were intended to make the implementation omit run-time checks, but declaration-as-assertions add a run-time check in default optimization settings? (Note that while it adds a type-check it uses that information to omit type-checks further down the execution stack, so it seems very much in line and in fact more lisp-y because it's safe by default.)
18:42:51
rpg
trittweiler: Yes, I think it's clear from the discussion that the type declarations were intended to support compiler optimizations, since the spec clearly says that implementations are allowed to trust them and do thins that would be unsafe when the declarations are erroneous.
18:44:23
pfdietz
But the compiler is also allowed to recognize their failure and generate errors. So while a CL implementation doesn't have to use declarations to do good type checking, it's certainly allowed to.
18:45:28
trittweiler
If you have a code base that uses declarations a lot in internal functions, rather than just at a high-level ("API functions" above), yes that may result in a lot of unnecessary type-checks and a slow-down.
18:46:11
rpg
It's clear that some aspects of the type system (e.g., SATISFIES) were intended to support run-time type checks, instead of either optimization or static analysis.
18:46:52
trittweiler
So I'm with you that the implementation philosophy of declarations has an impact on how a code base can look like, and it may not be trivial to just switch
18:47:01
rpg
trittweiler: Or the compiler could trust those declarations and generate very efficient code that would have the weakness of blowing up in odd ways if I was wrong about the declarations.
18:48:00
Bike
if the type system is expected to at least know that (subtypep (satisfies x) (satisfies x)) => T, subtype on satisfies types can be used as a SAT solver. just a fun fact there
18:48:18
rpg
Note that this isn't meant to be a complaint about CL -- the CL spec antedates the kind of expressive compile time type checking that (I think) first really showed up with ML.
18:51:12
rpg
shka_: E.g., if the calling point can assure that the typing is correct, you can jump into the function, otherwise you need to check the arguments before doing so?
18:52:14
phoe
except FOO and %FOO are not two different functions but rather two entry points to a single function