freenode/#lisp - IRC Chatlog
Search
23:15:31
aeth
Any list that lists GCL among its recommendations is so incredibly uncurated that I wouldn't trust anything on it.
23:16:34
akkad
and it's list gets out of date often, to show you inperfections that it is done by hand.
23:17:05
aeth
For that list to have gotten out of date and have GCL on it, it would have had to be written in 2005 or so.
23:46:40
jasom
We should have a "If you say you are using X on #lisp, we won't laugh you out of the channel" curated list.
23:50:14
aeth
If you're going to recommend a bunch of things in the same category, you should be opinionated and not just list them alphabetically. e.g. I'd recommend trying SBCL, CCL, and ECL in that order. awesome-cl puts SBCL last because it's alphabetical and ultra-niche ABCL first!
23:58:17
akkad
but cl has an image issue, and this goes a long ways to teach potential developers how cool it is
0:01:51
p_l
akkad: when GCL was making doornails look lively, XEmacs was still something I would suggest over Emacs :)
0:02:05
aeth
akkad: It's not good for the image of CL (a dead implementation that's barely supported by the ecosystem does not make a good first impression) or for the security of CL programmers (SBCL or CCL would patch a security issue next month... GCL would patch it in 5 years maybe?) to recommend inactive implementations.
0:04:11
aeth
It's a lot harder to determine things about commercial implementations. It's likely they're not in the ASDF+Quicklisp ecosystem with the rest of us and if there's some issue it *could* still be patched quickly through a commercial support contract even if there's one user.
0:08:20
aeth
aeth-lisp is also alive if someone is willing to pay $500,000 a year or whatever. Even if it has basically 0 presence anywhere else.
0:11:20
aeth
Josh_2: It's a lot harder than it looks. I can't just "git clone https://github.com/sbcl/sbcl.git" because I also have to find-and-replace all instances of the strings "SBCL", "sbcl", "Steel Bank Common Lisp", etc., except on the relevant copyright/contributor pages, etc.
0:43:13
p_l
aeth: SCL is kinda dead, moxcl is probably alive but isn't a full implementation, Liquid, Franz and Genera are in similar state of undead (you can still get support), I actually don't know about Interlisp because it feels at times that the owners forgot there was a language implementation under the program they were selling
0:45:15
p_l
(I'm ignoring implementations that died back on DOS or were so obscure good luck finding mentions, let alone software or parts)
1:42:12
aeth
Is there a way to define a function with a defclass given some custom metaclass? It's very trivial with a defclass* macro, but I'm not sure how it can be done in the MOP. (setf (fdefinition foo) (lambda (...) ...)) in ensure-class-using-class :before?
2:24:46
Bike
:before method sounds right to me. you don't get to control the macroexpansion to put a defun in there, if that's what you're hoping for.
2:26:36
equwal
I'm not sure I understand what aeth means either. Are you talking about polymorphism?
2:31:21
Bike
i think aeth just wants a defclass of their custom metaclass to define more functions than just accessors.
2:33:03
aeth
I have it, but it's not particularly pretty. I can't just (setf (fdefinition foo) (lambda (...) ...)) because I have macroish things I want to do so I have to (setf (fdefinition foo) (eval `(lambda (...) ...)))
2:33:21
aeth
And I also have to wrap it in an eval-when in CCL because of course CCL is picky about things and wants extra eval-whens
2:34:15
aeth
Bike: https://gitlab.com/zombie-raptor/zombie-raptor/commit/036af6464f6517c13bed17416c7317391d733db4
2:35:24
aeth
I now have the source of the shader class definition itself down to just: https://gitlab.com/zombie-raptor/zombie-raptor/blob/036af6464f6517c13bed17416c7317391d733db4/data/shader.lisp#L89-146
2:36:13
aeth
I guess the next step is seeing if I can generate the check-types in the setter automatically and perhaps doing the constructor type checks (via the generated function) automatically
2:37:30
Bike
but let me see if i have this right- you define a global function for every slot that takes an instance and checks that slot?
2:39:14
aeth
Bike: I define a check-foo that checks the type of every slot that has a reader. This can be called separately since CLOS objects can't really be trusted even with the constructor and setters having type checks.
2:40:03
aeth
I also add :before to every writer to ensure that the types are checked. Atm, I do this manually, but it probably won't be that hard to do it automatically now that I have everything set up.
2:40:27
Bike
you could just define a :before on (setf slot-value-using-class) since you have your own slotd class anyway.
2:40:58
aeth
Bike: And that would cover with-accessors, with-slots, and the constructor all together?
2:55:41
equwal
After several years of lisping this CLOS stuff still confuses me a great deal. In one ear and out the other. Hopefully it will click sometime.
2:58:00
equwal
I just have a hard time remembering all the details, and knowing when it is better than the functional paradigm I am accustomed to.
2:58:51
equwal
Do you recommend any resources? I've read Peter Siebel's book and Graham's On Lisp sections on CLOS, but I don't really get still.
3:11:11
equwal
I think the main problem for me is that CLOS is so much bigger than any object orientation I have tried to do before. 'Thing's huge.
3:12:13
aeth
And it's just underspecified enough for there to be annoying incompatibilities between implementations.
3:13:06
xsperry
what is your opinion of lisp-1 vs lisp-2 as far as functional programming go? and is there a way to reduce boilerplate in lisp-2 when doing that style of programming with some smart use of macros?
3:16:01
equwal
Well I like doing things like this ((lambda (x) x) 1) in scheme, whereas in lisp you must do (funcall #'(lambda (x) x) 1) which is not as cool.
3:17:14
aeth
symbol-macrolet <http://www.lispworks.com/documentation/HyperSpec/Body/s_symbol.htm> like in with-accessors <http://www.lispworks.com/documentation/HyperSpec/Body/m_w_acce.htm>
3:17:30
aeth
it won't help you with that particular case (although you *can* drop the #') but it can help when funcalling named things
3:17:32
equwal
But you get to do things like (define list (list) list) and have it work, whereas (define list (lst) lst) is not so good. I'm not really sure, but I know I've seen very good discussion on both sides.
3:19:31
xsperry
no. just calling a function stored in f variable, and then calling the function it returned
3:21:40
equwal
Yeah partial application is a mess. I'm not sure where I stand on the lisp-1 lisp-2, definitely pluses to both sides.
3:23:00
stacksmith
Good morning. Apologies for slightly off-topic question.. Can someone help me out with roswell? I royally screwed up my environment by deleting an old version of sbcl-bin...
3:24:07
xsperry
I only played with clojure briefly, but if f is a variable that stores a function that returns a function, I am pretty sure what I typed above will work.. ie ((f 10) 20)
3:25:16
equwal
Right, but you can make the function f like (partial f 10) out of a function (defun f2 (x y) something)
3:26:13
equwal
So you could do (funcall (partial f 10) 20) or whatever, which is marginally more readable I guess.
3:27:33
xsperry
actually I guess what I'd really like is do it in CL like haskell does it. where this would be just f 10 20 (since (defun f2 (x y) ..) equivalent in haskell is really just a function that takes one argument and returns a function that takes another)
3:28:13
xsperry
which would be ((f 10) 20) in lisp syntax, even if we defined f as (defun f (x y) ..)
3:28:15
xsperry
which would be ((f 10) 20) in lisp syntax, even if we defined f as (defun f (x y) ..)
3:28:35
equwal
Yes, I know exactly what you mean. You don't want to have to (defun f (x) (lambda (y) (+ x y)))
3:33:38
aeth
Bike: "you could just define a :before on (setf slot-value-using-class)" I can't get that to work. It doesn't seem to be called.
3:34:31
aeth
The only thing that has any noticable effect at all is (defmethod slot-value-using-class :before (class object slot) ...) which gives an SBCL error, which makes sense because I'm probably redefining some built-in.
3:35:05
aeth
loke: I'm trying (defmethod (setf slot-value-using-class) :before (new-value class object (slot slot-with-checked-type)) ...)
3:36:53
loke
aeth: I'm pretty sure you are notpicking up slot-value-using-class from the correct package (which is why you need to use SB-MOP, or load closer-mop so that you get a standard interface to it)
3:38:00
aeth
loke: Yes, and if I M-. it it'll take me to SBCL's definition (or it would if it had a valid builddir)
3:38:31
aeth
(defmethod (setf slot-value-using-class) :before (new-value class object (slot slot-with-checked-type)) (format t "~S ~S~%" new-value (slot-definition-checked-type slot)) (check-type new-value integer))
3:38:43
aeth
That should have two visible side effects. It should print and it should almost always fail
3:40:56
equwal
I whipped up some partial application last month and just uncovered that file, I'll just dump the code here. The function we are looking at is called partial. This is why I brought up this "solution," which really solves a different problem then "how can we write (funcall (funcall ...) better, and instead solves the problem "how can we take a two argument function and make it partially applied to one argument."
3:41:25
equwal
(eval `(partial-aux ,func ,@args))) ;; Example call: (funcall (partial #'subst 1 2) '(1 2 3)) --> (1 1 3)
3:45:31
xsperry
equwal thanks a lot for the effort! but I was thinking of tackling this from the other way around.. from the call site. so I can use all the functions that are available.
3:47:03
xsperry
(defun f (x y) .. ) to turn (f 10) into (lambda (x) (f 10 x)). and also to make curried functions callable like this ((f 10) 20), not like this (funcall (f 10) 20)
3:57:50
aeth
Bike, loke: This is what I have now. https://gitlab.com/zombie-raptor/zombie-raptor/blob/1e63646bb9af1d00223b9130868274915398b62a/util/util.lisp#L445-491
3:59:20
aeth
e.g. I can set the name to 42. (let ((s (make-instance 'shader :name :hello :stage :fragment-shader :source ""))) (setf (zombie-raptor/data/shader::name s) 42) (zombie-raptor/data/shader::name s))
4:00:05
xsperry
Bike interesting! I'll play with your and equal's code. I am curious, and I must be missing something, but why would the other thing require silly level of hacks? ((x 10) 20) is only legal in CL if x is lambda, as far as I know. so can't we just prepend all ((x .. ) .. ) forms with funcall?
4:00:06
aeth
I stripped out as much as I could and I've been changing around as much as I can in those 50ish lines for the past few hours
4:00:58
equwal
Look at Bike's solution, or https://rosettacode.org/wiki/Partial_function_application#Common_Lisp for a macroless thing that messes with the symbol table.
4:01:52
equwal
But you can't ((f 10) 20) without scheme. I'm trying to recall why, but I suspect Bike knows the specific reason.
4:01:53
Bike
yes. it's essentially like the definition on rosetta here, though maybe with a compiler macro too
4:03:52
loke
Technically, it works in scheme because the first element in a form is evaluated, while it isn't in CL
4:04:58
Zhivago
There is no principled reason that ((f 10 ) 20) shouldn't work in CL also -- it's just not supported.
4:06:52
xsperry
just so we are both on the same page, I am talking about this syntax only working in custom macro, that would walk the entire tree, and prend funcall to all such forms where car is a list. why wouldn't this work?
4:13:12
xsperry
and we can't just check if ((x ..) ..) x is a function. because even if it is, (let ((x 10)) ..) should still be left untouched
4:14:16
loke
Technically, it works in scheme because the first element in a form is evaluated, while it isn't in CL
4:15:51
loke
equwal: The problem is that you can have separate value and function bindings for a symbol.
4:16:30
aeth
Bike: I already thought of that. My current version subclasses standard-slot-definition and then I have double-inheriting versions for direct and effective
4:16:52
equwal
loke: in other words it is tangentially related to the lisp-1 lisp-2 debate we started out with.
4:17:31
loke
Here's the most recent code I wrote that implemented a custom metaclass and overriding SLOT-VALUE-USING-CLASS:
4:17:57
aeth
Bike: Okay, so I do get the side effect if I have the signatures (new-value (class checked-types) object slot) and ((class checked-types) object slot)
4:18:11
aeth
And if I make the side effect (format t "~S~%" (class-of slot)) I get #<standard-class sb-mop:standard-effective-slot-definition>
4:18:28
equwal
xsperry: I think you could get what you want by messing around with a parser. Flip to page 26 of SICP for details. There are problems with this kind of compiler, but whatever. http://web.mit.edu/alexmv/6.037/sicp.pdf
4:19:31
Bike
mm, maybe since you didn't define a method on compute-slots, it loses the :checked-type initarg
4:20:32
equwal
so the substitution model, replace ((f 10) 20) where f is definted using Bike's schonfinkel with ((lambda f (10)) 20) and you are in business.
4:23:28
aeth
This is what I have right now, btw, for the people following along. https://gitlab.com/zombie-raptor/zombie-raptor/blob/bbcfec7857cd8e7b38f9c27c875c8bf2ea879377/util/util.lisp#L445-487
4:23:38
loke
equwal: You could probably define (X ...) to be equivalent to (funcall X ...), but that was never done.
4:24:30
equwal
loke: Yeah, I think the easiest way is to merge the symbol and function tables into a Lisp-1 at this point.
4:24:55
loke
equwal: Easy, yes. That's why Scheme did it. They wanted to be simple. It's less useful though.
4:26:25
Zhivago
It doesn't matter for this -- given (a b c) which has been macroexpanded to evaluate, a names a function. Allowing a to be a function name producing form wouldn't affect lisp-1 vs lisp-2.
4:26:35
aeth
Well, I didn't import standard-effective-slot-definition and I did *NOT* get an error. Fixing that didn't fix it, though.
4:28:29
equwal
Zhivago: The loke asked what if #'a produces a symbol name. The answer is everything breaks because we are in a lisp-2
4:33:15
Bike
it takes a list of all the inherited direct slot definitions and returns an effective slot definition
4:33:29
Bike
the standard method doesn't know jack about your class and its extra slot, so it ignores it
4:39:03
loke
Here's my implementation of said method: https://github.com/cicakhq/potato/blob/master/src/potato/metaclasses.lisp#L109
4:45:56
LdBeth
gg, I believe it’s easier to work out a basic lambda calculator rather than hacking on CL’s read and eval behavior
5:05:39
aeth
compute-effective-slot-definition is simply too complicated, but if I can take the end result of it and set the unbound check-type value then everything would work
5:18:00
aeth
Okay, so the issue is here: https://github.com/sbcl/sbcl/blob/c5db3dca77303b6f0601601e064c0a3b05deb4a8/src/pcl/std-class.lisp#L1210-L1214
5:18:35
aeth
In my effective-slot-definition-class method, I was checking for checked-type. If checked-type was present, I returned (find-class 'effective-slot-with-checked-type) and otherwise I returned (call-next-method)
5:19:01
aeth
This is because the initargs are (compute-effective-slot-definition-initargs class dslotds)
5:22:10
Colleen
beach: karlosz said 8 hours, 52 minutes ago: yes, thats the special casing i am talking about
5:22:10
Colleen
beach: karlosz said 8 hours, 30 minutes ago: also, you surely must mean right hand side of the assignmnet
5:22:10
Colleen
beach: karlosz said 8 hours, 15 minutes ago: err, scratch that. the variable being assigned to is what we both mean. its not a terribly complex special case to add, but i fear that any manipulation with assignment instructions will end up having to test for something similar
5:58:45
aeth
loke: Well, now it works in SBCL and CCL. https://gitlab.com/zombie-raptor/zombie-raptor/blob/6f0360991ee3f27f4a918397d98a6713dd1211ca/util/util.lisp#L447-495
6:00:09
aeth
Apparently I can't use change-class with the MOP slot classes so the only way I could think of writing the implementation via :around is to make them all effective-slot-with-checked-type and use nil for the ones that don't actually have a type to check.