I have to write a game in Lisp. In order to make it clear, I wanted to split the code in different .lisp files.
How can I call a function out of a function in the ot
This is for Emacs Lisp (aka elisp)
Create a file at this location: ~/.emacs.d/init.el
Create a file at this location: ~/.emacs.d/file1.el
Create a file at this location: ~/.emacs.d/file2.el
Now, open up ~/.emacs.d/init.el
and write (and then save):
(load "~/.emacs.d/file1.el")
(load "~/.emacs.d/file2.el")
(defun run-both-functions ()
(interactive)
(switch-to-buffer "*Messages*")
(first-function)
(sit-for 2)
(second-function))
Now, open up ~/.emacs.d/file1.el
and write (and then save):
(defun first-function ()
(message "My name is Fred."))
Now, open up ~/.emacs.d/file2.el
and write (and then save):
(defun second-function ()
(message "My name is George."))
Now, restart Emacs and type: M-x run-both-functions RET
Any functions that you put into any of the three (3) files mentioned above will be accessible to other functions. You will note that run-both-functions
includes an (interactive)
statement, which means that the user can call the function with M-x
or a keyboard shortcut.
Just so you know, there are a variety of different Lisp systems. I'll post the answer for Common Lisp.
The naive way is to use (load "filename.lisp")
, but that doesn't really work very well after a while. Therefore...
Common Lisp has a library called "ASDF", which handles packaging and file management. There's a bit of setup to ASDF.
I use this in my .sbclrc
file (assuming that I created a .asdf file in ~) :
(pushnew "~/.asdf/" asdf:*central-registry* :test #'equal)
I usually use a previously built ASDF file and then modify it.
Here's a sample ASDF file's contents:
(asdf:defsystem #:cl-linq
:depends-on ( #:alexandria #:anaphora)
:components ((:file "cl-linq"))
:name "cl-linq"
:version "0.1"
:maintainer "Paul Nathan"
:author "Paul Nathan"
:licence "LLGPL"
:description "CL LINQ style interface with strains of SQL"
:long-description
"DSL for managing and querying datasets in a SQL/LINQ style
syntax. cl-linq provides a simple and usable set of primitives to
make data examination straightforward. ")
I put this code in a file cl-linq.asd
next to my source code (cl-linq.lisp
from the component "cl-linq"
in the defsystem) and then symlink the cl-linq.asd
file to my ~/.asdf/
directory.
Within my cl-linq.lisp file I include this:
(defpackage :cl-linq
(:use
:common-lisp
:anaphora)
(:export
#:query
#:cl-linq-select))
(in-package :cl-linq)
So for your case, I would have 2 components; each with their own defpackage form, exporting the functions out that the other package needed.
For the examples, I've taken the code from CL-LINQ, a project of mine. You are quite free to use it as a template.
With Common Lisp I done it like this:
In file1.lisp
I define a function sayHello
and export that function under the package name helloLisp
(defpackage :helloLisp
(:use :common-lisp)
(:export #:sayHello))
(in-package :helloLisp)
(defun sayHello () (print "Hello!"))
In the file file2.lisp
I require
this file like that:
(require "helloLisp" "./file1.lisp")
(helloLisp:sayHello)
Tested with SBCL 1.4.11
If you use the function load it can be useful to not specify the file type.
Loading files: fasl or source
Instead of (load "foo.lisp")
one can call (load "foo")
. Typically Common Lisp provides the feature of compiling Lisp files to fasl (fast load) files. Those are usually pre-compiled byte code or native code. Typically the Common Lisp implementation will load the compiled code if a file exists for it. This saves time (because compiled code usually can be loaded much faster than Lisp source code) and the code usually is faster (because a file compiler has compiled it).
Often one uses a function to load the compiled file if it is newer, or first compile the source file to a new compiled file.
Loading a file, based on the current file being loaded
In (load "foo")
the file foo
is not a complete filename. For example we don't know the directory where it is loaded from. This depends on things like the value of *default-pathname-defaults*
or in some implementations on a current directory (typical for Unix systems). It may be useful to load the file based on the file we are currently loading - if loading one file triggers more files to be loaded. For this Common Lisp has the variables *load-pathname*
and *load-truename*
(which is the real filename as used with the filesystem).
To load a file foo in the same directory as the currently loaded file call:
(load (merge-pathnames "foo" *load-pathname*))
To load a file foo in a subdirectory bar of the same directory as the currently loaded file call:
(load (merge-pathnames "bar/foo" *load-pathname*))