freenode/#lisp - IRC Chatlog
Search
11:43:20
tomlukeywood
Dose anyone know why this never returns "False" and just returns nil when (eql (aref universe cell-x cell-y) 0) is not true?
11:45:48
Shinmera
So instead of trying to decipher it, I'll just say (cond (t1 f1) (t2 f2) (t3 f3) (T f4) <=> (if t1 f1 (if t2 f2 (if t3 f3 f4)))
12:12:23
pjb
The extra windows are temporary and user configuration. Use C-x 1 C-x 2 C-x 3 and C-x 0 to deal with them.
12:14:50
pjb
paule32: honestly, I don't know, I never use menus; I even configure my emacs to hide them from me.
12:15:12
pjb
You may use the menu, but once you know the key binding for the command, it's easier and faster to use it.
12:15:35
pjb
Also, thru irc, it's easier to give you key chords to type, rather to tell you to go to such and such menu.
13:21:28
jmercouris
Given CLASS A, is there a way to enforce that all classes extending CLASS A implement a set of methods?
13:23:24
jmercouris
beach: Can you please explain further, what does it mean when a method is specialized? When it has slots with one of the type specifiers being class A?
13:24:33
Shinmera
jmercouris: What would you want to happen if there is no method specialising on a subclass of A?
13:24:38
beach
Well, since methods are classes, they do have slots, but in this case, it has to do with the parameter of the method being restricted to A.
13:26:30
jmercouris
Shinmera: The program should not be able to load, to enforce that all the methods have been implemented
13:26:45
beach
jmercouris: That's a very basic question about methods and generic functions. Are you sure you should be using such things without reading up first?
13:27:18
Shinmera
If you define a new subclass, should it just immediately error because the methods for it don't exist?
13:27:21
jmercouris
beach: I've read already, I find I learn best by doing, making mistakes, and then trying to understand what I did
13:28:01
jmercouris
Shinmera: I thought the check could happen during something like initialize-instance :after
13:28:04
Shinmera
If you can't define the class, because it errors due to a lack of said methods, you can't add the methods, because specialising on a class in a method requires the presence of the class.
13:29:23
Shinmera
If there is no method specialising on a class it will error when you try to call its generic function anyway.
13:30:03
jmercouris
The reason this topic keeps coming up in my head was because I was told some time ago, perhaps two weeks or something, that I should convert my "Interface" package to a CLOS object, and I want several interfaces to extend from a parent CLOS, but in order to be a valid extension, they need to implement a set of methods
13:30:35
jmercouris
Yeah, I am the only one using my internal API for now, I'll just avoid trying to force a protocol
13:31:05
Shinmera
What you can do, for your own safety, is implement a function that you can run manually to "check the integrity"
13:31:07
beach
jmercouris: An "interface" in a traditional object-oriented language often translates to a set of generic functions.
13:31:22
Shinmera
Said function would use something like compute-applicable-methods to discover whether the necessary methods are in place.
13:31:43
jmercouris
beach: But generic functions can remain unimplemented though, so I don't get that safety which is what I'm looking for
13:32:51
Shinmera
It would signal an error, giving you a debugger, and the ability to fix the issue.
13:33:14
Shinmera
When you've implemented the method you can then use the "retry call" restart and continue where you left off.
13:34:51
jmercouris
It's hard to "unlearn" so many years of other languages, I have to change my approach
13:35:08
beach
jmercouris: You are confusing two types of exceptional situations. One is a program defect, namely the programmer omitted to make sure some generic function can handle the kinds of objects that is given to it as an argument. Such an exceptional situation should indeed signal an error that the programmer must then deal with.
13:35:31
Shinmera
Lisp embraces the dynamism. Doing static checking is hard, because it would often make incremental approaches impossible or very annoying.
13:36:04
beach
jmercouris: The other exceptional situation is if the USER of your program does something that the program can not handle. Then there should be a friendly message and a way to continue using the program.
13:37:16
beach
jmercouris: To avoid having an error signaled when the USER is using your application, you test it before shipping it.
13:37:23
jmercouris
beach: The user can trigger a function that the program cannot handle because the programmer forgot to implement some function
13:37:54
beach
jmercouris: You test the program first. You have to anyway, to make sure those functions do the right thing.
13:38:12
jmercouris
Yeah, I'll have to do that, and I'll just have to "document and trust" with defgenerics in the superclass
13:38:49
jmercouris
I've at least stripped all of the foreign code and isolated it to a single interface
13:42:06
Shinmera
It's more useful to think about the generic function as operations, which are what you really care about, and classes as things to do these operations with.
13:43:19
Shinmera
I don't see an issue with saying that your operation operates on a certain hierarchy of objects, so defining the root of that alongside the generic function isn't a problem.
13:43:46
Shinmera
It's more that the class is defined alongside the generic functions than the other way around.
13:45:43
jmercouris
Shinmera: I think I'm finally starting to understand some of the value behind CLOS
13:46:41
jmercouris
and the real magic, is the functions, and different functions can specialize on different data containers
13:47:57
Shinmera
The general example that illustrates this point is if you have a (draw thing canvas) function. This operation depends just as much on what is drawn, as well as where it is drawn to. It makes no sense to try and attribute it to either one of the arguments.
13:48:02
pjb
paule32: even if types are associated with values, and not with variables, and even if T is the super type of all types, unless you have a specific reason to do horrors such as initializing a *menu* to an integer such as 0, you should avoid it!
13:49:09
jmercouris
Shinmera: Aha, yes, that does make a lot of sense, depending on the type of canvas object, the operations could be radically different, so you want to be able to specialize on multiple objects for a given function
13:49:24
pjb
paule32: also, in general you will want defparameter rather than defvar, since defvar assigns the value only if the variable is not already bound.
13:49:55
jmercouris
Thank you for the explanations, I'll need to absorb and internalize this information for a little bit, but I think I am getting there
13:50:26
pjb
paule32: you can iterate on lists with dolist, loop for x in list, map, mapc, mapcar, mapcan, mapl, maplist, mapcon, do, do*, etc.
13:50:58
pjb
paule32: so read in the Hyperspec about those operators, and then choose one of them to iterate in your menu list.
13:59:39
larsen
pjb: I think the very first implementation was in Basic (first experiment by Dan Ingalls)
14:01:05
pjb
jmercouris: currently, beach is right that you should test to detect such errors. However, you could perform a global analysis of your sources to check at "compilation" time whether all the required methods are implemented. You would probably need additionnal annotations (eg. in form of declarations).
14:05:04
pjb
jmercouris: you can easily come with algorithms to perform specific global checks such as this one.
14:06:58
pjb
jmercouris: the worst difficulty is actually reading the source of a lisp program. It's easy if you load it in the current image and perform introspection. But you can only validate it for the current implementation with the current set of *features* etc. Sometimes you would want to read it without modifying the current image, and analyse also the read-time variants. For this you can use something like my lisp reader, providin
14:07:45
pjb
(You still need to read yourself the sources, to process it, notably take note of the declarations, since there's no conforming API to get the declarations for a given form).
14:09:43
jmercouris
pjb: Sounds like a rabbit hole I don't want to go down just yet, or perhaps ever :D
19:41:12
Josh_2
When working with a large array is it better to destructively sort it or just change the array variable to a returned sorted array (the functional way)
19:44:49
Josh_2
Well I am going to run a list of words through a fuzzy string matcher, record the result and extract the highest answers from a large sorted array
19:57:08
Josh_2
I'm using my own quicksort implementation because this is coursework and I have to use 2 algorithms
19:58:05
sjl
the rule of "is X better than Y" is almost always "until you profile with real-world data, who knows"
19:58:40
sjl
something that could be interesting is writing a function to just extract the largest N elements from a sequence
19:59:16
Josh_2
That's a better idea, however I have to use two algorithms that I implement myself, so that's the reason for sorting
20:03:12
sjl
but if it's for a class and you've already got a sorting algo written, might not be worth redoing it
20:23:00
k-stz
Hey, I'm trying to read out from process memory. But when I feed some high address into it like: (file-position *process-mem-file* #xffffffffff601000). I get an error that it only accepts (signed-byte 64), but I need (unsigned byte 64). (sbcl, on a linux)
20:24:56
k-stz
code piece: https://github.com/k-stz/cl-ptrace/blob/c6fdf5a1d4b122ac659cf9b91cec57a55730cf0a/cl-ptrace/proc-pid-dir.lisp#L137
20:30:46
pjb
So if you get that error, it's a conformity error: complain with your implementation vendor (or provide a push request with a patch).
21:42:42
johnnymaster
(defun test-function (fn tree &optional init-val) (cond ((null tree) init-val) ((atom tree) (list tree)) (t (mapcan #'(lambda (x) (test-function fn x init-val)) tree))))
21:43:13
johnnymaster
With this I am able to get the list of elements from the tree, how can I use reduce to apply the function the the elements now?
21:43:54
johnnymaster
I'm hoping to keep it within one function (not use a helper) and hopefully make use of reduce
21:48:23
k-stz
johnnymaster: you implemented a function that flattens a list so far, now all you have to do is call (apply fn <on-the-result>)
21:49:22
johnnymaster
Yup, but given that my function keeps recursively calling itself, how do I get the list and then apply fn to it?
21:50:42
k-stz
well I'd make to functions since flatten is useful on its own, but if you insist you can make it a local-function using `LABELS'
21:59:45
johnnymaster
(defun reduce-tree (fn tree &optional init-val) (labels ((reduce-tree-helper (x) (cond ((null x) nil) ((atom tree) (list x)) (t (mapcan #'reduce-tree-helper x))))) (reduce fn (cons init-val (reduce-tree-helper tree)))))
22:16:53
Josh_2
I have a list of words and I want a an array for every length of word which contains only words of that length, but I don't want to write (let <55 arrays etc>)
22:28:06
Josh_2
This shows what I'm trying to do I may be completely wrong though https://pastebin.com/cQyM8jNj
22:40:46
pjb
Josh_2: if you have 55 arrays, then a good idea is to put them in a vector (make-array 55 :initial-contents (list array1 array2 … array55))
22:42:22
pjb
Josh_2: or of course; (map-into (make-array 55) (lambda () (make-array 0 :adjustable t :fill-pointer t)))
22:49:48
aeth
What's the most efficient way to go over a list that might be dotted list and then de-dot it?
22:50:25
aeth
I can't use dolist or loop for foo in list or the other things because they'll error at the last element
22:52:07
aeth
What I want is I want to take a list, and if it's a dotted list at the last element, turn that last element into `(&rest ,element) and otherwise just leave the list unchanged (probably copying the whole thing every time, I guess). i.e. turning a Scheme lambda list into a CL lambda list. e.g. (x y . z) => (x y &rest z)
22:52:24
aeth
There's also a case where it's not a list at all, in which case it'd just become (&rest z) but that's trivial
22:53:31
pjb
(loop for (x . rest) on '(1 2 3 . 4) if (null rest) then do (loop-finish) else if (atom rest) then do (process x) (process rest) (loop-finish) else do (process x))
22:54:26
aeth
Xach: I'm writing a Scheme in CL taking as many shortcuts as possible. It's a problem I come back to from time to time. The biggest shortcut of all is to implement a Scheme lambda as a CL lambda with a continuation parameter at the front and run it in continuation-passing-style with a trampoline that ensures tail recursion.
22:55:40
Xach
aeth: ok. i ask because destructuring-bind, for example, accepts dotted lists for destrucutring
22:55:58
pjb
aeth: of course, you can just use (com.informatimago.common-lisp.cesarum.list:list-elements '(1 2 3 . 4)) #| --> (1 2 3 4) ; 3 ; nil |#
22:56:20
aeth
I can define Scheme procedures in terms of foreign CL functions through a macro that emulates Scheme's define syntax, e.g. (define-scheme-procedure (+ &rest numbers) (apply #'+ numbers)) but to make that fully consistent it should use a Scheme lambda list, e.g. (define-scheme-procedure (+ . numbers) (apply #'+ numbers))
22:58:02
aeth
And I handle the nil vs. (#f and '()) issue by having two macros, define-scheme-procedure and define-scheme-predicate, where the latter replaces nil with :false (which might have to be something else if I add keyword support to the Scheme)
22:59:52
aeth
This way, the Scheme can use any CL code as a Scheme procedure as long as someone writes a trivial wrapper macro for it. (And the other way around would work even easier since the Scheme procedures are just CL lambdas with a continuation parameter and guaranteed TCO)