libera/#commonlisp - IRC Chatlog
Search
8:58:57
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)
8:59:49
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
9:00:23
lisp123
It gets rid of alot of the staging clutter that one may have to introduce by specifying lexical scope
9:00:27
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.
9:02:04
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.
9:02:55
contrapunctus
akater[m]: Org and Magit are...unfortunate relics of the past, same as Emacs, same as 99% of software.
9:03:17
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.
9:04:37
beach
Speaking of which, let me renew my suggestion for a McCLIM-based application that combines the features of Magit and gitk.
9:05:18
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.
9:05:46
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
9:06:32
mfiano
I am not a fan of implicit global state. I would rather be explicit with the client API
9:10:35
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
9:10:40
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.
9:10:55
lisp123
Most functions work on current-buffer, but you be explicit on which buffer to work on
9:20:59
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...
9:21:04
jackdaniel
I'm using it sometimes to add a protocol class to an unrelated 3rd-party class when I want to incorporate it
9:26:55
rain3
https://github.com/ahefner/piddling-plugins <- uses stealth-mixins to achieve dynamic plugin effect
9:35:33
_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?
9:40:53
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
9:43:30
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.
9:44:04
jackdaniel
well, there's also that these paywalls shield public from accessing knowledge funded from public money ,)
9:44:30
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
9:45:00
rudi
so - sci-hub away! It's good for everyone except Elsevier's bottom line and they can go *** ***** ****
9:45:11
mfiano
Right that was my point, and jackdaniel touched on the other aspect I was going to comment on...._publicly_ funded research
9:46:08
rudi
beach: while I'm procrastinating - have you looked at tree-sitter? They use GLR for incremental parsing and most-likely-error-location
9:48:23
rudi
beach: it seems to work in practice, if not in theory. (It's quite recent, maybe 3-4 years old)
9:49:08
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.
9:53:30
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
9:54:54
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.
9:55:03
_death
it might be better than regexes, but CL's syntax is very context-dependent, so perhaps tree-sitter won't be too useful..
9:56:22
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.
9:57:45
_death
I was somewhat disappointed that each language had a totally independent parse tree representation, without some baseline or higher level commonality..
9:57:58
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.
9:59:29
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.
10:00:07
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.
10:02:36
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)
10:03:53
mfiano
I have a hard time finding practical solutions to problems using the MOP for the stuff I work on.
10:04:22
jackdaniel
that's why I've mentioned amop, that gives you some "mindset exposure" I suppose
10:05:40
_death
Object-Oriented Programming: The CLOS Perspective.. it has some nice papers about CLOS and MOP
10:16:47
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
10:16:47
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
10:16:47
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.
10:17:48
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.
10:21:57
beach
hayley: You wouldn't believe how many times I corrected jimka's dissertation for strange places for "only".
10:22:16
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.
10:22:25
_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 ;)
10:22:36
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)
10:24:06
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".
10:25:15
jackdaniel
despite knowing emacs on a level to use it daily it still pisses^wamuses me with its warts
10:25:59
hayley
(Last week I got to remark to my classmates that I found the "crash Emacs" button. It hasn't crashed before.)
10:26:14
beach
I am thinking that Second Climacs could be a solution. It is not particularly tied to any keys and such.
10:26:46
jackdaniel
emacs has cua mode as well, I don't think that keys are the, ekhm, key problem :)
10:27:54
jackdaniel
I don't remember the exact actronym, but cua is "standard shortcuts - C-c for copy, C-v for paste etc)
10:28:36
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)
10:28:51
White_Flame
at least home/end keys, and ctrl-del/shif-t-del/shift-ins generally work nowadays
10:28:58
beach
jackdaniel: So what is the problem with Emacs, and why could that problem not be solved with Second Climacs?
10:30:09
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)
10:31:00
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. :)
10:31:21
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
10:32:04
jackdaniel
so I'm struggling to reposition my windows so I can have a look at _what I'm currently doing_
10:32:24
jackdaniel
yes, I've tried a few but all that amounts for a pain. Currently I'm storing the frame layout in a register
10:32:31
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 :)
10:33:50
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
10:34:41
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)
10:34:52
White_Flame
this is also why I always push back as emacs being an "IDE". It's not, it's just a general editor
10:36:07
jackdaniel
needless to say, marketing-wise having LSP implementation for CL would be beneficial for folks with random editors like vscode
10:36:15
White_Flame
emacs is not very integrated as far as the editor's awareness of your project/workflow is concerned
10:36:39
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 |#
10:43:09
mfiano
jackdaniel: LSP would be a step backwards as the protocol lacks too much required by CL, and poorly defines others.
10:44:15
jackdaniel
supporting worse *and* providing better solutions sounds like a good pitch, doesn't it?
10:45:16
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!
10:47:40
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.
10:49:05
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.
10:53:02
mfiano
yitzi: I was just stating that editor implementation support is lacking compared to LSP, making it not very far reaching or robust.
11:53:12
_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
11:53:13
_death
functionality, but maybe instead have an install-stealth-mixin operator (and have a remove-stealth-mixin operator)
13:14:01
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)) ...)
13:17:14
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).
13:21:05
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.
13:21:31
mfiano
This becomes important in my own codes at least, as I use progn method combination a lot with mixins :)
13:23:09
mfiano
In our codes, our define-* macro includes information for a topological sorting of mixin classes
13:23:28
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.
13:26:58
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
13:27:28
mfiano
It could be made more dynamic this way, changing the class of an arbitrary standard-instance at runtime for example
13:27:33
_death
with an install operator you can have a single class be a mixin for multiple victims, for example
13:30:25
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.
13:32:02
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
13:33:23
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.
13:47:50
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 :)
13:51:31
mfiano
Well they suck. The backtick is a stylized single "close" quote, very hard to differentiate between a quote character unless you look carefully.
14:07:43
jcowan
I doubt that's the font: some upstream process is trying to change straight to curly quotes, even in code.
14:14:06
mfiano
_death: is the "observer" pattern useful in Lisp? I'm not aware of what exactly this pattern is without reading GOF...
14:15:35
mfiano
I was under the impression most design patterns were invented to work around the design mistakes of class-centric object systems
14:18:18
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
14:19:03
_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
14:19:17
rain3
http://faculty.chas.uni.edu/~wallingf/teaching/172/materials/session13/ the observer pattern
14:19:29
mfiano
I usuallly handle that problem with a progn method as to not couple that information to the subject
14:20:49
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.
14:22:07
beach
Well, I guess any generic function specialized to any standard class at the very least.
14:23:49
mfiano
In recent codes I push messages to a queue, and eql specialize progn listener methods on the type of message.
14:24:11
_death
and with traditional observer as in the GoF book, iirc, you can add/remove listeners to particular instances
14:24:29
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
14:25:16
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"
14:25:33
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
14:25:50
_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
14:26:45
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
14:27:39
rudi
oh, thoroughly agreed about this! Check out Norvig's "design patterns for dynamic languages" if you haven't yet
14:27:44
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"
14:27:46
random-nick
saltrocklamp[m]: that would mean the observer pattern could just be an observable mixing?
14:28:30
_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"
14:28:54
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
14:29:22
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
14:29:58
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
14:30:03
rudi
Here's a pattern talk I enjoyed: https://www.deconstructconf.com/2017/brian-marick-patterns-failed-why-should-we-care
14:31:12
rudi
salt rock lamp: Hmm, my introduction to Alexander was a chapter in Gabriel's "Patterns of Software"
14:32:03
rudi
and "The Nature of Order" for an old-man, "I finally understood this" summary of his life's work
14:32:11
_death
rudi: interesting.. I don't think I've read Alexander's books.. or if I did, only a small part
14:41:47
_death
later on Naggum wrote a post about a split-sequence operator design which considered syntax-related patterns
14:44:54
rudi
It possibly involved EN but I distinctly remember Gabriel popping up while everyone was dunking on both the GoF book and patterns in general
14:51:06
rudi
It's in that thread, yes: "Here's another true statement about patterns: If there are no such things as... (full message at https://libera.ems.host/_matrix/media/r0/download/libera.chat/a1b3877c7832a07364bcb32a8090be3cf9639e06)
14:58:39
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.
15:26:50
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.
15:38:28
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.
15:40:41
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
15:56:03
Shinmera
Heck yeah, I made a big step with my new build system, Forge: https://filebox.tymoon.eu//file/TWpNMU9RPT0=
15:56:39
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.
15:58:16
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.
15:58:59
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.
16:00:59
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.
16:08:39
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
16:08:41
Shinmera
potentially compiled to) fasl. The policy could decide on one or the other if it matters to you.
16:39:17
CptJimKirk
lotuseater I would like to know about dfns and trains, and whether they exist in April
16:41:51
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
16:43:16
lotuseater
a big subset of APL is implemented and still much potential for what could be done
16:44:42
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 ⍺
17:39:00
Guest92
(which for whatever reason my brain is reducing to [W]est [C]oast CL??? stupid brain)
17:42:38
Bike
i don't know if there's any comprehensive table, but there kind of aren't a lot of pairs like that
17:46:22
Bike
n/sublis, n/subst(-if(-not)), append/nconc, revappend/nreconc, n/butlast, n/intersection, n/set-difference, n/set-exclusive-or, n/union, n/string-upcase etc, n/reverse, n/substitute(-if(-not)), remove/delete(-if(-not)), remove/delete-duplicates
17:46:45
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."
17:49:11
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.
17:49:28
shka
if there would be new CL standard, chances are that remove-if-not would be simply omitted
17:50:11
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
17:50:34
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.
17:53:11
mfiano
Yeah I thought as much. The global environment would have to be used and cleaned up afterwards at best.
17:55:18
Guest92
I thought labels was flet but I can refer to a name bound within the same ... ... what ever you call it?
17:55:59
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
17:56:04
Guest92
I thought that's the difference between flet and labels that I can mention f in g in labels
17:57:18
Guest92
my point is, in any other language, just use a different name? a more specific name?
17:57:49
shka
Guest92: so this code may look weird, but it is something which can be used as a paradigm when programming macros
17:58:08
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
17:59:54
Guest92
but isn't that handled by the dispatcher and not the scope in which the function is called?
18:00:42
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
18:01:12
Bike
I'd say the basic reason for flet/labels is less about the best way to name things and more about simple semantics
18:01:15
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
18:01:27
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)
18:01:38
shka
i don't think i can put this any other way, but different semantic leads to different name in lisp
18:02:40
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
18:03:08
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).
18:04:02
Guest92
(defun f ...) (another (play (labels ((f ...) (g ... (f ...))) (f ... this f is the same name as the other one, but "here"))))
18:05:59
shka
so you would rather do something like (labels () (stuff)) for recursive use case and (labels (:recursive nil) (stuff)) ?
18:07:50
Guest92
I have said "what are the differences between flet and labels except g calls f" like 5 times
18:08:31
shka
Guest92: the difference is that local function defined with labels can call itself, and the function defined with flet can't
18:10:01
Guest92
that's what a sensible person would do, use a different name instead of the same one
18:10:37
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.
18:11:27
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
18:12:30
Bike
The only difference is how the binding works. That's it. There are no other differences.
18:12:32
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
18:12:49
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.
18:13:01
Guest92
maybe I'm using pleb, non-chad CL terms because I don't know what the words are for things
18:13:18
Bike
Your terminology is fine, but I think you are confusing an issue of style with an issue of semantics.
18:13:46
Guest92
"The only difference is how the binding works. That's it. There are no other differences."
18:14:56
Guest92
is the availability of the names within the "binding area" as in "the parens within which the names are bound
18:15:27
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.
18:17:35
shka
Guest92: yes, because we agree with semantics, i don't understand what we are disagreeing on
18:17:36
Bike
Look, if I write (+ 2 2), and I want 5, and you say "just write (+ 2 3) instead", that's a different program.
18:18:27
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.
18:18:29
shka
Guest92: ok, so can you state that you think that labels can do everything flet can and more?
18:18:34
Guest92
flet is needlessly restrictive because if you just named things well you wouldn't need its behavior
18:19:07
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.
18:19:59
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.
18:22:31
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.
18:22:34
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"
18:23:23
Guest92
I would actually like to know so I don't go around making blunders all over the place
18:23:44
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.
18:23:47
Guest92
if it is changing program behavior, I should like to know what the difference to my program is
18:24:40
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
18:25:39
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.
18:25:47
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
18:27:20
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.
18:27:57
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
18:28:21
White_Flame
so all evaluation happens "outside" the binding, and the binding happens in parallel
18:28:59
White_Flame
if you want to have this sort of visibility with function parameters, you need to nest a separate binding before the call
18:29:37
_death
if you think FLET is silly, always use LABELS?.. maybe one day you'll find that you need FLET after all
18:30:55
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
18:31:46
Guest92
@_death I didn't say I think flet is silly, I said constantly rebinding existing names to other names is silly.
18:32:00
White_Flame
Guest92: I gave you explicit examples of where/when such nesting is necessary in general
18:33:10
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
18:33:13
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
18:33:44
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
18:33:56
_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
18:34:08
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
18:34:53
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
18:35:45
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
18:37:12
_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"
18:37:56
Guest92
i really don't know what the problem is... this is basically the beahvior of any other lexically scoped language
18:38:35
Guest92
so obviously if you define global-x, but then you have local-x, then when you call x it refers to local x
18:40:38
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
18:41:20
_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
18:42:43
Guest92
but then I remember something about *stdout* and *stdout* getting redefined in loads of differenct contexts for some kind of socket library thing
18:44:49
White_Flame
it's a great way to just let functions run, and redirect their output to wherever
18:45:15
_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
18:47:27
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
18:50:15
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
18:51:12
White_Flame
the dynamic bindings are completely associated with the nesting of the call stack & its directional graph
18:52:44
mfiano
A stupid piece of advice from the "Clean Code" series, of wrapping function parameters in objects if you ever have more than 2.
18:54:49
White_Flame
ok, so a big dynamic scope per thread is an exact implementation of thread-local storage, too
18:55:03
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
18:56:04
White_Flame
ok, so you actually never sit in a call graph for any appreciable length of cpu time?
18:59:49
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
19:00:50
White_Flame
usually dynamic interactive data. I do a lot with inference, AI, and GUI abstractions
19:02:28
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
19:03:00
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
19:03:17
pve
Guest92: Here's a silly example where flet is a better choice than labels (at least I hope, it's getting late here).
19:04:22
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
19:05:15
shka
anyway, my code demonstrates how you can use flet (but not labels!) to implement poor continuations
19:05:54
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
19:06:21
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
19:06:41
shka
Guest92: anyway, the thing with CL is that a lot of it is geared toward the macro programming
19:07:00
shka
that's why you need to have very, very, very precise semantics for the most basic operators
19:07:46
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...
19:08:21
shka
but from my experience, it is one trick in code generation that surprisingly can be useful
19:08:34
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
19:08:38
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
19:08:50
White_Flame
it's possible with such systems as yours, but IMO needlessly makes it more complex
19:09:24
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
19:10:26
White_Flame
and at that level, there can be little to no distinction between local and distributed
19:11:09
White_Flame
and having that sort of control and high abstraction level code generation is great even for single-process, multithreaded programs
19:12:29
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
19:12:49
White_Flame
something's annoying to implement, and you need to do it more than once? macro it out
19:13:17
White_Flame
which means that the tangible complexity for "large" single process applications shrinks
19:13:56
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
19:14:45
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
19:16:08
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
19:16:43
White_Flame
(which of course can be a total batch processing time vs responsiveness time tradeoff)
19:21:27
Guest92
I guess I don't have the experience with such applications to know what patterns are even involved with building them
19:25:52
White_Flame
personally, I find it very frustrating to work on complex codebases that don't actually do a lot of ... computing. ;)
19:26:13
White_Flame
but it is stil very challenging to get low latency high throughput network stuff, just a different challenge
19:27:39
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
19:30:58
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?
19:50:59
etimmons
Ok. I think it just threw me for a loop that it was terminated with a closing paren
19:52:10
Shinmera
etimmons: It's not terminated with anything, heh. [ is just used for the indicator.
20:23:02
pjb
Guest92: have a look at http://informatimago.com/~pjb/files/lisp/common-lisp/flet-or-labels.png