freenode/#lisp - IRC Chatlog
Search
5:23:28
beach
whoman: The reason for the slot options is so that you can apply fundamental principles of software engineering, such as access control, abstraction, data hiding, etc. If you remove those options, those aspects can't be controlled. But perhaps you are not used to programming in large projects where several people need to collaborate and where long-term maintenance is a real concern.
5:27:02
beach
This is also why most people here reject any attempts at "simplifying" class definition by defining a custom macro with fewer slot options. Usually, such attempts boil down to not caring about the difference between interface and implementation.
5:29:04
whoman
i can fully understand these things =) but, to type the same slot name twice i feel could be optional
5:33:47
rme
Lots of people try writing a defclass wrapper macro. Many ultimately decide it was a bad idea.
5:34:13
beach
Because then, when you reload the class, the slot will get a different name, and you will have huge classes in the end with lots of gensymed slot names.
5:34:57
beach
whoman: Furthermore, CLOS needs to know to merge slots with the same name in subclsses.
5:35:26
whoman
hmmm. what do people use as convention for slot/accessor name differences? i've seen '%'
5:36:32
beach
whoman: That's what I use. Some people put a suffix -of on the accessor. Not many people like that convention though.
5:37:11
beach
whoman: You may want to have an exported reader and a private writer, so you need two different names.
5:38:16
pjb
On the other hand, often (99.99%) slots are not sophisticated: their accessors don't do anything but setting or reading the slot.
5:38:51
pjb
And if they do something, often (0.009999%), they do something that is systematical, so you do want to generate them with your own macro.
5:38:55
beach
whoman: Also part of the verbosity you see is that in Common Lisp, you can write :ACCESSOR BLA wheras in Java, you have to write separate get_bla and set_bla functions which is even more verbose.
5:40:48
whoman
pjb, i agree there, but maybe then one should be using structs for the simple objects
5:41:16
pjb
If only you could redefine structs easily, and if only their accessors were generic functions…
5:41:39
beach
whoman: There is just so much variation between :initform or not, between a single :initarg or several, between :reader or :accessor, that it is usually not worth the effort to try to simplify.
5:42:41
pjb
When I say write your own macro, it should not be purely syntactic. It should be motivated by semantic reasons. For example, you can write a define-entity macro.
5:43:24
pjb
At the application level, you don't care about slot names vs. accessors, and what mechanism you have to put into accessors automatically. This should be abstracted in an application-level define-entity macro.
5:44:40
pierpa
defclass being verbose, means one has a few seconds more to think about what they are doing :)
5:45:42
pjb
That said, using a define-class macro with the same syntax as defstruct is a nice way to upgrade your structures to classes.
5:48:07
whoman
all of it agree! thanks guys =) the most i will do for syntax is to split up single slot defs on different lines, for my requirements of visualising my datatypes. then, doing the right thing at the application level.
5:49:07
whoman
i see a lot of lisp code that is too 'bare knuckle' , directly using low level system ops in application level. i definately feel the same, that building up higher level DSL to the application itself is the right way
5:49:44
whoman
i think the gap between "bad" lisp code and "good" lisp code is not as wide as with say, C or Java =)
5:59:37
beach
Well, C is a strange thing. Because of lack of capabilities for abstraction, it is unfit for application programming. And in order to use it for system programming, you often have to rely on behavior that is undefined in the language definition and therefore specific to a particular compiler.
6:13:21
stylewarning
But C is easy to write in the sense you can vomit something into your text editor and it will compile and behave approximately correctly
6:23:17
stylewarning
Yeah, “approximately correctly” should have been “remotely correctly but good enough for managerial sign off”
6:34:32
krwq
are there any recommendations for generic function which returns sequence of values ideally without allocating it? I was considering returning lambda which returns next value with each call and cl-coroutine - are there any recommendations/most popular conventions here?
7:07:43
pjb
krwq: (defgeneric foo (sequence) (:method ((sequence sequence)) (map-into sequence (lambda () (random 1.0))))) (foo (make-array 3)) #| --> #(0.40184024 0.6305135 0.7736664) |#
7:10:53
otwieracz
jasom: Thank you! There was late night already in my timezone, but I will test it right now!
7:15:26
pjb
(let ((pre-allocated (make-array 3))) (print (foo pre-allocated)) (print (foo pre-allocated))) #| #(0.86955583 0.60453916 0.62688285) #(0.96605814 0.63317955 0.62401444) |#
7:18:02
pjb
lazily evaluated sequences… Yes, in CL you can use iterators, ie. functions returning the next element.
7:18:52
Mr_Tea
how do I get a carreer in lisp? do I need to know it beforehand or do people train new hires if they can code.
7:19:22
pjb
Mr_Tea: you start up your own company, you get paying customers, you implement their solution in lisp.
7:20:01
pjb
Mr_Tea: actually, start first by finding paying customers. Then start up your company and implement their solution.
7:20:53
pjb
Mr_Tea: of course, the downside is that you must be prepared to do a lot of sales, hr, and management work, before you can write your first line of lisp code.
7:22:12
pjb
He's having a few talks with his rocket ingineers, but he spends most of his time managing his corporations, and finding paying customers and money to pay his rocket ingineers (and all the carbon fiber and stuff needed to build them).
7:24:08
aeth
Create a rocket company in addition to a Lisp company. Launch Lisp into space and use that to promote the Lisp company.
7:26:35
krwq
beach: how do I return that generator function in another function? I tried wrapping it in another lambda but neither works - only when I use it within body of that with-hash-table-iterator
7:27:44
pjb
krwq: it's useless for your purpose, but as an example, since hash-tables are stored in memory, not lazy data structures.
7:28:14
pjb
(defun make-integer-iterator (&optional (start 0)) (lambda () (prog1 start (incf start))))
7:28:41
pjb
(loop repeat 10 with iterator = (make-integer-iterator) collect (funcall iterator)) #| --> (0 1 2 3 4 5 6 7 8 9) |#
7:28:58
krwq
pjb: this sucks - i can't use both paradigms - I want to have lazy abstraction and use maphash for testing and lazy implementation for normal use
7:28:58
pjb
krwq: if your sequence are finite, you will want to return 2 values, to indicate the end of the sequence.
7:30:00
pjb
(defun make-integer-iterator (&optional (start 0) (end nil)) (lambda () (multiple-value-prog1 (if (and end (<= end start)) (values nil t) (values start nil)) (incf start))))
7:31:03
krwq
I feel like I need yield here: https://github.com/takagi/cl-coroutine - I can't find source code for cl-cont though
7:32:50
pjb
(loop with iterator = (make-integer-iterator 0 7) for (i done) = (multiple-value-list (funcall iterator)) until done collect i) #| --> (0 1 2 3 4 5 6) |#
7:33:45
pjb
krwq: Using closures to generate a single element (or equivalently, a class as in com.informatimago.common-lisp.cesarum.combination) is simplier than using co-routines.
7:38:56
pjb
That's the conforming way to implement them in CL, but it's inefficient, and it requires heavy machinery to wrap the code of the co-routines inside-out.
7:39:40
pjb
Implementing co-routines with threads would probably be a better way than the inside-out thing.
7:40:48
krwq
I don't know what your library does, I need a simple abstract collection which gives me next element when I ask it to
7:41:26
stacksmith
aeth: Don't forget to lose a billion a quarter, and promise to deliver a product that cannot possibly support your burn rate.
7:41:55
pjb
krwq: think about it! hash-tables are NOT sequences, they're direct access data structures!
7:43:40
aeth
If you want something more useful: (defun make-approximation-of-e (&optional (start 1)) (check-type start (integer 1)) (lambda () (prog1 (expt (1+ (/ start)) start) (incf start))))
7:49:09
krwq
returning function sounds good to me but I need to be able to know how to use it with all lisp collections such as hash table
8:01:03
krwq
i like do-children i'll be able to do lazy and non-lazy, will feel lispy and I will be able to pass both name and node as arg
9:35:07
flip214
when using QUUX-HUNCHENTOOT I've got the problem that the browser (and seemingly HT as well?) hangs as soon as I run into an error.
9:35:49
flip214
I'm debugging (interactively) via swank, but upon choosing eg. ABORT the browser still waits for data; further http connections hang as well.
9:38:47
flip214
with the normal hunchentoot taskmaster allows me to debug multiple requests (and abort them ;)
9:41:56
smokeink
http://turtleware.eu/posts/cl-charms-crash-course.html "We are also very drastic with bt:destroy-thread, something not recommended in any code which is not a demonstration like this one." Why is the use of bt:destroy-thread not recommended for recreating threads?
9:55:44
fe[nl]ix
smokeink: on any implementation that uses SMP threads, bt:destroy-thread is a bad idea
10:34:55
flip214
when calling a function, what's the easiest way to pass a place in, so that it can be modified?
10:38:38
White_Flame
I've used cons cells as locatives. Passing around a read/write function pair in a struct would be another reasonable solution to locatives.
10:38:44
flip214
well, that's just to store an intermediate result across multiple calls of that function (in a loop)
10:38:56
White_Flame
That is, of course, if you truly need them. Places, as Shinmera indicates, are pretty straightforward to keep macro-supported
10:39:06
flip214
White_Flame: yeah, I'm now passing in a CONS as well, and have a SYMBOL-MACROLET in the function
10:42:05
scymtym
a simple solution could be (defun make-box () (let (value) (lambda (&optional (new nil newp)) (if newp (setf value new) value)))). seems cleaner and more flexible than a CONS and simpler than two functions or a structure
12:03:58
hajovonta
flip124: (defparameter x (gensym)) (defun test (my-var) (setf (symbol-value my-var) 'any-value-you-want))
12:04:15
Shinmera
jackdaniel: The name isn't validated, don't worry. I got enough experience with those kinds of things :)
12:04:24
jackdaniel
(I'm mentioning that only because I had a few such unpleasent situations, not that I doubt you)
12:16:43
jackdaniel
smokeink: re bt:destroy-thread : for instance you have no guarantee that unwind-protect cleanup will be executed -- hence you may leave lock, erm, locked
12:38:14
neirac
this page is awesome http://lisp-lang.org/ I just found out about woo thanks to that
12:42:08
flip214
first few requests < 1msec, but after a while the performance gets worse and worse...
12:55:29
flip214
no, it's not QUUX... other multi-parallel writes to swank kill my editor chain, too
12:59:43
random-nick
ecraven: that is true, but swank was made for slime and is developed by slime developers
13:45:25
flip214
hmmm, seems that the output is too fast... "INFO: Control stack guard page unprotected"
14:42:29
gr8
hi, I have the following idea: I would like to have a fully functional programming stack, which means that the hardware primitives (assembler directives, register etc.) are exposed to a high-level language. Then the compiler should already be written in Lisp (or something similar) and output binary code
14:42:50
gr8
so that all hardware-specific optimizations can be accessed and programmed using a functional language
14:43:55
Xach
gr8: you can access the hardware directly with existing lisps, and the compilers are written in Lisp and compile to machine code...
14:44:55
ecraven
gr8: where would the language store its values, if you want to access them all the time?
14:45:17
Xach
gr8: https://www.pvk.ca/Blog/2014/03/15/sbcl-the-ultimate-assembly-code-breadboard/ has some info about fussing with that sort of thing
14:46:09
beach
gr8: Are you planning to compile Common Lisp programs, or programs in some other language?
14:47:55
gr8
beach, I'm thinking from the bottom up. My plan is to bootstrap a lisp/scheme language. Of course that can later be used to implement compilers for other languages
14:49:42
beach
gr8: Like Xach mentioned, the SBCL compiler is already written in Common Lisp. And Cleavir is a project meant to create an implementation-independent compiler framework.
14:50:42
beach
gr8: When you say "bootstrap a lisp/scheme language", what would you bootstrap it from?
14:55:23
dlowe
I imagine he envisions bootstrapping as something that will confer benefits rather than a nuisance.
14:56:22
beach
dlowe: That seems like a safe bet. But it is not enough information for me to understand what gr8 is trying to do.
15:03:22
beach
OK, so if you can explain a bit more in detail what you want to accomplish and what you want to start with, that would be great.
15:06:13
gr8
actually I am just thinking about it yet. My original reason was that I am missing the *transparency* of C. When programming in C, (at least when not using all the optimization), I am having some kind of intuition for what is happening on the byte level. With Scheme, you have a scheme interpreter and then it stops, it's a blackbox.
15:06:58
gr8
so in order to have transparency down to the machine level, it would be necessary to make the lower primitives visible in Scheme/Lisp as well
15:08:29
beach
But, what would you use this transparency for? Would you allow the application programmer to access those lower levels?
15:09:24
gr8
optionally! I mean you can write abstractions on top of it and then use them, or you can access lower primitives if necessary, or just look at the code and see what would happen
15:09:50
ecraven
but wouldn't that need for transparency severly hamper you too? how can you have generic arithmetic, for example? you never know *which* exact operation will be called.
15:10:31
gr8
abstraction? Define some default semantics. Isn't that what is done by all other programming languages as well?
15:10:34
ecraven
gr8: probably every Scheme ever has e.g. fx+ and fl+, which can be compiled directly to the respective adds
15:10:39
beach
gr8: What ecraven says. You would have to have a very simple compiler that generates extremely predictable machine code in order for that low level to be exploitable by the application programmer.
15:11:03
ecraven
gr8: the point is, lisp *does* support writing very low-level code where you know what is generated, but you mostly just don't want that
15:11:04
beach
gr8: and such a simple compiler would generate code that is way too slow for most purposes.
15:11:41
ecraven
in most cases, I really don't care which exact instructions are emitted, the compiler should worry about that. if I want to care, in SBCL I definitely can (see the link above)
15:12:29
razzy
in slime i got error :] Symbol "ASDF-SYSTEM-FILES" not found in the SWANK package. do not know where t ostart looking :]
15:13:12
gr8
sure, at some point you have to optimize. But you know that many todays C compilers are a huge mess. I would like to do that optimization in Scheme, using very basic Scheme primitives that access the hardware, like you said
15:13:27
attila_lendvai
razzy: first I'd update slime, your lisp, and quicklisp. then I'd look again if it still fails...
15:17:19
ecraven
pre-scheme? it doesn't have a GC, no generalised arithmetic... it's really not very high-level
15:21:48
gr8
stacksmith, thanks I think Picolisp gets pretty close. https://software-lab.de/doc64/asm
15:27:11
gr8
from https://en.wikipedia.org/wiki/PicoLisp "In 2009, the 64-bit version was released, another rewrite, this time written in a generic assembler which in turn is implemented in PicoLisp." Exactly this "generic assembler" is the abstraction level I was looking for
15:31:08
stacksmith
gr8: the picolisp chat is pretty good, and the developer hangs out and enjoys talking shop...
15:42:09
flip214
I think my brain is broken in some way... would somebody care to tell me the difference between the two LABELS in https://pastebin.com/EHH6LbX4?
15:43:32
|3b|
francogrex: that code looks like it uses ~1.3GB of heap, which is large enough that just running out normally is plausible without anything odd happening
15:46:21
|3b|
you could run in a 32 bit lisp (i was assuming 64), which would reduce heap used, but also probably reduce heap available so might not help
15:46:25
flip214
ie. I just wanted to rewrite the tail recursion (which breaks sooner or later) with an explicit loop
15:46:59
|3b|
though then you would also lose immediate single floats, which might cost you most of your savings
15:47:27
|3b|
if you are storing specific types of data (like all single floats), you could save some space with typed arrays
15:47:50
pjb
francogrex: for example, you could keep an index into the do array instead of coping the elements.
15:49:04
pjb
(defparameter vc (map-into (make-array pa) (lambda () (random 1.0)))) (defun do-index (vc-index) (* 3 vc-index))
15:50:10
pjb
francogrex: (defun vc-ref (vc vc-index index) (if index (aref vc vc-index) (aref do (+ index (do-index vc-index)))))
15:54:09
francogrex
ok. pjb I will try your solution. it is expected to save me a lot of heap space I suppose
15:55:16
pjb
francogrex: of course, the question is whether you will modify the do array? If you do, it will impact the vc abstraction.
15:56:29
flip214
Bike: ah right, thanks a lot... the (read-client-data) doesn't overwrite but just appends. remind me at ELS, one beer is on me!
15:57:24
francogrex
I will fill it out with ints. I omitted that part: something like (loop for i from 0 below 50000000 do (setf (aref do i) 1)) , but it won't be just 1s...
15:58:46
pjb
francogrex: you may want to add an explicit check: (defun vc-ref (vc vc-index index) )(if (<= (+ 3 (do-index vc-index)) (length do)) (if index (aref vc vc-index) (aref do (+ index (do-index vc-index)))) (error "invalid vc-index"))
16:00:05
pjb
francogrex: well, you just implement the abstraction you need to map the indices as you wish.
16:01:21
|3b|
francogrex: if your ints are bounded, you might be able to save some space with typed arrays
16:05:05
pjb
francogrex: again, the point here is that if you can compute the data, then compute the data. Don't store it.
16:05:44
|3b|
though even typed vectors are a lot of overhead per 3 values, so still probably better to store the values in a single vector and just pass around offsets if possible if you are working close to your heap limits
16:19:50
flip214
Bike: yeah, that's what I did. "netstat" shows 10 open TCP connections (saturating my 10 threads), each with unread data.
16:23:42
attila_lendvai
razzy: don't know what you mean, nothing is wrong with your problem. it's just a good approach generally to first update everything, and then go out looking for a solution, because some others may have resolved your problem already
16:42:30
beach
razzy: So is there anything you need that is not provided by a particular implementation?
16:46:06
flip214
can anybody else reproduce QUUX-HT hangs via high load? (I'm using "wrk" to test latency)
16:53:58
razzy
beach: if asynchronous multiprocessing was implemented in some basic common lisp functions, people would use it without even knowing :]
16:55:03
jackdaniel
razzy: if someone uses asynchronous multiprocessing without knowing what he's doing then something is wrong
16:59:30
jackdaniel
multiprocessing is hard - asynchronous access is a source of many bugs for instance
17:00:30
beach
razzy: Oh, you mean like some implementation using multiprocessing for implementing the sequence functions?
17:00:47
beach
razzy: Sure, an implementation is often free to do that, and perhaps some of them do.
17:01:41
beach
razzy: I have been thinking about multi-threaded implementations of primitives such as SORT, FIND, POSITION, etc.