freenode/#lisp - IRC Chatlog
Search
14:34:05
scymtym
cl-ppcre has an example of this approach and illustrates a caveat: for a long time it did "if (constantp regex env) then (load-time-value (compile-regex regex))". this is wrong if REGEX is constant in ENV but not in the null lexical environment
14:55:15
heisig
I conclude - the right way is to use constantp without an environment and then load-time-value. Thanks everyone!
15:22:25
dim
is there a good documentation somewhere on CL environments and how to use them as a CL user? I'm lacking the practical implications of the idea, and I have no idea how to use &environment in the operators where it exists...
15:23:21
jackdaniel
dim: as it is specified in CL &environment is mostly good for only passing it to other macros
15:23:47
jackdaniel
some important primitives did not get through to ANSI CL, but they were specified in CLtL2
15:24:00
pfdietz
The only thing I have consistently used environments for is as an argument when manually expanding macros.
15:25:04
jackdaniel
dim: for more useful things check out https://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node102.html#SECTION001250000000000000000 (they are defined in both sbcl and ccl, they will be defined in ecl too)
15:42:22
pfdietz
The thing I've used it for is to exploit the environment as a kind of poor man's symbol table. If I have a macro that wants to make declaration-like things visible to lexically enclosed forms, I encode that with macrolets whose only purpose is to be deliberate expanded by other macros to get the information back out again.
16:58:45
sjl_
Is there a guide on how to use a proxy to make quicklisp download over HTTPS so it's not horrifyingly insecure?
16:59:09
sjl_
I know about http://netprophetblog.blogspot.com/2014/02/tool-posting-quicklisp-with.html because it's linked from the docs, but that's about how to layer a SECOND proxy over an existing one.
16:59:59
sjl_
I have tinyproxy running locally. I can e.g. `curl https://beta.quicklisp.org/... --proxy http://localhost:8888` and this works fine
17:00:30
sjl_
but when I tell quicklisp to use that proxy with (ql-config:config-value "proxy-url") it's still making the requests to http://beta.quicklisp
17:01:01
Xach
sjl_: I don't know of a guide, sorry. you can modify ql-http:*fetch-scheme-functions* to use e.g. drakma or something with ssl support.
17:01:29
sjl_
I tried setting (setf ql::*client-base-url* "https://beta.quicklisp.org") but that doesn't affect the archive urls that it fetches, because I think it reads those straight from releases.txt which has the bare http:// in there
17:02:27
sjl_
Xach: running tinyproxy should handle the SSL stuff, I just need a way to tell quicklisp to request https:// instead of http://
17:04:32
sjl_
Is a config option for "Please use HTTPS urls everywhere, I'll provide a proxy for you" something that could be added to quicklisp?
17:05:13
sjl_
I'm not even sure having QL use Drakma would work, because wouldn't it still be requesting http://?
17:06:24
Xach
I think *fetch-scheme-functions* is attractive because everything that fetches flows through it.
17:06:57
sjl_
Oh, so you're saying I can wrap the existing "http" fetch-scheme-function to rewrite the URL and then delegate to the old one
17:07:25
Xach
sjl_: I don't know if that will work - I don't know what the existing one will do with a https URL.
17:08:29
Xach
I mentioned this yesterday, but I have a system that is almost ready to deploy that involves fetching signed things and checking checksums and adding more confidence aside from https.
17:11:23
sjl_
Ah, so the user would download your public key over https (bundled in the initial setup file or whatever) and then this pure-CL implementation of PGP checks that whatever it downloads is correctly signed?
17:11:54
Xach
sjl_: yes. the bootstrap file embeds a pgp signature checker and the initial dist key.
17:12:20
sjl_
That would work, I think. Doesn't really matter if I get MITM'ed if it can be detected before executing the code.
17:13:06
sjl_
And if someone wants to use a dist other than yours, they'd get the author's pubkey securely somehow and add it into the list of keys that QL trusts
17:14:23
Xach
there isn't the web-of-trust component that i know is an important part of a real system. this is my attempt at the best "simple" thing when https isn't easily available everywhere.
17:15:18
aeth
d4ryus: The way I know about to print part of a string is this way: (write-sequence "Hello, world!" *standard-output* :start 7 :end 12)
17:15:49
aeth
d4ryus: In general if you think in sequences, they almost have start/end (or start1/end1 and start2/end2)
17:16:17
aeth
If you only want to print the first n characters than you can just say ":end n" and have no :start
17:17:20
sjl_
Xach: Hmm, well wrapping the fetch-scheme-function didn't seem to work, so I guess I'll just wait for that patch to land.
17:25:47
sjl_
Xach: which seems like it should be okay, but tinyproxy says https://plaster.tymoon.eu/view/1078#1078 and I don't have time to dig into how the request is actually happening
17:31:03
sjl_
depending on what kind of graph you're talking about, I shell out to either graphviz or gnuplot
17:31:25
aeth
Several options. You could take a do it yourself approach and build on top of something like https://github.com/vydd/sketch (2D) or https://github.com/cbaggers/cepl (3D) at the most basic level.
17:33:39
aeth
I've personally had decent success with graphviz, you just need to generate a .dot ("dot dot"?) file. The format is not quite as high level as I would have liked if you want it to render nicely (even though it *will* render with spaghetti connections if written the naive way)
17:34:10
Selwyn
i notice there are quite a few Lispy interfaces to graphviz - cl-dot, s-dot, cl-graph etc
17:37:18
aeth
Not sure if cl-dot supports it but for complicated graphs you probably want to create intermediate blank nodes so you can control the chaos of the long, overlapping arrows a bit.
17:38:58
Xach
sjl_: this isn't quite what you had in mind, but https://plaster.tymoon.eu/view/1079#1079 was my first try. it doesn't actually work and i'm not fully sure why -- (ql:update-dist "quicklisp") fails for me.
17:40:36
aeth
(Coincidentally, A->B is valid dot, that's not what I meant, of course. I meant instead of "A"->"B" you have "A"->"intermediate" [dir=none] and then "intermediate"->"B" where you'd have a separate entry for "intermediate" that makes it a tiny shape. I can't give the CL syntax because libraries could differ)
17:40:37
Xach
no problem, sorry it's not better already - i spent my extra time before work chainsawing a hole through a frozen instead of polishing pgp
17:40:53
Selwyn
aeth: it's a shame that it can't figure out how to render complicated graphs in a nice way. i wonder if it is a particularly hard problem to solve?
17:42:22
aeth
Selwyn: With dot files, you can break things up into a subgraph, and put the tiny intermediate shapes I was talking about as "inputs" to the subgraph area, which can group things a bit. But if something's complicated it's complicated.
17:43:43
Xach
sjl_: ahh, i got the signature of ql-http:fetch wrong. the file fetched is the second value. adjusting ssl-fetch to return (values nil (drakma-fetch-to-file ...)) fixes things.
17:45:09
aeth
Selwyn: If you're okay with your lines looking roughly like -------*------*-----*----> where * is a tiny shape, except in 2D going in various directions (and iirc the polyline instead of smooth style so it stands out less), then you can micromanage the lines when the program would make it do something really bad.
17:45:14
aeth
Of course, this won't work if the graph itself is arbitrary, but it could work for a Lispy preprocessor for fixed data.
17:45:37
aeth
There might be a better, more approved way, but that's what I hacked together last time I had something really complicated
17:45:51
thrig
or with spendy software you can import dot into omnigraffle or maybe visio and then clicky drag stuff around
17:50:27
Selwyn
aeth: thanks for the tips. for now, i am dealing with simple graphs and don't need the output to be too polished
17:50:40
aeth
Imo a hacky .dot (or anything else visual) is at least in theory easier to update by updating generating .lisp file than hand cleaning it
17:53:38
aeth
Selwyn: You should check to make sure the library you settle on using can handle generating "subgraph cluster_foo { ... }" then because that's probably the most complexity you'll need (e.g. something that's very clearly in two or three semi-independent parts).
17:54:34
aeth
Right at the main page here https://graphviz.gitlab.io/ you can see the subgraph cluster feature in the first screenshot here: https://graphviz.gitlab.io/_pages/Gallery/directed/cluster.png
17:55:26
aeth
Without that, graphviz will basically group the nodes in the way that makes the most sense for it, not necessarily the way that makes the most sense for humans
18:52:24
asarch
One stupid question: generic dispatch is the same as polymorphism (both happen at run-time)?
19:01:01
aeth
But without fancy libraries like those, the only polymorphism you will see that are not at runtime (afaik) are number and sequence and array (and possibly stream?) operations that you cannot (portably) define yourself.
19:01:57
aeth
And all of these (afaik) will default to a slower runtime generic if there is not enough information at compile time.
19:11:38
aeth
Typecase is great when there's one, or maybe two, arguments that you want to use the typecase on. Beyond that you would essentially have to build a truth table (except with potentially more than two values) out of nested typecases.
19:14:01
aeth
Just assume your dispatch is using a typecase for list or sequence (with sequence coming second so it's really sequence-and-not-list), which seems fairly common. If you want to be able to mix the two types then one argument is just 2, two arguments is 4, three arguments is 8, etc. Very similar to writing out the left hand side of a truth table.
19:18:12
aeth
What's nice about typecases, though, is that you could have the sequence-generic version in an inline function and have it consist only of an etypecase/ctypecase that calls either the list version optimized for conses or the other-sequence version assuming O(1) elt access (really, it's written with vectors in mind, but it's also a fallback for implementations with extensible sequences).
19:19:39
aeth
With the sequence inline typecase design, if the type is known to the compiler and the function is actually inlined by the compiler then the inline etypecase/ctypecase dispatch is removed and it directly calls the non-generic version. Otherwise, it has a very cheap dispatch left in there without inlining a potentially huge function.
19:19:55
aeth
It's a neat trick that can be an alternative to generics, especially if you only have one sequence argument.
19:26:10
jasom
I usually just start with generic functions and then if profiling tells me it's a problem I rewrite the parts that need it.
19:27:06
aeth
jasom: Yes, this is just a very special case where the performance gains and how to get them are a fairly simple pattern.
20:26:12
jackdaniel
since nothing is going on I'll share a screenshot with clim streams maintaining a baseline and word wrapping (new feature): http://i.imgur.com/FjuYQ04.png
20:30:07
holycow
interesting to see the autowrap feature autowrap on full word and partial. i don't know if that is a standard to toolkits, but neat.
20:30:48
jackdaniel
per-character wrap is part of clim specification, on full word is an addition which was not pushed yet
20:31:42
jackdaniel
this word wrap is a greedy approach, but I'm tempted to implement minimum raggedness
21:15:46
anamorphic
When building a CFFI wrapper for something, what are the pros and cons of wrapping pointers in a defclass like, (defclass wrapper () (ptr :initform (cffi:null-pointer))? I see charms (the cl-ncurses fork does that for curses window-types.
21:23:12
Bike
anamorphic: i would think the main thing is you can distinguish different kinds of pointers
21:29:59
aeth
The main con is pretty obvious: performance. You might be able to get some of that back in SBCL (not sure if other implementations have that optimization) by using defstruct instead of a defclass and typing the pointer's slot with the :type cffi:foreign-pointer
21:32:10
aeth
(I think I have seen this struct-wrapped pointer thing before, so some people seem to think it's worth it)
21:40:32
aeth
The implementation-specific read-eval optimization is probably unnecessary, though. Especially since you'd almost always initialize it *with* a pointer provided.
21:43:25
anamorphic
I guess my subclass would be via (defstruct (foo-wrapper (:include wrapper))) and in CFFI, i'd be doing something like (cffi:defctype foo (:wrapper :to-lisp #'make-wrapper :from-lisp #'wrapper-ptr))
21:45:31
anamorphic
and for the high level cffi wrapping function, something like this: (defun my-func (foo bar) (check-type foo 'foo-wrapper) (check-type 'bar-wrapper) (low-level-cffi-my-func foo bar ...
21:47:36
aeth
Are you using autowrap? I wouldn't pull in that very large library for what's essentially a two-liner
22:14:55
atgreen
I just built a containerized mirror of the full quicklisp archive, and hacked the quicklisp client to use it in my environment (OpenShift). Xach - if you can suggest a better way to access it, I'd love to hear...
22:25:47
hjudt
antoszka: it has been posted earlier today by Xach: https://github.com/quicklisp/quicklisp-client/tree/pgp
22:26:16
asarch
From Slime manual: "Now we need to create the tunnel between the local machine and the remote machine."
22:27:26
asarch
And why do I get: ssh -L 1.0.0.1:4005 asarch: Bad local forwarding specification '1.0.0.1:4005'
22:28:30
hjudt
asarch: from server to client. try ssh -nNTR <someport>:localhost:4005 user@client-host
22:32:12
Xach
atgreen: hmm, I don't know - do you need access to everything just in case? or are there subsets you need for a particular task?
22:33:36
asarch
Just for fun. With CL REPL I can easily: | CL REPL [Server] |--->| Swank |--->| 1.0.0.1:4005 [Listening] |<---| Slime [Client] |
22:34:36
asarch
However, this time I am trying to use the SBCL of another PC: | SBCL |<---| Slime |--->| Swank |--->| 1.0.0.1.4005 [Listening] |<---| Slime [Client] |
22:34:58
atgreen
Xach - the mirror is no problem. I build the whole thing. The question is really about the best way to access it. I hack the quicklisp client for now
22:35:10
atgreen
https://github.com/container-lisp/s2i-lisp/commit/7367dcda4d70bf24eb995b1cdc211c2153de3fd4
22:36:42
Xach
atgreen: hmm, maybe it could be done with the ql-http:*fetch-scheme-functions* instead.
22:37:52
Xach
atgreen: i think a mirror is a fine thing to do but I am not currently sure of the best way to use it with quicklisp. i'll have to think about it.
22:38:42
atgreen
ok, thanks. The mirror is useful as a container because it's easy to deploy, and helpful in my case where I am doing regular CI builds
22:40:05
atgreen
patching the client works fine for now. I had a quick look at *fetch-scheme-functions*, and I suppose you could map "http" to a new mirrored-http-fetch function that swaps the hostname before calling http-fetch.
22:40:47
hjudt
Xach: another question about quicklisp. when you build a system, you also test it by calling the -tests package or similar. i suppose this is done automatically and there is some scheme to follow to implement this correctly?
23:00:24
hjudt
Xach: in case of packages using foreign libs, do your tests also check which foreign libraries those need and whether they are present?
23:44:15
phoe
hjudt: the basic test done by Xach means that a library is loaded into the Lisp image; if a Lisp system depends on a foreign library, that means the foreign library is loaded as well. And, for that, it needs to be present on the system.
2:17:41
hectorhonn
how to execute some common lisp code at slime startup? such as setting optimization level
2:19:58
verisimilitude
A cursory glance with C-h v shows a slime-connected-hook you may be interested in.
2:21:10
aeth
If it's common initialization code between multiple implementations and multiple methods of starting Lisps (not just SLIME) you could put it in a quicklisp system in ~/quicklisp/local-projects/ and then do (ql:quickload :foo :silent t) at the start
2:26:00
hectorhonn
verisimilitude: i thought of putting it in sbclrc, but that would affect non-slime sessions. i think slime-connected-hook run elisp instead of cl?
2:27:11
hectorhonn
aeth: erm, that works? does that mean any other quicklisp package can declaim things and it will affect my package as well?