freenode/#lisp - IRC Chatlog
Search
21:54:38
no-defun-allowed
is there anything on using cl-nlp? i found tokenizing but just doing apropos on variable names doesn't seem too efficient
21:59:35
fiddlerwoaroof
margaritamike: using lquery, it would be something like this: (lquery:$ (initialize "<html><!--foo--></html>") (children) (contents) (filter #'plump:comment-p))
22:00:17
fiddlerwoaroof
lquery is a little dsl wrapper around plump that makes traversing xml a lot nicer
23:27:39
djeis[m]
The trouble is that parsing of the whole file happens before evaluation when you use compile.
23:28:12
margaritamike
What should I use instead of defvar for my my variable to load up after quickload has finished importing the library?
23:28:27
pjb
Indeed. ql:qiuckload is a function. This form is evaluated only when the file is loaded, not when it's compiled.
23:30:08
djeis[m]
You need the eval when if you want the ql:quickload to happen at compile time at all, which you do want because you need to be able to refer to the drakma package. That's why we usually use a build system like asdf to manage load-order lol
23:30:29
fiddlerwoaroof
you can do something like sbcl --eval '(ql:quickload :dependency)' --load my-script.lisp --eval '(my-script-package::main)' --quit instead
23:30:56
djeis[m]
You need the quickload to be evaluated before you compile the rest of the file is all.
23:31:06
pjb
Then asdf can take care of doing the things that need to be done at compilation time, vs. load-time.
23:31:58
no-defun-allowed
cl-earley-parser seems good enough for what i need, i just need to write the grammar and scrape a dictionary
23:32:12
djeis[m]
If you use load directly that might solve the issue, because it might (I forget exactly...) evaluate each form before it even parses the forms afterwards.
23:32:33
djeis[m]
But compile-file needs to parse the whole thing, and it won't go about evaluating stuff you haven't explicitly told it to.
23:34:42
margaritamike
I just want to load a file into slime and have it execute what i tell it to sequentially. I don't want to have to learn asdf if it's not required right now. Still getting a hang of quickload and drakma.
23:36:30
fiddlerwoaroof
margaritamike: if you insist, you want to do this: https://fwoar.co/pastebin/3c2b5cd1ddb15117de83096eff495b3091ccc00d.lisp.html
23:38:10
pillton
margaritamike: You want defparameter instead of defvar if you want to continue working this way.
23:39:06
fiddlerwoaroof
You could also do this: https://fwoar.co/pastebin/cecc07593809dea7daeff8b0ad4a4bd4c8f2a02c.lisp.html
23:41:23
margaritamike
I just want a variable to reference and pass the response on to a parser to search the DOM tree for random junk
23:42:26
pjb
Even if you write a script, it's important to write functions, and to call the main function at the end, avoiding to do anything else at the toplevel.
23:43:01
pjb
This is because scripts are read by buffer load, and if you are editing the script when it's executing, then you will read broken sexps across buffer boundaries!
23:43:43
Jachy
fiddlerwoaroof: I'd add #-quicklisp in front of the load, no need to load it again if you didn't run it as a script...
23:43:50
margaritamike
Why was the compiler not smart enough to tell me any of this. I would not have figured this stuff out from the stacktrace it gave me.
23:44:34
fiddlerwoaroof
margaritamike: the problem is you aren't really working the way CL expects you to work
23:45:13
pillton
margaritamike: Ok. SLIME starts a single lisp machine with a global environment. This global environment is updated every time you compile and/or load a file.
23:45:51
Jachy
margaritamike: What is it you want the compiler to tell you? Admittedly it's confusing at first to understand setf/defvar/defparameter and when it's appropriate to use them at the top level...
23:46:40
pillton
margaritamike: The first time you loaded the file you pasted, a dynamic variable was created for *response* and the value returned by (drakma:http-request "http://lisp.org") was bound to the *response* variable.
23:47:44
pillton
margaritamike: The second you loaded the file you pasted, the binding of the *response* variable was NOT updated because DEFVAR was used instead of DEFPARAMETER.
23:50:18
pillton
margaritamike: From clhs defvar you see "defparameter unconditionally assigns the initial-value to the dynamic variable named name. defvar, by contrast, assigns initial-value (if supplied) to the dynamic variable named name only if name is not already bound."
23:51:13
pillton
margaritamike: When in SLIME, you always have to remember that you are constantly mutating a single global environment.
23:52:16
margaritamike
This is why it seemed like there was some weird caching issue going on I guess xD
23:56:18
aeth
The most useful use of defvar that I have found is for something like this: (defvar *cache* nil) and then later on in your program (if (and *cache* cache-p) *cache* (really-expensive-computation-that-takes-a-minute))
23:56:48
Jachy
Stylistically (at least what i remember from PAIP) defvar indicates something meant to change in the running of the program with setf forms, defparameter indicates something more meant to change the overall behavior of the program, during the running it usually stays constant. i.e. a change to the parameter is a change to the program, while a change to a var is a change by the program.
23:56:52
aeth
With *cache* you can repeatedly run/debug your entire program from the start while working on it without having to repeat the expensive part.
0:01:51
aeth
I guess I could just have *cache* be unbound and then do (boundp '*cache*) instead. This might be more useful if you give it a type because instead of DECLAIMing the type (or null foo) you can just declaim the type to be foo and then no user can set it to NIL after it was already initialized once. But in my particular example you probably want to be able to let the user run it all again.
0:02:34
aeth
(This is, of course, assuming you are using an implementation that respects type declarations.)
0:10:49
aeth
Oh note that if you're using defvar you probably only want to use it in one location and set it in one location, if you don't want to wind up with unexpected results.
0:12:33
aeth
e.g. this is the only place where *cache* should show up (fixed): (if (and *cache* cache-p) *cache* (setf *cache* (really-expensive-computation-that-takes-a-minute)))
0:16:35
aeth
It essentially becomes the API function for that variable, which shouldn't be exported in the package.
1:13:13
rritoch
Hi, I have questions about packages but I'm not entirely sure how to word them so please be patient with me.
1:13:20
rritoch
A package contains variables, macro's and functions, but does it contain anything else?
1:13:59
verisimilitude
A package contains symbols, including whether the symbol was imported from elsewhere, created there, is external, is internal, etc.
1:14:09
aeth
rritoch: The full name of the symbol is foobar:foo but if you are inside of the package foobar or use the package foobar or import foo from foobar you can refer to it as foo
1:14:21
rritoch
aeth: But doesn't the packages have two namespaces, one for variables, and one for functions & macro's ?
1:15:38
aeth
rritoch: foobar:foo is the symbol foo in the namespace foobar, which could depending on the context it is used in be referring to a function, a variable, a type, or several other things. I think there might be 6.
1:15:45
verisimilitude
The idea, rritoch, is that a symbol has a name, a home package, a function, a value, and a property list; usually, a symbol is only bound as a function or a value and the property list is typically unused.
1:15:52
rritoch
aeth: In one package you can't have a macro and a function with the same symbol, but you can have a function and a variable with the same symbol, right?
1:17:21
rritoch
verisimilitude: Ok, so you are saying that a package only contains symbols, but the symbol contains a value (possibly undefined) and a form (either function or macro and can be undefined)
1:17:31
aeth
rritoch: The third that is commonly seen is types (e.g. deftype). I think types and classes share a namespace, and a class (either standard-class in defclass or structure-class in defstruct) creates a type. I think the distinction is that types can include more than just classes, such as (integer 0 5)
1:19:12
aeth
verisimilitude: By "two kinds of namespaces" I mean the type-based namespace (if that's the correct way to refer to it) and the package-based namespace. The former is often called Lisp-2 but that's more than two.
1:21:33
aeth
rritoch: Symbols, which have a name and a package (and can be internal-only in that package) can have a function/macro, a class/type, a variable, and a few other things that I can't find right now. Symbols also have a plist, which is a separate feature that is rarely used in modern Lisp code.
1:22:31
verisimilitude
These are some symbols used in multiple ways and you may find it educational to take a look at them.
1:24:07
rritoch
aeth: verisimilitude: Thank you very much :) The answer was far more complicated than I expected but it gets me forewards
1:24:26
aeth
It looks like conditions use the same namespace as classes and types. e.g. (define-condition foo (error) ()) then (defclass foo () ()) then (deftype foo ())
1:24:38
rritoch
I'm starting a new open source project to build a common lisp interpreter that is fully fused in python (no external lisp interpreter)
1:24:41
verisimilitude
Common Lisp is a nice language, but it is also a large language, although still small compared to Python, Java, C++, et al.
1:25:51
aeth
That's good enough to treat them as the same namespace for practical purposes, though. As in, don't get conflicts in certain implementations.
1:26:13
verisimilitude
So, conditions can be the same classes, but I don't believe they're required to.
1:26:37
aeth
verisimilitude: Yes, but the question is if they are in the same *namespace* as classes.
1:26:52
Bike
condition types don't have to be classes but you can't have a class and a condition type with the same name
1:27:29
aeth
"It is possible to define new type specifiers using defclass, define-condition, defstruct, or deftype." http://www.lispworks.com/documentation/HyperSpec/Body/04_bc.htm
1:27:40
aeth
So even if define-condition has its own separate namespace, too, it creates a name in the type namespace.
1:28:48
aeth
This might be of interest, too. http://www.lispworks.com/documentation/HyperSpec/Body/04_cg.htm
1:30:04
aeth
Bike: Do you know if there are namespaces separate from functions/macros, variables, and types/standard-classes/structure-classes/conditions? I tried looking around the HyperSpec but I can't find it.
1:31:34
fiddlerwoaroof
1. bindings whose denotations are restricted to a particular kind. ``The bindings of names to tags is the tag namespace.''
1:31:53
aeth
I went around in circles in the glossary for a while, only going to other related glossary entries
1:34:17
fiddlerwoaroof
Anyways, I'm not sure that "namespace" is a particularly precisely-defined term
1:35:17
fiddlerwoaroof
I'd be inclined to say that there are an indefinite number of namespaces because a programmer can use a symbol as an identifier for anything they please
1:35:25
aeth
fiddlerwoaroof: Seems pretty precise to me. There are two kinds of namespaces: packages, which namespace the symbols, and binding namespaces, which are based on the "particular kind" (I guess because they're not technically types?)
1:36:10
aeth
fiddlerwoaroof: Short of implementing your own bindings via objects or hash tables, you'd really be using some other binding, with its particular namespace.
1:37:14
fiddlerwoaroof
There's some standardized syntactic sugar for referring to class metaobjects indexed by symbols
1:37:56
aeth
fiddlerwoaroof: Even if you count custom bindings, you can still set a lower bound for n in Lisp-n, which is clearly more than 2 (as I said earlier, 3 are very common). Of course, a program could add to that n.
1:38:22
aeth
Really impossible to avoid adding features to a language with both Lisp-style macros and reader macros
1:38:37
rritoch
Next question. Say I want an implementation of common lisp (possibly with small standards compliance violations) with resource limitations such throwing an error if a loop has been running for more than 5 minutes. Has something similar ever been achieved? Ideally I want a system that can run untrusted code in a sandbox with no risk of crashing the environment.
1:39:06
fiddlerwoaroof
rritoch: it's possible to do that sort of thing using interrupt-thread and stuff
1:39:12
verisimilitude
You could hack something together using timers and BORDEAUX-THREADS, rritoch.
1:39:55
fiddlerwoaroof
The bigger issue, though, is preventing access to unsafe functions: you'd need a safe reader and custom logic for figuring out how to resolve uninterned symbols to a "safe" set of symbols.
1:40:48
aeth
What I usually do is not even control the loop in the thing being looped, and instead just tick up a counter. Obviously, it's imperfect if there's an infinite loop within the thing, so perhaps a combination is the best way (do it by ticks so one greedy loop doesn't take too much time, but also kill the individual iteration if it takes too long).
1:41:26
fiddlerwoaroof
You can have an EVAL with a verified-safe set of special forms and a "fuel" that ticks down every time a function is called
1:41:27
aeth
I find it's easier to work with a "tick" system than with real real-time. e.g. Start at 0 and increment every 10 ms or something.
1:41:59
rritoch
I'm not actually coding right now. I'm setting up specifications for an open source project to create a lisp interpreter that runs in python and is fully fused with python.
1:42:08
fiddlerwoaroof
That will guarantee a max running time of your longest-running special form * fuel
1:42:35
aeth
rritoch: You might find it's easier to go the other way around and implement a Python interpreter in Common Lisp.
1:42:41
fiddlerwoaroof
rritoch: you might also look at stuff like Dhall that give up Turing-completeness in order to make it safe to evaluate arbitrary code
1:42:49
rritoch
But running untrusted code has been something I've always wanted to do, since my days coding MUD's in LPC
1:43:42
rritoch
aeth: But its not an option because I need low-level python capabliities, such as GPU acceleration, and in the future Quantum Computing.
1:44:05
fiddlerwoaroof
rritoch: there's also things like burgled-batteries that use real python code
1:44:17
verisimilitude
There's nothing reasonable a properly written 6502 emulator, say, can do to break into the greater system.
1:44:23
aeth
rritoch: Yes, but CL is a fairly low level language. You can do things like JSCL but then you wind up having to disable features (and it would have to do so even if JSCL was a complete implementation of the part specified in the CL spec). So you can get a CL, it's just not a particularly sastifying one unless you have no choice (which it sounds like you might not have)
1:45:19
aeth
fiddlerwoaroof: The only thing high level that is essentially forced on you is a GC. But yes, it's multi-storied.
1:45:36
rritoch
aeth: I'm with fiddlerwoaroof: on this one! I would argue that there is no language that is higher-level than lisp
1:46:53
aeth
rritoch: I kind of see CL as a tool for building high level things rather than a high level thing itself. As in, CL is basically a tool for writing your own 5GL. https://en.wikipedia.org/wiki/Fifth-generation_programming_language
1:47:38
aeth
Of course, the failure of fifth-generation programming languages as a thing probably makes CL seem high level.
1:48:25
aeth
These days we'd probably just call the languages "declarative". I used the intentionally archaic term because CL was designed in that era.
1:49:54
fiddlerwoaroof
Really, I think the high/low-level distinction is a better fit for things like Python and C where you can't (realistically) work at all levels in a single language
1:50:32
fiddlerwoaroof
CL is more like a unix shell that's also a decent systems programming language as well as a decent scripting language.
1:51:37
fiddlerwoaroof
It might not always be the most efficient/performant for any given task, but it can generally do a decent job at almost anything you throw at it.
1:52:21
fiddlerwoaroof
And when you run into boundaries, there's things like CFFI that are almost unimaginable in any other language
1:53:11
aeth
CL is basically in the same class/niche of languages as Java or C# even though CL is normally AOT-compiled.
1:53:18
fiddlerwoaroof
What I meant isn't that it _is_ a unix shell, but you can almost use it as a login shell without missing anythign
1:53:50
verisimilitude
Well, I do my ``scripting'' with it. Unlike sh, I can easily write a program that actually works with it.
1:53:56
fiddlerwoaroof
When I'm working on CL stuff, I use quickload for the sort of things that I use apt/brew for in osx
1:54:28
verisimilitude
There's no similar ``This filename contains a space or a newline or a tab.'' misdesigns.
1:55:14
rritoch
Well, I see "high-level" as being more data than code. Something thats modular and can be easily changed in real time. You can use LISP in place of JSON {'foo' : 'foovalue'} => (("FOO" . "FOOVALUE"))
1:55:15
verisimilitude
It's very simple for me to write file-manipulation code in CL; sh is a minefield and I refuse to use it.
1:55:19
fiddlerwoaroof
It's fairly difficult to write certain filenames in a portable fashion, without using something like UIOP
1:55:57
aeth
I can't really say I write portable CL, I can only say that I haven't discovered non-SBCL issues yet.
1:56:10
fiddlerwoaroof
I forget the details, but there are issues when your filename has more than one dot in it, for example
1:56:44
verisimilitude
There can be, sure, and I simply try to take it into account when writing the programs.
1:57:32
djeis[m]
The actual contents of the :directory component of a pathname aren't, technically, even specified IIRC.
1:57:32
aeth
This channel recommends that, and I guess it makes sense. Any issues will probably be discovered through ASDF itself.
1:58:12
verisimilitude
Also, for throwaway programs, it's not even an issue, which I'd figure much of ``scripting'' falls under.
1:59:05
djeis[m]
That directory component contains a special wildcard component, if memory serves, that explicitly notes that it's wild in part of the directory name.
1:59:33
aeth
What's fun about a natively compiled CL is that you can basically go as low as you want to go. Just use some very high level libraries (including some of alexandria's APIs like curry/rcurry) or disassemble and try to get exactly the asm you want
2:00:07
djeis[m]
I love the pathnames system in principle, and when I get to be SBCL specific I love it in practice, but only portable at a very surface level.
2:00:16
verisimilitude
It's also nice how DISASSEMBLE is present; you can view a function easier than you can in the supposedly low-level languages.
2:00:40
aeth
fiddlerwoaroof: well I write assuming 64-bit and the commercial Lisps charge for that so I have 0 experience with them
2:00:42
djeis[m]
Yea DISASSEMBLE basically takes the place of something like godbolt's compiler explorer.
2:01:00
aeth
fiddlerwoaroof: I'll also never support them in my libraries unless they send me a copy (even if the copy's restrictions are simply that I can only use them for writing my libraries)
2:01:04
fiddlerwoaroof
ACTION wishes there was a trivial-assembler library that provides a portable interface to the implementation's code generators
2:04:28
aeth
Yes, definitely, if it's non-conforming behavior it can be fixed. But if it's #+acl or something, there's no way I can maintain that even if it works at the moment of the patch.
2:04:33
fiddlerwoaroof
Also, it's kinda annoying, but CAPI/LW is the easiest idea->reality way to write GUIs
2:05:47
djeis[m]
ACTION wishes I could seriously recommend McClim, resets my timer to check in on it for another month or so
2:07:04
aeth
djeis[m]: Your best bet is probably to do a Blender-style GUI in OpenGL. Of course, it works in Blender because you can assume that someone doing 3D modeling is going to have good 3D drivers/hardware.
2:07:21
aeth
mcclim had an OpenGL backend but it was like 20 or so years out of date when it was removed!
2:07:47
fiddlerwoaroof
I really kinda want to develop this to a point where I can write an Emacs clim backend :)
2:08:19
fiddlerwoaroof
Emacs already has font-lock which can be used for dynamic text styling (I think)
2:08:37
aeth
djeis[m]: You could try implementing a mcclim backend in cl-opengl + cl-sdl2 (or some other window/input library that gives cl-opengl what it needs).
2:58:43
rritoch
Stupid grammar question, what is the formal name of CL "Common lisp", "Common Lisp", "Common LISP"
3:55:18
beach
shka_: The book is highly regarded. I have mixed feeling, as I do with most textbooks in computer science.
4:09:21
rritoch
I have the project setup on github, https://github.com/fclpy/fclpy and Pypi https://pypi.org/project/fclpy/ , I'm still working on the azure devops setup.
4:11:16
rritoch
I'm seriously considering previous suggestions though that python just be used to bootstrap it and have the actual implementation in LISP source code
4:12:11
beach
rritoch: What do you expect the advantages of your interpreter to be compared to other Common Lisp implementations?
4:13:42
rritoch
The advantage is to extend python to include common lisp code that can natively call python code.
4:14:55
beach
But then you want to write an interpreter (as opposed to a compiler) to run the Common Lisp code.
4:17:07
rritoch
See the eval function > https://github.com/fclpy/fclpy/blob/master/fclpy/lispfunc.py#L570-L574
4:18:21
rritoch
Ideally the end product would be fullly implemented in python, but since that is an insanely huge project, simply getting it to the point where it could bootstrap an existing impelmentation written in LISP should be enough.
4:19:15
rritoch
performance wise I suspect it will be about 4X slower than python, unless someone gets greedy and decides to accelerate it with some c libraries :)
4:19:59
rritoch
beach: Thanks. Right now I'm mostly just using it for a few small things as it isn't fully functional, but I hope it will one day become fully functional.
4:22:26
rritoch
beach: Yes, I just hope I don't run out of storage space, lol. I've been coding for like 36 years, sometimes I worry I'm running out of storage space. 90% of what I've learned is no longer relevant.
4:25:10
rritoch
Example, being able to code assembly language on a Apple II is somethign that I haven't used in over 26 years
4:25:31
rritoch
I have the worst luck, the only technology I ever learned that is still relevant, is lisp.
4:29:14
rritoch
It seems to me that Ruby and Java are declining, Python is picking up, but Common Lisp seems to maintain relevance, or it simply grows at a slow pace.
4:29:56
rritoch
10 years from now I'm quite sure all my Ruby, Java and Python code will be useless, but the Common Lisp code will still run.
4:32:01
beach
rritoch: So why concentrate on a Common Lisp implementation written in Python rather than one of the excellent existing Common Lisp implementations?
4:40:40
rritoch
LdBeth: I have no idea, I've literally only been programming in python professionally for about 2 months. I did most of my previous work in Java and even made my own fork of ABCL to make it pass all of the ANSI tests.
4:43:24
rritoch
beach: Between modifying a completely functional system, and building an entirely new one in CL
5:08:11
djeis[m]
SBCL has support for the instructions, but I have yet to see it actually make use of them ootb.
5:08:45
djeis[m]
Libraries have been written with explicit SBCL extensions to have it generate SSE code tho.
5:14:25
no-defun-allowed
i imagine a compiler could fold something like (map '(simple-array double-float (*)) #'+ a b) into some SSE code
5:17:21
no-defun-allowed
i've seen https://pvk.ca/Blog/2014/08/16/how-to-define-new-intrinsics-in-sbcl/ so far
5:17:45
fiddlerwoaroof
https://www.pvk.ca/Blog/2014/03/15/sbcl-the-ultimate-assembly-code-breadboard/
5:18:56
djeis[m]
Which actually goes through example VOPs that use SSE instructions, if memory serves.
7:18:01
fiddlerwoaroof
My brain's not working right now, what's a predicate that tells me whether an object is an instance of a particular class?
7:20:52
fiddlerwoaroof
I'm using a library that fails spectacularly if I accidentally feed it a string instead of an instance of one of its classes, so I'm putting an ASSERT in
7:31:49
margaritamike
what does an & next to a parameter for a function in documentation mean for lisp?
7:33:30
beach
http://www.lispworks.com/documentation/HyperSpec/Body/v_lambda.htm#lambda-list-keywords
9:41:49
shka_
loke: few data-structures with common interface, including functional dictionaries, functional vectors, functional quoues plus protocol for Java 8-like streams
9:43:10
loke
I built one like that myself, but it's not very good. _however_ it does contain what I believe is the only correct implementation of read-black-trees in Common Lisp.
9:44:34
shka_
loke: ideally, yes, but i would have to find some time for that, and i am already committed to make few other things
9:46:56
loke
I'd really like my version to somehow make it only Quicklisp, as the other two available versions are buggy
9:47:23
loke
(I had an application that hit the trees very heavily and both those versions tends to lose elements in some edge cases)
9:48:06
fiddlerwoaroof
loke: in theory you could package it up and implement some other library's interface
9:48:27
loke
Here's my implementation in any case: https://github.com/lokedhs/containers/blob/master/src/rbtree.lisp
9:49:00
loke
shka_: Yes. The test cases for my implementation specifically tests for the cases where I discovered the others to fail.
9:49:35
loke
I have no idea to to minimise the test case. I found it by recording production dataunil I had a crash and then found a sequence of adds and removes that lost elements.
9:50:15
shka_
currently i have no ordered dictionary of any kind in the cl-ds so i may eventually want to include this
9:50:28
loke
(I also have two similar bugs in my implementation, caused by subtle typos in my transformation of the original C code). What's really annoying is that when you get something wrong it works for all obvious test cases, but will fail in some edge cases.