freenode/#lisp - IRC Chatlog
Search
16:51:16
p_l
beach: well, environment that is accessible... For LispM the equivalent would be to write some utility functions and (on symbolics only) a Command Processor applet
17:10:56
aeth
I think a lot of people think that there are two kinds of languages, "systems languages" and "scripting languages", and that there is a clear line between the languages, even though these terms describe roles not languages. For instance, CL can do both. And this division makes it unclear where to place languages like Java and C#. And, of course, Wikipedia lists 5 different kinds of "scripting". https://en.wikipedia.org/wiki/Scripting_langua
17:14:17
aeth
Imo, the only reason some general purpose languages are called "scripting languages" is because their current implementations are too slow. You can obviously use any general purpose language for anything, but performance requirements might restrict your choices.
17:14:43
aeth
makomo: And, yes, I was as vague as possible but the more you add to it (and it's often things like you said), the less accurate it is.
17:15:28
aeth
Or they'll talk about the interpreted vs. compiled benefits and drawbacks and literally all of the benefits of "interpreted" would also apply to SBCL, which is AOT compiled.
17:16:01
TMA
there are several layers of meaning to 'scripting language'. without a proper clarification the term is almost but not quite useless
17:16:15
aeth
dlowe: Okay, you're right about that. And another one that doesn't apply to SBCL is "sandboxing".
17:16:28
aeth
dlowe: But if it's a list of 20 only those 2 won't apply to SBCL and thus are actually inherent of interpreters.
17:33:40
Bike
but it has a few holes as far as sandboxing goes. that's not what beach came up with them for.
17:35:42
jmercouris
makomo: surely you recognize teh difference between an interpreter and a compiler right?
17:37:02
scymtym
Fare: speaking of cl-launch (hours ago, admittedly), could you clarify the license? (see https://gitlab.common-lisp.net/xcvb/cl-launch/issues/6 )
17:37:39
shka_
Bike: well, being able to actually use SICL as your lisp implementation would be cool
17:37:47
pjb
dlowe: it's not because it's an interpreter that: 1- the language is easy to understand and program with, 2- the system provides you with a REPL and a good interactive debugger.
17:37:58
makomo
because somehow for them, a compiler between two languages, of which neither is machine code, is not a real compiler
17:38:01
aeth
makomo: "transpiler" is shorter than "source-to-source compiler" and everyone still knows what you mean
17:39:31
jmercouris
I think the distinction here is that a transpiler is not intended to produce machine code
17:39:44
pjb
makomo: Once you have an implementation of a language, (be it a compiler or an interpreter or anything else), you have a machine for that language, so programs written in that language are machine code (for that "virtual" machine).
17:39:52
jmercouris
whereas a compiler is usually intended, or at least connotated with producing machine code
17:40:51
makomo
true, but that's how the terminology becomes fuzzy, because people use "compiler" and "interpreter" to mean a lot of things
17:41:02
pjb
the abstraction is the T forms for compilers, the V forms for machines and the I form for interpreters.
17:41:53
makomo
but formally, the processor is an interpreter for machine code, although it's implemented in hardware
17:42:23
aeth
makomo: Because over time interpreters look more like compilers and compilers look more like interpreters. Just like any other division in languages. Although some divisions are going away faster, like static vs. dynamic typing.
17:43:12
makomo
the difference between the two is fine, but the meaning of "interpreter" itself is fuzzy
17:43:29
makomo
people call main python program an interpreter, even though it does the exact same thing as java
17:45:34
makomo
i also think of it as an interpreter, because it reads the java bytecode and "executes" it
17:45:41
aeth
jmercouris: There is only one meaningful distinction in programming language design. "blub" and "Lisp"
17:46:15
makomo
i always wondered about the Blub thing, how do we know, as lispers, that lisp isn't just another blub that we can't see past :D
17:46:58
aeth
dlowe: Obviously the point was that Common Lisp is yet another blub and Arc is the way forward.
17:47:22
jmercouris
I believe we should be programming in assembly, it places no limits on the programmer
17:48:06
dlowe
I had that idea and it turns out that assemblers are actually annoyingly large and complicated.
17:54:10
aeth
I think the biggest confusion in language categorization is probably dynamic vs. static typing. e.g. CL is not dynamically typed. Some implementations might be. SBCL is gradually typed, but afaik most of the error-catching benefits of static types stay within one file.
17:57:25
pjb
You cannot really say lisp is dynamically typed, opposing that with static typing, because this is not the most meaningful distinction of the lisp type system.
17:57:51
pjb
What lisp does, is to assign types to values, instead of assigning it to variables like it's done in "statically" typed languages.
17:59:28
Bike
the type system does a bunch of different things that don't always cohere together. values being typed instead of variables is a pretty good start though.
17:59:30
aeth
In SBCL if you use type declarations, it does static type checking within one file or compilation unit. It then also does dynamic, runtime type checking on those type declarations unless (safety 0)
17:59:49
pjb
When you have values lost in memory, in lisp, they still have their type. The garbage collector can find them, and call their finaliser function. But in usual C implementations, if there's no variable to refer to the value, then the value is just bits, without a type, and nothing can be done with them.
18:00:53
aeth
At the very least, if you view it as dynamic xor static typing, SBCL does blur the lines, and other languages are finally catching up there, too
18:03:01
pjb
I would just say that there are compilation-time analysis, local or global analysis, and there are run-time ("JIT") statistics and checks, and that you can use both to optimize the processing.
18:19:52
aeth
Lisp has a different view of compilation time than most compilers. (eval-when (:compile-toplevel) (uiop:launch-program "ksudoku"))
18:38:50
pjb
Write a lisp program using midi to generate this static: https://www.youtube.com/watch?v=hgll-XTqcS4
19:08:24
edgar-rft
whartung, there indeed are/were several programs for midi recording by turning midi-events plus their timestamps into Lisp code
21:01:25
p_l
CL is dynamic/strongly typed language. The former because of runtime type checks (with gradual static support as optimizations in compilers), the latter because it has a very strong notion of what a type is etc. (a bit too strong, in a sense, with satisfies)
21:18:48
Xof
mgsk: none at all. (I was only a speaker, not the poor victim who has to edit the videos)
21:20:02
aeth
p_l: Calling CL dynamic is misleading when some compilers, perfectly permitted by the standard, do both static and dynamic, making "gradual typing" a more accurate descriptor.
21:22:31
White_Flame
"gradual" never seems right to me. Each instance is a boolean, either assuming or checking the type
21:22:33
aeth
Calling it "dynamic" implies that you can't (defun foo (x) (declare (single-float x)) ...) although, yes, that isn't entirely portable behavior because in theory some non-existent (afaik) implementation could assume types instead of either statically typing (SBCL) or ignoring the declaration (most implementations).
21:23:09
aeth
SBCL at safety 0 is a bit tricky. It assumes the types at runtime, but probably still does its limited static type checking at compile time.
21:24:52
aeth
I said probably because I'm not going to write a test case right now, but I'd be surprised if it removed the limited static type checking.
21:27:35
aeth
White_Flame: "gradual typing" implies that you're going to start out dynamic and then gradually add static typing as your program advances. I think "mixed typing" would probably be a better name, but since dynamic/static is often confused with strong/weak, I'm sure "mixed typing" could confuse people into thinking that the language is both strongly typed in places and weakly typed in places or something.
21:28:21
White_Flame
but again, the doesn't distinguish itself as being part of the strong/weak or static/dynamic spectrum
21:28:27
p_l
aeth: dynamic is perfectly fine with (defun foo (x) (declare (single-float x)) ...) - it just means that type check will be done at runtime
21:28:40
aeth
One problem with CL, though, is that :type in CLOS isn't really respected. Only CCL seems to respect it by default, although SBCL respects it with high debug values, implying that it's only useful for debugging.
21:29:28
aeth
Another problem with static-typing-in-CL is that there aren't typed lists (trivial to write your own with structs if you can accept a performance loss) or hash tables, and non-T arrays are very limited in what types that they can have.
21:30:12
p_l
that's so long as you keep to portable standard, yes (though lists I believe are untyped in all implementations)
21:31:04
aeth
p_l: You're incorrect about type declarations. SBCL will do the type check at compile time as well, as long as it's within the same compilation-unit. SBCL actually has typed functions, with typed parameters and a typed return value (although the latter is rarely seen).
21:31:43
aeth
It's limited, though, because the function can be recompiled at any moment to have a completely different function type so SBCL will only trust it in limited cases, most commonly when it's in the same file.
21:31:56
p_l
aeth: I'm trying to stick to what the standard says, and even on SBCL you can end up with uncompiled code trying to call the functions so unless you do (safety 0) the type check will happen
21:32:45
aeth
p_l: Yes, in SBCL it's both statically and dynamically typed when you use type declarations, unless it's safety 0. Although I would assume most gradually typed languages that come at the problem from the dynamically-typed side would behave similarly.
21:32:59
White_Flame
I'm always amused when SBCL compiles an expression it warns about to a simple call to raise an error
21:33:51
p_l
aeth: that's what I'm getting at. By default we get dynamic, but compilers are free to go further where possible. Meanwhile with many "statically" typed you need to write your own type checks and variant code
21:34:24
aeth
pjb: Typed collections are wonderful. You type-check on setting or initialization and you can trust the type on access, providing more information to the compiler's type inference, without having to have a fancy macro inserting THEs all over the place (which SBCL won't even trust, so you'd need truly-the for SBCL)
21:35:25
White_Flame
there's always Haskell, if you want to program in types as your primary feature
21:35:26
aeth
And you couldn't even trust a the/truly-the macro because the user somewhere else could just bypass it.
21:36:09
pjb
aeth: it's ludicruous: all the reference types, and most integer types are compiled into the same binary!
21:36:43
pjb
aeth: in anycase, you can always use libecl, or greenspun like crazy, of course. But this is not what C programmers do.
21:36:54
copec
imo going into experimental programming thinking about type is like going in thinking about optimization before you've even flushed out your idea
21:38:06
aeth
White_Flame: I'm not sure why you'd recommend Haskell when I said "set rarely and accessed often". I think Haskell wouldn't be the ideal language for setting (i.e. mutation) because it's discouraged.
21:38:33
White_Flame
no, but it's focused on programming in types first, then adding a bit of implementation glue
21:40:40
p_l
excuse me, we are very obsessed with optimizations, we just do it without creating crazy UB in compiler
21:41:21
aeth
p_l: You could write an entirely statically typed program in CL. Sure, the staticness wouldn't be portable, but you could probably write a portable static checker like people do for various languages that don't even have an implementation like SBCL. The define syntax would be inconvenient, but a wrapper macro on top of defun is so trivial I've probably done at least a dozen such define-foos in one program.
21:41:59
Fare
scymtym: thanks for noticing. Why didn't gitlab.common-lisp.net warn me that the issue was open???
21:42:14
p_l
aeth: I'm actually tempted to branch out further from "keep to very simple CL" and do a lot of macrology this time, because I'm trying to write a performant Lisp Machine emulator :)
21:42:29
aeth
p_l: And assuming type T when no type is specified is actually the reasonable default. Why do otherwise?
21:43:02
p_l
White_Flame: it's something I'm actually tackling recently, where I have a function that recompiles a bunch of very statically controlled stuff when I need to
21:43:27
p_l
(in my case, it involves a lot of macros iterating over objects and constructing a function from them)
21:44:56
White_Flame
p_l: yeah, CL needs to move into the JIT world if further gains on speed are going to be introduced
21:45:31
White_Flame
well, that's what you're talking about, isn't it? recompiling things if the assumptions change?
21:46:30
White_Flame
but yeah, the literal acronym "JIT" isn't sufficient to describe such optimizations. I guess "dynamic recompilation" would be a better fit
21:46:32
p_l
White_Flame: I'm essentially making macros that build functions that are then processed by macros to build an uber-function that implements the dispatch unit of a Symbolics Ivory chip
21:47:04
p_l
the function to rebuild this is going to be called manually, when I change something like adding new instruction or modifying the macros that help me build the instruction-functions
21:47:39
aeth
White_Flame: You only need JIT if you can't directly specify what you mean. That's probably why LuaJIT is such a performance win over Lua. When everything is a table, you need JIT magic to magic things into more appropriate representations.
21:48:12
aeth
I'm not sure a JIT could beat SBCL in performance because of all of the engineering effort put into SBCL
21:48:13
White_Flame
aeth: specifications are burdensome, and heuristics can find specs that you might not be able to
21:48:27
p_l
most CL implementations already include the kind of dynamic programming that JIT optimizers do, btw
21:48:51
aeth
White_Flame: But once you know what you're doing, you can make a macro out of it and get rid of almost all of the boilerplate.
21:50:14
copec
I would like to do some investigation into CL performance as it relates to the graph on https://julialang.org/ starting from here: https://github.com/JuliaLang/Microbenchmarks/
21:52:17
aeth
White_Flame: Imo what CL's best at is this: Specify exactly what to do, in a macro, and give a high-level declarative interface. Most languages that give you the opportunity to do the latter don't give you enough control over the former.
21:53:21
White_Flame
I want to teach it how to get things done, and how to figure out how to gain performance on its own. I've spent decades doing all that by hand, and it's a repetitive waste of time
21:54:43
White_Flame
especially for large, complex projects, hand-tuning everything gets superlinearly burdensome
21:54:59
Fare
If you have an account on gitlab.common-lisp.net, you may want to check your email setting
21:55:21
White_Flame
and that includes creating simple macros and such to help manually declare the hand-tuning
21:56:49
aeth
White_Flame: I find it more convenient to use a define-function macro as a target for my macros, rather than directly using defun. It'll handle things like (declaim (inline foo)), type declarations, etc., and since I directly control it I can add whatever else I need.
21:57:44
aeth
I originally intended only for the highest level to use fancy macros that hide most things, but it seems to work well at most middle levels, too.
21:58:53
White_Flame
"since I directly control it", ie, you put yourself & manual effort in the critical path ;)
21:59:05
aeth
I've been aggressively reducing reptition. e.g. I wrote a with-accessors* that is just like with-accessors except (foo bar (quux baz)) becomes ((foo foo) (bar bar) (quux baz)) because it's very common for me to just name the symbol macro created by with-accessors after the accessor.
21:59:19
aeth
And, sure, I directly control most of these convenience macros, but most of them are trivial.
21:59:29
aeth
I compose quite a few trivial macros to do more elaborate things and simplify the more advanced macros.
22:00:27
aeth
Using define-function and with-accessors* gets rid of a lot of repetition in the macros. Combine the two in one macro and now I no longer have to handle type declarations directly in that macro and I don't have to have the (lambda (x) `(,x ,x)) all over my code that with-accessors (and similar interfaces) would produce
22:00:57
White_Flame
it's about offloading actual autonomous programming & optimization work to the environment
22:01:41
aeth
That's the thing, though. This work only has to be done once, then it's a framework for someone else to use.
22:02:00
aeth
The CL community is small. That's the only reason why "doing it once" is often you doing it, and not finding a framework
22:02:28
White_Flame
but again, as I said, this is my soapbox. People who are working on different problems don't necessarily see the need for other people's desired solutions
22:04:45
aeth
White_Flame: I guess my point is that you don't have to worry about performance in CL if someone else has done that worry for you in the domain you're in. It's just that the small community means that that is unlikely.
22:07:19
p_l
White_Flame: you might want to search for information about "Programmer's Apprentice", I believe that was the name
22:07:27
White_Flame
the domain is highly dynamic, changing assumptions that should be reflected in compiled code
22:08:32
p_l
White_Flame: also, look for Marko Heisig (iirc) presentation at ELS2015 (I think it was 2015) where he describes dynamic programming (i.e. auto-adapting) on a supercomputer :)
22:08:44
White_Flame
as such, the entire body of work for statically arriving at an optimal static compilation is a red herring
22:10:53
rpg
Oddball question: if I have a structure of class node, and there's an extension of node, counter-node, that adds a slot, is there some way to copy a node instance to a fresh counter-node instance? I was trying to copy-node my node instance, and then change-class the fresh node into a counter-node, but change-class doesn't work on structure-class objects...
22:11:39
rpg
possibly the right thing is to simply replace my structure class with an object class, but that's at least a mild pain.
22:54:01
zazzerino
Is `eq` the correct equality function to compare keywords? (It works on sbcl, but I'm wondering if this is portable...)
23:00:07
aeth
From looking at the spec: eq, eql, equal, and equalp should be identical for symbols (including keywords) and there is no symbol= in http://www.lispworks.com/documentation/HyperSpec/Body/c_symbol.htm
23:00:48
aeth
eq will be slightly faster if the type is unknown because eql will use = on numbers and char= on characters, but I think most people would use eql in their style
23:01:47
aeth
the spec will describe how they all differ, e.g. http://www.lispworks.com/documentation/HyperSpec/Body/f_eql.htm
23:04:10
pierpa
EQL means equivalent. The two objects must act identically on every possible operation, with the only possible exception of EQ.
23:06:02
aeth
I wonder if (eql -0f0 0f0) => nil is correct because "If x and y are both numbers of the same type and the same value" seemed to give me the impression that (eql -0f0 0f0) => t
23:07:37
White_Flame
zazzerino: symbols are usually interned. So :foo and :foo will always be the exact same object in memory, so you can use the most specific comparator
23:08:20
edgar-rft
aeth: In a spec it's sufficient to look at the pictures, you don't need to read the text.
23:08:24
White_Flame
at a practical leve, you can consider eq to be a CPU register equality comparison
23:08:39
aeth
edgar-rft: well, you'd think that they'd put the edge cases in the examples in addition to the text
23:08:47
White_Flame
eql will also compare larger numbers and characters, which might be boxed (ie, larger than 1 machine register, living on the heap somewher)
23:09:54
White_Flame
and there are more type specialized comparisons, like = for numbers specifically, string=, etc
23:09:55
aeth
equalp uses = for numbers, equal uses eql for numbers. eql, I guess, can be thought of as using = on numbers of the same type except for the -0 vs +0 issue on floats if the float representation has them as distinct values.
23:12:16
aeth
I guess there's no concise way of explaining eql's behavior there, especially because of bignums and boxed floating point representations.
23:18:08
aeth
White_Flame: time for an equal? that ignores string case including unicode string case
23:19:04
White_Flame
so if you want to value-compare composite data structures, you either do it case-insensitively, or write your own descender (or override EQUALP to a custom function)
23:22:30
pillton
White_Flame: It is possible that equalp was defined in accordance to principles of the "Common" in Common Lisp.
23:24:21
aeth
On the one hand you get an ugly, inelegant language that is compatible with things no one uses anymore. On the other hand, attempts to start a Lisp from scratch miss very obvious features that large applications need.
23:24:43
White_Flame
pillton: certainly, I"m curious what that history is, for that particular issue
23:25:38
White_Flame
I've gone through pretty much all the genera manuals, but I think that was probably too recent
23:32:45
aeth
"Note: Every time you use EQUAL on a number, you will get a warning that the function EQL is undefined. Don't worry. This will be fixed later."
23:40:48
rme
Xach: FYI, I finally found and committed a fix for the call-next-method problem that you ran into in the 1.12-dev branch of ccl.
3:30:21
edgar-rft
skidd0, is the Lisp REPL not text enough? Or what specifically are you looking for?
3:31:38
skidd0
so, mostly placing text around the terminal display, with some | bars and +---+ beams
3:36:04
edgar-rft
I usually use cl:format for ASCII graphics, but I think there are ncurses bindings for colors and stuff in the <https://www.cliki.net/>
3:48:47
ZombieChicken
skidd0: Might also try termbox. I think there is a lib to interface with it via FFI