<moon-child>
on x86, why does cmucl generate code that pops the return address manually and jumps to it, instead of using the native RET instruction?
<hayley>
I've never used CMUCL, so I don't have the disassembly on it. But one thing which came up when discussing the calling convention of SICL was that you also have to pop more of the stack before returning.
<moon-child>
hmm, I see
<moon-child>
It's a shame; I understand there is a dedicated return predictor, which is being bypassed in favour of a (much harder to predict) indirect jump. I wonder how setting up the return stack manually at the call site would compare
dstein64 has joined #commonlisp
<hayley>
The choice here was to put another location on the cold end of the stack, which we copy the return address to. While I guess jumping makes more sense, meddling with the stack to get RET to work makes some predictor work.
<moon-child>
(so the return address is pushed before the arguments)
<hayley>
But then you don't have CALL, and I think the predictor works on CALL/RET pairs.
<moon-child>
anyway 'A Last-In-First-Out buffer, called the return stack buffer, remembers the return address every time a call instruction is executed, and it uses this for predicting where the corresponding return will go.'
<moon-child>
hmm, if you do something like this: push L1; push arg; push arg; call func; L1: then you will have a redundant entry on the stack, but the return predictor will work correctly
random-nick has quit [Ping timeout: 252 seconds]
tyson2 has quit [Remote host closed the connection]
molson_ has joined #commonlisp
molson__ has quit [Ping timeout: 260 seconds]
karlosz has joined #commonlisp
Fare has joined #commonlisp
nature has quit [Remote host closed the connection]
nature has joined #commonlisp
X-Scale has quit [Ping timeout: 252 seconds]
lisp123 has joined #commonlisp
<beach>
Good morning everyone!
<beach>
moon-child: What we do is leave a space right near the frame pointer, so we do push <arg1>, push <arg2>... call. Then we pop the return address and put it first in the frame. So then, to return, we first deallocate the arguments and then RET.
asarch has joined #commonlisp
sm2n has quit [Ping timeout: 265 seconds]
Oladon has quit [Quit: Leaving.]
sm2n has joined #commonlisp
akoana has left #commonlisp [#commonlisp]
semz has quit [Ping timeout: 260 seconds]
nature has quit [Ping timeout: 260 seconds]
semz has joined #commonlisp
lisp123 has quit [Remote host closed the connection]
Oladon has joined #commonlisp
karlosz has quit [Ping timeout: 245 seconds]
lisp123 has joined #commonlisp
conjunctive has quit [*.net *.split]
hubvu has quit [*.net *.split]
katco has quit [*.net *.split]
loke[m] has quit [*.net *.split]
Mrtn[m] has quit [*.net *.split]
greyrat has quit [*.net *.split]
ski has quit [*.net *.split]
mmk2410 has quit [*.net *.split]
anddam has quit [*.net *.split]
eta has quit [*.net *.split]
bldr has quit [*.net *.split]
ski has joined #commonlisp
bldr has joined #commonlisp
mmk2410 has joined #commonlisp
mmk2410 has joined #commonlisp
mmk2410 has quit [Changing host]
conjunctive has joined #commonlisp
hubvu has joined #commonlisp
nature has joined #commonlisp
hubvu has quit [Changing host]
hubvu has joined #commonlisp
greyrat has joined #commonlisp
anddam has joined #commonlisp
lisp123 has quit [Ping timeout: 252 seconds]
Mrtn[m] has joined #commonlisp
loke[m] has joined #commonlisp
katco has joined #commonlisp
ski has quit [Ping timeout: 265 seconds]
Inline has quit [Quit: Leaving]
nckx has quit [*.net *.split]
madnificent has quit [*.net *.split]
ggoes has quit [*.net *.split]
etimmons has quit [*.net *.split]
santiagopim[m] has quit [*.net *.split]
happy-dude has quit [*.net *.split]
mikko has quit [*.net *.split]
jfb4 has quit [*.net *.split]
hisacro has quit [*.net *.split]
|3b| has quit [*.net *.split]
pok has quit [*.net *.split]
leo_song has quit [*.net *.split]
samebchase has quit [*.net *.split]
deck4rd has quit [*.net *.split]
hirez has quit [*.net *.split]
skempf has quit [*.net *.split]
antoszka has quit [*.net *.split]
pok_ has joined #commonlisp
samebchase has joined #commonlisp
pok_ is now known as pok
|3b| has joined #commonlisp
mikko has joined #commonlisp
madnificent_ has joined #commonlisp
leo_song has joined #commonlisp
pok has joined #commonlisp
pok has quit [Changing host]
hirez has joined #commonlisp
Kabriel has joined #commonlisp
deck4rd has joined #commonlisp
hisacro has joined #commonlisp
antoszka has joined #commonlisp
jfb4 has joined #commonlisp
ggoes has joined #commonlisp
nckx has joined #commonlisp
etimmons has joined #commonlisp
igemnace has quit [Ping timeout: 260 seconds]
santiagopim[m] has joined #commonlisp
igemnace has joined #commonlisp
nature has quit [Ping timeout: 265 seconds]
happy-dude has joined #commonlisp
diskzero has joined #commonlisp
lisp123 has joined #commonlisp
lisp123 has quit [Ping timeout: 265 seconds]
gaqwas has joined #commonlisp
shka has joined #commonlisp
rain3 has joined #commonlisp
<rain3>
beach: is it a good idea to separate "add-mixin" out of define-stealth-mixin ? https://termbin.com/2o62 Sometimes I need to add to victim classes mixins which are already defined so I need this add-mixin
<beach>
I think STEALTH-MIXIN handles that case fine.
<moon-child>
rain3: that is not a _pretty_ solution, but it is effective and concise
<beach>
rain3: If you want to write ADD-MIXIN, I'll add it to the library.
<moon-child>
beach: I think they just did--in the termbin.com link
<beach>
Oh, heh!
Oladon has quit [Quit: Leaving.]
<contrapunctus>
I don't know anything about OOP in other languages, and all I know of OOP is basic CLOS. Is there anything I might read to understand what mixins are, and how they're created and used in CLOS?
<beach>
OK, well then, send me a pull request.
<rain3>
beach: okay
<rain3>
contrapunctus: read the paper about stealth-mixins
<beach>
contrapunctus: Technically, they are just ordinary classes. What qualifies them as mixins is just conventional use.
<rain3>
nothing complicated
<beach>
contrapunctus: They are not intended to be directly instantiated, and instead are used as superclasses to "normal" classes in order to capture common things between several "normal" classes.
CrashTestDummy2 has joined #commonlisp
<beach>
contrapunctus: Example: (defclass name-mixin () ((%name :initarg :name :reader name))) could be used as a superclass for both a PERSON class and an ORGANIZATION class.
<Alfr>
It's only undefined, so some implementation might simply behave as shown in that example.
<moon-child>
hehe
<mfiano>
it's also not part of the spec, so spec is saved from the bonk
<rain3>
moon-child: see this example, for DESCRIBE-ing circular objects https://termbin.com/cabo add-mixin allows one to add an existing mixin that has behaviour defined through defmethod . It is different from using a #:dummy class which has no behavior
<moon-child>
mfiano: not part of the spec, or just normative?
<mfiano>
^
<moon-child>
rain3: why is it different from using a dummy?
cjb has quit []
<moon-child>
mfiano: notably 'so that we retain the flexibility needed to update these sections even at the last minute without fear of needing a formal vote to change those parts of the document'. Given that, I think they are not intended to be unauthoritative
<rain3>
moon-child: how do you define methods specialized on objects of a class named #:dummy ?
<moon-child>
rain3: I meant that, instead of writing '(stealth-mixin:add-mixin 'safely-describe-mixin 'c1)', you can write (stealth-mixin:define-stealth-mixin #:dummy safely-describe-mixin c1)
<rain3>
oh, to write it as a superclass there
<moon-child>
yes
<rain3>
okay got your point. btw add-mixin can be written as a function rather than as a macro
<mfiano>
moon-child: That quote is regarding front and back matter only. Examples only pertain to the rest of the section.
amb007 has quit [Ping timeout: 252 seconds]
amb007 has joined #commonlisp
diskzero has quit [Quit: My MacBook has gone to sleep. ZZZzzz…]
diskzero has joined #commonlisp
diskzero has quit [Ping timeout: 268 seconds]
spiaggia has joined #commonlisp
<spiaggia>
mfiano: Does your code handle redefinition of the victim class?
<spiaggia>
gilberth went to a lot of trouble to make sure it works. .
attila_lendvai has joined #commonlisp
<mfiano>
Well I am not sure, but I can explain how my code works
lisp123 has joined #commonlisp
<spiaggia>
Sure. But I don't think I can digest that right now. Monday mornings,...
Fare has quit [Ping timeout: 260 seconds]
<mfiano>
#'MIX is the main interaction. It takes as arguments a standard instance and a standard-class type.
<mfiano>
It constructs a new anonymous class with the class of the instance and the class denoted by the type argument as superclasses
<mfiano>
and then change-class's instance to be that class
<spiaggia>
Oh, I think that's very different from what stealth-mixin does.
<mfiano>
Ok :)
<spiaggia>
STEALTH-MIXIN adds a superclass to an existing class, so that client code can, say, add its own slots to a library class that wasn't designed for it.
<spiaggia>
Thanks to the package system, there is no conflict involved.
<mfiano>
How does it handle conflicting keyword-interned initargs?
<spiaggia>
It doesn't as far as I know.
mjoerg has quit [Remote host closed the connection]
<spiaggia>
I guess to be safe, the stealth mixin class should use ordinary symbols.
<mfiano>
Yeah, same here. It's unfortunate because some slots with initargs may be implementation details not intended for make-instance to be used.
<mfiano>
Well all slots should be implementation details in my opinion...and I guess to make initargs "private" they'd need to be interned into the library package
<spiaggia>
I am not sure why that is a problem, but I take your word for it.
<spiaggia>
I think it is fine if the client which defines the mixin use symbols in its own package only.
<mfiano>
The reason why I don't use this pattern much though, is due to something you hinted at above
<spiaggia>
What was that? [Sorry again, distracted...]
<mfiano>
SBCL will emit a style warning if slots have the same symbol name but different package. I really don't want to wrap defclass in my own macro to muffle that, as most of the time the user will be defining their own mixin classes
<spiaggia>
Oh, yes, that sucks.
<spiaggia>
I wonder who came up with the idea to emit a style warning, and why.
<mfiano>
I have no idea. It's probably my biggest complaint about SBCL, as small of problem it is, it has a large effect on my codes.
<spiaggia>
I mean, to avoid the style warning, client code must know the implementation details of the library, which is contrary to the idea of modularity.
<mfiano>
Yes, and also contrary to the idea that slots should be implementation details.
<spiaggia>
Indeed.
silasfox has joined #commonlisp
<spiaggia>
I would much rather have a style warning when a DEFMETHOD is used without a DEFGENERIC for the same function.
<mfiano>
That used to be the case, and I agree.
amb007 has quit [Ping timeout: 252 seconds]
<spiaggia>
We will make sure to do that for SICL. :)
<mfiano>
:)
amb007 has joined #commonlisp
Cymew has joined #commonlisp
pve has joined #commonlisp
<saturn2>
newbies tend to assume exporting the class name from a package also exports all the slot names
<saturn2>
i wonder if that's why sbcl did it
<mfiano>
spiaggia: Why don't I remember seeing you here before in all the years I've been paying attention? Did you change your nick?
<moon-child>
spiaggia is beach
<mfiano>
Huh. Interesting
amb007 has quit [Ping timeout: 268 seconds]
amb007 has joined #commonlisp
peterhil has quit [Ping timeout: 252 seconds]
asarch has quit [Quit: Leaving]
<mfiano>
I guess he only brings that nick on for special occasions and to confuse me :)
<hayley>
I think spiaggia uses spiaggia when he is strand(h)ed from the computer logged into beach all the time.
pranavats has left #commonlisp [#commonlisp]
<mfiano>
too many puns in this early hour for me :)
<hayley>
Put all blame on defunkydrummer, because he once called spiggia Robert Strandh"ed at the beach".
<spiaggia>
mfiano: Italian vs English translation of my last name.
<spiaggia>
hayley: Heh, correct!
<spiaggia>
I have been know to use playa, plage, and Ufer as well in the distant past.
amb007 has quit [Read error: Connection reset by peer]
amb007 has joined #commonlisp
<mfiano>
I raised the topic (again) in #sbcl. If this behavior affects anyone else, I kindly ask you to voice your opinion.
<spiaggia>
The unjustified style warning?
<mfiano>
Yes, it is like the 3rd time I raised the issue.
<mfiano>
It is not gaining traction for some reason
<spiaggia>
I don't hang out in #sbcl, but it is fine to let them know I agree.
<mfiano>
Help would be appreciated
<spiaggia>
I am accumulating evidence that the package system was used a lot less in the past, but I have seen no reason why that would be the case.
<spiaggia>
The naming convention for slot accessors in a bit older code is also evidence in that direction.
<spiaggia>
CLIM uses that convention, like SHEET-PARENT, and CLIM also has only two package defined by the specification, CLIM and CLIM-INTERNALS.
<mfiano>
Yes I see.
<spiaggia>
If I were to write the CLIM specification today, I would probably define many more packages; maybe one for each "module".
<mfiano>
I frown when I see the class prefix on accessor names instead of utilizing packages, at least for non-legacy code.
<spiaggia>
Yes, and it looks silly when inheritance is deep, like (SHEET-PARENT PANE) in CLIM.
<mfiano>
ha yeah
<spiaggia>
Yay, I am again allowed to enter my office!
spiaggia has left #commonlisp [ERC Version 5.3 (IRC client for Emacs)]
<Cymew>
Hasn't Graham or someone else vocal described the CL package system as "somewhat weak" or words to that effect?
<beach>
If what you want is a module system, then it is weak. But if you use it for what it is, it is great. I think the two concepts are orthogonal.
<beach>
Unfortunately, of course, Common Lisp doesn't have a module system.
<beach>
But first-class global environments play that role in SICL.
<Cymew>
Personally I think the word "orthogonal" is overused, but otherwise my experience mirror yours.
<moon-child>
beach: what do you mean by 'module system'?
<beach>
moon-child: A thing that can encapsulate sets of entities such as classes, functions, types, etc. As opposed to just map names to entities as the package system does.
<beach>
moon-child: I am not sure I can formulate the argument immediately, since modules are so fundamental in programming.
<hayley>
In the code examples there is a "platform" object which is eerily similar to a first-class global environment, in my opinion. But this object is an explicit argument used when instantiating a "library" class, and not an implicit "argument" like the FCGE.
<moon-child>
beach: ok
lisp123 has quit [Ping timeout: 268 seconds]
<beach>
moon-child: Let me give you an example instead: People often complain that you can't have two versions of the same library loaded into the same image, which is problematic because some client might want one version, and a different client a different version.
<beach>
moon-child: A module system would put one client and one version of the library in one module, and the other client with the other version of the library in a different module.
<mfiano>
beach: For what it's worth, I am familiar with modules, but I am curious to hear your thoughts as they relate to the missing Lisp piece (outside of FCGI)
<hayley>
The other difference is that a library in Newspeak is a class, where as a library in Common Lisp with first-class global environments is an effect on a first-class global environment, and the library is only reified if you use a fresh environment for each library.
<beach>
hayley: I'll read the paper at some point.
<mfiano>
beach: How does that address the primary issue; colliding package names in the global environment.
<beach>
First-class global environments? Well, since they allow multiple global environments, that's how.
<hayley>
The solution is to give either client its own environment, where each environment has access to the desired version of the module.
igemnace has quit [Ping timeout: 268 seconds]
<mfiano>
So you mean that I can refer to either package #:foo (in module A) or #:foo (in module B) in client code (or even both if that is your cup of tea)?
<hayley>
(I had to think this through as one day Gnuxie showed me the Newspeak paper, said modules-as-objects looked neater, and it took a while for me to figure what my gut told me when it said FCGEs could be made more ore less equivalent.)
<beach>
Right, each first-class global environment has its own mapping from strings to packages.
<mfiano>
That is much more useful that I originally thought about fcgi. I wonder what client code looks like for interacting with different gi's from user code
<beach>
mfiano: It would be used only fairly infrequently. I am not thinking of any fine-grain use of this feature.
<beach>
In fact, I invented it (jcowan says I "reinvented" it) to solve the bootstrapping problem, which requires me to execute SICL code in a host Common Lisp system, and to prepare for CLOSOS so that different users have different environments.
<mfiano>
beach: I am thinking as it relates to a "dependency manager" (as to not overload "package" from other languages), that supports versioned dependencies, where the transitive graph could include many of versions of the same library.
<hayley>
Another useful ability would be to share packages between environments, so that it is still possible to have another module which is a client of both of the forementioned modules.
<moon-child>
first-class environments have definitely existed for a while
<mfiano>
the client code here is the code that loads systems. the invidual systems can't be modified to refer to some particular gi
<beach>
moon-child: But all attempts I could find required a hash-table lookup for each function call.
<hayley>
In 20 years, we will surely have someone saying that you should explicitly prefix global environments somehow, rather than implicitly :use-ing environments :)
<beach>
mfiano: First-class global environments have no features for managing dependencies.
<moon-child>
beach: javascript 'requires' a hash-table lookup for every slot access. Obviously there are fast javascript implementations. I see your point, though
<mfiano>
beach: Yes I understand that. The issue is loading multiple versions of the same library, perhaps with the same package-name, into an image. The fact they came from a dependency graph is kind of irrelevant
<beach>
hayley: Hmm. We'll see.
<hayley>
Still, if you load each module into a fresh global environment, you more or less have module "objects".
<White_Flame>
moon-child: JS compiles down to typecheck & direct ptr/offset access
<mfiano>
The point I'm trying to make, is the code being loaded is not aware of any environment
<mfiano>
Only the code that is loading them
<mfiano>
If that makes sense
<beach>
Sure.
<hayley>
Sure, that's how it works.
<beach>
rain3: Merged! Thanks!
<beach>
rain3: If there is a problem, you get to be the maintainer. :)
<rain3>
Okay
<mfiano>
This problem is why I gave up on my "quicklisp alternative" some years ago, and why CLPM opted to not recursively resolve manifest files.
<beach>
Also, I see first-class global environments as a safety issue. For SICL, I want to put all the code for the compiler in a separate first-class global environment, and then just import COMPILE, COMPILE-FILE, and EVAL to the default global environment.
<beach>
Then it would take an environment switch to alter the code generator, and presumably that switch is password protected, so that loading any arbitrary code can not easily alter the code generator.
<hayley>
Well, there may be a few things which appear to "break" if you go through environments in specific ways.
<beach>
Like what?
<hayley>
For example, a symbol from another environment might or might not have a function binding in the current environment, even if it was bound in the environment from whence it came. So using such a symbol as a function designator might not be a good idea.
<hayley>
But this kind of situation would probably only occur in my very absurd plan to use first class global environments as part of a Newspeak-esque module system, while still using modules written in normal Common Lisp.
<moon-child>
so symbols are not closed over their packages?
<beach>
Correct. They are not.
<beach>
hayley: That would not happen in Clostrum environments. Code is "tied" to an environment when it is loaded, so references to named global functions are resolved then.
<hayley>
Right, but I don't think tying would affect something like having (defun f (symbol) (funcall symbol)) evaluated in one environment, and having (defun g () 'welcome-stranger) (defun h () (f 'g)) evaluated in another environment which a function binding for F.
<beach>
moon-child: There are certain aspects that we haven't worked out yet. For instance, I am not sure whether (SYMBOL-PACKAGE <SYMBOL>) could return a different package in different environments.
pranavats has joined #commonlisp
<mfiano>
beach: the style warning was intended to catch a hard-to-debug programmer-error situation: where they intended to extend a slot, but because of a package snafu ended up "silently" creating a new slot instead.
<mfiano>
The solution they want to take is to only emit it if the slot in question is exported, and thus not an implementation detail.
<hayley>
Would we evaluate (h), the function binding for G would be looked up at runtime, no?
<beach>
hayley: Right, an example like that would go through FDEFINITION which will result in a hash-table lookup.
<moon-child>
it occurs to me that symbols not being closed over their environments is consistent. If you redefine a package, symbols which were already interned into it will continue to be
<beach>
moon-child: Like I said, I haven't imagined all possible scenarios. I think that more experience will be required to iron out the details.
hendursa1 has joined #commonlisp
<beach>
What I think I do know is that I don't want any "module prefix", so that one could say <module>.<function-name> or something like that.
<moon-child>
however functions _are_ closed over their environments. If symbols were too, then SYMBOL-PACKAGE would always have to return the same package regardless of which environment it were evaluated in
<moon-child>
beach: idneed, but that's no reason not to speculate!
<pve>
I'm trying to understand these first class global environments. Would it be possible to implement them (meaningfully) as a library that could be loaded into any CL implementation?
<beach>
moon-child: Right. I am just explaining why I am unable to think very fast, so I don't have an answer to all potential issues.
<mfiano>
As a library? I don't think so. As an extension proposition like PLN, probably.
<moon-child>
err, sorry, in 'symbols not being closed over their environments is consistent', 'environments' should have been 'packages'
hendursaga has quit [Ping timeout: 276 seconds]
<beach>
pve: Well, Clostrum is a library that implements first-class global environments, and we certainly use it during SICL bootstrapping to isolate the host environment from multiple SICL environments, but executing code relative to an environment currently takes a factor 4 or so performance hit compared to host code.
<beach>
pve: So I don't think you can use it in a transparent way as a library.
asarch has joined #commonlisp
<beach>
pve: Essentially, every reference to a global function, variable, etc. in source code must be replaced by a load-time access to a particular first-class global environments in order to find "cells" containing the entity being referred to.
<mfiano>
Ok good, the stealth-mixins paper is rather short. I don't have time for too much attention today :)
<beach>
pve: And the way we do it now is to turn source code to a Cleavir AST, and then turn that to host code for compilation by the host compiler.
<beach>
pve: Probably, that process could be optimized a bit, but I have seen no reason for it, since it is plenty fast as it is for SICL bootstrapping.
<pve>
beach: Ok, I see. And is there any amount of package trickery (renaming packages etc) that could be done to "simulate" FCGEs (or a module system)?
lisp123 has joined #commonlisp
<beach>
pve: Probably. That's what SBCL does for bootstrapping. I just found that unappealing which is why I didn't want it.
<mfiano>
Good call
<beach>
Thanks.
<pve>
beach: oh, didn't know that about SBCL, thanks.
<mfiano>
Just noticed I said FCGI twice and GI twice instead of FCGE and GE. You know it's a Monday :/
<beach>
pve: There is a paper about that.
<moon-child>
mfiano: oh!--I was trying to figure out what the present discussion had to do with fastcgi :)
<hayley>
beach: Yeah, and so if someone wrote a module which actually relied on passing around symbols as function designators, they would find that the program looks for the FDEFINITION in the "wrong" environment.
<beach>
So a typical SICL "module" (now "module" means ASDF system definition plus package definition) has a package definition that :USEs only the CL package, and every component starts with (cl:in-package <module-name>), like (cl:in-package #:sicl-array) for instance.
<beach>
hayley: I don't think so, because FDEFINITION would be in a particular environment and it would look for functions in that environment.
<hayley>
Right.
amb007 has quit [Ping timeout: 268 seconds]
<beach>
hayley: So code doing (FDEFINITION 'FOO) would be loaded into some environment E, and FDEFINTION would be resolved to the one in E and functions returned would be those in E.
<mfiano>
moon-child: Yeah, that is why I probably made that connection...I am not completely with it yet today.
* beach
has an abbrev "fcge", so if it doesn't expand, it is not used right.
<hayley>
I would expect FDEFINITION to look for the function in the former environment (which we evaluated the (defun f ...) form in), and so it would be unable to find the function named G in the latter environment.
amb007 has joined #commonlisp
<beach>
hayley: In your example, it would be the G in the environment that FUNCALL is taken from.
<mfiano>
beach: Not everyone uses Emacs, or a client with abbreviations. Some people prefer the typewriter experience :) I for one, despise Emacs, and only use it is a barely sufficient means to interact with CL.
<beach>
mfiano: Well, I find it very surprising that there are clients without abbrevs.
<mfiano>
IRC is simple enough to use netcat to communicate with
<mfiano>
If that's your thing
<hayley>
On the other hand, expecting FDEFINITION to work across environments would require some sort of ambient authority (probably by unnecessarily sharing bindings for H between environments somehow?) so I'm theoretically fine with that. I'm, however, less fine about how normal Common Lisp code might expect such code to work.
silasfox has quit [Quit: silasfox]
cosimone has joined #commonlisp
<rain3>
I only recently have started using emacs without 'evil-mode' . I had been under the impression that it is not possible, because vi was my first editor and my psyche shaped after it
silasfox has joined #commonlisp
<mfiano>
rain3: I took the opposing path, because years of non-evil Emacs use has hurt my fingers.
<beach>
Here is my opinion: First-class global environments solve a real problem for bootstrapping, and also likely for a multi-user Common Lisp system. But there are details that need to be figured out. Either way, it will work better than without them. My brain is too small to figure things out a priori, so it is fine for others to try that, but I am not going to be much help at this point.
<contrapunctus>
mfiano: why do you "despise" Emacs? O.o
<rain3>
abbreviations and hot keys are so useful that they should be available even across clients= the operating system/a background service should deal with them
<hayley>
I agree. Really I'm only doing stupid thought experiments and wondering why they run into stupid problems.
<beach>
I think Emacs is fine, except possibly for editing Common Lisp code. :)
<mfiano>
contrapunctus: Plenty of reasons, such as its terminal mode not supporting truecolour unlike vim, or font-locking being unbearably slow compared to Vim on old hardware/large buffers. Mostly though, I just prefer the UNIX philosophy, so shoot me
<beach>
rain3: I totally agree.
<contrapunctus>
mfiano: hm...
Lycurgus has joined #commonlisp
<beach>
rain3: I get very angry every time I use (say) bash, and don't have the spell checker or the abbrev processor.
<contrapunctus>
rain3: I've recently used this program called kmonad to do some crazy (/s) things like having Space act like Ctrl when held down, and Shift to insert () when tapped. Might be pretty good to avoid the Emacs pinky, too.
<akater[m]>
I'm only interested in Lisp because it makes environments like Emacs possible. (Or rather, I'm only interested in programming because of that.)
<beach>
rain3: Or M-/ completion, or ....
<beach>
akater[m]: Yes, it seems clear from your utterances that you are not particularly interested in Common Lisp as such.
<hayley>
Does "only" qualify that you don't have any other reasons to be interested in Lisp, or that the reason is unique to Lisp?
<contrapunctus>
mfiano: I do feel a little dissatisfied with Emacs in that it does not have much in the way of means of composition for users. Perhaps keyboard macros, at most.
<hayley>
I would joke and say "I'm only interested in Lisp because it makes environments better than Emacs possible", but the same could be achieved in Smalltalk, and it is not the only reason that I like Common Lisp.
<lisp123>
I was thinking today, Elisp is basically an 'embedded language' in Common Lisp, that's my new company line on the two - Elisp is for the most parts well designed for customising text editors
<contrapunctus>
mfiano: Interop between Emacs packages happens by conscious design, not automatically through the design of the environment.
<mfiano>
contrapunctus: My opinions are mine and just that, opinions. Please don't take this as the start of a holy war. I accept that I have to use it, and I get by with things like evil-mode, even though it is barely acceptable to me.
<rain3>
I have made my own tool with common lisp that can program any additional usb keyboard . It doesn't support abbreviations yet or key combinations , but I can program any single key to do execute arbitrary common lisp code (including code that simulates text typing and pressing key combinations ,since that was the primary purpose of this program)
<beach>
hayley: Well, your phrase means "I am only INTERESTED in Lisp...", as opposed to also being (say) INVOLVED in it.
<hayley>
Also true, yes.
<contrapunctus>
mfiano: you shared you dissatisfactions with Emacs, I'm sharing my dissatisfactions with Emacs...where's the "holy war"? 🤷️
<beach>
rain3: Sounds very useful.
<rain3>
beach: I may release it after I clean it a bit. it uses codes stolen from here and there
<mfiano>
contrapunctus: Ok good. I didn't want to imply I was claiming "the other editor" to be superior to Emacs in any way, especially CL interaction (because it is severely lacking there)
<lisp123>
What are the deficiencies of Emacs for CL interaction? Does it boil down to having to pass data between the CL image and Emacs?
<akater[m]>
Common Lisp has a community with attitude to programming that I'm comfortable with, good compilers, good books, and if I had enough money, I'd spend it on adding proper CL support to Emacs. It's just that there are less and less reasons to write in CL when Elisp gradually gets feature parity. I have only one CL library published — due to optimisation techniques that would be wasted in Elisp at the moment.
<lisp123>
I have started writing some tools that go across Elisp & CL, its annoying having to learn parts of the Elisp API & rules, but I wonder if they alternative of not having an Elisp approach will make it harder to write text editing tools for CL
<hayley>
In part. Other pain points include that the syntax detection in Emacs could be better, the debugger interface could be better, and generally a real "integrated development environment" needs more information passed to the editor.
<mfiano>
One of the big mistakes of Vim as it relates to CL integration, is indentation is fully static. If you need some macro to indent differently, you have to add it to a flat file with information about how many spaces to indent it.
<rain3>
akater[m] why not contribute to Climacs
<mfiano>
For Emacs, it has similar problems with indentation, but at least it is dynamically reconfigurable with SLIME.
<lisp123>
hayley: ok that makes sense. I guess one is limited to Emacs UI (which is quite unique and can't really be extended without hacks). I think syntax detection could be improved with simply more refined code on the Elisp side, unless I am missing some particular difficulties
<mfiano>
CL indentation piggybacks off of elisp indentation code in Emacs, and as such, is not aware of packages. If you load 2 macros into your image that should both be indented differently, the latter one will get added to the "lossage table", and the indentation of the former will be used.
<mfiano>
That is, indentation is only symbol-name aware
<beach>
lisp123: Emacs doesn't do a good job analyzing the Common Lisp code. It has no idea of the role of different symbols for instance. Try (let ((x<newline> 234) (prog1<newline> 234))... and observe the mysterious difference.
<mfiano>
beach: I found a really ugly indentation case recently
<_death>
mfiano: slime has a cl-indent module, and it takes packages into consideration.. it had an issue with package nicknames, which I patched in my slime fork
<beach>
akater[m]: So you are trying to convince is to switch?
<beach>
_death: This is not a package issue though.
<mfiano>
"DEF"* in operator position indents it like an operator, even if said symbol is uninterned or it is some arbitrary DSL list like :depends-on
<beach>
mfiano: Wow, yes, I see.
<lisp123>
beach: thanks, that's a strange result. Will look into it. Okay that is helpful, without full understanding of the CL image, I can imagine it would be harder to get all edge cases right for indentation
<hayley>
Another thing is that, even with the big and fancy IDEs, you still are spending time looking at dead code. While it is not hard to come up with testing data to poke at after you learned some library, you start out with some dead code, and documentation if you are lucky.
<akater[m]>
rain3: Mostly because I have not seen a single Climacs user. The proper way would be to add CL runtime to Emacs in parallel to Elisp. 5000 packages can't be replaced. Org and magit alone can't be replaced.
<beach>
lisp123: Emacs uses regular expressions to parse the Common Lisp code, which is obviously incorrect for Common Lisp. That's why Second Climacs uses Eclector instead, which is a full Common Lisp reader, so it analyses the code correctly.
<rain3>
The Best Way to Predict the Future is to Create It
<lisp123>
beach: But that could theoretically be solved by using the CL reader within Emacs, right? To me it looks like the biggest issue is not having full access to image / package / etc.? That one seems insurmountable
<hayley>
rain3: s/Create/Invent/
<beach>
_death: My example with (let ((x...) (prog1...)) is not a package problem.
<mfiano>
_death: Interesting. I admit it's been some years since I looked at SLIME code, and that I was mostly speaking of Sly above. Does SLIME not have an equivalent of (slynk:print-indentation-lossage) ?
<beach>
lisp123: That's what I just said. We use Eclector.
<akater[m]>
beach: No of course not. But I think my observation “Elisp is gradually getting feature parity with CL while allowing the same level of freedom of expression and utilizing Lisp code that is very, very compatible, to the point of porting not being needed at all in some cases” is valuable to anyone who wants CL to prosper.
<beach>
lisp123: But you can't do it with any Common Lisp reader. It would have to be much better with error recovery.
<beach>
lisp123: Sure, our plan is to run it in the same image as the Common Lisp system.
<_death>
beach: I agree that there are more correct approaches to indentation, but I was replying about the current approach used in slime
<beach>
akater[m]: Oh, we get SOOO many ideas on why Common Lisp is not prosperous at the moment, and each one is accompanied with a different "solution" to the problem.
<lisp123>
beach: Yes that makes sense and I was agreeing. I was mostly replying to the regex part - but yes I agree with you on your points overall
<beach>
_death: Got it. Sorry.
<beach>
akater[m]: Another way of viewing what you say is that Emacs Lisp is turning into Common Lisp, so that Emacs will become another Common Lisp application. That sounds great!
<lisp123>
The Elisp approach (heavy use of special variables) is actually not too bad for its specific purposes. Something to consider for any CL text editors of the future
<beach>
lisp123: In what way are special variables good for that particular application?
Qwnavery has joined #commonlisp
<_death>
mfiano: I think there is a precedence order, where if a symbol doesn't have a package-specific indentation, the indentation associated with the symbol's name only is used
<mfiano>
It's my understanding that all local bindings in Emacs are dynamic in scope by default.
<mfiano>
I could be wrong though
<lisp123>
beach: https://plaster.tymoon.eu/view/2634#2634 (I need to find a better example, also I may be jumping on and off from my computer, so apologies if I reply late)
<lisp123>
But stuff like (newline), (insert "asdf"), (line-beginning-position) --> all are standard functions that are much easier to write when you assume which part of a program you are in
<lisp123>
It gets rid of alot of the staging clutter that one may have to introduce by specifying lexical scope
<beach>
lisp123: That looks awful to me. I would create a parser that would work incrementally each time the buffer contents is altered, and I would have commands like this operate on the output of the parser.
<beach>
lisp123: And that is indeed how we do it with Eclector in Second Climacs.
<lisp123>
beach: As in you use special variables?
<contrapunctus>
akater[m]: Emacs is at its heart a text editor. It's a cool environment and head and shoulders above most software. But even if Elisp suddenly turned into Common Lisp, it would not do a thing about Emacs' core assumptions and limitations.
<contrapunctus>
akater[m]: Org and Magit are...unfortunate relics of the past, same as Emacs, same as 99% of software.
<mfiano>
It's circulatory system has a failing heart then.
<beach>
lisp123: I am afraid I don't see any more usage of special variables in your example, nor in our parser, than would be normal in most programs.
<rain3>
contrapunctus: even git itself, is not very great
<beach>
Speaking of which, let me renew my suggestion for a McCLIM-based application that combines the features of Magit and gitk.
<lisp123>
beach: Its not the best example (also ignore the parser thats a red herring, this is more of a general note). For example, I do not mention which buffer I am working on, which text region I am in, etc. Everything happens on the back of the global values of current-buffer, point (where I am currently in the screen), etc.
<lisp123>
Perhaps you are already doing that, but that was the main point I was making. A beginner just has to type (newline) to get a newline --> no need to specify too many details
<beach>
Sure.
<mfiano>
I am not a fan of implicit global state. I would rather be explicit with the client API
asarch has quit [Quit: Leaving]
<lisp123>
mfiano: The interest part is that it its implicit global state as the default values for the variable, but you can also override them and be explicit on how you want to use a particular function
<mfiano>
I tend to establish methods on generic function hooks that specialize on a "context", that can usually be extended with some mixin extension to CLOS.
<lisp123>
Most functions work on current-buffer, but you be explicit on which buffer to work on
<mfiano>
But I accept that Emacs is full of global state
silasfox` has joined #commonlisp
silasfox has quit [Ping timeout: 268 seconds]
ln43 has joined #commonlisp
xsperry has quit []
pjb has quit [Ping timeout: 260 seconds]
<mfiano>
beach: Do you use stealth-mixin for more recent projects other than Gsharp?
<beach>
SICL uses it in a few places.
<mfiano>
Ah
<beach>
We add slots to instructions to avoid hash-table lookups.
silasfox has joined #commonlisp
<beach>
for instance.
silasfox has quit [Client Quit]
silasfox` has quit [Remote host closed the connection]
<beach>
And just yesterday, I used it to add a slot to a Clostrum class.
<mfiano>
It sounds like something that would be useful for a project I have been designing on paper for a while. Reading more of the paper...
<jackdaniel>
I'm using it sometimes to add a protocol class to an unrelated 3rd-party class when I want to incorporate it
tfeb has quit [Read error: Connection reset by peer]
<mfiano>
rain3: Thanks for the link. I hadn't seen it before
<_death>
beach: I see that there is a paper "Using Stealth Mixins to Achieve Modularity" but the stealth-mixin repository does not contain it.. is there a link to it?
<beach>
Unfortunately not. I think that conference was pretty strict about copyright.
<mfiano>
I could only find it on IEEE Xplore, if you have access
kakuhen has quit [Quit: Leaving...]
<rudi>
also sci-hub but as a working scientist I strongly discourage the use of a website where papers are freely accessible to the public
<_death>
;)
<hayley>
"What's a pirate's favourite letter? P, without it they would be irate."
cosimone has quit [Remote host closed the connection]
<beach>
rudi: Are you the "Rudi" I know?
<rudi>
In the sense that I had some wine at your home once?
<mfiano>
I am against piracy and try to support creators as much as I can, but at the same time, I do not believe in these paywalls for research information where the creators don't even get any of the money.
<beach>
rudi: Wow, long time no see! Welcome back!
<Qwnavery>
hayley: heh
<jackdaniel>
well, there's also that these paywalls shield public from accessing knowledge funded from public money ,)
<hayley>
gilberth told me he would be fine with it, but that doesn't make it legal of course.
<rudi>
mfiano: scientific publishing is weird and screwed up - any author will be so happy if you read their paper, and we don't collect any royalties
<rudi>
so - sci-hub away! It's good for everyone except Elsevier's bottom line and they can go *** ***** ****
<mfiano>
Right that was my point, and jackdaniel touched on the other aspect I was going to comment on...._publicly_ funded research
<rudi>
beach: I'm still mostly gone, just hanging out ;)
<Qwnavery>
arXiv for the win
<beach>
rudi: Still.
* jackdaniel
quickly check mcclim copyrights
<jackdaniel>
and is englightened ,)
<rudi>
beach: while I'm procrastinating - have you looked at tree-sitter? They use GLR for incremental parsing and most-likely-error-location
<rudi>
Seems to work ok for them in practice, cross-language
<beach>
rudi: Yes, I looked into GLR at the time was into parsing.
<beach>
jackdaniel: You will find rudi's name in a few McCLIM files.
<jackdaniel>
sure, I remembered that there was some Rudi, that's why I have checked
<jackdaniel>
(and got englightened)
<beach>
Heh.
<rudi>
haha, I was in the periphery of many projects
<beach>
rudi: But not specifically at tree-sitter.
<rudi>
beach: it seems to work in practice, if not in theory. (It's quite recent, maybe 3-4 years old)
<beach>
Interesting! I should have a look. Now, though, scymtym is in charge of most of the parsing I am using, and he is mostly using packrat parsing.
scymtym has joined #commonlisp
silasfox has quit [Quit: WeeChat 3.2]
silasfox has joined #commonlisp
<rudi>
It looks like emacs 29 will have support for tree-sitter built-in. Meaning in practice, major modes can tell emacs to load the dynamic library containing the parser for their language, and then always have access to an up-to-date parse tree
<beach>
rudi: The problem is that Common Lisp does not have a fixed syntax. That's why we use Eclector to parse Common Lisp code in Second Climacs.
<_death>
it might be better than regexes, but CL's syntax is very context-dependent, so perhaps tree-sitter won't be too useful..
<beach>
Exactly.
<rudi>
right, I assume so. It's a cheap way of supporting the n+1 other languages out there
<beach>
rudi: It takes into account things like read tables, but it can also do Common Lisp analysis, so it can determine different roles of the same symbol.
<_death>
I was somewhat disappointed that each language had a totally independent parse tree representation, without some baseline or higher level commonality..
<mfiano>
beach: Reading your stealth-mixin paper is scaring me. The progression of possible solutions happens in the same sequence as some recent thoughts I had for a similar modular project.
<mfiano>
The two different ways of obtaining attributes with the hash table mediator is very unsatisfactory, and about where I left off before writing my mixin solution.
<mfiano>
Plus it assumes that the keys that are to be consumed by the view be exported from the model, or interned into the keyword package...both poor solutions to the problem.
<jackdaniel>
meet mop, the saviour ,)
Qwnavery has quit [Quit: WeeChat 3.2]
random-nick has joined #commonlisp
<mfiano>
I need to be exposed to more MOP code. My use of it has been few and far between
<beach>
mfiano: I see.
<jackdaniel>
mfiano: reading through amop is a very fine experience - it is written in a very digestable way (along with the motivation for mop, open questions for its future development etc)
<jackdaniel>
and as well - practical problems that inspired particular solutions
<mfiano>
I think I read some of it years ago. It might be on my bookshelf somewhere still.
<mfiano>
I have a hard time finding practical solutions to problems using the MOP for the stuff I work on.
<jackdaniel>
that's why I've mentioned amop, that gives you some "mindset exposure" I suppose
<mfiano>
Probably just because I haven't had much MOP exposure
<_death>
there's also the Paepcke book
<_death>
Object-Oriented Programming: The CLOS Perspective.. it has some nice papers about CLOS and MOP
<mfiano>
Ok, I'm moving those 2 books to the top of my reading queue.
<mfiano>
Indeed I have them
<mfiano>
Thanks btw!
<jackdaniel>
sure. I haven't read the other book
<mfiano>
Oh no, I don't have the Paepcke book
<mfiano>
I confused it with a similar title...the Keene book
seok has joined #commonlisp
<seok>
How does py4cl work? where is the python environment ?
<_death>
it works by communicating with a python process
<_death>
unfortunately it doesn't cleanly separate control and data
<akater[m]>
beach: The fact that Elisp is on the track of getting feature parity with CL doesn't mean it turns into a Common Lisp application unfortunately. Code is very compatible but still not automatically translatable. My point is, people get to write essentially the same code they would be writing in CL but in a much more rewarding environment: immediate applications to everyday needs, larger community (bound by political goals, not solely
<akater[m]>
technical, which also works in its advantage), and with feature set offered by the language getting closer and closer to that of CL. If feature parity is ever achieved (the advantages listed above make it likely), there'll be virtually no reason to even look at CL anymore — except if you want an ANSI standard language no matter what, or implementanion-specific features — by that time it will likely be easier to add them to Elisp
<akater[m]>
I'm not making any conclusions. It's just that many people would say CL is in a somewhat undesirable situation because parenthesis, or because Clojure/Scheme attracts all the mindshare, or because “Lisp curse, get a language with more bondage or die out”. Elisp story shows that all this is not very important.
<akater[m]>
compiler(s) as well.
<hayley>
Hm.
<hayley>
I am tempted to disagree, because some people only think that Lisp can be a scripting language. They wouldn't dare write a whole application in Lisp.
<beach>
They only THINK that? :)
<_death>
one feature of CL is that it has a standard
<hayley>
It seems I have given beach ideas.
<White_Flame>
I think emacs might put off non-lisp people more than lisp itself :-P
<beach>
hayley: You wouldn't believe how many times I corrected jimka's dissertation for strange places for "only".
<mfiano>
White_Flame: Agreed, lol
amb007 has quit [Ping timeout: 268 seconds]
<hayley>
Not only do people think that Lisp is good for scripting, they also act upon their thoughts and don't write applications in Lisp.
<_death>
often I see certain people on the emacs-devel list pushing for backwards-incompatible changes (although others do an admirable job of resisting the agents of chaos ;)
amb007 has joined #commonlisp
<jackdaniel>
right, I often have a feeling that many people are dropping the idea of learning cl because they are shoved with emacs (as in a package)
<beach>
jackdaniel: That happened recently with my brother. :(
<hayley>
There is a substantial stretch between "I use Lisp to customize a text editor" and "I use Lisp to implement all of the network stack that one can reasonably be expected to implement".
<mfiano>
At least we all don't converge to AutoLisp conventions
john-a-carroll has joined #commonlisp
<jackdaniel>
beach: I'm sorry to hear that
<beach>
Me too! But it is not essential that he learn Common Lisp. He is a hardware person.
<jackdaniel>
despite knowing emacs on a level to use it daily it still pisses^wamuses me with its warts
<hayley>
(Last week I got to remark to my classmates that I found the "crash Emacs" button. It hasn't crashed before.)
<beach>
I am thinking that Second Climacs could be a solution. It is not particularly tied to any keys and such.
<jackdaniel>
emacs has cua mode as well, I don't think that keys are the, ekhm, key problem :)
<beach>
"cua"?
<jackdaniel>
I don't remember the exact actronym, but cua is "standard shortcuts - C-c for copy, C-v for paste etc)
<mfiano>
Common User Access
<jackdaniel>
I'm not sure whether these conventions were pioneered by ms or apple but they are adopted in various user-facing applications (and treated often as granted)
<White_Flame>
at least home/end keys, and ctrl-del/shif-t-del/shift-ins generally work nowadays
<beach>
jackdaniel: So what is the problem with Emacs, and why could that problem not be solved with Second Climacs?
<jackdaniel>
I have not asserted that it can't be solved with second climacs
<beach>
Oh, misunderstood. Sorry.
pjb has joined #commonlisp
<jackdaniel>
one of emacs issues I have constantly are ever-changing buffers, it is hard to keep a constant layout (and I'll just wave my hand at people who will say that with sufficient amount of elisp I may prevent that)
<mfiano>
jackdaniel: Can you elaborate?
<beach>
Yes, I see.
<beach>
I mean, it would be cute if we supplied a mostly-VIM-compatible interaction style for Second Climacs. Then VIM users would have a better Common Lisp editing environment that Emacs users. :)
<beach>
s/that/than/
<jackdaniel>
mfiano: say I'm running some application from a repl, and I have two buffers with the source code. then I have an error and a debugger pops in in a random place
waleee has quit [Ping timeout: 252 seconds]
<jackdaniel>
then I start magit, it also opens in a random place destroying my layout
<beach>
Yes, that is annoying.
<mfiano>
Ah yes, I have a couple solutions to that problem
<jackdaniel>
so I'm struggling to reposition my windows so I can have a look at _what I'm currently doing_
amb007 has quit [Read error: Connection reset by peer]
<jackdaniel>
yes, I've tried a few but all that amounts for a pain. Currently I'm storing the frame layout in a register
<mfiano>
One is to use Sly, which patches SLIME to pop up new buffers in a deterministic window. The second is to use purpose-mode, to extewnd that to any Emacs package :)
amb007 has joined #commonlisp
<lotuseater>
jackdaniel: Oh I totally know what you mean. :)
<jackdaniel>
either way that's the problems of a person who uses emacs for years, imagine that you want to learn common lisp and you are strongly asserted that doing CL without Emacs (and SLIME) is bad™ and that you should learn emacs
<jackdaniel>
in other words, I believe that a nice environment in cl (with sub-par features compared to emacs) would be superior (for learning purposes, and for seasoned emacs users like myself)
<White_Flame>
this is also why I always push back as emacs being an "IDE". It's not, it's just a general editor
<jackdaniel>
needless to say, marketing-wise having LSP implementation for CL would be beneficial for folks with random editors like vscode
<White_Flame>
emacs is not very integrated as far as the editor's awareness of your project/workflow is concerned
<pjb>
jackdaniel: embrace them ever-changing buffers. Store your position and window configuration in registers! C-x r C-h #| ERROR: Unbound variable: c-h |#
<pjb>
s/ #| ERROR: Unbound variable: c-h |# //
* jackdaniel
waves his hand at pjb
alanz has quit []
alanz has joined #commonlisp
<mfiano>
jackdaniel: LSP would be a step backwards as the protocol lacks too much required by CL, and poorly defines others.
<rudi>
both LSP and tree-sitter are Worse Is Better solutions
<mfiano>
But I consider that a failure at this point, given current editor support
<jackdaniel>
supporting worse *and* providing better solutions sounds like a good pitch, doesn't it?
<rudi>
jackdaniel: there's tab-bar-history-back (I bind it to C-c t C-/) and winner-mode
<jackdaniel>
rudi: I've tried a few things and I'm (barely) satisfied with juggling with frame registers, I've sank enough time on configuring emacs to not want to try it again - thanks though!
yitzi has joined #commonlisp
<mfiano>
That's the thing about Emacs. You allocate a few minutes of your time to fix one thing, and 2 weeks later you have a new config due to everything tripping over all the global state and monkey-patching of foreign packages.
<yitzi>
mfiano: DAP is not quite as bad as LSP as far as CL is concerned, IMHO. I have a CL DAP inside of common-lisp-jupyter and biggest problem is supporting restarts which I did by adding extra stuff to the continue request.
<rudi>
"So, how did you spend the pandemic year?" "Well, there's this text editor ..."
amb007 has quit [Read error: Connection reset by peer]
amb007 has joined #commonlisp
<mfiano>
yitzi: I was just stating that editor implementation support is lacking compared to LSP, making it not very far reaching or robust.
john-a-carroll has quit [Ping timeout: 252 seconds]
Lycurgus has quit [Quit: Exeunt]
<yitzi>
mfiano: Ok, understood.
yitzi has quit [Quit: Leaving]
theBlackDragon has quit [Ping timeout: 260 seconds]
rain3 has quit [Ping timeout: 268 seconds]
ln43 has joined #commonlisp
shka has quit [Quit: Konversation terminated!]
shka has joined #commonlisp
theBlackDragon has joined #commonlisp
icer has quit [Ping timeout: 265 seconds]
Fare has joined #commonlisp
tyson2 has joined #commonlisp
yitzi has joined #commonlisp
khrbt has quit [Ping timeout: 252 seconds]
khrbt has joined #commonlisp
ln43 has quit [Quit: Connection closed]
<_death>
beach: I've read the stealthy mixins paper.. I think it's a good solution for annotations.. for the events problem, I think the usual solution is the "observer" pattern, often with per-instance granularity, which may be efficient for some scenarios and inefficient for others, but the paper made no mention of it.. for implementation of the idea, I'm not sure I'd go with a define-stealth-mixin operator that includes defclass
<_death>
functionality, but maybe instead have an install-stealth-mixin operator (and have a remove-stealth-mixin operator)
silasfox has quit [Remote host closed the connection]
silasfox` has joined #commonlisp
silasfox` is now known as silasfox
frgo has joined #commonlisp
silasfox` has joined #commonlisp
X-Scale has joined #commonlisp
silasfox has quit [Ping timeout: 268 seconds]
nckx has joined #commonlisp
Fare has quit [Ping timeout: 268 seconds]
minion has quit [Read error: Connection reset by peer]
specbot has quit [Remote host closed the connection]
specbot has joined #commonlisp
minion has joined #commonlisp
Bike has joined #commonlisp
peterhil has joined #commonlisp
makomo_ has joined #commonlisp
frgo_ has joined #commonlisp
<beach>
_death: Thanks.
frgo has quit [Ping timeout: 268 seconds]
<mfiano>
beach: I am confused at what you mean when you say you specialize on an instance rather than a class, and then the method lambda list in the associated figure looks like (class (name (eql 'c)) ...)
<beach>
I am sorry, but I don't remember. I can re-read the paper if you like (but I don't have time right now).
raeda_ has joined #commonlisp
<_death>
an instance of symbol
raeda has quit [Remote host closed the connection]
<beach>
Maybe so.
<mfiano>
Ah it was talking about instances of metaclasses so I assumed I missed something
<mfiano>
I haven't finished reading the paper yet. My mind is multi-tasking today. One thing that I didn't see mentioned (yet) is the utility of being able to specify WHERE in the superclasses of the victim class the new class is inserted.
<mfiano>
This becomes important in my own codes at least, as I use progn method combination a lot with mixins :)
<beach>
I am pretty sure we didn't think of that.
<_death>
mixins should usually come first, so that's what it does
<mfiano>
Sure, but first is not specific enough when multiple exist
silasfox` has quit [Quit: ERC (IRC client for Emacs 27.2)]
<mfiano>
In our codes, our define-* macro includes information for a topological sorting of mixin classes
<_death>
indeed when that matters you may need some way to specify precedence
<beach>
I am still angry with my co-author (John Hamer) about that paper. He and I were both in Auckland when we wrote the paper together, and I was back in Bordeaux when the conference took place, but he refused to take the 3 hour flight to Melbourne, so I had to take the >20 hour flight from Bordeaux.
<jmercouris>
maybe he has a fear of fllying
<mfiano>
I tend to agree with _death though about being able to install/deinstall a mixin and perhaps removing the need for the define-* form
<beach>
jmercouris: Nah.
<mfiano>
It could be made more dynamic this way, changing the class of an arbitrary standard-instance at runtime for example
<_death>
with an install operator you can have a single class be a mixin for multiple victims, for example
<mfiano>
and that
<beach>
OK, I have a suggestion. This is a small-ish library, so someone should feel free to either clone it and improve it, or just create a better one. Once it is in Quicklisp, I'll use the new one instead.
<pjb>
beach: and you didn't find any compensations from this travel itself?
<mfiano>
I was thinking of possibly doing that actually, whenever I get time. I tend to copy/modify my smallish mixin code I linked above in various projects
<beach>
pjb: I don't remember, but stuff like that was typically reimbursed by my employer. But that's not the point. It's more about the wasted jet fuel and time.
<beach>
mfiano: Perfect.
john-a-carroll has joined #commonlisp
<mfiano>
beach: Do you still write papers with a proportional font for Common Lisp code blocks? I will admit it is a bit difficult to read some of the code for me :)
<beach>
No, I don't. I suspect the layout was done by Hamer.
<beach>
Or maybe the publisher re-typed it.
<mfiano>
Well they suck. The backtick is a stylized single "close" quote, very hard to differentiate between a quote character unless you look carefully.
<mfiano>
Actually no, it appears the backtick is an open quote and quote is a close quote.
frgo_ has quit [Read error: Connection reset by peer]
frgo has joined #commonlisp
nature has joined #commonlisp
<jcowan>
I doubt that's the font: some upstream process is trying to change straight to curly quotes, even in code.
<mfiano>
_death: is the "observer" pattern useful in Lisp? I'm not aware of what exactly this pattern is without reading GOF...
vats has joined #commonlisp
<_death>
mfiano: of course it's useful..
<mfiano>
I was under the impression most design patterns were invented to work around the design mistakes of class-centric object systems
cosimone has joined #commonlisp
<saltrocklamp[m]>
i think the idea of "having a collection of listeners that are notified upon certain events" is definitely not an OO-specific pattern
<_death>
mfiano: I don't take that view.. while they may be implemented differently or as part of the language in Lisp, it's still useful to name and describe these patterns
<mfiano>
I usuallly handle that problem with a progn method as to not couple that information to the subject
<mfiano>
Maybe that is bad? I don't know
<beach>
As I recall, in traditional object-oriented languages, the observer pattern has to be implemented by the observed, so it has to be designed in from the start.
<beach>
Whereas in Common Lisp, any client can observe anything.
<_death>
what do you mean by "anything"?
<beach>
I no doubt forget the details.
<beach>
Well, I guess any generic function specialized to any standard class at the very least.
ec_ has joined #commonlisp
<_death>
if you think progn combination or :before/after, that means you need the right GFs
<_death>
so you need to think of the events you want to make possible to listen to anyway
<beach>
You may be right. I should be quiet since I forget the details.
<mfiano>
In recent codes I push messages to a queue, and eql specialize progn listener methods on the type of message.
<_death>
and with traditional observer as in the GoF book, iirc, you can add/remove listeners to particular instances
<mfiano>
and also the context class of course, to support many listeners per message type
<saltrocklamp[m]>
that's my understanding as well; the observed thing needs to have 1) a collection of things that are observing it, and 2) some way to notify those things. i suppose that's the core of design patterns, managing which parts of the code "know" which pieces of knowled
<saltrocklamp[m]>
how exactly you implement that i think is and should be language-dependent
<saltrocklamp[m]>
*pieces of knowledge
<rudi>
Once in comp.lang.lisp, Richard Gabriel briefly surfaced during an instance of the patterns discussion and said (paraphrased) "If there are no patterns, there's nothing a more experienced programmer can teach a newbie"
<rudi>
I think about this a lot
<mfiano>
I'm not sure what is wrong with that as opposed to the observer pattern that seems to need to have a list of listeners coupled to the observed
<_death>
so if you have a lot of instances and you need to listen to them all, you have duplicate entries which is a bit inefficient.. but if you only need to listen to a few, it makes sense.. the stealth mixins approach is more class-oriented, e.g., all instances will have annotation class slots, whether or not they need them
<rudi>
(FWIW, he also tacitly agreed on the worth of the GoF book ;) )
<saltrocklamp[m]>
rudi in python help forums, i frequently caution newbies against "learning design patterns", because a lot of the related documentation and literature is very OO-oriented, and i don't want to encourage excessively OO python code
<rudi>
oh, thoroughly agreed about this! Check out Norvig's "design patterns for dynamic languages" if you haven't yet
<saltrocklamp[m]>
maybe i should be making a more nuanced recommendation, "learn the patterns, but keep in mind that you can implement these things more easily in python/(or whatever) than the examples in C# and Java"
<random-nick>
saltrocklamp[m]: that would mean the observer pattern could just be an observable mixing?
<saltrocklamp[m]>
i haven't, i will!
<rudi>
s/for/in/
<random-nick>
s/mixing/mixin/
<_death>
rudi: yeah, I guess RPG's criticism would be that the GoF book doesn't place enough emphasis on the concept of a "pattern language"
<rudi>
salt rock lamp: it's an extended dunk on the GoF book - highly enjoyable
shka has quit [Quit: Konversation terminated!]
<mfiano>
My favorite author describes patterns as purported “master programmer advice” strongly suggesting to young or otherwise impressionable programmers that the design patterns convey important concepts, practices, or principles that have been “prethought.”, as if you could simply dish out a small number of generic solutions for generic situations, as opposed to every situation being
<mfiano>
different and warranting its own solution.
shka has joined #commonlisp
<rudi>
The best thing that patterns did for me was getting me to read Christopher Alexander's books, which changed me and how I look at the world
<saltrocklamp[m]>
the other thing about GoF design patterns for me is that they're not the kinds of "patterns" that total newbies should be learning. they're really intermediate patterns for when you are progressing to large applications
<jcowan>
The difference once you get past the absolute beginner stage ("What, I have to couont all these parens?") is in writing macros as opposed to using other people's macros.
john-a-carroll has quit [Quit: Ping timeout (120 seconds)]
lotuseater is now known as rotateq
rotateq is now known as lotuseater
Fare has quit [Quit: Leaving]
cosimone has quit [Remote host closed the connection]
<lotuseater>
had there been a ROTATEQ in one of the other lisps that predate CL?
makomo_ has joined #commonlisp
waleee has joined #commonlisp
makomo_ has quit [Client Quit]
<beach>
lotuseater: I don't know the answer, but why do you ask?
<lotuseater>
Just by accident. :) I tried if this as a secondary nickname is still free and as there is ROTATEF I had this thought, like with SETQ and SETF.
<bhyde[m]>
lotuseater: probably not
<_death>
there was SETQQ though ;)
<lotuseater>
Oh where was it? :)
<lotuseater>
And what did it do exactly?
<_death>
it quoted both arguments
<lotuseater>
Back when I wasn't aware about PSETQ, PSETF and ROTATEF it was a good exercise writing a SWAP macro to let two things switch places.
<lotuseater>
Ah okay.
markthom_ has joined #commonlisp
<_death>
BBN Lisp had it.. and Interlisp as well
<lotuseater>
The BBN is new to me.
<bhyde[m]>
i'm trying to recall the author of a paper in the mid70s by a guy at CMU that argued for swap and rotate over assignment. good for reducing memory leaks
<lotuseater>
yay
<lotuseater>
Carnegie Mellon seems to had done much such research, not just CMUCL :)
waleee has quit [Ping timeout: 260 seconds]
<bhyde[m]>
i don't recall any (much) lisp at cmu prior to cmucl.
<lotuseater>
Wikipedia says yes and that from that came the CMUCL implementation.
<Shinmera>
It's now able to analyse a loose graph of dependencies and version constraints, and devise a graph of actions to take to perform the necessary operations to reach a requested effect.
<beach>
Shinmera: Congratulations! Is Forge meant to replace ASDF?
<Shinmera>
First part of the buffer is the definition of components and operations (similar to ASDF), and effects. RUN-TEST is a simple setup of known components and dependencies. Then the repl shows some sample plans that prove it's properly resolving the version constrains.
<Shinmera>
beach: Sssort of. It will be able to do more than ASDF, but I don't have the time to go rewrite all the ASDs people wrote. So my hope is to have it drop down to ASDF for systems it doesn't have "natively", or provide some kinda translation. Not sure yet.
<beach>
Got it.
<Shinmera>
My next step is going to be devising the RPC stuff and making sure a Lisp image can spin up a Forge process, ask it to do something, and then serve as a client to execute the necessary side-effects. That should allow out-of-process building.
santiagopim has quit [Ping timeout: 252 seconds]
<Shinmera>
Another neat thing not shown in the above demo is that, since Forge distinguishes the "effect" of something from the operation and component that spawn it, you can have multiple known ways to achieve the same effect in the system, and the chosen policy object can disambiguate it. So for instance in order to achivee "load system A", it can either be loaded from source or loaded from (and
<Shinmera>
potentially compiled to) fasl. The policy could decide on one or the other if it matters to you.
<bhyde[m]>
yup, slice lisp mutated into cmu lisp
<beach>
bhyde[m]: "Spice" not "slice".
<bhyde[m]>
+1
<lotuseater>
So it gets spicy and doesn't get cut into slices. ^^
<bhyde[m]>
custom microcode/instruction sets - popular for a while back then
d_run has quit []
d_run has joined #commonlisp
amb007 has quit [Ping timeout: 260 seconds]
amb007 has joined #commonlisp
gendl has quit []
gendl has joined #commonlisp
Inline has joined #commonlisp
Guest734 has joined #commonlisp
<Guest734>
phoe oh hellp
<Guest734>
phoe oh hello
<phoe>
Guest734: hello
<Guest734>
is there someone named @phantomics here?
<Guest734>
or who would otherwise be here?
<phoe>
seems like he's not here at the moment
waleee has quit [Ping timeout: 268 seconds]
<beach>
The April person?
<Guest734>
yes
<lotuseater>
Guest734: yes but in the last days not :/
Guest734 is now known as Cpt
Cpt is now known as CptJimKirk
<lotuseater>
CptJimKirk: do you have a special question?
cage has joined #commonlisp
shka has quit [Quit: Konversation terminated!]
shka has joined #commonlisp
<CptJimKirk>
lotuseater I would like to know about dfns and trains, and whether they exist in April
<CptJimKirk>
and to what extent
<lotuseater>
phew okay so deep I'm not yet into it
<CptJimKirk>
Just looking at the examples of April, it looks like it is actually fusing together K ideas with APL, and I do see {⍺×⍵} there so I guess dfns exist to a degree
<lotuseater>
a big subset of APL is implemented and still much potential for what could be done
santiagopim has joined #commonlisp
<lotuseater>
and yes you could also do things like (funcall (april-c "{⍺×⍵+⍺}") 1 2) but (what I also had to realize) then the first arg is going to the ⍵ and the second for ⍺
<lotuseater>
or calling it automatically on arrays too of course ^^
<lotuseater>
shall we go to #apl with that?
CptJimKirk has quit [Quit: Client closed]
Guest794 has joined #commonlisp
Oladon has joined #commonlisp
santiagopim has quit [Ping timeout: 268 seconds]
zxcvz has joined #commonlisp
Guest794 has quit [Quit: Client closed]
amb007 has quit [Ping timeout: 260 seconds]
Guest92 has joined #commonlisp
amb007 has joined #commonlisp
tyson2 has quit [Ping timeout: 252 seconds]
amb007 has quit [Read error: Connection reset by peer]
amb007 has joined #commonlisp
amb007 has quit [Read error: Connection reset by peer]
amb007 has joined #commonlisp
amb007 has quit [Ping timeout: 268 seconds]
amb007 has joined #commonlisp
markthom_ has quit [Quit: Client closed]
<Guest92>
is there a table of | DESTRUCTIVE FUNCTIONS | NON-DESTRUCTIVE EQUIVALENTS |
<Guest92>
also what is WSCL?
<Guest92>
(which for whatever reason my brain is reducing to [W]est [C]oast CL??? stupid brain)
santiagopim has joined #commonlisp
<lotuseater>
I wrote it to you for what it stands, Well Defined Common Lisp.
<Guest92>
wouldn't that be WDCL/
<lotuseater>
oh wait ..
<Bike>
i don't know if there's any comprehensive table, but there kind of aren't a lot of pairs like that
<Bike>
probably less than ten?
<lotuseater>
okay then iirc it stands for structured, sry
<Bike>
"well-specified"
<lotuseater>
thanks Bike ^^
lisp123 has quit [Remote host closed the connection]
<Bike>
"Well Specified Common Lisp is intended as a more strict version of the current Common Lisp standard. It is more strict in that it attempts to specify required behavior of implementations in many cases where the current Common Lisp standard is either silent on the subject, or specifically mentions unspecified behavior."
<shka>
it is essentially bug fix version of the common lisp standard
<Guest92>
will that include fixing the names?
<shka>
no
<shka>
whatever this means
<Guest92>
ehem... filter *cough*
<shka>
what is wrong with filter anyway?
<Bike>
not going to do anything that incompatible, no
<Bike>
presumably Guest92 means that filter would be a better name than remove-if-not
<Guest92>
yes
<Guest92>
but how about include that
<Guest92>
AND filter
<Guest92>
then its compatible, and also better
<shka>
opinionated
<Bike>
adding symbols can still screw things up because most packages use the CL package
<jcowan>
I spotted something that may be a SBCL bug or a failure to specify: (symbol-name :) => "" (which is right, I think), but (symbol-name ::) => "" also.
<Bike>
so if they define their own symbol "filter", there's a conflict
<shka>
if there would be new CL standard, chances are that remove-if-not would be simply omitted
<lotuseater>
and the ANSI standard is defined since 1994
<jcowan>
Anyone have a view of whether that belongs in a WSCL or a SBCL ticket?
<shka>
you can instead remove-if (complement predicate)
<Guest92>
re:opinionated yes. "remove-if-not" not only inverts the reading of the word "remove" so that it adds a layer of indirection to the expression, but also is just an obscene amount of characters to type of what is basically a boolean expression
<Guest92>
(3 > x) / x
<Bike>
this is not the kind of question WSCL is supposed to target
<Guest92>
pseudo apl
<mfiano>
I saw some mention of pre-ANSI GENERIC-FLET and GENERIC-LABELS. I guess these got dropped, but I am curious if these would need to be special operators like their non-generic counterparts, or if they could be user-defined macros.
<Bike>
jcowan: how are you doing this? i get an error from either one
<Bike>
mfiano: i don't see any way to define them with flet/labels
<Bike>
you can't use a proxy
<jcowan>
huh, I must have screwed up somehow
<Bike>
i think either one is invalid per 2.3.5 but i'm not sure
<Guest92>
why is there a distinction between let and labels
<jcowan>
Ah, it's ECL that does that.
<Guest92>
or let and let*?
<Guest92>
why would the more general case not simply be default?
<Guest92>
sorry *flet and labels
<mfiano>
Yeah I thought as much. The global environment would have to be used and cleaned up afterwards at best.
<jcowan>
let* binds sequentially, whereas let binds concurrently
<jcowan>
so let* can be reduced to nested lets
<jcowan>
but let cannot be reduced to let*.
<Guest92>
are let blocks typically so large that actually matters?
<lotuseater>
Guest92: also for runtime security
<mfiano>
We don't call them blocks. "block" means something else entirely
<Guest92>
what does that mean?
<Bike>
sometimes you have enough bindings that nested lets would be inconvenient, sure
lisp123 has joined #commonlisp
<Guest92>
let ... bodies?
<jcowan>
yes
<shka>
Guest92: label is not more general case of the flet
<shka>
as for let* vs let, lisp is weird language because of the code generation prevalence
<Guest92>
I thought labels was flet but I can refer to a name bound within the same ... ... what ever you call it?
<Guest92>
declaring scope?
<Bike>
in the same form, you could say
<Guest92>
what idk what you call that part of the thing
<Bike>
but that doesn't make it more general. an flet definition referring to a name also bound by the flet isn't undefined, it just refers to an outside definition
<Guest92>
I thought that's the difference between flet and labels that I can mention f in g in labels
<Guest92>
but not in f
<Guest92>
but not in flet******
<mfiano>
Guest92: swap f and g and it will still work, unlike serial LET bindings of course.
<Bike>
the difference is that you can refer to THAT f in g
<Bike>
with flet you can refer to a DIFFERENT f
<Bike>
one isn't a subset of the other
<Guest92>
my point is, in any other language, just use a different name? a more specific name?
<shka>
Guest92: so this code may look weird, but it is something which can be used as a paradigm when programming macros
<Bike>
what?
<shka>
Guest92: you mean, why this convention in particular?
<Guest92>
I can't think of any time you'd define an f, then in a nested place define another f, but then later on in another nested context... another f
<Guest92>
that just seems like the author is bad at naming things
<Guest92>
so just... name things better
<Bike>
They're bad at naming things because they keep naming functions shit like "f"
<Guest92>
I'm using f as an example
<Guest92>
so I don't have to type out a fully qualified name like group-itmes-by-key
<shka>
Guest92: lisp, by convention uses separate names for separate object types
<Guest92>
15 times in an example
<shka>
so you have defun, but also defmethod
<Guest92>
but isn't that handled by the dispatcher and not the scope in which the function is called?
<Guest92>
like the CLOS associates methods with its typeclass?
lisp123 has quit [Ping timeout: 252 seconds]
<shka>
generic function is not an ordinary function
<Guest92>
I realize that I'm probably coming accross as combative, but really its just that I don't know what things are called and I'm trying to understand why things are the way they are
<Bike>
I'd say the basic reason for flet/labels is less about the best way to name things and more about simple semantics
<Guest92>
so not trying to be combative. I really just don't know the difference between flet and labels and why there should be both
<Bike>
flet is the way it is because you say: the functions bound by FLET are evaluated in the environment the flet is in (which includes outer functions)
<shka>
i don't think i can put this any other way, but different semantic leads to different name in lisp
<Bike>
whereas for labels they are evaluated in the new environment
<Bike>
which may do shadowing.
<shka>
lisp rarely reuses symbol meaning
<Guest92>
I don't think I mean to suggest reuse, but that there is 1 actual use, and the other is a more specific though unnecessary use given adequate name separation
<shka>
this is also arguably a good thing
<mfiano>
With flet you can locally "patch" a function in the global environment, and still call it if need be (perhaps in a different branch or as a prologue/epilogue).
<shka>
Guest92: can you provide a specific example of that?
<shka>
because neither flet/labels or let/let* is that
<Guest92>
(defun f ...) (another (play (labels ((f ...) (g ... (f ...))) (f ... this f is the same name as the other one, but "here"))))
<Guest92>
like, just rename (defun f ...) or use a different name for f in labels
<shka>
Guest92: yes, and how this is the same as flet?
<Guest92>
how is flet different than labels if not for this one specific usage?
<mfiano>
Consider (funcall #'f) vs (funcall 'f)
ln43 has joined #commonlisp
<lotuseater>
the functions defined there can call each other recursively
<Guest92>
not necessarily recursively
<Guest92>
g calls f, doesn't mean f calls f
<shka>
so you would rather do something like (labels () (stuff)) for recursive use case and (labels (:recursive nil) (stuff)) ?
<shka>
am i getting this right?
<Guest92>
I don't know what I would rather do, you're talking about something else
<Guest92>
this is a horrible format for sharing code btw
<Guest92>
what I'm trying to say
<shka>
i agree
<lotuseater>
it is indeed
robin has quit [Read error: Connection reset by peer]
robin_ has joined #commonlisp
<Guest92>
(labels ((f ...) (g ...(call f ...)))
<Guest92>
g calls f
<Guest92>
that is what labels is for
<Guest92>
if this is the most generic form
<mfiano>
Not the only thing, but go on
<Guest92>
then why would you ever want flet
<shka>
well, labels is for label to call itself, actually
<Guest92>
@mfiano I've asked for more information like 5 times
<Guest92>
I have said "what are the differences between flet and labels except g calls f" like 5 times
<Guest92>
if there are differences, I'm all ears, I would like to know what they are
<shka>
Guest92: the difference is that local function defined with labels can call itself, and the function defined with flet can't
<lotuseater>
*sigh*
<mfiano>
Well f could call f in labels. funcall behaves differently as well
<Guest92>
@shka that's what I just said
<Guest92>
labels
<Guest92>
is the generic flet
<mfiano>
No
<Guest92>
it allows me to refer to names in the binding scope
<mfiano>
It is not generic at all
<shka>
Guest92: not really
<Guest92>
how
<Guest92>
is it not generic?
<mfiano>
No
<Guest92>
flet restricts behavior that lables provides
<lotuseater>
he said already to you it's not the generic form
<Bike>
Because flet doesn't do LESS than that, it does something different.
<Guest92>
but they both bind names to functions
<shka>
Guest92: first of all, generic function in lisp has different meaning
<Guest92>
@bike please, ftlog, tell me what that is
<jcowan>
I think this should go to #lispcafe
<Bike>
As I said, the F will refer to an outer function.
<shka>
secondly, labels is not superset functionality of flet
<Guest92>
right
<shka>
not, at, all
<Guest92>
so use a different name
<jcowan>
or rather the Lisp school channel (thinko)
<lotuseater>
or #clschool
<Guest92>
that's what a sensible person would do, use a different name instead of the same one
<mfiano>
Guest92: Calm down and express your problem slowly and clearly in #clschool
<Guest92>
I'm calm
<mfiano>
No need to lay on RET then
<Guest92>
I'm just tired of asking the same question, getting the same non-answer
<Bike>
Guest92: I am telling you why FLET and LABELS are different and FLET is not a subset of LABELS. If you think using FLET like that is dumb, fine, but it does a different thing and its semantics are not a subset of LABELS's semantics.
<shka>
you can't implement labels with flet, and you can't implement flet with labels
<Guest92>
functionally it is. whether its implemented that way or not is not the point I'm making. FLET functionally binds names to functions, labels functionally binds names to functions that can also refer to the names of the functions withing the binding ... area
<shka>
you could implement let with let*, but that would be a little bit pointless
<Guest92>
that means unless you can be more specific, flet is a subset of labels
<Bike>
It's not! People use FLET in this way you think is dumb!
<Guest92>
ok, then please tell me what the actual difference is
<Bike>
It's not a non-issue even if you don't like it.
<Guest92>
i never said what I like
<Guest92>
I'm asking what the differences are
<Bike>
The only difference is how the binding works. That's it. There are no other differences.
<shka>
Guest92: i mean, Bike explained this pretty clear, and that dumb think flet is used for is a real use case for macro programming
<Guest92>
@bike and that's exactly what I'm saying
<Guest92>
the binding works different
<Bike>
But what FLET does is not a subset of what LABELS does. They have different semantics. Programs using one or the other have different behavior.
<Guest92>
maybe I'm using pleb, non-chad CL terms because I don't know what the words are for things
<Bike>
Your terminology is fine, but I think you are confusing an issue of style with an issue of semantics.
<Guest92>
@bike but that isn't what I'm saying... that's something else
<Guest92>
you're saying the behavior is different
<Bike>
Yes.
<Guest92>
yes, and I was saying
<Bike>
It is different.
<Guest92>
"The only difference is how the binding works. That's it. There are no other differences."
<Bike>
Yes.
<Guest92>
but then you added
<Guest92>
the program behavior is different
<shka>
Guest92: which is pretty important difference may i add
<Guest92>
how is it different?
<Bike>
Uh?
<shka>
Guest92: because you can use flet when you can't use labels
<Bike>
How the binding works is obviously part of the program's behavior?
<Bike>
How could it not be?
<Guest92>
...
<Guest92>
and what I'm trying to say
<Guest92>
is that the only difference so far as I can percieve
<Guest92>
is the availability of the names within the "binding area" as in "the parens within which the names are bound
<Guest92>
yes?
<shka>
Guest92: pretty much, which leads to labels being used for recursive functions
<Bike>
Depends on what you mean by "availability". It is not the case that LABELS necessarily makes more names available than FLET, but rather different names.
<Guest92>
not more or less
<Bike>
or well, it makes different bindings available, i should say
<Guest92>
the names bound within the parens of (labels (...)) are available within (...)
<shka>
Guest92: yes, because we agree with semantics, i don't understand what we are disagreeing on
<Bike>
Look, if I write (+ 2 2), and I want 5, and you say "just write (+ 2 3) instead", that's a different program.
<shka>
really
robin_ has quit [Ping timeout: 268 seconds]
<Guest92>
look the same thing, but I gave it another name
cosimone has joined #commonlisp
<Bike>
None of these operators are really "needed". We could just use lambda calculus.
<Guest92>
this is where we're diverging
<Bike>
I mean you don't need labels or flet at all. You can use anonymous closures. And you don't even need closures if you do lambda lifting yourself.
<shka>
Guest92: ok, so can you state that you think that labels can do everything flet can and more?
<Guest92>
flet is needlessly restrictive because if you just named things well you wouldn't need its behavior
<Bike>
This is what I meant by a style issue.
<Bike>
You think writing things like this - un "well" as you put it - is wrong. Which is an opinion you're entitled to, but it is a separate question from the actual semantics of the language.
<Guest92>
@shka (defun f ...) (flet (g () 3) (g)) also returns 3
<Guest92>
:O
<Guest92>
@shk waiwaiwai 1 more
<shka>
ok, give me a second
<Bike>
If I said using anonymous functions was bad style and that you should just always use flet instead, that would be a style opinion. But if I said that flet can do everything lambda can do that would not be correct.
<Guest92>
@shka (defun f ...) (labels (g () 3) (g)) what does this return?
<Guest92>
I think its 3
<Guest92>
could be wrong
<Bike>
you dropped some parentheses
<shka>
Guest92: ok
<Guest92>
write, because I'm trying to code inside of irc
<shka>
Guest92: give me 5 minutes
<Guest92>
instead of idk, something that has paredit installed
amk has quit [Remote host closed the connection]
<shka>
because it seems you need an example
<Guest92>
yes, that's what I've been asking for for half an hour now
<Guest92>
that would be wonderful
<Guest92>
and thank you for making one
<shka>
you could be more explicit
<Guest92>
↑ not sarcastic
Guest92 has quit [Quit: Client closed]
<Bike>
What do you want an example of, exactly? Oh, well, okay.
Guest92 has joined #commonlisp
<Guest92>
@shka I literally don't know the words to ask more explicitly
<Bike>
What do you want an example of?
<Guest92>
I was trying to be as explicit as possible
<Bike>
We cannot provide an example of a program using flet that could not be rewritten to use labels, any more than we could provide a program using numbers that couldn't be rewritten to use Church arithmetic.
<Guest92>
@bike a proper demonstration that invalidates the assumption of my question, which was for the umpteenth time "what is the difference between flet and labels as it would appear that flet is just a subset of labels"
<Guest92>
I would actually like to know so I don't go around making blunders all over the place
<Guest92>
if its merely a naming thing, then I'm ready to go
<Bike>
Okay. Let's step back. What do you mean by "subset". Because you evidently do not mean that labels's behavior is a superset of flet's behavior.
<Guest92>
if it is changing program behavior, I should like to know what the difference to my program is
<Guest92>
@bike I"m saying labels is the generic form of flet
<Bike>
What does "generic" mean.
<Bike>
Talk to me like I'm five. I'm trying to understand.
<Guest92>
it means that labels does the properly generic form of binding names to *things*, in that I can refer to a *thing* by its *name* within a particular scope
<Guest92>
whereas *flet* does not allow me to do so
<Guest92>
I can define a name, but I'm not allowed to refer to it by name
<Guest92>
I can define a name, but I'm not allowed to refer to it by name by the same rules
<Guest92>
.... as other names
<Bike>
FLET does not allow you to refer to another function from the same flet form in the definition of one of those functions. On the flipside, we could say that LABELS does not allow you to refer to an outside function that has the same name.
<Guest92>
so in that sense, labels gives me the same ability that other forms of function definition allow, which is that I can refer to the function itslef within its own body
<Guest92>
flet doesn't allow that, meaning flet is a more restrictive behavior
<Guest92>
flet restricts the referencing of names bound by itself, labels does not
<Guest92>
labels > flet
<Bike>
LABELS doesn't allow you to refer to an outside function.
<Guest92>
it isn't that it doesn't allow you to Bike
<Guest92>
it is that you overrode the name in the local context
<White_Flame>
let's walk this back to LET vs LET*
<Guest92>
the name in labels is "more local" than the other name
<Bike>
How is that not allowance?
<White_Flame>
LET can be implemented with LAMBDA
<Guest92>
@bike because as you said its a matter of style
<Guest92>
if you want to go around overriding names of things
<White_Flame>
(let ((a 1) (b 2) (c 3)) ...) => ((lambda (a b c) ...) 1 2 3)
<Bike>
You know, it doesn't matter. You understand the difference between FLET and LABELS fine. You're not going to screw up writing programs.
<Guest92>
go right on ahead, but that's just silly
<lotuseater>
what is silly?
<White_Flame>
In the lambda perspective, all expressions are evaluated before passed into the lambda function. Those parameter expressions cannot reference each other; no container for them yet exists until the lambda is entered
<Guest92>
lotuseater read my comment in the context of my chain of previous comments
<White_Flame>
so all evaluation happens "outside" the binding, and the binding happens in parallel
<White_Flame>
if you want to have this sort of visibility with function parameters, you need to nest a separate binding before the call
<White_Flame>
which is what a nested LET/FLET would do
<_death>
if you think FLET is silly, always use LABELS?.. maybe one day you'll find that you need FLET after all
<lotuseater>
i read the most. think of who you call silly with that
<Guest92>
I'm just saying, I can't think of a context in which, in any other language I would go around rebinding names to things within nested contexts, particularly with functions. I think that's silly stylistically, and you could very well give it some kind of additional designator to distinguish it from other forms of similar functions
<lotuseater>
Yes so as you say, *you*.
<Guest92>
@_death I didn't say I think flet is silly, I said constantly rebinding existing names to other names is silly.
<White_Flame>
Guest92: I gave you explicit examples of where/when such nesting is necessary in general
<Guest92>
I'm still trying to get my head around it
<White_Flame>
eg, with any language that calls functions with parameters :-P
amk has joined #commonlisp
<Guest92>
I just don't see why you would ever do that with functions, unless you're doing some kind of "import all" of someone else's library where the could be potential naming conflicts
<White_Flame>
define function foo(a,b,c), call foo(1, a+1, a+2), except "a" doesn't exist yet because you haven't entered foo yet
<Guest92>
modular code however wouldn't have that problem simply because modules oughtn't be large enough to warrant defining of multiple functions by the same name
<Guest92>
but that goes back to style
<_death>
Guest92: suppose you have a macro that defines a local function called COLLECT, and you want to give a nice error when COLLECT is used outside the context set up by the macro
<White_Flame>
all parameters are evaluated outside the functino scope (with its respective parameter names), then all parameters are bound effectively in parallel as the function is entered
<_death>
(say, the error message should mention the macro's name)
<White_Flame>
the very explicit control of scope in CL is very advantageous to avoid bugs and have more clarity in the intent of bindings
<Guest92>
@_death doesn't that begin to violate lexical scoping rules?
<_death>
Guest92: how so?
<Guest92>
like, I got my scope, I got a name in it, someone on another planet be calling my names but he doesn't know about them, and he's going to suffocate because the error wasn't caught and his oxygen supply is now bugged out
<Guest92>
I shouldn't have to error if someone outside the scope refers to my names
<Guest92>
because... that's already an error
<mfiano>
Sigh
<mfiano>
Night all
<lotuseater>
night mfiano
<_death>
Guest92: it's an error, but the message is a generic "COLLECT not a function" instead of "COLLECT may only be used inside a WITH-COLLECT context"
<Guest92>
i really don't know what the problem is... this is basically the beahvior of any other lexically scoped language
<Guest92>
the "most local scope" of the name is the name that it refers to
<lotuseater>
we're not any other
<Guest92>
so obviously if you define global-x, but then you have local-x, then when you call x it refers to local x
<Guest92>
I think the thing I'm missing is how much CL is reliant on globla scope
<Guest92>
because I literally can't even with global scope
<Guest92>
the model doesn't fit in my brain
<lotuseater>
okay so now the thing is figured out
markthom_ has joined #commonlisp
<Guest92>
I would only ever define globally what must be used everywhere throughout an application, like a DSL. But at the same time I'm not going to go around redefining my DSL all over the place inside of nested contexts, where an FLET would be useful
<Guest92>
because that invalidates the purpose of the DSL in the first place
<_death>
Guest92: what I said would work with either FLET or LABELS.. but now, think of a different operator that can be used in a local context, but that may need to call the global COLLECT on some condition
<Guest92>
scary
<Guest92>
I would relaly just give them different names
<_death>
Guest92: or instead of "global COLLECT", the collect of the outer context
<Guest92>
like (if t *collect* COLLECT)
yitzi has quit [Quit: Leaving]
<Guest92>
but then I remember something about *stdout* and *stdout* getting redefined in loads of differenct contexts for some kind of socket library thing
<Guest92>
that just seems utterly filthy to me
<shka>
shadowed
<shka>
not redefined
<White_Flame>
not even shadowed, but having a new thread-local binding for it
<White_Flame>
it's a great way to just let functions run, and redirect their output to wherever
<Guest92>
and scary
<White_Flame>
are pipes on the unix shell scary?
<Guest92>
no but then they're sequential
<_death>
if you want to call the COLLECT of the outer context, inside your inner COLLECT, then you can use FLET.. alternatively you could use a variable to hold a reference to it and funcall.. but why do that when you have FLET
<White_Flame>
there's nothing non-sequential about redirection in a lisp scope either
<Guest92>
except that I can mutate state on the moon, and behavior on pluto changes
<White_Flame>
yeah, that's why people don't do that :-P
<Guest92>
exactly
<White_Flame>
(let ((*standard-output* my-stream)) ...) is not a mutation
<White_Flame>
it's a thread-contained scope
<Guest92>
you said its a great way for functions to continue running and redirect output
<Guest92>
this implies that you're about to run a new function that has its own output
<Guest92>
sorry, this example
<Guest92>
but the statement implies that some funciton somewhere else is running and its about to have its whole career ended by someone else doing god knows what
<White_Flame>
no other thread can be running which will see that scope
<White_Flame>
any new function called within that scope will see the new binding
<White_Flame>
this is a feature that no popular language really does
<White_Flame>
and the problems of those other languages don't actually apply here
<Guest92>
APL has dynamic scope
<White_Flame>
because it's not a global mutation of the stdout slot
<Guest92>
so i get dynamic scope and what it does, but I stay clear the hell away from it
<_death>
my condolences
<White_Flame>
"popular language"s ;-)
<Guest92>
nah, life's honky dory over here without dynamic scope
andreyorst has joined #commonlisp
<White_Flame>
if you never use dynamic scope, then you always have to either mutate global scope, or pass around tons of contextual parameters manually even if they're not being changed
<Guest92>
Right, but then the idea is that programs should be a directional graph
<White_Flame>
(or create and mutate explicit scope objects that configure functions, etc)
<White_Flame>
the dynamic bindings are completely associated with the nesting of the call stack & its directional graph
<mfiano>
The parameter object idiom from Uncle Bob is here to the rescue.
<Guest92>
dynamic scope makes that graph all kinds of topsy turvy
tyson2 has joined #commonlisp
<Guest92>
what is that?
<White_Flame>
also, do you ever use thread-local variables?
<Guest92>
meaning?
<White_Flame>
TLS, thread local storage, etc
<mfiano>
A stupid piece of advice from the "Clean Code" series, of wrapping function parameters in objects if you ever have more than 2.
cosimone has quit [Ping timeout: 268 seconds]
<Guest92>
oh idk much about uncle bob except his reputation
<Guest92>
White_Flame I think that's most of the data I work with?
<White_Flame>
ok, so a big dynamic scope per thread is an exact implementation of thread-local storage, too
<Guest92>
I don't do much threading. Most of the applications I work on are some kind of event or data driven model, and small amounts of data from streams are processed, so I'm not really dealing with thread-safety issues
<Guest92>
because data is small and behaviors are deterministic for the most part
<White_Flame>
ok, so you actually never sit in a call graph for any appreciable length of cpu time?
<Guest92>
not actually
<Guest92>
the ones that I do are very flat graphs
<White_Flame>
that kind of programming usually externalizes all its state to a database
<Guest92>
Yes, either a database or further processing which will trigger other behaviors
<White_Flame>
if that's the case, then yeah you're not going to have much to do with larger stateful features in code, though the side-band parameterization of dynamic bindings for things like stdout, print styles, and other config is extremely handy, when the amount of parameterization for things is large
<Guest92>
What sorts of applications use the models you work with?
<White_Flame>
usually dynamic interactive data. I do a lot with inference, AI, and GUI abstractions
<White_Flame>
large ram footprint, high cpu appliactions
<White_Flame>
but most of the unique strength of CL, IMO, is its metaprogramming facilities
<Guest92>
A lot of the work I've done is monitoring streams at intersections of network layers and network barriers for packets, streams, configurations of devices, requisition of resources, etc
gaqwas has joined #commonlisp
<White_Flame>
which means you can basically write pseudocode, and have it directly expand and execute, using all these features to have hll->hll compilation directly at runtime
<pve>
Guest92: Here's a silly example where flet is a better choice than labels (at least I hope, it's getting late here).
<Guest92>
I think my problem at the moment is I did enough common lisp to trigger a change in my brain years ago... but I've forgetten most of it and I'm trying to reacquaint myself. I did a lot of macro practice and trivial code challenge typ things, but never built anything meaningful. I was only getting the hang of ASD before I moved on to APL for the
<Guest92>
past few years
<shka>
anyway, my code demonstrates how you can use flet (but not labels!) to implement poor continuations
<pve>
shka: your statement applies to my example as well :)
<shka>
pve: heh, i'll take it!
<White_Flame>
I'm honestly not a big fan of fine-grain event-based, rdbms-based applications. The actual code is clean, safe, and small, but the overall complexity of the application then has no real infrastructure (or externalized infrastructure) to try to wrangle it in a much more cat-juggling way
<_death>
pve: good example, but you need a nested loop there to show the difference
<White_Flame>
as what the program actually does is not directly expressed in the code anywhere, but is a gestalt of all the little micro-behaviors
<shka>
Guest92: anyway, the thing with CL is that a lot of it is geared toward the macro programming
<White_Flame>
so the complexity, IMO, is hoisted away without a good concrete expression
<pve>
_death: hmm I was thinking if escape-form wants to call a global (escape) function
<shka>
that's why you need to have very, very, very precise semantics for the most basic operators
<shka>
no sane person would write code in style like i have just did
<_death>
pve: ah, yeah, that'd work too
<Guest92>
White_Flame you are correct. It is very easy to write applications to where no one understands what is being done on what systems and what triggeres the events...
<Guest92>
And it requires discipline in organizaiton and documentation
<shka>
but from my experience, it is one trick in code generation that surprisingly can be useful
<Guest92>
but the networking world is the culprite, I don't think its the applications so much as it is impossible to observe network systems easily
<White_Flame>
in contrast, I like to express the entire system as a data spec or pseudo code, and have the behavior stem from there
<White_Flame>
it's possible with such systems as yours, but IMO needlessly makes it more complex
zxcvz has quit [Quit: Leaving]
<White_Flame>
yes, we do distributed, heterogeneous language systems, too
<Guest92>
White_Flame that's how I designed our application. data is the specification, so at any intersection you can view the contents of a message and should be able to understand that leg of the application
<White_Flame>
no, I'm not talking about message data
<White_Flame>
I'm talking about a spec for the overall system
<Guest92>
hmm
<White_Flame>
the actual workflow, orchestration, error response, etc definitions
<Guest92>
oh
<White_Flame>
and at that level, there can be little to no distinction between local and distributed
<White_Flame>
s/can/could/
<White_Flame>
and having that sort of control and high abstraction level code generation is great even for single-process, multithreaded programs
<White_Flame>
or even just defining individual library-ish components
<White_Flame>
and since metaprogramming is so easy in CL (as opposed to nightmarish in most other languages), it's used in the small, too, which eliminates boilerplate and reduces friction in writing code in general
<White_Flame>
something's annoying to implement, and you need to do it more than once? macro it out
<White_Flame>
which means that the tangible complexity for "large" single process applications shrinks
<White_Flame>
I put that in quotes, because the abstraction power of lisp tends to keep codebases from blowing up as big as most other languages do when the projects get big
<White_Flame>
and from this perspective, you can see my view that the manual fine-grain chopping up of workloads tends to be underneath a more powerful, comfortable level of abstraction
<White_Flame>
and in a practical sense, CPUs have way better throughput when they can do a ton of crunching at once, instead of always dispatching into little bit sized pieces of work
<White_Flame>
*byte-sized
<White_Flame>
(which of course can be a total batch processing time vs responsiveness time tradeoff)
<White_Flame>
((but then that's where a good threading discipline comes in, etc etc)
IUSR has quit []
waleee has joined #commonlisp
IUSR has joined #commonlisp
<Guest92>
I guess I don't have the experience with such applications to know what patterns are even involved with building them
Oladon has quit [Quit: Leaving.]
<White_Flame>
personally, I find it very frustrating to work on complex codebases that don't actually do a lot of ... computing. ;)
akoana has joined #commonlisp
<White_Flame>
but it is stil very challenging to get low latency high throughput network stuff, just a different challenge
yitzi has joined #commonlisp
rain3 has quit [Ping timeout: 268 seconds]
<White_Flame>
but even there, the ability to have good abstractions for your queues etc, and have each compiled & optimized (even at runtime) to your config or heuristic balance takes great advantage of lisp's strengths
cage has quit [Quit: rcirc on GNU Emacs 27.1]
<etimmons>
Shinmera: congrats on the Forge progression! I'm trying to understand it, but am getting tripped up on the `([ 1 2))` in the dependency list of 3. What does that mean?
jmercouris has quit []
jmercouris has joined #commonlisp
<Shinmera>
It means the version must be in the interval of versions 1 and 2.