freenode/lisp - IRC Chatlog
Search
7:38:03
quazimodo
i asked what the strategy is when streaming an audio file, playing & saving it to disc simultaneously. Does the stream go straight to disk & the player just reads from there, or is the data stream multiplexed, one lot into a buffer for audio player consumption and the other lot into a buffer for the disk writer
7:38:24
quazimodo
and if it's the 2nd approach, at what point do you swap from memory buffer from the stream to the disk?
7:45:03
quazimodo
lieven: so some sort of coherent 'write this new stuff from this position x', and 'read this other stuff from this position y' on an open file handle?
7:46:27
quazimodo
and if the network is fast enough, the write's would happen at faster or more of the reads, where you'd check the current write position(x) against the read position(y) to see what can be read, thus putting the actual audio player into a 'pending' state until more info comes in and a read is allowed?
8:49:15
madrik
Would Lisp, Common Lisp in particular, and the Lisp language family in general, is a good language for newbies to programming?
8:50:55
beach
madrik: It is not widely agreed upon what languages belong to some "Lisp family" so it is hard to say anything about languages other than Common Lisp. Plus, this channel is dedicated to Common Lisp.
8:51:22
ioa
madrik i also think so. In fact, I think it's better to start with lisp, especially because of the REPL and the debugger.
8:51:24
beach
madrik: The Common Lisp programming model is MUCH simpler than that of languages such as C or C++.
8:52:03
schweers
It also gives better error messages (no SEGFAULT nonsense, unless you’re doing something naughty)
8:53:07
schweers
beach: do you have experience teaching Lisp to people who have never programmed before?
8:53:48
beach
I can't say I do, no. But I am utterly convinced that it would be much better to start with Lisp than with something like C.
8:54:50
schweers
I would have guessed the same, but I’ve never taught anyone how to program, and I’ve never taught anyone Lisp. So I don’t have any experience to back this up. Hence my question.
8:56:18
schweers
As teaching scheme as a first language was widespread practice at a time, this idea may not even be that radical or novel.
8:57:11
madrik
Doesn't /Winston and Horn/ presume that the reader is a newbie not simply to Lisp, but also to programming?
8:57:58
madrik
Most of the good Lisp books suppose that the reader is at some level beyond the beginning stage.
8:59:51
madrik
And keeping it in the family, /How to Design Programs/ by Felleisen et al is, I understand, a tour de force in pedagogy.
9:00:37
madrik
I think I read somewhere it was a sort of spiritual successor to /The Little Lisper/.
9:01:23
beach
madrik: The second edition looks like it assumes very little prior programming knowledge. But the code looks old and not so idiomatic by today's standards.
9:02:28
minion
madrik: look at gentle: "Common Lisp: A Gentle Introduction to Symbolic Computation" is a smoother introduction to lisp programming. http://www.cs.cmu.edu/~dst/LispBook/
9:03:09
madrik
beach: I just checked the 3rd edition of /W&H/, and it uses Common Lisp as it was around 1989. So, not quite ANSI CL, but good enough.
9:03:10
beach
madrik: I found that book tiresome to read, but I wasn't a beginner when I did read it, so I may not be representative.
9:04:16
madrik
beach: I thought the design recipe was a gimmick at first, but I learned to appreciate it later on. It proved most useful in two Common Lisp projects of mine.
9:10:42
shrdlu68
madrik: I can't think of a language whose proponents would say is not good for beginners to learn. Well, maybe Scala.
9:11:35
madrik
While on this topic, would you say that a Lisp system ought to have an interpreter along with a compiler, or would a compiler suffice?
9:12:04
shrdlu68
beach: I think they would say "C++ may not be the best for beginners", but they would not go as far as say that it is not good.
9:13:13
schweers
I had the impression that C++ folks think its the end-all and be-all of languages, and that none other need to exist. So, yes, according to some, one should start with C++.
9:13:26
beach
madrik: There are no intrinsic reasons why an interpreter would have better debugging support. But it depends on how much energy the developers put into the debugging support.
9:15:41
madrik
SBCL has a compiler, Clozure CL has a compiler, CMU CL has both, Allegro CL has both, and LispWorks has both.
9:17:22
beach
madrik: As an implementer of Common Lisp, I would not include both. It would be a waste of my time and it would result in an increased maintenance burden. I would much rather spend my time making the compiler emit excellent debugging support.
9:17:56
madrik
loke: But doesn't the SBCL manual say, "SBCL is essentially a compiler-only implementation of Common Lisp"?
9:19:12
loke
There is a global variable you can set to force interpretation. It's a bad idea to use it :-)
9:22:52
scymtym
the interpreter can be useful in very specific situations like changing the compiler in a running image or parallel compilation
9:23:40
jackdaniel
it may be also useful in case of limited platforms like ios (where you can't compile in your application)
9:24:05
jackdaniel
or to be more precise, you can, but your application won't be accepted to their repositories
9:24:43
madrik
I was reminded of this old discussion in comp.lang.lisp regarding the relative advantages of interpreters and compilers:
9:25:04
loke
schweers: They ban (or can ban, it's apparently not consistently applied) anything that allows you to do anything resembling programming.
9:25:16
no-defun-allowed
i assume so, but they have a swift playground app which is ok cause they made it >:(
9:25:58
no-defun-allowed
i remember when i was knee-high to a cons, there was a port of scratch to iOS which got removed by apple
9:26:23
no-defun-allowed
though, yeah, two years ago i remember a python interpreter that ran on iOS
9:26:39
madrik
It was said that the merit of an interpreter is that modified macros will affect their users immediately.
9:26:50
loke
jackdaniel: There is a SageMath (which includes Maxima) on Iphone. I assumed it was based on ECL.
9:27:19
loke
jackdaniel: Then again, it's so horrifyingly slow that I believe it runs ECL in interprted mode, and restarts the image for each command.
9:27:22
jackdaniel
either way this is a silly limitation which makes me glad I don't own any Apple devices
9:27:29
no-defun-allowed
old news (2010) but it did happen despite scratch being a very, very stupid interpreter
9:32:39
madrik
I use Debian myself as I'd like security support for all packages in the archives. I understand that Ubuntu has no such complete coverage.
9:39:42
madrik
LdBeth: While perusing the archives (late 1990s-early 2000s) of the newsgroup, I recall he had plans for an intermediate to advanced book on Common Lisp.
9:40:50
madrik
I've read some of his prose works, and I thought to ask whether he had published anything new.
9:46:40
madrik
schweers: You joked earlier that C++ people thought of C++ as the alpha and omega of languages, and that one could (should?) begin with C++.
9:48:05
madrik
"Steve Heller teaches C++ from scratch, through a one-on-one conversation with an intelligent beginner who asks the questions you'd ask. Heller's unique dialog format is brilliantly designed to clarify the concepts you might otherwise find confusing, so you can quickly learn today's most powerful and valuable C++ development techniques."
9:51:45
beach
madrik: I firmly believe that the feature that I describe as "uniform reference semantics", i.e. that Common Lisp behaves AS IF every object is manipulated through a reference to it, makes the programming model way easier to understand than that of languages such as C and C++.
9:53:33
madrik
beach: Indeed. I now think of C, at least, as a language left for more advanced stages of learning.
9:54:39
schweers
I still don’t have a satisfying answer on what to do on embedded devices (apart from simply not going there). Lisp still seems to need too much memory. Maybe forth?
9:56:08
no-defun-allowed
uLisp exists, but it's not suitable for doing any processing given it interprets
9:56:30
no-defun-allowed
(there's no way to compile on an Arduino, that said, the program and volatile memories are in separate address spaces)
10:07:12
loke
madrik: (loop for n = (read-sequence ...) while (plusp n) do (something-with-sequence))
10:13:35
jackdaniel
maybe my eye is not very used to loop, but one looks pretty the same as another one (i.e I don't see any adventage of one over another)
10:14:54
jackdaniel
that said, judging if something is a good approach based on a snippet without a context may be hard
10:22:16
loke
madrik: That version gives you access to N, the return value, which you probably need when processing the result.
11:10:46
pjb
beach: it's clear that uniform reference model simplifies things a lot. This is the "everything's an object' of Smalltalk. And unfortunately, Java distinguishes C-line int from OO Integer. Objective-C Cocoa Frameworks too have a NSNumber class and must inherit C integers since Objective-C is a strict superset of C.
11:12:00
pjb
beach: like in Objective-C, we can in C use a programming style where uniform references are used most systematically. There's some boilerplate, some repeative code to be written, because of the C type system, but this can be wrapped in cpp macros…
11:12:34
beach
Yes, when I still programmed in C, I would use pointers for basically everything (except integers, etc.)
11:13:20
r13l
morning all! is there a supported way to handle signals in SBCL? i’ve been googling & reading docs, but to no avail. found trivial-signals, which appears to be broken, and sb-unix has some stuff vaguely related, but it states that it’s not intended for end users (also, is UTF-8 okay on #lisp?)
11:33:01
jackdaniel
r13l: long story short: (sb-sys:enable-interrupt sb-unix:signame (lambda (signal code scp) (sb-sys:with-interrupts (bla-bla))))
12:06:39
madrik
Are implementations supposed to notify or otherwise enter the debugger when they read a DEFCONSTANT from in a file on successive loads?
12:09:05
shka_
"A constant defined by defconstant can be redefined with defconstant. However, the consequences are undefined if an attempt is made to assign a value to the symbol using another operator, or to assign it to a different value using a subsequent defconstant. "
12:13:02
madrik
So, if I have a string housing a file name that is supposed to be unchanging, should I not use DEFCONSTANT?
12:14:46
madrik
Okay, I checked the glossary in the HyperSpec, and indeed, two objects are _same_ if they are EQL.
12:16:39
loke
madrik: I was going to write the code for it, but it's a few lines... But you can use ALEXANDRIA:DEFINE-CONSTANT which wraps the defconstant in a check that ensures that you're not trying to redefine the value with an incompatible value. That way you can define string constants without getting compiler errors.
12:16:56
TMA
madrik: you can use interned symbol instead of the string: (defconstant +filename+ '|file.name|) ; it does not feel right though
12:18:41
pjb
madrik: the purpose of defconstant is to allow some compiler optimization. Namely; defconstant tells the compiler that it can use immediate addressing for the micro-instructions using the value.
12:19:26
pjb
madrik: for a symbol, the compiler can generate an absolute addressing mode, that will be filled by the linker when the image is loaded. This works, because symbols are interned and have identity.
12:20:54
madrik
pjb: In case of a string, then, it would be best to wrap a macro around DEFCONSTANT, as loke explains?
12:22:22
pjb
So defvar doesn't assign the variable if it is already bound. It's good for program parameters, where you would set the variable before loading the program. The defvar form would give a default value, in case it's not already bound.
12:22:41
pjb
On the other hand, defparameter always assign the variable. So it's better for global variables of the program.
12:22:52
pjb
Notice of defvar is good for program parameters, and defparameter is good for program values.
12:23:30
pjb
In short: use defparameter, unless you don't want the variable to be reset when you reload the program.
12:25:15
pjb
There's a programming saying: "variables won't, constants aren't. Which means that variable won't vary, (because you should be writing functional code, so you won't modify the value of your variabels). And that constant are not constant, because you will want to change their value when the environment or the platform changes.
12:26:33
pjb
The only case you may use a global variable, is for debugging purposes, when you want to store an internal data there, so you may access it easily when debugging.
12:29:04
madrik
pjb: Does not Lisp -- Common Lisp, especially -- sport multiple paradigms besides the functional? Should one not use the others -- imperative and OO, etc. -- as fits the design?
12:29:40
pjb
This is why while you should not use global variables, there's the possibility to define them and to use them if you know better than me.
12:30:35
pjb
Also, defvar and defparameter define special variables, ie. dynamic variables, which may be what you want for some purpose (eg. the *print-…* and *read-…* variables).
12:32:12
madrik
pjb: I'm curious. A lot of functional programming seems to emphasize recursion and mapping rather than iteration. Don't you fear you'll blow the stack? Or do you only use Lisps that make a point of handling tail-call recursion well?
12:33:52
pjb
Indeed. You can use recursion up to a limit (the maximum stack size). There are optimization such as tail-call optimization, but it cannot always be implemented (and is not always implemented in CL). In CL, unwind-protect (which hides in a lot of macros) and dynamic binding may prevent TCO.
12:34:50
schweers
I don’t know where this myth comes from that Lisps are functional languages. Even scheme is not particularly suited for functional programming.
12:34:52
pjb
Notice that the processors, and the universe, is not functional. There are a lot of objects that can only be mutated.
12:35:15
pjb
schweers: it comes from the fact that it was the first programming language where you could write recursive functions.
12:36:08
schweers
C has recursive functions too, and doesn’t get accused of being a functional programming language
12:37:02
pjb
Also, lisp was the first language having a garbage collector, where you could therefore write (f (g (h))) without leaking the memory allocated and returned by h and g.
12:37:56
pjb
You can write pf=f(pg=g(ph=h()))); free(ph); free(pg); return pf; in C. Doesn't look quite functional.
12:39:52
madrik
schweers: I suppose the other myth from that time is that Lisp is interpreted -- not implementations, but the very /language/ itself.
12:41:15
madrik
Just for fun, here's a couple of Myths that Winston and Horn state on page 6 of their book:
12:43:25
schweers
Well, Lisp gives us great power, so there is more to learn. Macros for instance. Or multimethods. But I’d argue it is easier to learn how it is done in Lisp than to badly reinvent it and be a human compiler for some lesser language.
12:43:38
madrik
On the point of expensive computers, in 1989 they wrote, "... even the fastest LISP systems running on LISP-oriented workstations cost well under a hundred thousand dollars."
12:47:00
madrik
I'll make a note of it. I've mostly learned some portion of its full capabilities from the HyperSpec and the documentation for it in the CL package in Emacs.
12:52:12
schweers
Why do most languages (Lisp included) not have any facilities to automatically release any non-memory resource? I know that this can be tricky, as a GC does not guarantee when an object will be released. But honestly, I often don’t care for when it will be released, only that it will be in the not-too-far future.
12:52:36
madrik
This talk of books calls to my mind another question: when you read a good book, like /Introduction to Algorithms/ by Cormen et al, or any other book whose examples are in a different language, do you try to translate into Lisp, or do you go with the flow of the book?
12:53:34
schweers
I know, but that really is not that flexible. It’s fine when one can create an object at the same dynamic context in which it will be released, but this is not always the case or convienient.
12:55:08
pjb
schweers: and other languages with a garbage collector have finalizers, and some CL implementation have them too.
12:55:48
schweers
hmm, does java have them? Anyway, not every CL implementation seems to have them, so I guess I can’t really use them.
12:55:50
pjb
schweers: but the problem of course, is WHEN you release non-memory resources. This is the difference between memory and non-memory resources: it doesn't matter when you release the memory.
12:56:40
pjb
So if you use finalizer to release external resources, you may be unhappy, because the memory doesn't fill fast enough so the garbage collector is not called.
12:57:25
pjb
There's also another problem, when you take several resources: you may have rules on the order of relasing them. Finalizers can be called in any order.
12:58:26
schweers
I know, but this is not really an issue for me (at least I think so). While I do have resources which must be released in a certain order, those can always be put together into a struct or class
13:10:37
beach
madrik: It is almost fine. You are violating a rule that it cited on page 13 of the LUV slides.
13:13:51
beach
I often do (loop with eof = (list nil) ... until (eq line eof)), but only when the thing being read can be NIL, like when I use READ rather than READ-LINE.
13:16:13
madrik
In these situations, if an end-of-file value besides nil is used, would that value be freshly made on each loop iteration? Or is it reused, once made?
13:19:29
madrik
beach: Ah, I see. Macroexpanding the code shows that eof is let-bound before the loop proper. Okay.
13:21:14
shka_
wheter the value returned from the read-line function is the same is the same instance as the one constructed in with clause
14:11:16
pjb
Some would say that (loop for line = (read-line stream nil nil) while line) is idiomatic. Personally, I don't have problem eliding the explicit test for NIL in lisp. However, in C I started to test explicitely for NULL when testing pointers, because 0 as a symbol representing the null pointer is true only in some context. Notably, and horribly, when as argument to a function, 0 is not interpreted as the null pointer, but as an in
14:13:27
pjb
For example, CL:AND and CL:OR are very explicitely defined to return the first or last values of the argument expressions. So using (or var :default) or (and (predicatep foo) foo) are perfectly readable, just as: (loop while line) is.
14:16:58
beach
pjb: That's one leap you just made. Essentially, you are saying that anything that is semantically well defined by the language is readable to the maintainer.
14:18:06
TMA
I even use '\0' in comparisons because of the intent is more apparent (and while '\0' is equivalent to 0 in C, it is not in C++); the same goes in lisp: make the intent apparent, preferably without needless reference to something external
15:43:37
beach
My guess is that the first C compiler was not terribly smart, so you had to write code like that to get the best performance. That changed with GCC.
15:49:12
madrik
Maybe it's just looking to the past, but I get a kick out of thinking that there used to be implementations of other languages besides Lisp on the Lisp machines.
15:50:41
dlowe
I've wondered if it'd be possible to do FFI in sbcl by providing a libc implementation that used underlying sbcl code, so that allocated memory would be gc'd as usual
15:51:45
dlowe
as far as I know, all the CL implementations keep non-CL code in its own little space
16:03:18
pjb
schweers: well, since char are upgraded to int when passed as parameter and in other places it's essentially the same.
16:04:37
pjb
The difference would be '\0'+'\1' = (char)1 instead of 0+'\1' = (int)1, but againm since (char)1 would be upgraded, I don't remember any circumstance where it would make a difference. (but there may still be one obscur case).
16:07:06
pjb
(let ((s #(1 2 3 4)) (d #(1 2 3 0)) (i 0) (j 0)) (loop :while (= (prog1 (aref s i) (incf i)) (prog1 (aref d j) (incf j)))) (list i j)) #| --> (4 4) |#
16:08:23
pjb
(let ((s #(1 2 3 0)) (d (vector 0 0 0 0)) (i 0)) (loop :while (prog1 (plusp (setf (aref d i) (aref s i))) (incf i))) d) #| --> #(1 2 3 0) |#
16:09:04
pjb
(let ((s #(1 2 3 0)) (d (vector 0 0 0 0)) (i 0) (j 0)) (loop :while (prog1 (plusp (setf (aref d i) (aref s j))) (incf i) (incf j))) d) #| --> #(1 2 3 0) |#