freenode/#lisp - IRC Chatlog
Search
2:38:44
aeth
The main reason I wrote define-shader to translate from s-expressions to GLSL is because I kept slipping up in the syntax by switching back and forth between GLSL and CL and it was getting annoying.
2:51:56
attila_lendvai
this seems to do the trick: (setf uiop:*uninteresting-conditions* uiop:*usual-uninteresting-conditions*)
3:18:01
beach
flip214: I think I'll pass on the Alexandria issue. I have too many other things to do at the moment.
3:24:31
fouric
mfiano: would you, or anyone else, happen to know how to override evil-cleverparens' bindings?
4:23:31
krwq
got question, how do you convert string to utf-8 bytes? I've tried this but flexi-streams seem to be ignoring format: https://pastebin.com/DGkUCLnB
4:24:33
beach
If there is no library to do it, you would just have to apply the rules of UTF-8. They are not that complicated.
4:26:41
beach
ACTION now fully expects a complaint that the Common Lisp standard is deficient, since it doesn't define such a function.
4:33:49
Bike
if i understand the flexi streams manual correctly, in memory streams are binary, and don't have external formats so you can't use characters
4:35:09
krwq
beach: Bike: do you know any library providing a way to convert string to utf-8 without allocating new buffer (= using preallocated buffer)
4:36:43
Bike
(babel:string-to-octets "hello world" :encoding :utf-8) => #(104 101 108 108 111 32 119 111 114 108 100)
4:42:17
nydel
i'm curious why MOD and FLOOR both exist in any implementation i can think of. MOD in my mind being (CDR (FLOOR X)) ... is MOD actually quite a different program than that? documentation in sbcl or clisp offers little on how they are related.
4:46:36
beach
nydel: There are several possible explanations. One (very likely) is that MOD exists for reasons of backward compatibility with other Lisp implementations.
4:46:43
Bike
the clhs entry on mod says: "mod performs the operation floor on number and divisor and returns the remainder of the floor operation."
4:48:24
beach
nydel: Another one is that it is more costly in terms of performance to manipulate multiple values, so MOD is probably faster than to use FLOOR and then take the second value.
4:49:00
beach
nydel: And if you were right that FLOOR returns a list, then MOD would be WAY faster, because memory allocation is expensive as well.
4:50:26
nydel
i somehow have taken clhs out of my things-i-can-immediately-reach circle, i need to remedy that, thanks Bike
4:50:45
beach
But yeah, there are two common competing discussion here in #lisp. 1. Why is this very special function that I need not in the standard. I mean, almost everybody needs it right. 2. Why is this general function in the standard when the effect can easily be obtained form combining other functions in the standard.
4:52:34
beach
I am guessing that neither of these two discussions exist for languages that don't even have a standard, which seems to be what many people use these days. Somehow, having a solid, well tested, reliable, fixed standard, seems to be a disadvantage to a language.
4:54:30
nydel
but beach in a brighter pov my meaning was to find out "what's the thing i usually look at for a question like this?" and the answer was CLHS ... i have no opinion one way or the other on whether one/both exist, the question was about where i was failing to keep my documentation complete
4:55:36
nydel
i never feel that commonlisp is lacking in documentation, and that is largely i would believe because of it having a standard.
4:57:27
nydel
i definitely see the two points discussed in circles all over the place and never directly
4:57:48
nydel
enter pillton to directly address it right as i claim it's never directly addressed :)
4:58:42
beach
Both types of complaints, by the way, are typically aired by people who know nothing about language design, nothing about language implementation, and nothing about the history of Lisp.
4:58:49
pillton
Who needs these things to promote interoperability? #+(me) #+(and) #-(others) all the way down.
4:59:08
krwq
nydel: btw if you use emacs you can move your cursor on the symbol in slime and C-c C-d h
5:00:38
nydel
krwq: thank you - i haven't had a question like this in a while (i rarely use #'MOD but it came up in a japanese lisp book - a predict the day of the week function, you get it) so i forgot it exists(CLHS) .. good to have the keystrokes, thank you!
5:01:36
nydel
ok so pillton are you going to fork sbcl to sbcl-unstandardized-b'tches! or is beach gonna handle that
5:03:48
pillton
nydel: It took 10 years for me to find things in CL that I annoy me enough to transition from apathetic to emotional.
5:05:56
krwq
I'd be nice if beach's implementation was generic enough so that compilers can use it instead of their own
5:06:36
nydel
would be interested to look at beach's lisp if it is in some kind of version control repo or tarball etc
5:14:38
beach
krwq: The Cleavir compiler framework is meant to be just that. In fact, it is already used by Clasp for its main compiler.
5:44:12
krwq
beach: any ideas why is this (let ((.foo))`(,.foo)) saying that `foo` is unbound? (I know I can add space between comma and dot and that this is a bad idea to name vars like that)
5:51:14
fouric
beach: do you have a minute to elaborate on what "implementation-independent compilation framework" means (context: SICL)?
5:52:03
beach
It means that the compiler is written so that it can be customized to implementation-specific details.
5:52:26
beach
Otherwise, it is common that implementation-specific details are scattered all over the compiler source code.
5:53:08
fouric
(I'm just trying to find a few concrete examples of "implementation-specific details")
5:53:18
beach
But take the situation where the compiler needs to interrogate the environment for information about variables and functions.
5:54:14
beach
The Cleavir compiler defines a CLOS-based protocol for doing that, and it explains what an implementation must do to customize that protocol so that the Cleavir compiler can use it.
5:55:32
beach
Furthermore, the Cleavir compiler uses an intermediate form called HIR (for High-level Intermediate Representation) that is independent of how objects are represented in a particular implementation. On this representation, we can do several transformations such as type inference, escape analysis, etc.
5:56:08
beach
Again, your typical Common Lisp compiler will have object-representation details scattered all over it.
5:57:34
beach
There are a few instances where HIR (and also the preceding representation: AST) need to be customized for each implementation, but again, there are CLOS protocols put in place to make this customization straightforward, using auxiliary methods on generic functions.
5:58:14
beach
But take the SBCL compiler, for instance. It couldn't do something like that as easily, because it was designed not to use generic functions, for reasons of bootstrapping.
5:58:25
fouric
Hm. Let me see if I'm getting this right: would the following example be correct: Cleavir providing an implementation of FUNCALL that calls generic functions to get the symbol-function from a symbol, and each compiler implements the generic function that does so?
5:59:36
beach
Cleavir defines a generic function called FUNCTION-INFO that it calls when it needs information about a function (whether it's a macro, whether it has a compiler macro on it, its type, etc).
6:00:11
beach
One of the arguments to FUNCTION-INFO is a function name, and the other is an object representing a global environment.
6:00:59
beach
Implementations customize this generic function by defining a method on it that will specialize on some implementation-specific environment object, and then call the implementation-specific function to build the information that the Cleavir compiler needs.
6:01:42
beach
So, for example, SICL doesn't store the function in the symbol object, but instead in the environment objects, so the methods are very different in SICL and (say) Clasp.
6:04:28
fouric
I don't understand what "environment objects" are, but I think that I can guess at the relevant bits well enough to understand Cleavir's purpose as a whole.
6:06:09
beach
SICL has an explicit object that store the environment information, but most implementations scatter this information all over, like the function being stored in the symbol, and the type information in some hash table, etc.
6:08:39
beach
Mainly because nobody thought of a technique that have the same performance but a more modular environment object. Hence the paper. Also, for historical reasons.
6:08:45
fouric
...although this paper makes it sound like you implemented SICL's "global environment as first-class object" approach without much of a performance hit
6:09:01
beach
When people see SYMBOL-FUNCTION they immediately think the function must be stored in the symbol
6:10:30
beach
So, an implementation that does not have an explicit object for the environments will customize Cleavir by creating a dummy environment class that is only used for generic-function dispatch, and the method specializing on that class will just call the implementation-specific functions to gather the information.
6:13:59
beach
I know of no other Common Lisp compiler that has been specifically designed this way, which is why I call Cleavir an implementation-independent compiler framework.
6:14:47
fouric
Does Cleavir do any (native) code generation, or is that all deferred to the implementation itself?
6:15:12
whoman
afaik the GL world calls it a "reference implementation" - like how Mesa is sometimes used
6:15:34
beach
At the moment, it is up to the implementation. Mainly because the only client implementation is Clasp, and it already does its own code generation.
6:16:46
beach
fouric: It gets harder after HIR. The next layer is MIR (Medium-level Intermediate Representation) where object representations are exposed and address calculations are made explicit.
6:17:59
beach
fouric: The MIR layer requires way more customization than HIR, and it has not all been worked out. But we need it, because we plan to implement optimizations in MIR as well.
6:19:18
beach
I think I will first hash out MIR for SICL, and then see what generic function are needed to generalize it to other implementation.
6:20:10
beach
Oh, and MIR may also depend (at least somewhat) on the backend, like what kind of instructions the processor is capable of.
6:20:50
aeth
Is there any advantage to actually creating an object at compile time in a macro and using make-load-form instead of essentially generating code that will at run time create the object?
6:23:06
aeth
I essentially have an elaborate group of things that's done entirely at compile time, and then is just constant data by the time run time comes
6:28:08
aeth
fouric: Describe the hardware itself in Lisp, now that RISC-V exists as an open instruction set.
6:29:44
aeth
There are multiple efforts to generate JavaScript and multiple efforts to generate GLSL. So generating VHDL and/or Verilog probably wouldn't be too hard.
6:30:45
whoman
=/ curious why no other llvm efforts? theres several for a lot of langs, i notice today
6:38:34
beach
fouric: Sure. I feel like I had a very productive morning explaining important Cleavir concepts to at least one interested listener.
6:41:13
beach
whoman: Another reason is that LLVM is mainly a C++ library, so it is non-trivial to interface to, and that LLVM is mainly designed for compiling C++-like languages, so the fit is not perfect for compiling Common Lisp. Case in point, Clasp uses C++ exceptions to implement non-local exists in Common Lisp, and C++ exceptions were not meant to be used that often, so they are very slow.
6:42:00
whoman
beach: oh geez, that is terrible =( i did not know that. i thought JVM and CLR were specific enough already
6:42:03
beach
whoman: Yet another reason is that LLVM is a moving target, so that if one were to use some essential feature to implement Common Lisp, then that feature may disappear or get modified in future versions of LLVM.
6:42:04
Bike
i think that might be due to a choice to use C++ abi functions, rather than llvm itself strictly
6:42:38
beach
But then, LLVM does not suggest an alternative that can be used with Common Lisp or other similar languages.
6:43:02
Bike
well it has its own low level mechanism. i actually think it could be a good fit for CL, but i haven't gone into it much
6:43:33
Bike
it's built for C++ which sometimes, but not all the time, needs to execute arbitrary code upon exiting a scope, which is true for C++ with desctructors, and for CL with unwind-protect
6:44:57
beach
whoman: More reasons: Apparently, LLVM has problems with code that moves, probably because that doesn't happen in C++ since it doesn't have GC. So Clasp (as I recall) can currently not move code or recover space when a function is redefined.
6:47:13
beach
The right thing to do here would be to write a system similar to LLVM, but written in Common Lisp and designed for dynamic languages. It is a big project, but not huge. It would be much simpler than LLVM because of the superior abstraction mechanism we have at our disposal.
6:47:31
whoman
today i heard that c++ gets nasty-slow when it gets into a thing called 'chain of destructors' or somesuch. sounds scary -- been close to it in my day
6:48:09
beach
Bike: It probably seems bigger than it really is because 1. It is written in C++ and 2. It is designed to handle all the obscure stuff of C++.
6:48:15
Bike
whoman: yeah when you exit a scope you have to run destructors for any automatic-allocation objects, and those destructors can run other destructors, and so on
6:49:21
Bike
and there's lots of complicated stuff in there for, like, reordering conditions based on... path... I'm tired
6:52:01
jack_rabbit
Bike, Yes, I would be very surprised to find out there isn't. But beach has done far more work with it than I.
6:52:05
Bike
clasp has to do more conceptual work before it can even worry about that though. making sure we don't gc a function we're in the middle of, and so on
6:54:56
Zhivago
There's nothing particularly special about chains of destructors -- it's pretty much the same as unwind-protect.
6:55:49
Zhivago
The fundamental problem with destructors is that they don't make sense in systems with GC.
6:56:32
Bike
since you know when objects are released, you can use them for, basically, unwind protect
6:56:43
Zhivago
A destructor is code that runs sometime after the reference count to an object reaches zero.
6:57:12
Zhivago
Which is problematic for a destructor, since a destructor needs access to the object.
6:57:33
aeth
whoman: If CL was like SH, then "destruct" would be a thing with the api (destruct &rest ignored) that destroys your drive. Then you'd never be able to typo "defstruct"
6:57:47
Zhivago
Which means that the reference count is really above zero, and then you have the issue if what happens if the destructor generates new references to the object which would bring it above the destruction level?
6:58:12
Zhivago
Which is why objects in Java can be resurrected from the dead, and have to remember if they've been destructed or not.
6:58:17
beach
jack_rabbit: I have not worked with LLVM. I wouldn't. I am just following the discussions in #clasp.
6:58:42
Zhivago
Which is why GC systems that aren't designed by insane people used finalizer semantics instead, which do not involve the object that has been GC'd.
6:58:53
aeth
Bike: What changes would have to be made to bring RAII to CL, if that even makes any sense at all?
6:59:44
Bike
in CL we can just unwind protect to say "execute this when you leave this block" and we don't need to bother with tying it to objects
7:00:28
beach
whoman: Code that must be run sometime after an object is no longer accessible is problematic in all GC systems that explicitly do not touch dead objects, like copying collectors.
7:01:17
Zhivago
It just requires sharing those resources with a suitable finalizer, rather than mediating access to them through the object.
7:01:56
Zhivago
A more serious problem is the lack of generalized resource management integration with garbage collection.
7:02:32
Zhivago
If your GC is responsible for freeing up file handles, what happens if running out of file handles doesn't invoke GC?
7:03:34
Zhivago
If you have optional resources -- like file handles that could be closed or kept open for performance, who tells you that there's a shortage and would you kindly close the handles you don't really need right now?
7:04:32
Zhivago
GC allows all of these things to be deferred whereas RAII forces them to be eager -- and that requires a more thorougher design.
7:07:53
Zhivago
On the other hand GC is kind of a symptom of the problems of undisciplined shared memory, so perhaps it's just enabling the problems that it solves, and we might be better off by replacing it with restricted memory arenas.
7:10:32
Zhivago
If they're contained in an ephemeral process, maybe you just don't care, because you'll send the final non-garbage somewhere else, and then disappear.
7:11:15
Zhivago
(Which is a kind of GC, but with radically different requirements, since you can't just scribble on the one true graph of objects, since there isn't one.
7:16:13
Zhivago
Or you could say that GC is a problem of implicit persistent storage, and solve it by not having any.
7:18:19
Zhivago
But imagine if every function call happened in its own temporary process, receiving arguments via a message and sending a result via a message (effectively).
7:21:32
Zhivago
If the function is implemented as a procedure which happens to produce garbage, then you might need something if it runs out of resources to recycle that garbage.
7:22:02
Zhivago
But if it doesn't, then no recycling is required, and that recycling is what GC algorithms are about.
7:23:08
whoman
there is no argument. because listen, there is a law of relative space in effect here. objects cut from fabric cannot be larger than the original fabric. and so on, recursively as we cut out of the main fabric
7:23:34
whoman
at some point everything is recycled back to the fabric, all being 'temporary' -- there is always garbage being collected no ?
7:23:37
Zhivago
whoman: You appear to be gibbering. I will stop talking to you until you become coherent.
7:25:38
aeth
oh, hey, it might be a speed advantage to use make-load-form on things that are constant
8:58:55
hjudt_
i have a problem with dexador: if i use (dex:head "https://my-host/url" :verbose t :headers '(("Accept" . "application/json"))) then i can see in the server response it would send me json. but when i use (dex:get "https://my-host/url" :verbose t :headers '(("Accept" . "application/json"))), the server sends me back "application/xml". however, when i use wget -O - --header "Accept: application/json", the
9:00:24
hjudt_
(perhaps i should add that the server can respond with json or xml depending on the accept header i send it)
9:03:30
hjudt_
strange thing is that dexador verbose output tells me it does set "Accept: application/json". so what's the difference between dexador and wget here?
10:44:46
shrdlu68
hjudt_: Easiest thing to do is probably to inspect the traffic with something like wireshark
13:33:28
flip214
Shinmera: any ETA for ELS registration? No need to hurry, just curious. (And HR wants to know ;)
13:42:27
AeroNotix
Zhivago: your thing about temporary processes and making per-function calls in those slightly reminds me of Erlang.
13:43:06
AeroNotix
in Erlang each function is executed in its own "process" which is not a unix process but an actor within the beam vm. Each process has its own GC and GC happens in isolation from every other process.
14:34:15
AeroNotix
but each function is always executed within a process and all processes are executing concurrently
14:34:18
White_Flame
right, that's an ambiguous implication that to me read as a function gets its own unique process