Getting asdf to load all files in a directory - common-lisp

Is there a way I can make asdf load all files (*.lisp) in a directory without naming them all in my .asd file? Using wildcards in both directory or filename spec doesn't work. Can someone please help?

See DIRECTORY:
CL-USER> (directory "*.lisp")
=> ("a.lisp"
"b.lisp"
...)
Then, call LOAD for each file.
But then, you could also do:
CL-USER> (loop for f in * collect `(:file ,(pathname-name f)))
((:file "a") (:file "b"))
Then, you can copy that in your .asd file, so that your dependencies are a little more explicit.

You could use the “package inferred system” extension of ASDF: https://common-lisp.net/project/asdf/asdf/The-package_002dinferred_002dsystem-extension.html#The-package_002dinferred_002dsystem-extension. You will have to adhere to a directory and file naming convention for this, but it is (superficially) a bit closer to how such things are organized in other languages.
I have to admit that I prefer the explicit layout in the asd file, though, because it keeps the concepts of systems, packages, and files clearly apart.

The asdf repository comes with a asdf/contrib/wild-modules.lisp extension that does what you say. I'd still use package-inferred-system instead.

Related

Load Common Lisp Module Programmatically

I just started learning Common Lisp a few weeks ago, so sorry if this is an obvious question. How can I load modules programmatically? I have a directory of "tasks", each a Lisp program, and would like to import each and run a specific function that they all contain.
I found out a way to iterate over a directory (via UIOP:DIRECTORY-FILES). But I'm stuck trying to figure out a way to load a module "as" a specific name, as in Python. That would allow me to load "module-1.lisp" as mod and then load "module-2.lisp" as mod in a loop.
Pseudocode:
for path in directory
(load path as mod)
(mod:function)
If there is a better way to achieve what I am trying to do, feel free to say so! Thanks in advance for any help!
Quick summary of packages and systems
"Loading as" is not something meaningful in Common Lisp, because loading is not the same as defining a new system or package. In Python, a file is a module etc. but not in Lisp.
Lisp has a concept of packages, which are namespaces. They are used to organize symbols (symbols are first-class values). In other words, they use, export or maybe shadow symbols from other packages and that's it. When you evaluate (in-package pack), you can write all accessible symbols from pack directly, like my-fun, otherwise you need to fully qualify symbols, as some-package:their-func.
There are extensions that allows you to import a package with a different name, but this is not standard (see https://github.com/phoe/trivial-package-local-nicknames)
Loading a Lisp script is not necessarily the same as defining a package, it depends on what belongs in the file (if it as defpackage forms).
When you want to organize your source code in Lisp, you define a system, using ASDF. A system list all its dependencies, its components (files) and the dependencies between their components. That's how you describe in which order files should be loaded, compiled, tested, etc.
Packages and systems are independant but in small systems you often have the the same name for a system and the unique package it defines. For larger systems there might be multiple packages.
See 21. Programming in the Large: Packages and Symbols.
Your question
Each of your file needs to define a package, to avoid polluting a single namespace, for example:
(defpackage :common-name.01
(:use :cl :utils)
(:export #:run-me))
(in-package :common-name.01)
;; some code
But once they are all loaded, either using your approach or by defining a proper ASDF system, you want to be able to access all the RUN-ME functions, in all the packages.
You can write some introspective code that lists packages, etc. but I think a better approach would be to have a way for each of your file to declare that their RUN-ME functions should be registered in your framework, like test frameworks do.
For example, at the end of your files, you could write:
(provide-function 'run-me)
This assumes that e.g. your utils package defines and exports a function named provide-function that stores values in a central registry.
For example, in utils.lisp:
(defpackage :utils
(:use :cl)
(:export #:provide-function
#:run-all))
(in-package :utils)
(defvar *all-interesting-functions* nil)
(defun provide-function (f)
(pushnew f *all-interesting-functions* :test #'eql))
And when you want to run all the functions, you can iterate over this list:
(defun run-all ()
(mapcar #'funcall *all-interesting-functions*))

Using Swank functions in a library

I use SLIME/SBCL/Emacs and Quicklisp on Ubuntu Raring. I have the function defined below. I would like to add to my Lisp library's top .lisp file, i.e., the one every other one depends on, so that I can use it in all the functions I write with my library by just adding (update-swank) to a function instead of having to add the entire function below to each piece of code that uses it.
(defun update-swank ()
"Grabs SWANK connections and tells it to handle requests.
Call this every loop in the main loop of your program"
(continuable
(let ((connection (or swank::*emacs-connection*
(swank::default-connection))))
(when connection
(swank::handle-requests connection t)))))
When I do this and restart emacs, loading my library in the process because I have the asdf:load-op in my .sbclrc file, I get a
READ error during COMPILE-FILE:
;
; Package SWANK does not exist.
in inferior lisp, and SLIME is stuck polling because the library doesn't load because in my current setup SLIME/SBCL doesn't know what swank is at the time the .lisp file that update-swank is in is loaded. I tried adding (in-package :swank) to the file that update-swank is in, but got
The name "SWANK" does not designate any package.
in inferior lisp when my library is loaded at emacs startup.
I searched through CEPL (where i got update-swank from https://github.com/cbaggers/cepl/blob/master/cepl-utils.lisp) and then copied what the creator of CEPL did and exported the function in my packages.lisp. I made sure the function was added like he did on line 20 of cepl-utils here https://github.com/cbaggers/cepl/blob/master/cepl-utils.lisp......I load my library btw with
(asdf:operate 'asdf:load-op :cl-test)
(in-package #:cl-test)
in my .sbclrc file which i assume is loaded before my .emacs file loads slime at emacs start up (i have (slime) in my .emacs file) ...I just tested removing the adsf:load-op and in-package and from my .sbclrc and running the asdf:load-op after slime/swank has been loaded and what i've been trying to do here worked with no error....but i would like to be able load my library automatically at emacs startup and the way i usually do that is by adding the asdf:load-op to my .sbclrc....If someone could tell me another way to load my library automatically at emacs startup after swank has been loaded that would answer this ?
If there is not a package defined in a running Lisp, then this package can't be used. First you need to define the package and then you can read symbols from that package. Packages are not created when CL tries to read a symbol from an unknown package.
If (find-package "FOO") returns NIL, then you can not read a symbol like FOO::BAR.
Two solutions to that are:
execute the package definition before a symbol from that package is read
remove the symbols from the source code:
Example:
foo::*bar*
replace with
(symbol-value (find-symbol "*BAR*" "FOO"))
Above finds the symbol at runtime and retrieves the symbol value.
Also:
(foo::bar :baz t)
replace with
(funcall (symbol-function (find-symbol "BAR" "FOO")) :baz t)
Above finds the symbol at runtime, retrieves the function and calls it.
This was made to sit inside the main loop of the game/realtime-demo as that was what was blocking the repl from updating. Luckily we are in control of the loop so that is easy. Now you are wanting to use this in your library (probably with opencv) so you need to identify what is blocking the update, this is generally some kind of 'main loop' if you have access to the main loop then call update-swank from in there.
If the main loop is being controlled by a foreign library then perhaps you can put it in a function that gets called every 'loop'. All you really need is it to be called often enough that the repl feels responsive.
Other than that you can try changing the settings of swank to run on a separate thread though I have no experience doing that so I cant tell you how well that would work.
You can see it inside the main loop in the (run-demo) function of this example
Also I talk about it in this video. Though albeit perhaps not in enough detail :)
The fact you are getting "swank does not exist" is very odd. It suggest that swank is not loaded, but if you are using slime then swank must be there!
p.s. Remember that this is for use with Slime or Slim, which means you are using them with emacs or vim. If you are not using Slime+emacs or Slim+vim this function will not work!
[EDIT]
Ok so I duplicated your issue by putting (ql:quickload :cepl) at the end of quicklisp's setup.lisp file. This gave me the 'Package SWANK does not exist'. One quick way to address this is to specify swank as a dependency in your project's asd file. So for example:
(asdf:defsystem #:cepl
:serial t
:depends-on (#:cl-opengl
#:swank ;;<---HERE
#:lbm-sdl
#:varjo
#:cl-utilities
#:cl-ppcre
#:symbol-munger
#:classimp
#:temporary-file
#:md5)
:components ((:file "package")
(:file "maths/base-maths")
(:file "base-macros")
;; (:file "base-lispbuilder")
(:file "cepl-utils")
Hope it helps :)

How to organize Ada project in directories?

How can I load two packages with the same name but located in seperate folders?
Example:
/src/alpha/foopackage.ads
/src/beta/foopackage.ads
I then would like to use foopackages using:
with alpha.foopackage;
with beta.foopackage;
Also, if you have any other tips about organizing projects in Ada please write. There is not much info about project organization in Ada on the net.
You've already solved the problem!
src/alpha/foopackage.ads contains:
package alpha.foopackage is
...
end alpha.foopackage;
while src/beta/foopackage.ads contains:
package beta.foopackage is
...
end beta.foopackage;
Now you will run into a temporary problem if you're using GNAT and its default naming convention. This naming convention requires that the files be named alpha-foopackage.ads and beta-foopackage.ads, respectively.
If you insist on using foopackage.ads as the filenames, this convention can be worked around. With GNAT, see Handling Arbitrary File Naming Conventions with gnatname, Using Other File Names, or Alternative File Naming Schemes.
This is almost a duplicate of the question which led to this answer.
However, there's another issue to do with naming, which is that GNAT (I think you are using GNAT?) has a default file naming convention (there are ways of overriding this convention, but you'd need a Good Reason to bother).
So your source files, whatever directory you choose to put them in, should be named alpha-foopackage.ads and beta-foopackage.ads respectively.

Locating ASDF systems on disk

When trying to use an mpd interface for common lisp, the corresponding asdf system having been named simply "mpd", I came across a peculiar problem. When I loaded the system, it would appear to succeed, yet when I tried to use the functions, it would claim they were undefined. Experimentally, I tried to rename the system "cl-mpd", and load that, only to find that it worked. I therefore concluded that ASDF were loading a different system, also named "mpd". Generally wanting to avoid such hackery as renaming systems, I looked for the offending system in the installation directories for quicklisp, to no avail. I searched for it in my home folder, with no success.
So now I ask you: is there a way to get the location of an ASDF system on disk?
Is this what you're looking for?
(asdf:system-relative-pathname :foo "foo/bar/baz.lisp")
(asdf:component-pathname (asdf:find-component :foo '("bar" "baz")))
find the system
get the components
look at one of them
Example:
(describe (first (asdf:module-components (asdf:find-system "mpd"))))

How can I include a local header file in Rcpp inline, without hardcoding the directory?

I have an R script with some inline C++, and I'd like to include a header file in the same directory. I can get the following to work:
library(Rcpp)
library(inline)
code <- '
// my C++ code here
'
settings=getPlugin("Rcpp")
settings$env$PKG_CXXFLAGS='-I /hard/coded/path/to/header/'
myfunction <- cxxfunction(signature(x="numeric"),
plugin="Rcpp", include='#include "myheader.hpp"',
settings=settings, body=code)
But it seems like there should be a convenient way to include a header file in the same directory. I just can't see what it is. I'd really like a way to include c++ files which are located in the same directory.
(Also apologies: I'm not a c++ (or R) ninja, so I may be missing something very obvious.
Can you clarify what directory you refer to when you say "in the same directory"? Same as what?
If it is the current directory, you still need -I. as that directory may not added as a default. But if that is indeed the directory you want, then its relative path (saying "current dir") is more general than the absolute -I/hard/coded/path/to/header.
Otherwise, what you have done is the correct way to modify the plugin to provide extra flags to the compiler.
Edit: Made a test or two and it turns out that the inline package always use R's tempdir to compile -- so -I. makes no sense as we generally do not know where that is.
That leaves you with two choices:
Use an absolute path as you have done.
Use R to read the content of the header file into a variable passed to the include= argument.
Edit 2: Turns out that we do that in one of the examples shipped with Rcpp itself:
settings <- getPlugin("Rcpp")
settings$env$PKG_CXXFLAGS <- paste("-I", getwd(), sep="")
and then uses settings=settings in the call to cxxfunction.

Resources