freenode/#lisp - IRC Chatlog
Search
0:30:21
griddle
Does anyone know of a good reading source for how lisp JIT compilers or ahead of time compilers work? I'm mostly interested in how scoping is implemented
0:33:19
Bike
The most obvious way is that the (lambda (y) ...) produces a "closure", which stores the binding of x along with the function.
0:37:53
griddle
and you'd have some kind of feature to lookup information in that structure? Or would you know ahead of time where in the structure that value lives
0:47:14
aeth
griddle: Naively, there could just be a defstruct to create a structure-object for every scope except the global one. Gensym its name to avoid the problem with redefinition.
0:47:21
jasom
griddle: In a compiled implementation, a lexical binding is just a mapping from an identifier to a location (i.e. lexical bindings do not need to exist in a meaningful way at runtime, only at compile time).
0:47:59
aeth
(I say structure-object because they're simpler and they can have inline accessors, or something like that. i.e. the location is known to the compiler at compile time)
0:48:23
Bike
i think if griddle doesn't know what a closure is they might be unfamiliar with defstruct.
0:49:02
griddle
I've implemented a lisp interpreter in the past, I'm just looking into how things like lexical scoping is done in a JIT if you can define different variable names at runtime
0:49:10
jasom
what usually happens is compilers have an expensive binding implementation that works in all cases and lives on the heap, but then a fast binding implementation for when a variable is never closed over (or is only closed over by lambdas that don't escape the heap).
0:49:53
jasom
griddle: for the most part, compiled implementations of lisp do not allow manipulation of lexical bindings at runtime
0:50:52
jasom
dynamic bindings have a defined lifetime at runtime, and those can be accessed via symbol-value.
0:52:23
griddle
yeah in past I've just had a really slow implementation with a recursive scope lookup of dynamic bindings
0:53:16
jasom
griddle: for variables that are never closed over, the value can be stored in a register. For variables that are closed over by lambdas that don't escape the dynamic scope, it can be the stack. For variables that are closed over by lambdas that might escape the dynamic scope, they must be stored on the heap.
0:53:44
jasom
griddle: I think you have dynamc and lexical backwards. Dynamic bindings are trivial to implement with global variables and unwind-protect.
0:56:55
aeth
jasom: Absolutely (re: expensive and fast implementations). The variable isn't even guaranteed to exist unless (debug 3)
0:57:22
aeth
On the plus side, that means that there's no (runtime) cost to naming intermediate steps if you want to
0:58:07
jasom
griddle: if you're familiar with compilers for less dynamic languages, all the approaches used there for temp allocation work just fine for any variables that are never closed over.
1:02:57
verisimilitude
Well, I enjoy the colorful phrasing RMS used, comparing the stack to a government agency.
1:03:17
verisimilitude
Put simply, treat the stack as a stack until it can no longer be treated as a stack, in which case it was never really a stack at all.
3:06:13
jcowan
I understand the idea of conditions with restarts, such that the condition-catcher can choose which restart to invoke, do a snippet of code set up by the signaler, and then either return or do a non-local exit
3:34:50
jcowan
Bike: I was thinking of restart-bind and friends, the ones that push the restarts into the dynamic environment
3:35:28
Bike
well, probably restart-case expands to restart-bind, actually. the condition association is a separate thing.
3:36:20
Bike
in sbcl at least, with-condition-restarts just puts the condition on a list stored within the restart.
3:37:52
Bike
usually handler-bind and resetart-bind just shove the thing on an internal dynamically bound list
3:41:05
Bike
you can do an ASSERT, and when an ssert fails it'll pop up the debugger and ask for new values to use
3:42:34
no-defun-allowed
if i'm destructuring in a loop for clause, can i give the destructured values of-types?
4:49:58
jcowan
I push some restarts on the stack and invoke some code that eventually calls assert. The user, or I on the user's behalf, chooses a restart, its code is executed, and the assert returns. But presumably the caller of the assert was doing that because some assumption that it depends on is being violated, and what is the caller to do when unexpectedly he gets control again?
4:50:44
Bike
i think you're misunderstanding something. control won't return from the assert unless the restart was set up in the assert.
4:51:13
Bike
if you have like, (restart-case (... (assert ...) ...) (foo ...)) and select the foo restart when the assert fails, control returns from the restart-case. the assert is abandoned.
4:53:35
Bike
with restart-bind you can have a restart that doesn't transfer control like that or at all, but i honestly have no conception of why anyone would want that, so i can't help there.
4:57:59
verisimilitude
You may be interested in the similarities between Common Lisp condition handling and PL/I and Multics, jcowan, if that's something you already find interesting.
5:13:18
jcowan
It appears to be plain exception handling with resumption semantics, like Scheme or Mesa (both of which I have used). But restarts seem to be only in CL and Dylan.
7:41:21
hectorhonn
the primary unit of abstraction in java is classes. what is the primary unit of abstraction in lisp?
7:53:00
hectorhonn
beach: i see its a chapter 5. looks like a good book, how do i get to the other chapters?
7:54:09
no-defun-allowed
beach: irrelevant, but how do you typeset those nice looking function/class/gf description lines in your documentation on closos and sicl? Is it something you made yourself or is it a common LaTeX library?
7:56:16
beach
no-defun-allowed: I am using a small library that came with the CLIM documentation called specmacros.tex
7:59:04
hectorhonn
beach: erm, what's the take away from chapter 5? i'm don't feel like i've learnt anything
8:03:19
hectorhonn
beach: so, the primary unit of abstraction in lisp is also classes? and generic functions?
8:04:57
hectorhonn
beach: for example, suppose i want to write a parser manually, as an exercise. should i represent the AST as a defclass?
8:07:49
verisimilitude
I'd think symbols and lists and functions and that manner of thing are the primary abstraction of Common Lisp.
8:08:11
verisimilitude
You could boil any language down to ``protocol'' as the primary unit of abstraction, if you wanted to.
8:09:04
verisimilitude
Common Lisp has an OO system called CLOS, hectorhonn, but you can rather entirely ignore it if you feel like it.
8:14:50
verisimilitude
Macros rely on the homoiconic nature of Lisp, related to its lists. Lists are important for abstraction.
8:16:47
hectorhonn
i guess what i really wanted to ask was, for example in java, i would write a XyzToken class for each type of token parsed, with a common base class Token, maybe with some common and specific operations. Then another class to represent a list of Tokens. so i have somehow represented (or abstracted?) this idea of "token" in the program,
8:17:16
hectorhonn
In haskell there would be a record sum type, and several functions that can act on the record. then another record type to represent a list of tokens
8:18:07
jackdaniel
(i.e it is less opinionated how you should write your program than Java or Haskell)
8:18:49
beach
In Common Lisp, you would choose whatever is appropriate in terms of performance. It could be symbols, lists, hash tables, arrays, standard objects, whatever.
8:19:03
jackdaniel
so while having "the one way" how to do things is comfortable it is also limiting
8:20:32
jackdaniel
you may arrange your program around protocols (like in haskell), you may create a class hierarchy with functions operating on it (like in Java), or you may write your own dsl with macros (like verisimilitude suggests). I think that finding the programming style which suits you best is a hard but worthwhile endavour
8:21:24
verisimilitude
Your main options are making a class for tokens which you instantiate, making a structure representing tokens, or just using an informal representation, such as a list of whatever you need, hectorhonn.
8:21:53
verisimilitude
Until you have a good idea of what you're doing, the list of whatever you need option is the easiest and most flexible.
8:22:01
jackdaniel
i.e there are libraries in Common Lisp which are referentially transparent (something often praised among programmers who fancy functional programing), but there are also many libraries depending heavily on OO
8:22:58
minion
hectorhonn: paip: Paradigms of Artificial Intelligence Programming. More about Common Lisp than Artificial Intelligence. Now freely available at https://github.com/norvig/paip-lisp
8:23:30
minion
hectorhonn: have a look at pcl: pcl-book: "Practical Common Lisp", an introduction to Common Lisp by Peter Seibel, available at http://www.gigamonkeys.com/book/ and in dead-tree form from Apress (as of 11 April 2005).
8:24:00
jackdaniel
and this book is more concentrated about mainstream (these days) style of CL programming heavily depending on CLOS (but starts from basics)
8:25:30
hectorhonn
haha... ever get that feeling when trying to start drawing something on a blank canvas? CL gives me that no restriction feeling
8:25:47
verisimilitude
Lisp is best, I think, when you don't quite know what you're doing yet, hectorhonn.
8:26:03
jackdaniel
hectorhonn: if you decide to listen to my advice, I'd recommend starting reading PAIP
8:26:08
verisimilitude
There are plenty of better languages if you know exactly what you're going to be doing, but Lisp is good for exploration.
8:26:41
jackdaniel
since it provides many case studies analyzing and evolving code bit by bit towards the sketched goal
8:27:39
verisimilitude
Also, hectorhonn, I noticed I've yet to recommend you any reading material, even in our last discussion, so I'll recommend something you already have.
8:27:50
hectorhonn
ok, so combining advice from beach, jackdaniel, and verisimilitude, i should start out with lists, explore different ways to find out which style i like best, and remember that i can use *anything* in lisp, there is no idiomatic way like in haskell or java. that right?
8:28:35
verisimilitude
There's a saying that if you give twenty different Lisp programmers something to do, you'll get twenty different programs, hectorhonn.
8:29:16
verisimilitude
The related saying is if you give twenty different Java programmers something to do, you'll get twenty copies of the same program.
8:29:18
jackdaniel
hectorhonn: another way of studying (which proves to be more engaging for some people) is to contribute to open source projects
8:29:54
jackdaniel
then you have some conventions already in place, so you are not left without any clues how to do things
8:32:00
ealfonso
I have a non-lisp source file vars.conf which I need to read from lisp. using a path relative to (uiop:current-lisp-file-pathname) works on the repl, but fails with no-such-file when the lisp source file is in ~/.cache/common-lisp: /home/USER/.cache/common-lisp/sbcl-1.3.14.debian-linux-x64/home/USER/git/path-to-file/vars.conf. How can I either make the compiler include the vars.conf next to the compiled source files, or refer to the
8:32:03
jackdaniel
I don't see much value in belittling programmers of other languages (or other programmers in general) [re java programmers]
8:32:27
hectorhonn
"The related saying is if you give twenty different Java programmers something to do, you'll get twenty copies of the same program" Actually this is exactly what a language should strive for, no? clear semantics
8:35:36
jackdaniel
hectorhonn: cffi maintainers are very nice people to work with. from other projects you could help with mcclim and ecl (I'm working on these); but I think that the best advice is to look for something you find useful and fun to work with
8:36:02
jackdaniel
slime project is also something benefitting whole community, so even small improvements have big impact
8:36:44
verisimilitude
If we're recommending Common Lisp projects now, I'd recommend you at least start with projects that are implemented in pure standard Common Lisp, hectorhonn.
8:38:39
verisimilitude
Put simply, there are plenty of Common Lisp programs or libraries that either only work on one implementation, usually SBCL, or use the CFFI and offload all of the work onto something written in a different language, both of which I believe should be avoided.
8:41:42
verisimilitude
I was writing a program with an interactive terminal interface and did take a look at the available libraries.
8:42:44
verisimilitude
You have Common Lisp, this nice language, and yet these libraries risk memory leaks for what amounts to printing text.
8:43:25
hectorhonn
verisimilitude: that's a pragmatic decision i guess, ncurses library already exists and can interface easily with the os
8:43:25
verisimilitude
Not only that, but it's so much more bothersome to lead a Common Lisp library that wants an entire C library with it.
8:46:52
verisimilitude
As a tangent, Github is awful, hectorhonn, and you should avoid it wherever possible.
8:47:17
verisimilitude
I'd much rather a company need to bother my VPS provider than just email Github and demand something be taken down, which happens.
8:48:55
hectorhonn
verisimilitude: i see. that's good to hear. stuff taken down probably violates copyright
8:49:51
verisimilitude
https://torrentfreak.com/fuckr-developer-right-or-not-backs-down-in-fear-of-grindr-copyright-lawsuit-181014
8:50:20
verisimilitude
It would be much harder to abuse copyright for taking down things you don't like, if so many people weren't all in a centralized location.
10:43:29
pjb
verisimilitude: lists are important for abstraction, only if you use them to represent everything. If you were ready to use CLOS classes for everything (like in Smaltalk, say), then classes would become an abstraction device. Until that, they're just a representation device. It can be used to represent external objects, and thus abstract _them_, but not as an internal abstraction, since you could also have structures, vectors,
10:45:53
pjb
verisimilitude: also, there is a way to distinguish the representation from the abstraction. This week, I had to debug a bug in C (it would be the same in lisp) where I had a typedef struct { void* data; int size } buffer; with a function buffer_new(int size) and a function buffer_free. The call to free failed on invalid pointer even thought it was allocated in buffer_new.
10:46:14
pjb
verisimilitude: the reason why that some client code used &buffer->data and incremented the pointer.