How to delete a function or variable from the lisp image? [duplicate] - common-lisp

This question already has answers here:
How to delete variable/forms in Lisp?
(4 answers)
Closed 3 months ago.
I have a function called read-csv that I created.
I started using the package cl-csv that also has this function.
After renaming my function, I notice that read-csv is still part of my image.
(do-symbols (sym :my-package)
(print sym)) ;; => includes read-csv
The same is true with variables.
If I define this:
(defparameter hi "Buongiorno")
;;change my mind and recompile
(defparameter hi-there "Buongiorno")
> hi
"Buongiorno" ;;<---- still exists
> hi-there
"Buongiorno"
How do I completely remove a symbol, variable or function from my lisp image?

(makunbound 'hi)
(fmakunbound 'read-csv)

Related

Common Lisp: How to choose the package a symbol belongs to in the read function [duplicate]

This question already has answers here:
Common Lisp: Why is cl lnterning symbols to the wrong package when reading from file?
(2 answers)
Closed 2 years ago.
This seems to be a very simple question, but I am still a beginner in common lisp.
I tried to load files like the following. Without packages the symbols 'year
'month etc. can be compared to in every file.
;;; file db.lisp
((year 2010
(month 5
(1 100 "A")
(2 -5 "B"))
(balance 10)
(month 6
(1 -7 "C")
(2 -8 "D")))
(load-from-csv-format-1 "db2011.csv")
(load-from-csv-format-2 "db2012.csv"))
I managed to convert the existing lisp code the following
(defpackage :db
(:use :common-lisp :db.csv-format-1))
(in-package :db)
(defun read-db ()
(let ((db (with-open-file (stream "db.lisp")
(read stream))))
...
(case (car x)
(year (expand-year x))
(load-from-csv-format-1 (load-format-csv-format-1-impl (second x)))
(load-from-csv-format-2 (load-format-csv-format-1-impl (second x)))
...
Now all symbols belong to the package :db. This has one disadvantage for me, as
all calls to read-db have to be done from within :db. If I now want to separate
all the different csv-formats in different packages, it doesn't work anymore, since
e.g. 'balance below belongs to the db.csv-format-1 package which cannot be compared
against the db::balance symbol.
(defpackage :db.csv-format-1
(:use :common-lisp)
(:export :load-from-csv-format-1-impl))
(in-package :db.csv.format-1)
(defun load-format-csv-format-1-impl (path)
(list 'balance 20))
So my question is, how is this done properly in lisp? Can one specify to read somehow,
in which package to create symbols and then access these symbols somehow outside this
package?
read
interns whatever it reads in
the package *package* so you can
do this:
(defun read-db ()
(let* ((*package* (find-package #:db))
((db (with-open-file (stream "db.lisp")
(read stream)))))
...))
PS. As a beginner, you might enjoy reading some of the books recommended in Resources for learning Lisp.

Error: Symbol at (1) is not a DUMMY variable [duplicate]

This question already has answers here:
"Unclassifiable statement" when referencing a function
(1 answer)
Fortran array cannot be returned in function: not a DUMMY variable
(1 answer)
Closed 3 years ago.
I tried to write a code which gives GCD of two number:
program main
implicit none
integer::A,B,gcd,ans=0
read*,A,B
gcd(A,B)
write(*,*)'GCD of ',A,' and ',B,': ',ans
end program main
recursive function gcd(A,B) result(ans)
implicit none
integer,intent(in)::A,B
integer::ans
if (A==0) ans=B
if (B==0) ans=A
!base_case
if (A==B) ans=A
!recursive_case
if (A>B)then
ans=gcd(A-B,B)
else
ans=gcd(A,B-A)
end if
end function gcd
My input was:
98 56
I expect 14 but got this error:
source_file.f:5:4:
gcd(A,B)
1
Error: Unclassifiable statement at (1)
I didn't understand why I am getting this error? I heartily thank if anyone explain me why am I getting error.
You cannot specify intent(out) or any other intent or related attribute for the result variable. See Fortran array cannot be returned in function: not a DUMMY variable
Use just
integer::ans
In addition, just
gcd(A,B)
is not a valid way to use a function in Fortran. Use
ans = gcd(A,B)
or
print *, gcd(A,B)
or similar.
Please realize that ans declared in the main program is a variable that is not related to the result variable of the function. Even if the name is the same, they are two different things. It will be better to rename one of them to make it clear.

Undefined variable in function declaration while it is clearly defined [duplicate]

This question already has answers here:
What is the difference between Lisp-1 and Lisp-2?
(2 answers)
Closed 5 years ago.
I'm working on a function that will let you measure the run-time of a passed function run-n-time. It's not close to finished, because while writing the code, I came across a strange error. Note that I'm quite new to common lisp.
Inputting this into my sbcl-repl (version: SBCL 1.3.1.debian)
(defun run-n-time (fn times argn)
(loop for n from 0 to times
do (apply fn (argn n))))
Gives me this output (unimportant stuff removed)
; caught STYLE-WARNING:
; The variable ARGN is defined but never used.
; in: DEFUN RUN-N-MEASURE
; (ARGN N)
;
; caught STYLE-WARNING:
; undefined function: ARGN
It states that argn is unused and undefined.
I have no idea what's going on here, it's such a simple piece of code :(
Common Lisp has separate function and value namespaces.
The form (argn n) uses the argn operator, not the variable. You need to use funcall here: (funcall argn n).

What's the meaning of "#+" in the code of cl-mysql? [duplicate]

This question already has answers here:
operator #+ and #- in .sbclrc
(2 answers)
Closed 6 years ago.
Recently I tried to read code about cl-mysql, but got stuck with the #+.
Tried to google it, but not work, so turn to here
(defun make-lock (name)
#+sb-thread (sb-thread:make-mutex :name name)
#+ecl (mp:make-lock :name name)
#+armedbear (ext:make-thread-lock)
#+ (and clisp mt) (mt:make-mutex :name name)
#+allegro (mp:make-process-lock :name name))
And looks like it is for different backend lisp compiler. But still no idea why write something like this.
Anyone can help me make it clear, thx.
#+ is a reader-macro that checks if a keyword is in the special variable *FEATURES*. If it isn't there, the following form will be skipped over (by the reader; the compiler will never see it). There is also #- which does the opposite.
There are some things that aren't part of the Common Lisp standard, but are important enough that all (or most) implementations provide a non-standard extension for them. When you want to use them in code that needs to work on multiple implementations, you have to use read-time conditionals to provide the correct code for the current implementation. Mutexes (and threads in general) are one of those things.
Of course there may be features provided by third party libraries as well. The contents of *FEATURES* will look something like this:
(:SWANK :QUICKLISP :SB-BSD-SOCKETS-ADDRINFO :ASDF-PACKAGE-SYSTEM :ASDF3.1
:ASDF3 :ASDF2 :ASDF :OS-UNIX :NON-BASE-CHARS-EXIST-P :ASDF-UNICODE :64-BIT
:64-BIT-REGISTERS :ALIEN-CALLBACKS :ANSI-CL :ASH-RIGHT-VOPS
:C-STACK-IS-CONTROL-STACK :COMMON-LISP :COMPARE-AND-SWAP-VOPS
:COMPLEX-FLOAT-VOPS :CYCLE-COUNTER :ELF :FLOAT-EQL-VOPS
:FP-AND-PC-STANDARD-SAVE :GENCGC :IEEE-FLOATING-POINT :INLINE-CONSTANTS
:INTEGER-EQL-VOP :INTERLEAVED-RAW-SLOTS :LARGEFILE :LINKAGE-TABLE :LINUX
:LITTLE-ENDIAN :MEMORY-BARRIER-VOPS :MULTIPLY-HIGH-VOPS :OS-PROVIDES-DLADDR
:OS-PROVIDES-DLOPEN :OS-PROVIDES-GETPROTOBY-R :OS-PROVIDES-POLL
:OS-PROVIDES-PUTWC :OS-PROVIDES-SUSECONDS-T :PACKAGE-LOCAL-NICKNAMES
:PRECISE-ARG-COUNT-ERROR :RAW-INSTANCE-INIT-VOPS :SB-DOC :SB-EVAL :SB-FUTEX
:SB-LDB :SB-PACKAGE-LOCKS :SB-SIMD-PACK :SB-SOURCE-LOCATIONS :SB-TEST
:SB-THREAD :SB-UNICODE :SBCL :STACK-ALLOCATABLE-CLOSURES
:STACK-ALLOCATABLE-FIXED-OBJECTS :STACK-ALLOCATABLE-LISTS
:STACK-ALLOCATABLE-VECTORS :STACK-GROWS-DOWNWARD-NOT-UPWARD :SYMBOL-INFO-VOPS
:UNIX :UNWIND-TO-FRAME-AND-CALL-VOP :X86-64)
So if you wanted to write code that depends on Quicklisp for example, you could use #+quicklisp. If you wanted code that is only run if Quicklisp is not available, you'd use #-quicklisp.
You can also use a boolean expression of features. For example,
#+(or sbcl ecl) (format t "Foo!")
would print Foo! on either SBCL or ECL.
#+(and sbcl quicklisp) (format t "Bar!")
would only print Bar! on SBCL that has Quicklisp available.
One could imagine that we can write:
(defun make-lock (name)
(cond ((member :sb-thread *features)
(sb-thread:make-mutex :name name))
((member :ecl *features*)
(mp:make-lock :name name))
...))
But that does usually not work, because we can't read symbols when their package is not existing and some packages are implementation/library/application specific. Packages are not created at read time in a lazy/automatic fashion.
In Common Lisp, reading a symbol of a package, which does not exist, leads to an error:
CL-USER 1 > (read-from-string "foo:bar")
Error: Reader cannot find package FOO.
1 (continue) Create the FOO package.
2 Use another package instead of FOO.
3 Try finding package FOO again.
4 (abort) Return to level 0.
5 Return to top loop level 0.
In your example sb-thread:make-mutex is a symbol which makes sense in SBCL, but not in Allegro CL. Additionally the package SB-THREAD does not exist in Allegro CL. Thus Allegro CL needs to be protected from reading it. In this case, the symbol sb-thread:make-mutex will only be read, if the the feature sb-thread is present on the cl:*features* list. Which is likely only for SBCL, or a Lisp which claims to have sb-threads available.
The feature expressions here prevents the Lisp from trying to read symbols with unknown packages - the packages are unknown, because the respective software is not loaded or not available.

Can I use require :as with Java interop? [duplicate]

This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
Aliasing a java package name in clojure
If I have a Java API like this:
com.very.long.and.boring.names.Abc
com.very.long.and.boring.names.Def
com.very.long.and.boring.names.Ghi
Can I use it from Clojure (1.4.0) with a "fake" namespace like this:
(foo/Abc)
(foo/Def)
(foo/Ghi)
I don't want to (use 'com.very.long.and.boring.names) because Abc / Def / Ghi may clash with my Clojure functions. So basically I want to "map" "com.very.long.and.boring.names" to "foo".
I tried several things at the REPL but couldn't make it work.
I don't believe that this functionality exists as yet.
However if the purpose is to use the Class object at runtime, you can always just do:
(def s java.lang.String)
(.newInstance s)
=> ""
I think you're basically asking this same question:
Aliasing a java package name in clojure
Apparently the functionality doesn't actually exist yet...
However, class names usually start with capital letters, whereas function names are lower-case by convention. Unless the Java classes or your functions aren't following these conventions then you shouldn't have any conflicts.

Resources