freenode/#lisp - IRC Chatlog
Search
20:23:34
jmercouris
the advantage of a closure? honestly, I find it really rarely comes up in my workflows
20:23:51
jmercouris
that could just be a product of how I think though, maybe others find themselves using them much more frequently
20:25:04
jmercouris
there are those contrived usages that I see occassionally to illustrate how clever they are, but I don't find them applicable oft
20:38:29
Xach
cl-ppcre uses closures in a nice way to compile its regular expression matchers without using cl:compile.
20:44:00
jackdaniel
jmercouris: (defun start () (let ((app (make-app))) (bt:make-thread (lambda () (loop (poke-a-bear app)))) (run-app app)) ; comes to mind
20:44:43
jmercouris
jackdaniel: yeah, but that isn't like a super clever usage of a closure or anything
20:45:09
jmercouris
I'm talking about people that would use it to made a function like "counter" or something that captures a value to know how many times it has been invoked
20:47:15
jmercouris
just to be clear, I'm making a joke here, I'm sure cl-ppcre makes a good usage of closures
20:47:38
jmercouris
we actually use them in Next quite a bit, specifically for candidate completion, we often build closures that capture some state and complete upon it in the minibuffer
20:47:58
jmercouris
to avoid continuosly polling whatever state we are completing against with every keypress
20:51:00
aeth
A closure is the only way to get true encapsulation in CL afaik... but you rarely need that.
20:52:00
jmercouris
I guess if all of your objects were encapsulated in closures or something, you could have true OO in CL
20:52:35
aeth
I tend to prefer to have an explicit state argument to a function passed in as a higher order function over making a closure. I can see why you'd want to do it the other way because it makes the API cleaner, but it also makes it, well, less transparent each step.
20:53:41
jmercouris
jackdaniel: https://en.wikipedia.org/wiki/Object-oriented_programming#Encapsulation
20:53:56
aeth
An OOP definition is basically "choose 4 of these 15 things from the list and turn it into your OOP definition"
20:53:56
jmercouris
"programming concept that binds together the data and functions that manipulate the data, and that keeps both safe from outside interference and misuse"
20:54:17
jmercouris
it's very clear that CL doesn't make this guarantee, like for example private in java, which does
20:54:32
aeth
You can encapsulate slots in CL in two ways... one, you can make the slot name a symbol like %foo and not export the symbol... if you trust your users
20:55:22
aeth
jmercouris: MOP isn't standard, and even if that's the case, you can probably override the MOP in your metaclass to protect them!
20:56:29
jackdaniel
I read it: so you can use functions to manipulate data without accessing it, not that you enforce lack of such access. that said I think that there was a very good post by Erik Naggum explaining why you are wrong with this "trueness"
20:56:29
aeth
(On the other hand, closure encapsulation might be safe from the debugger if (debug 3) isn't the current optimization level, because the private variables might be optimized away.)
20:57:19
jmercouris
jackdaniel: well, there is no official governing authority on what is OO and what is not, I'm sure there is quite some debate
20:57:38
aeth
I'd personally consider defclass encapsulation using a slot definition like (%foo :accessor foo :initform 42) to be an acceptable encapsulation... at least for the user. The MOP and a few other things make things too dynamic for the compiler or interpreter
20:57:39
jmercouris
it doesn't provide encapsulation because you can always violate the encapsulation
20:58:39
aeth
jmercouris: A definition that excludes Python, an extremely OOP language, is imo too strict. I think in Python you just make things private via names, like __foo__ or something
20:59:12
jackdaniel
also, it seems that the person writing this wiki entry indeed thinks that OO = C++
20:59:41
jmercouris
however the lack of multiple inheritance, and having to use protocols instead, a bit of a bummer
21:00:13
aeth
Java has things that violate its own OOP purism like having a separate 'int' type from 'Integer'
21:00:31
aeth
You also don't have to force everything to live with a class to use OOP heavily, as both Python and C++ show
21:00:57
aeth
jmercouris: Common Lisp has integer without harming performance, and is sometimes better than Java here
21:01:51
aeth
well, fixnum is a subclass of integer, and can be handled as a special case without really existing as an "object" instance except when you do things like (class-of 42)
21:02:23
jackdaniel
there it is: https://www.xach.com/naggum/articles/3243735416407529@naggum.no.html
21:03:31
aeth
jmercouris: Method calling in CL is expensive because CL is (mostly) dynamically typed, so it can't optimize the call at compilation time, except perhaps if you add type declarations (although that's rare enough that I doubt that's optimized in most cases in most implementations)
21:03:36
jackdaniel
description on the wiki page of OO reminds me people confusing weak and dynamic typing
21:04:18
jmercouris
you could edit it if you really disagree, however you'll have to provide literature...
21:06:00
jackdaniel
I could but I won't ;) all I'm saying is that I'd be careful with definite claims about "true" <whatever>
21:09:11
aeth
An object oriented programming language is only object oriented if and only if it has a metaobject protocol[1], thus making Common Lisp and Perl rare examples of object oriented programming languages. [1] source: my blog
21:11:35
jackdaniel
I'm cure I've said (paraphrasing): you are wrong about that encapsulation defines trueness
21:12:46
aeth
Anyway, encapsulation depends on the language local conventions if there isn't a "private" keyword or similar. In Python, it is good enough to do __foo for a private member. In CL, a private slot name is just %foo if %foo is not exported in the package. Pretty simple and straightforward.
21:12:56
aeth
I don't think that that is particularly controversial, although a C++ or Java programmer might dispute it
21:13:25
jackdaniel
aeth: one could even claim, that slot names are implementation details and using slot-value is in bad taste
21:14:04
aeth
jackdaniel: I do, but I make that claim by making all of my slot names %foo style. Anything that isn't is an old-style defclass of mine and essentially a bug.
21:14:51
jackdaniel
sure, %foo makes sense. also adding accessors with name %whatever to bypass "official" protocols with all auxiliary methods
21:16:12
aeth
jackdaniel: I sometimes do things like (%foo :accessor %foo :reader foo :initform 42) where %foo is the "internal" reader/writer (easier to have two readers than having a writer with a different name than the reader)
22:42:24
aeth
https://github.com/cl-babel/babel/blob/546fa82ecce6f325a0d9dfc7da40652ac38662d5/src/enc-iso-8859.lisp
0:28:32
remexre
(I'm developing a native-code library alongside a Lisp application, and don't wanna have to restart the REPL every change)
6:37:50
ralt
So, hm. I've been thinking about how lisp is all great to have programs running forever, with the image based things, and the live update facilities. I really like that. But servers die. Things need reboots. So it's just not a viable model these days.
6:38:57
ralt
So I've been thinking: is there a way to have programs that can run forever? Say, something that "distributes" the process on several machines, so that you _can_ have an application running "forever".
6:39:25
aeth
Some would say to come up with a way to serialize it to the disk periodically, but that's no fun, just to be able to restore from a snapshot.
6:39:53
aeth
Having 10 redundant systems so that you can rebuild when some go down, now that's more with the spirit of things
6:40:20
ralt
That said, I know one of the hard problems in my use case is earmuffs variables. I'm just not sure how to solve that.
6:40:23
no-defun-allowed
Well, lfarm does across machines, but it's a worker-manager model and not really distributed.
6:40:56
jackdaniel
ralt: having persistent memory for program (where ram is only a small cache to it) is something what beach proposed years ago
6:41:15
ralt
Like, if your program is really logically a single entity, then things like `(setf *foo* "bar")` can work, and you don't even need a database, ever
6:42:58
jackdaniel
no-defun-allowed: it takes only a little imagination to think about workers as both managers and workers, and data distributed is the actual application state
6:43:48
jackdaniel
databases are highly optimized for things for which lisp image is not meant for (i.e querying for a particular kind of data)
6:43:58
ralt
I also don't mean it should be running across several machines, it's still a single entity that runs single-threaded (and if you make threads, who knows where they run), but somehow it can work across machines.
6:44:00
aeth
ralt: "you don't even need a database, ever" is how you get MUMPS. https://en.wikipedia.org/wiki/MUMPS