libera/#commonlisp - IRC Chatlog
Search
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
3:04:08
beach
I admire everyone's patience with Guest92. That's a very strange way of trying to learn a language.
3:05:24
Guest92
Trying to reconcile the differences between two seemingly similar primitive forms in a language by trying to rearticulate it in my own words?
3:07:28
waleee
but you'd have to join their zulip since they jumped the irc-ship even pre freenode-calypse
3:08:36
waleee
one of the main maintainers is a huge fan of the socratic method when helping beginners
3:09:41
Guest92
The point isn't to be pedantic. What is the main activity one engages in when attending college? Likely writing, which serves the purpose of forcing the student to formulate their understanding in their own terms.
3:10:17
Guest92
What I learned earlier is that my understanding of flet and labels is correct, but my formulation wasn't
3:11:00
Guest92
It allows me to confront my assumptions directly, rather than concealing my assumptions until a later time when it becomes costly
3:11:13
hayley
I might be unable to navigate the documentation, but a thought I've found more evidence for is that it seems that the Common Lisp standard is unique in describing how you evaluate things, and not just describing the standard library.
3:16:01
hayley
The exceptions that I can think of are Standard ML, Scheme, TLA+ with operational(?) semantics, and Smalltalk-80 with a metacircular interpreter. Otherwise, it's like you're supposed to get the syntax, evaluation order, and everything else.
3:18:05
hayley
Nah, you usually find a description for types and syntax. But evaluation order is often not mentioned, for example.
3:18:25
Bike
easier to do when you can write your language at least somewhat as reduction rules, i guess
3:19:32
hayley
Right. But in languages without fancy standards, it seems that there is absolutely no discussion of evaluation order, not even that it is undefined.
3:20:34
hayley
It's not implementation documentation; you couldn't write some classes of programs in that language if you don't know the evaluation order.
3:20:38
Guest92
Most language docs treat the user as someone who just wants to know "how do I do x in y language" not "in this context x is evaluated to an intermediate value..." Yeah yeah, but what's the behavior?
3:20:41
moon-child
hayley: so you are saying: cl is somewhat unique in that it is standardised at all?
3:21:37
Bike
understanding the evaluation semantics in detail is actually useful for writing programs correctly, not just for implementing the language
3:22:49
Bike
do it vaguely and it's like C compilers for microcontrollers that can't apply optimizations because people keep writing empty for loops to pause execution
3:25:11
hayley
With the Pony language website, for example, I only see a tutorial and standard library documentation, and tutorials don't tend to be normative.
3:26:31
beach
hayley: With most languages no documentation is normative, because there is no standard. So, to me, there is then no "language" either. Just a programming system the behavior of which can change arbitrarily.
3:26:37
waleee
they have https://patterns.ponylang.io/ and some lectures but there's sparse docs available
3:26:37
hayley
One of the first parts of the tutorial states you use a program called "ponyc" to compile the program. Is an implementation which calls the compiler "pony-compiler" not a correct implementation of Pony?
3:27:38
hayley
beach: Yes, I suppose I am indirectly stating that most programming languages are just the description of one programming system.
3:28:35
beach
I mean, one of the first sentences I read was that Pony is "open source". I don't quite know how a programming language can be "open source".
3:29:38
hayley
But, even if the documentation is not normative, properties like eager or lazy evaluation are never explicitly mentioned. You're presumably expected to guess that is eagerly evaluated.
3:30:51
hayley
If I managed to teach someone programming only with Haskell and Prolog, for example, I am sure they would struggle to figure out any code in the tutorial, despite having "some experience programming already".
3:34:12
jcowan
moon-child: By bno means unique, There are ISO standards for Ada, Algol 60, APL, Basic, C, C++, C#, Chill, Cobol, ECMAscript (JavaScript), Eiffel, Forth, Fortran, ISLisp, Modula-2, Mumps, Pascal, PL/I, Prolog, Ruby, and SQL.
3:35:42
hayley
But still, Smalltalk-80, Standard ML and TLA+ have useful specifications without having any official standards.
3:35:53
moon-child
jcowan: hence 'somewhat'. I'm sure there are many more entries on this list https://en.wikipedia.org/wiki/List_of_programming_languages than languages that have been standardised
3:36:54
jcowan
There are also ANSI standards for APT, Common Lisp, Dibol, PL/B, Rexx, and Smalltalk (so there is an official standard for that). Scheme has an IEEE standard.
3:40:44
jcowan
SML never went through an official standards org, but its standard is very high quality, including its formal semantics.