freenode/#lisp - IRC Chatlog
Search
22:50:22
mfiano
Yeah CL is strange in that order is context-dependent. Many different functions unituitively have reverse order. It's just something you grow used to. eldoc helps though
22:52:31
aeth
generally it should go (foo item index) unless it's just there for backwards compatibility
22:52:47
aeth
and the reason why the order flipped (obviously nth is much older than most of these) is because of aref being multidimensional
0:08:42
drmeister
Energy efficiency of different languages. Lisp fares very well - Python is a disaster.
0:11:08
jmercouris
pjb: and I have this run file here: https://github.com/nEXT-Browser/nEXT/blob/master/next/run.lisp
0:11:26
jmercouris
when I try to load a system I've defined here: https://github.com/nEXT-Browser/nEXT/blob/master/next/next.asd
0:11:36
jmercouris
it simply complains that whatever package is not installed isn't, doesn't attempt to install
0:13:13
pjb
You may also rather symlink your next source directory to ~/quicklisp/local-projects/next so you don't have to touch *central-registry*, and can directly (ql:quickload :next) instead of (laod "run.lisp")
0:15:16
jmercouris
that file is here: https://github.com/nEXT-Browser/nEXT/blob/master/next/make.lisp
0:16:00
pjb
I usually name it generate.lisp or generate-application.lisp and call it from a Makefile.
0:16:31
jmercouris
the issue I have is if you see on line 4, I was normally loading all of the things manually
0:16:42
jmercouris
like this: https://github.com/nEXT-Browser/nEXT/blob/master/next/dependencies.lisp
0:17:42
pjb
Those dependencies can always be dealt automatically by quicklisp. But you need some other setup, and notably when generating the executable, you want to control what is loaded in your lisp image…
0:18:24
aeth
drmeister: seems to be in line with general benchmark results, where there are very fast languages, "normal" languages, and very slow languages.
0:18:40
pjb
But the loading of your system and other stuff, you have to do in a script to build the application.
0:19:45
pjb
jmercouris: notably, in generate-application, I quickload the libraries needed by the builder.lisp script which is common between generate-application.lisp and loader.lisp
0:20:31
pjb
Not instead. The makefile only serves to record how the lisp implementation should be run on the make.lisp script to build correctly the program.
0:21:55
pjb
Another example: https://framagit.org/nasium-lse/nasium-lse/tree/master/src in this one, the makefile lets you choose between several versions of binaries (server, cli).
0:23:56
pjb
jmercouris: the requirements: 1- you want all the dependencies in asd files. 2- you want to avoid duplication between loading an image for an executable and loading to develop/debug. 3- you want a reproducible build (in different environments) to generate the executable.
0:24:32
pjb
And depending on the complexity of the project, you may have additionnal things, such as downloading, installing and compiling dependencies that are not in quicklisp! :-)
0:26:12
pjb
So for the later, I run the scripts manually, but in Patchwork I use logical pathnames to point to the directories where those dependencies are stored.
0:27:15
pjb
It is conceivable to combine both scripts, to be able to download automatically non-quicklisp dependencies when needed.
0:28:26
pjb
Yes, it depends on the degree of ease you want to provide for co-workers, or other developers getting your sources and compiling them.
0:29:13
jmercouris
I think a little bit too much room to break if I pull in other sources as well, I think i'll just leave it how it is, maybe only automating download of quicklisp dependencies
0:55:21
jasom
Xach: am I misinterpreting systems.txt or does QL think that cl-unicode/build depends on the system cl-unicode? That seems wrong to me.
1:49:13
drmeister
I'm trying to debug what I think is the last bug in my implementation of beach's fast-generic function approach.
1:50:03
drmeister
Every generic function maintains a call-history of all calls that were previously made to it and their effective method functions.
1:50:20
pjb
For example, you could do it lazily, when a generic function is called with an instance of a subclass, that subclass will have be passed to a call to update-instance-for-redefined-class, and then the subclass will have to be updated itself (so I assume by metaobject protocol, be passed to such a call too).
1:50:29
drmeister
The call-history (as I understand and implemented it) is an alist of (selectors . effective-method-function)
1:51:17
drmeister
When a class is redefined - I need a list of all generic functions that could dispatch on that class (and maybe it's subclasses - but I'm not sure that is necessary because they may be handled when they get updated).
1:52:07
drmeister
I'm trying to figure out how to get the minimal list of generic-functions that may need to be invalidated when a class is updated.
1:52:12
pjb
Now since redefining classes is not done often at run-time, you could have a global flag, and let the generic functions check it?
1:53:27
drmeister
What I did was add a call from ensure-class-using-class that invalidates all generic-functions that could be effected/invalidated by that class redefinition.
1:54:27
drmeister
I can compile cclasp using Cleavir (lots of generic functions) using the new dispatch method.
1:54:40
pjb
Also, redefining a class may change the applicable methods, so yes, you should probably update all the generic functions concerned.
1:54:54
drmeister
Except for one error that is triggered by the redefinition of a class when I'm compile-file'ing all of the code.
1:58:12
pjb
"Easy": for all symbols, find the fdefinition of the symbol and of (setf ,the-symbol), check if they're generic functions, then get the methods of the generic function, and for each method, find the method specializer, and search for the class or an instance of the class or a subclass in them.
1:59:24
pjb
The question is whether it is more efficient to maintain a list of methods dispatching on a class, or to scan them when needed?
2:00:10
drmeister
I think this is a scan them as needed situation - like you said - redefining classes is uncommon.
2:12:05
jmercouris
hey everyone, I'm getting a strange error when I run my program: https://pastebin.com/AYRtnk5D
2:13:07
pjb
It may be a problem of incompatible asdf version. Or not having loaded asdf early enough?
2:15:51
edgar-rft
the debugger should spit out a list of the functions that were called before the error happened or at least have an option to produce such a list
2:18:23
edgar-rft
(defvar *default-etld-names* (asdf:system-relative-pathname :quri #P"data/effective_tld_names.dat")) probably calls that fuction internally somewhere
2:19:47
edgar-rft
have you tried if the same error happens if you evaluate (asdf:system-relative-pathname :quri #P"data/effective_tld_names.dat")
2:19:49
pjb
jmercouris: possibly, the problem here is that defvar doesn't evaluate the initial-value at compilation-time, but at (:load-toplevel :execute) time.
2:20:40
jmercouris
I know the function will work normally on my machine, I'm able to load and use the library just fine
2:21:09
jmercouris
but what is happening is that I'm basically making a monolithic lib using asdf, and I am embedding it into an executable, so asdf is not available in that executable, causing this issue
2:21:54
pjb
And it's a tad difficult to include asdf in the binary, because it may be loaded/reloaded by the rc-file at run-time.
2:25:23
pjb
Ok, so it's for a default path to some data. When you run your binary, that data file (in the quri source directory) may not exist anymore.
2:25:42
jmercouris
right yeah, that's exactly the problem, I wish it would have been just embedded in the code
2:26:20
pjb
You would have either to copy that data file as resources for your program, and then initialize *default-etld-names* at run-time to point to that copied resource file, or reset it to some default value such as "/dev/null".
2:26:55
pjb
Unfortunately, not lisp library programmers have ever generated executable images,so they don't all realize the special situation there.
2:28:52
pjb
It looks like this resource file is needed in any case, so you would have to package it and install it with your binary.
2:29:03
pjb
(defvar *default-etld-names* (asdf:system-relative-pathname :quri #P"data/effective_tld_names.dat"))
2:29:21
jmercouris
I don't need all of that logic though, I literally just need the ability to take "google.com" and turn it into http://www.google.com" if necessary
2:30:44
pjb
neachdainn: it's a convention to denote variables that will be bound by the pattern matching function.
2:39:09
pjb
(well, perhaps there was already something like that in NSS, but let's say that LISP is the child of NSS and FLPL).
2:45:07
neachdainn
So, don't tell me totally how to do this, but what's a hint for how I could find a pattern in a list of items
2:50:04
neachdainn
My career is in robotics - almost all of my programming is C/C++. Lisp is something I'm trying to learn
2:52:26
pjb
But what you want is to define a function that can distinguish symbols whose name starts with "?" and the other symbols.
2:56:28
pjb
(defun simple-match (pattern list) (mapcan (lambda (pattern item) (cond ((variable-symbol-p pattern) (list (list pattern item))) ((eql pattern item) '()) (t (match-fail pattern item)))) pattern list)) (simple-match '(on ?a ?b) '(on the table)) #| --> ((?a the) (?b table)) |#
2:56:52
neachdainn
So, if I'm reading this correctly, variable-symbol-p return T if the first char of symbol is '?', and nil otherwise. Right?
2:56:56
pjb
Of course, it must be more sophisticated: when you have collected all the bindings, you must check they are unified. You cannot have both (?a the) and (?a a) in the result!
2:57:57
pjb
You will have functions for repeated matches, optional matches, alternative matches, etc…
2:58:59
pjb
The macro would be more sophisticated, since it'd do compile-time work to expand to a let with the bindings…
3:00:09
neachdainn
I think that's getting far more sophisticated than my fourth Lisp function needs to be. Hahah
3:35:29
neachdainn
Is there a way to zip lists? E.g., (zip '(1 2 3) '(4 5 6)) => ((1 4) (2 5) (3 6))
4:22:32
minion
beach, memo from Bike: there are instructions for converstions between float types but no primops/asts; i was going to add them with two types so you'd write like (cleavir-primop:coerce single-float double-float x). also, there's one for "unboxed integers", does this mean fixnums with tag shifted out to take advantage of machine instructions?
4:32:10
drmeister
I should (1) identify the minimal set of generic functions that may need their call histories edited to remove entries that have selectors that match the redefined class and and remove those entries and (2) I should invalidate the dispatchers for those generic functions.
4:33:28
drmeister
I need to invalidate the dispatchers because their code contains the old stamp for the class.
4:34:07
beach
And you can either recompute the dispatcher on the fly, or you can set it so something that will.
4:34:32
drmeister
Honestly, I've been wracking my brains for hours why I might need to remove the entries from the call history - I can't recall. I also can't recall how to obtain the minimal set of generic functions that need invalidation. I was wondering if you could point me in the right direction.
4:37:38
drmeister
ensure-class-using-class calls the function that invalidates dispatchers that are effected by the class change.
4:38:11
drmeister
How does that function use specializer-direct-generic-functions given the class PRETTY-STREAM to get the generic function INITIALIZE-INSTANCE.
4:38:45
drmeister
Do I accumulate all of the generic functions that are specializer-direct-generic-functions of the class-precedence-list of PRETTY-STREAM?
4:39:11
drmeister
Because the only specializer that INITIALIZE-INSTANCE is a specializer-direct-generic-functions of is (find-class 'T)
4:39:51
drmeister
I can't recall why I was removing the call history entries - if I don't have to that is a relief and I will stop trying.
4:41:21
drmeister
As I said - I don't recall - it's just there in my code that I do it - but I wrote no comment why I was doing it. I wrote a fair amount of code to achieve it - so I assumed there was a reason. If there is no reason - then I will remove the code.
4:42:22
drmeister
That being said - it seemed harmless to remove the entries - because they would be added back in the next dispatch miss.
4:42:25
beach
Certainly, when a class is redefined so that its class precedence list changes, then whether some methods are applicable or not to a particular signature may change.
4:43:11
beach
And not only the entries for a particular class that is being modified, but also for all of its subclasses.
4:44:22
drmeister
But see what I wrote above about not finding all of the generic functions that needed to be updated when I simply append together the results of calling specializer-direct-generic-functions on the subclasses of the specializer.
4:45:12
beach
I think you need something similar to SPECIALIZER-DIRECT-GENERIC-FUNCTIONS but that keeps track of what is in the call history instead.
4:46:46
beach
I think you need a function called (say) SPECIALIZER-CALL-HISTORY-GENERIC-FUNCTIONS that takes a class and returns a list of all generic functions that specializer in its call history.
4:50:16
drmeister
Yes - that is what I need to write - I'm trying to figure out how to do it efficiently.
4:50:38
drmeister
I could search every generic function - that's a no-brainer - I was looking for something a bit more ... focused.
4:52:48
drmeister
Would that be better than calculating it on the fly? In the worst case it's a loop over all call-histories for every generic function.
4:53:24
drmeister
I can get every generic function by calling specializer-direct-generic-functions on every class - bleh.
4:54:20
drmeister
But maybe better than keeping specializer-call-history-generic-functions up to date?
4:58:28
drmeister
Nope - no reasons - just anxiety over updating state like specializer-call-history-generic-functions would require. Especially in a multi-threaded environment - every specializer will need a lock won't it?
5:03:03
drmeister
I'm just exploring options. I'm starting to warm to the idea of maintaining a specializer-call-history-generic-functions and a mutex to protect it in each class.
5:04:26
drmeister
There are only two functions that modify call histories in Clasp, one that adds to them and another that removes from them.
5:05:55
drmeister
I talked with scymtym about his implementation - he doesn't handle class changes yet. Interestingly - he doesn't use integer stamps. He uses the address of sbcl's 'layout' object in some sbcl mode where layouts don't move in memory.
5:27:04
drmeister
Well, I'm off to bed. I'll think about specializer-call-history-generic-functions and probably implement it tomorrow.