freenode/#lisp - IRC Chatlog
Search
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.
10:29:26
jackdaniel
jmercouris: it is enough to look in the spec for definition of * and + functions
10:29:59
trittweiler
shka: You can git blame NEWS in the sbcl git repository, to determine which commit the changelog entry is about. Usually, changes come with tests. See https://github.com/sbcl/sbcl/commit/dfddbc8ada - you could try that test in sbcl 1.4.2 to see exactly what happens. But yes, to me that reads like game over.
10:30:36
jackdaniel
because (*) is by definition = 1, part of the spec. it is only natural, because neutral element for multiplication is 1
10:32:05
jackdaniel
you would be suprised what happens, if you supply negative number of arguments, try it! :-)
10:33:29
jmercouris
okay, so to multiply something, we agree that you need at least two values, right?
10:33:47
trittweiler
shka, there should also be a mail on sbcl-devel around dec 4, 2017, about this problem - as per the commit message
10:36:05
jackdaniel
do you have *any* practical purpose of these questions, or you just broadly share your amusement? (given you know [from the spec] how * and + functions work when supplied with 0 arguments)?
10:36:55
scymtym
jmercouris: (*) emulates a syntactic convention from mathematics that is convenient for associative operations with a neutral element. consider (list (* 1 2 3 4) (* (* 1 2) (* 3 4)) (* (* 1) (* 2 3 4)) (* (*) (* 1 2 3 4)))
10:37:47
jmercouris
okay, fine, it is not arbitrary, but it is still not grounded in something that satisfies me
10:39:25
jackdaniel
jmercouris: since you want to dig from the groud up to computing, start here: https://en.wikipedia.org/wiki/Abelian_group
10:40:12
jmercouris
jackdaniel: I'm okay without :D, perhaps my curiousity is not as strong as I thought
10:41:56
jmercouris
it's not like I am proud or anything, I don't think I've ever brought it up on this channel before
10:42:19
LdBeth
I should look at J’s introductory, i remember there’s a section gives a explain about that
10:42:48
jmercouris
beach: Yeah, it is because math is quite difficult for me, at least certain types of math, I'm very good at geometry, physics, but not so good with discrete mathematics and algebra
10:42:56
scymtym
jackdaniel: an Abelian group is a group plus commutativity if i recall correctly, but the commutativity is not relevant to this discussion (i completely agree with pointing out the concept of a group as the underlying reason, though)
10:53:21
LdBeth
Well, then, J just tells 0 = +/ 0$0, 1 = */ 0$0,and I have to explain what’s identity and rank to make it more clean. So i give up.
10:53:31
jmercouris
I guess the real problem with languages like python is primitive operators change the function order
10:59:30
jmercouris
I can only say that the naming conventions, and the argument order are very confusing frequently
11:00:54
jmercouris
I would be very much in favor of this, but I understand it would take a lot of work from many people
11:02:01
jmercouris
Yes, this argument comes up every time, and it is valid, but it would feel nice to have a new specification
11:02:30
tfb
I think the diffference is that, if you feel that CL is creaky (which I do slightly, now), you can, in almost all cases, make your own variant which is not and which will run on top of the existing language. You can't do that in Python without serious pain
11:04:12
tfb
beach: yes, agree -- if you want a new better (for you) CL implement one on top of the old CL, which is what we all do.
11:05:10
jmercouris
yes, but if everyone is doing that, wouldn't it be nice to have a unified set of improvements?
11:26:45
jackdaniel
CL lacks semantics for efficient (i.e without emulation) implementation of call/cc
11:30:56
beach
jackdaniel: Only if you insist on a fairly direct translation from Scheme to Common Lisp.
11:33:44
tfb
beach: I think it's only interesting if the shim is fairly thin (so, say, you could call into and out of Schemy things) as otherwise you might as well just use one of the 9 billion existing schemes
11:42:15
jackdaniel
right, I'm not claiming that you can't write Scheme compiler in CL (vice versa is possible too) - both are general purpose programming languages after all
11:45:29
jmercouris
tfb: I was thinking in the context of gentle introduction to symbolic computation
14:26:21
jeosol_
anyone following AWS summit in NY. It will be nice to see how CL plays into most of these. As a single developer, I am trying to see how I get my apps to scale if I get to that step
14:31:58
jeosol_
jmercouris: thanks for your input about running my remote jobs. I saw it but could not respond back. My use case is a bit crazy, something between running in slime and running jobs on LINUX command line after launching SBCL
14:33:22
jeosol_
So what I do normally, I have a monitor on one side with code, and some linux terminals. Since I am testing different configs, I usually create a new defun, and just run it on the a linux terminal.