freenode/#lisp - IRC Chatlog
Search
0:51:39
no-defun-allowed
if you can chase the last cons in the list you can append to the end very quickly
0:52:03
no-defun-allowed
eg the results of (macroexpand '(loop for n from 1 to 10 collect n)) might involve such cons chasing
0:52:19
sjl
Sure. I could also use the queue implementation I wrote a while ago... I'm looking for a portable built-in or one-liner equivalent
0:55:36
sjl
starting with a vector and v-p-e would work, but v-p-e's args are in the wrong order and CL doesn't have flip
0:56:49
sjl
well, if I had flip and could live with reversed output it could be (flip #'cons) I guess
1:21:36
sjl
exactly. if append doesn't solve the problem, nconc will only not solve the problem faster and more dangerously
3:53:11
beach
What is your intended use for CL-R? It is hard to give advice unless the purpose is clear. Like, why would you want to give up reflection?
3:56:48
beach
jcowan: Another way of asking the same question, I guess: What problem with full Common Lisp is CL-R meant to solve?
3:57:56
pfdietz
Perhaps it's intended for more minimal, static compiled apps? Sort of a scheme-like CL?
3:59:13
beach
I am not saying there is anything wrong with wanting such a thing. I am just curious about the goal.
4:14:25
jcowan
I don't have in mind to actually write such a compiler, just lay down the work for what such a compiler might reasonably accept
4:15:25
jcowan
The hope would be to be able to get good performance from a more naive compiler than SBCL or SICL.
4:17:05
beach
And for the size part, are you thinking of a small number of applications for an operating system like UNIX?
4:17:47
beach
I am asking this, because if you give up either one, there are simpler ways of obtaining what you want.
4:18:03
jcowan
"The Lisp community must listen to the marketplace, which has shouted small, small, small and efficient, efficient, efficient for two decades [as of 1992]" (Henry Baker)
4:18:38
jcowan
His proposals are far more radical than anything I have in mind, and indeed in some ways more radical than Scheme or Racket
4:19:26
beach
jcowan: I am asking because, if think you might have a large number of applications, you can put most of the code in a shared library, so each application would be small.
4:19:32
jcowan
I was actually thinking about embedded processors and other highly constrained environments
4:20:26
jcowan
By 2018 standards, essentially all 1992 computers, to say nothing of 1972, were highly constrained environments.
4:21:25
jcowan
With whole-program compilation, tree shaking is trivial: omit anything not in the call graph
4:26:14
jcowan
Not when someone's library has the complete works of Shakespeare embedded in it. (Sorry, can't find the reference offhand.)
4:28:13
beach
For example, in order for CLOS to be efficient, you need the compiler at run time. So you probably need to give up CLOS as well in order to get both small size and good performance.
4:28:50
beach
And then the language is so far removed form Common Lisp that the CL part of the name is probably no longer justified.
4:29:29
jcowan
Why do you need the compiler at run time if you only have a fixed number of immutable classes, all known at compile time?
4:36:01
aeth
jcowan: For instance, I've come to the exact opposite conclusion about "Using (declare (type ...)) is the least-desirable mechanism to use"
4:36:48
aeth
jcowan: I've actually put a substantial amount of work into making macros that handle both declare and check-type at the same time to silence the critics because declare is simply too useful not to use in implementations that handle it reasonably.
4:37:01
jcowan
Am I right to think that (eval-when (:compile-toplevel) ...) has the effect of making any defuns it wraps available at compile time only? That would be the Right Thing for procedures at (Scheme) phase 1; that is, used only in the implementation of macros.
4:38:01
aeth
Macro-implementation functions tend to be available all of the time, possibly for easier debugging/testing, and they often are in a separate file to avoid a giant 300-line eval-when
4:46:26
pillton
jcowan: I don't understand why you would do it this way. Why don't you implement a CL compiler which isn't restricted to fast LOADing?
4:53:15
jcowan
The idea is that because CL-R is supposed to have full access to CL at compile time, you can write compile-time-only functions (for use in macros) that invoke features not part of CL-R.
4:53:49
jcowan
CL-R functions would be implemented in CL-R (or C or whatever) and then just compiled with the user's program.
4:55:03
pillton
jcowan: They all have the load requirement though. i.e. Function bindings aren't immutable, class bindings aren't immutable, classes aren't immutable and so on.
6:30:57
elderK
I was doing backquote expansion in my dreams last night, coming to terms with ``(,,a) kind of thing.
7:41:52
no-defun-allowed
what packages are there for making ASCII-art cons trees? i remember seeing one in a book
8:15:03
LdBeth
#'no-defun-allowed: and there's one output to CLX also in there, althought only works on CMUCL
8:54:19
jackdaniel
jcowan: as of ECL, feel free to ask questions on #ecl channel, I'll try to answer what I can
8:55:11
jackdaniel
what may be interesting to you is that I plan to slowly convert ecl_min (which is an ad hoc lisp implementation for bootstrapping working inside ECL's CLR) to be a conforming EuLisp Level 0
8:56:15
jackdaniel
sure, but I'm suffering from a constant lack of time, this project is high on my priority list, but this list isn't short anyway
9:01:56
jackdaniel
as of lisp-1 / lisp-2 here, it is strictly interpreted, so modifying evaluator here won't be a big problem
9:13:37
ogamita
jackdaniel: if you can make a defpackage and load and run those programs in that package, then it's a subset of CL.
9:14:52
ogamita
jackdaniel: I mean, you defpackage in CL to define the subset language, exporting only what's in it.
9:15:33
ogamita
For example, if your bootstrap language doesn't have hash-tables, you can export everything but hash-table stuff (and but defpackage if it doesn't have it).
9:16:33
jackdaniel
I don't quite follow, but if possibility to bootstrap CL from the base language (given sources in some form) is enough to make that language CL subset then fine, it is CL subset by such definition
9:16:48
ogamita
There are a few things that would require more work, as if it uses modular arithmetic. Then it may be a superset of a subset of CL: you would have to implement modular arithmetic in CL to run those programs as intended.
9:17:39
ogamita
It's not the possibility to bootstrap CL, but the possibility to run on CL that makes it a subset language.
9:17:39
jackdaniel
well, I'm fine with any label you come with for ecl_min (I don't really care, if it is CL subset - even better)
9:18:28
ogamita
The thing is that it would be better if it was CL, second best if it is a subset. Then you can use any CL implementation to bootstrap ecl!
9:19:23
jackdaniel
only part of sources is compiled with CL, rest is part of libecl core runtime (implemented in C)
9:20:06
jackdaniel
so compiling ECL with another Common Lisp is not possible (unless you reimplement ECL's core runtime in Common Lisp)
9:20:53
ogamita
Wouldn't going toward this direction be better than toward EuLisp? Isn't it essentially dead?
9:22:21
jackdaniel
it is a minimal language with a good specification (in contrast to CL as a maximal language with a good specification)
9:23:59
jackdaniel
I mean with respect to doability to provide standarized language for bootstrap environment
9:24:50
jackdaniel
(safe and standarized, ecl_min at the beginning is very unsafe without any condition system for instance)
9:27:54
jackdaniel
(by strictly interpreted I mean: it is minimally compiled to bytecodes and bytecodes are interpreted, not cons structures)
9:29:41
jackdaniel
but before I even start to work on that higher on the stack are: green threads and delimited continuations (I have a working prototype locally), compiler refactor for different backends and fast gf dispatch
9:33:28
elderK
makomo: I think I finally understand! At least, I was able to write my own once-only!
9:34:10
elderK
I wrote the usual pattern that we use gensyms with. Then I thought, right, how do I generate that?
9:34:29
elderK
Then there's the business of remapping a or whatever to the gensym, so when the body says ,a it's really referring to the gensymed stuff.
9:34:46
elderK
Once I wrote the expected expansion in a normal macro, I then worked backwards from that to try and replicate it.
9:35:32
makomo
yup, that is a very good approach to developing macros imo -- you see a pattern (i.e. start from an example) and try to abstract it
9:35:33
elderK
makomo: So, I have learned for instance that ``(,,a) -> `(,b). I.e. we have two ,,s so we're going to patch something in. But we only replace the ,a, not the entire ,,a
9:35:58
elderK
I was confused by seeing ,,@(....). But I figured out that it makes sense: Whatever is spliced in, the , kind of distributes.
9:36:36
elderK
Then I learned that ,`(.....) is basically a nop. It just means "Carry the thing after the , into the expansion, verbatim."
9:36:51
dim
I have once again a bug report containing: There is no applicable method for the generic function #<STANDARD-GENERIC-FUNCTION PGLOADER.CATALOG:FORMAT-TABLE-NAME (1)> when called with arguments (NIL).
9:36:59
elderK
So for ,`(,b) well, the next level just has the (,b). When that's expanded, the value of b will be chunked in, etc.
9:37:27
elderK
makomo: I wound up doing some "silly things" like color-coding parts of the macro, to highlight "when things actually do shit"
9:37:29
dim
I'm fed up of having those function calls with a NIL argument where it should be an instance of something, usually that's because I'm using find or the like and it didn't raise any result
9:37:40
elderK
Mentally, it's still a little fuzzy. But it felt like jumping between realities :P lol
9:37:52
dim
is there in CL an approach like the Maybe option type that would help systematically address the NIL propagation>?
9:38:55
elderK
:P Or it could just be that I've memorized PCL's version. I guess I'll try again in a week or so and see if I realy CAN do it from basics without referring to PCL :D
9:39:39
elderK
It's not returning null. It's basically returning a value wrapper. You can get the result from that, or say : Oh, it's null.
9:39:53
jackdaniel
elderK: this doesn't tell me much (I knew some C++, but it could be before this option was introduced)
9:40:21
elderK
Okay, well, imagine you have a wrapper. This wrapper can store a value of whatever. BUt it also has a flag that says whether it stores something ATM.
9:40:39
elderK
So, instead of returning null, you return an instance of this wrapper. And you can ask it: Hey, do you have a value?
9:40:59
elderK
It's useful in situations where "null" is not a good error return value, because it would be a valid result, say.
9:42:30
elderK
One benefit, at least in C++, is that it also adds a sense of assurance. Let's say you return some NULL and use it without checking. Well, you're going to crash MAYBE at some point. Depending on waht happens.
9:43:48
dim
jackdaniel: it's basically a way to say that if you receive NIL as an argument, just return NIL already
9:44:20
dim
in PostgreSQL you can also create function x(...) returns ... return null on null input ... ; which does the same thing, conceptually
9:44:38
jackdaniel
another approach would be using filtered-functions which add preprocessing step to generic functions
9:44:49
dim
well because I would have to do that for a lot of generic functions, and then I have to check that every call point knows how to handle NILs too, etc etc
9:47:20
jackdaniel
yes, this maybe operator looks like a common lisp type which is not a class, and you can't specialize on such types
9:49:02
jackdaniel
dim: closest thing to handle such thing would be using filtered-functions, but I'm not sure if it buys you anything
9:50:04
Bike
conceptually it would be a class; the Maybe's equivalent to "nil" is a distinguished value not used for anything else, unlike nil
9:50:22
Bike
then haskell can use static typing information to avoid actually allocating anything when a function returns a Maybe.
9:50:45
jackdaniel
i.e you have a base class foo and two subclasses null-foo and sql-foo and if filtered function encounters nil it calls it with a null-foo instance
9:51:12
jackdaniel
(that way your method specialized on foo would handle proper data and null data when nil is passed there)
9:51:46
jcowan
I've just written implementations of Maybe and Either in Scheme, but not posted them yet: they would be easy to translate into CL
9:52:44
jcowan
jackdaniel: I'm trying to follow the ECL manual's instructions for building an executable. I get as far as calling c:build-program, but that symbol does not exist.
9:52:48
scymtym
but does Maybe automatically make all functions return Nothing when they receive Nothing as an argument? i thought that required Monad lifting or something like that
9:52:51
jackdaniel
Bike: I think that the gist of the problem comes from the fact, that NIL sneaks to the gf call, am I right dim?
9:53:39
jackdaniel
jcowan: did you (require 'cmp) ? also I don't think build-program is exported, you may have better luck with c::build-program
9:54:47
dim
jackdaniel: thanks for introducting filtered-functions, I like that approach... I'm not sure it's useful to prevent the class of bugs I have in mind now, though
9:55:00
Bike
as wikipedia more or less puts it, (>>= mx f) = (if (justp mx) (funcall f (just-value mx)) none)
9:57:10
jcowan
but now when I run the executable my program runs and then drops into the ECL REPL. Is that expected? If I explicitly call (ext:quit) all is well.
9:58:52
jcowan
https://bitbucket.org/cowan/r7rs-wg1-infra/src/default/MaybeEither.md is my docs for the Maybe/Either library
10:01:37
makomo
elderK: although some people don't agree with that (and neither do all of the implementations), but that's why we had that wager the other day
10:02:09
elderK
makomo: Well, it seems if you expand it out the long way, then "collapse" it back into shorthand, you get what looks like distribution.
10:03:17
makomo
jackdaniel: i took a quick look but right now i have 4 exams coming up next week, all 1 day apart. i want to do it properly and make a detailed analysis, but i can't do that without failing my exams :-)
10:04:03
jcowan
Bike: I've specced out but haven't written a general monad library. But yes, without static types you have to pass the monad instance (a struct of functions) explicitly to each monad operation.
10:04:25
jackdaniel
elderK: only sbcl supports ,@,@ and imho it is not portable CL, I've pasted my analysis a few days ago
10:04:44
Bike
i mean, with a cl generic function, it could be done, but there'd be run time checks of course, and you'd have to trust the mfunctions are ok
10:05:58
dim
well I guess in practical terms I have to care everywhere that I don't get a NIL where my code expects something else, and that's going to be a large amount of work because I didn't do that thoroughly from the beginning
10:06:22
jcowan
The trouble with using a gf is that you can only have one monad instance per CL's idea of a class, which is restrictive. When it comes to monoids (which it will), how would you provide both Sum and Product without wrapping numbers in a class, making them unusable as numbers?
10:07:27
elderK
jackdaniel: Thanks jackdaniel :) I was just thinking about it. It would be pretty crazy to see it used.
10:07:42
elderK
jackdaniel: I'll have to consult the CLHS again to see if it's like, iono, disallowed.
10:19:25
elderK
My mental model is the case where '`', ',' and ',@' are just shorthands for operators.
10:20:11
jackdaniel
this discussion was not about intuition but about conforming Lisp code, I can imagine having such intuition
10:21:49
jackdaniel
and last statement (that first two strategies are incorrect) is not well thought through, reader doesn't necessarily return a cons structure, but still third strategy is more convenient and also conforming. either way, conclusion that ,@,@ can't be used in portable code due to ambiguity stands.
10:22:02
elderK
Aye, I see that. You've raised good points. Although, I'm not sure I can fully appreciate those points just yet :)
10:51:19
jackdaniel
https://nullprogram.com/blog/2018/11/21/ (Why Arent' there C Converences, first sentence "Heck, even Lisp has one." linked to ELS ^_^)
10:54:43
jcowan
Bike: You declare two static type synonyms for Number, Sum and Product, each of which can be an instance of Monad.
10:56:45
jackdaniel
yes, I think that was a pretty uneducated sentence (that's why I found it funnY), also you may do more interesting things in Lisp
10:57:52
jackdaniel
it isn't dead, there is just not much to talk about (wrt C) - it is not extensible whatsoever. it evolves though
10:58:25
jackdaniel
_death: well, sentence implies, that it is suprising Lisp has a conference (like as if it is a dead language)
10:58:28
aeth
idk, language popularity measurements are all pretty arbitrary and have wildly different results so I propose the language conference language popularity measurement. ;-)
10:59:50
_death
jackdaniel: maybe it's more about exposing the general readership to the fact that it exists ;)
11:00:31
jackdaniel
I've presented my interpretation of it, I'm not insisting in others agreeing with me, still I found it funny :)
11:01:28
_death
https://european-lisp-symposium.org/2018/index.html look up the author's name under Committee
11:02:51
jackdaniel
alright, I concede it is hard to believe he is uneducated ;) still this sentence sounds (to me) as if he is
11:26:09
shrdlu68
Someone describes something they made as "Written in Rust, a modern, low-level, high-performance language without garbage collection."
11:27:08
jackdaniel
jcowan: it is expected, default value of epilogue-code for :program is `(si::top-level t)
11:27:20
Bike
a language arising from the wide scale and far reaching transformations in western society beginning roughly after world war one
11:27:49
jackdaniel
remember to wrap your toplevel function in a handler-case if you want to avoid suprises
11:28:38
jackdaniel
(i.e unwind-protect not being executed on error which is not handled anywhere up the stack)
11:29:33
jcowan
Bike: I would say that the modern (phase of) languages begins around 1650, at least in Europe.
11:30:17
_death
witten in Common Lisp, an ancient, multi-level, high-inducing language without garbage.
11:32:23
dim
Common Lisp is first of all a very modern programming language for me, even more so when compared to Python, C, Java, PHP, or some others that I've been using
11:34:33
dim
there are so many useful things in the language, in ways that other just can't think about (multiple dispatch, control flow operators, conditions, standard types as classes, interactive debugging by default, running your own code at compile time with defvar/defparameter, and so much more, macros and reader macros of course)
11:35:00
shrdlu68
"Scala combines object-oriented and functional programming in one concise, high-level language."
11:35:06
jackdaniel
i.e things like update-class and elaborate condition handling is something very modern and tailored especially for a lasting solutions
11:35:21
_death
Odin hanged himself upside down for nine days to discover the secret of Common Lisp...
11:36:40
dim
jackdaniel: sometimes I want to play around with LFE (a Lisp on-top of Erlang), where hot code reloading in a distributed cluster is a normal thing to do... ;-)
11:37:26
jcowan
I think it's fair to say that Go, Ada, and Algol 68 are concurrent languages: the concurrency is a language feature, not a library feature. (I grant that this distinction is not very relevant to the Lisps.)
11:38:19
dim
what Erlang guys said is that if you want to have software that runs without downtime, first thing you need is being able to patch it while it's running, because you will have bugs, and specs will change
11:41:11
jcowan
But note that in Erlang the unit of replacement is whole modules, not individual objects, and only one old version is allowed as opposed to an arbitrary number of versions in CL. (Granted, this restriction could be lifted in an Erlang runtime.)
11:51:56
jcowan
Version skew is still a problem even in shared-nothing architectures. I had to make a last-minute patch to my back-end change that added a new key to a JSON request from the front end, because we had to deal with the fact that for perhaps 15 minutes old front ends would be trying to talk to new back ends, which would crap out for lack of the field.
11:52:15
jcowan
The fact that we didn't think of this until the day before release is the disturbing part.
11:58:24
zigpaw
you also have the support for rolling updates in kubernetes - as an example of completly different approach to the zero-downtime problem.
11:58:25
dim
compatibility matrixes, dependencies, ordering pushes to productions of independant components, yeah it's hard
11:59:37
dim
zigpaw: does it solve changing the current state in the application? that's what Erlang is very good about...
12:10:25
shrdlu68
Most codebases not written specifically with that in mind would require significant change.
12:26:59
dim
yeah that's where Erlang is very strong, statefull and hot code reload, plus other things, I really enjoyed using it back when I had to
12:36:09
zigpaw
shrdlu68: yes, as I have mentioned - it is a completly different approach. Inferior in some ways, but that's how other people are dealing with this problem.