How to find unused lists/procedures in scheme? - scheme

I am cleaning up some (Chicken) scheme code and I want to identify all lists/procedures not used in a given program. Is there a specific option to pass either to the Chicken compiler or to csi -s I can use to do so without listing out each define and grep-ing for the identifiers in the *.scm scripts?

you could use the repl function from eval unit and pass to that an evaluator function that keeps track of the symbol if it is a list or a lambda before calling eval on the argument.

It is not possible to decide which top-level entries will be used, because it is possible to dynamically craft expressions:
(eval (list (string->symbol "+") 1 2)) → 3
It would be necessary to evaluate all possible permutations of your program.

If you put your code in a module, it will show a warning about unused, unexported identifiers when compiling it (you might need to use csc -v to show them).

Related

How to determine if a variable exists in Chicken Scheme?

Is there a way in Chicken Scheme to determine at run-time if a variable is currently defined?
(let ((var 1))
(print (is-defined? var)) ; #t
(print (is-defined? var)) ; #f
EDIT: XY problem.
I'm writing a macro that generates code. This generated code must call the macro in mutual recursion - having the macro simply call itself won't work. When the macro is recursively called, I need it to behave differently than when it is called initially. I would use a nested function, but uh....it's a macro.
Rough example:
(defmacro m (nested)
(if nested
BACKQUOTE(print "is nested")
BACKQUOTE(m #t)
(yes, I know scheme doesn't use defmacro, but I'm coming from Common Lisp. Also I can't seem to put backquotes in here without it all going to hell.)
I don't want the INITIAL call of the macro to take an extra argument that only has meaning when called recursively. I want it to know by some other means.
Can I get the generated code to call a macro that is nested within the first macro and doesn't exist at the call site, maybe? For example, generating code that calls (,other-macro) instead of (macro)?
But that shouldn't work, because a macro isn't a first-class object like a function is...
When you write recursive macros I get the impression that you have an macro expansion (m a b ...) that turns into a (m-helper a (b ...)) that might turn into (let (a ...) (m b ...)). That is not directly recursive since you are turning code into code that just happens to contain a macro.
With destructuring-bind you really only need to keep track of two variables. One for car and one for cdr and with an implicit renaming macro the stuff not coming from the form is renamed and thus hygenic:
(define-syntax destructuring-bind
(ir-macro-transformer
(lambda (form inject compare?)
(define (parse-structure structure expression optional? body)
;;actual magic happens here. Returns list structure with a mix of parts from structure as well as introduced variables and globals
)
(match form
[(structure expression) . body ]
`(let ((tmp ,expression))
,(parse-structure structure 'tmp #f body))))))
To check if something from input is the same symbol you use the supplied compare? procedure. eg. (compare? expression '&optional).
There's no way to do that in general, because Scheme is lexically scoped. It doesn't make much sense to ask if a variable is defined if an referencing an undefined variable is an error.
For toplevel/global variables, you can use the symbol-utils egg but it is probably not going to work as you expect, considering that global variables inside modules are also rewritten to be something else.
Perhaps if you can say what you're really trying to do, I can help you with an alternate solution.

Strange error when generating method with a macro?

Here's a short snippet that demonstrates the problem:
(defmulti test-dummy type)
(defmacro silly [t]
`(defmethod test-dummy ~(resolve t) [some-arg] "FOO!"))
(silly String)
Evaluating this results in "Can't use qualified name as parameter: user/some-arg", but running macroexpand gives a perfectly good result:
(defmethod test-dummy java.lang.String [some-arg] "FOO!")
Typing ~' before the argument name to make it evaluate into a symbol works, but what is going on?
Okay. So the issue here is that Clojure attempts to enfoce macro hygiene by ensuring that no symbols in a macro's expansion are unqualified locals which could capture from the macro's expansion environment.
Traditionally, Lisp dialects have allowed macro expansions to contain arbitrary symbols. This creates issues where the expression containing a macro to be expanded defines a symbol some-arg which is used without definition in the expanded result of the macro. This means that the macro is "capturing" a symbol/value from its expansion environment which is rarely desired behavior. This is exactly what the Clojure compiler thinks is going on here with your symbol some-arg. The Clojure compiler attempts to resolve some-arg to a namespace level symbol (a previous definition or require creating an alias to the symbol some-var) and it fails to do so thus generating the warning that user/some-arg is undefined.
There are two cannonical solutions to this problem. The first is to use a gensym for some-arg which the macro expansion system knows denotes a local and will not attempt to resolve.
(defmacro silly [t]
`(defmethod test-dummy ~(resolve t) [some-arg#] "FOO!"))
The other method is that you can use the macro splice operator ~ to insert the value of a quoted symbol.
(defmacro silly [t]
`(defmethod test-dummy ~(resolve t) [~'some-arg] "FOO!"))
In both cases you have to use the same expression (either the gensym or the splice) at all uses of the symbol. The gensym will as the name suggests generate a symbol for use and thus will not produce repeatable naming. This is a feature for escaping symbol collisions. The splice however will enable you to always generate a specified symbol in case you need a real human-usable name for something (say a def) or you actually do want to close over something from the environment explicitly.

How do I get a list of functions defined in an emacs-lisp file

Is it possible to get a list of functions defined in an emacs-lisp file? I found this sort of related answer: How do I get a list of Emacs lisp non-interactive functions?, but it involves a map over all of the atoms defined, not just what is in a file.
If the file in question has already been loaded, then you can modify the code in the question you link to filter out the symbols defined in other files:
(let ((funclist ()))
(mapatoms
(lambda (x)
(when (and (fboundp x) ; does x name a function?
(let ((f (symbol-file x)))
(and f (string= (file-name-base f) "my-file.el"))))
(push x funclist))))
funclist)
If the file has not been loaded, you would have to scan it with scan-sexps and find defun forms.
You might, however, prefer to use etags or imenu instead of scanning the file yourself.
Maybe a faster way is to look for the file in load-history, which will then give you the list of variables and functions defined therein.
Not sure if your asking for a non interactive approach.
With M-x occur ENT (defun.* ENT you get a buffer with more or less all function-definitions found in (current-buffer).
The quick&dirty way: extract all defuns via regex. It works instantly on a buffer with 5000 lines.
(-map 'cadr (s-match-strings-all "defun \\(.*?\\) " (buffer-string)))
This returns a list of function names that are defined via defun in the current open buffer. buffer-string returns content of a current buffer in a string, -map and s-match-string-all are taken from dash and s third party libraries (their GitHub pages explain how to install them), cadr returns a 2nd element of a list.
-map is analogous to Emacs built-in mapcar, it applies a function to each element of a list and returns a new list, s-match-string-all returns all possible regex matches in a string, parentheses in a regex denote a group (read more how to form Emacs regular expressions from EmacsWiki).
If you run it in eval-expression (Alt+:), it will just throw it into echo area, but that's not what you need. So below are variations that work with custom buffer or file. with-current-buffer allows to temporarily switch a buffer, while some code does actions inside it, f-read is a file reading function form another third-party library f.
(defun list-defined-functions (buffer)
(with-current-buffer buffer
(-map 'cadr (s-match-strings-all "defun \\(.*?\\) "
(buffer-string)))))
(defun list-defined-functions-in-file (file)
(-map 'cadr (s-match-strings-all "defun \\(.*?\\) "
(f-read file))))
Read Emacs Lisp manual and try to come up with whatever is useful for you.

How to trace a program for debugging in OCaml ?

I have a general question regarding coding practices...
While debugging, at some point of my code, I need some code to print the current state; When I don't debug, I don't want to leave the code there because it bothers visibility of other code...
It is hard to package them into one function because most of the time, it involves local variables, and I don't want to pass everything as arguments...
So how do you generally manage this kind of "printing/checking" code? is there any good practice?
I used to have a debug function, that would only print the final string only if a flag was set. Now, I prefer to just add if statements:
they are not much longer
nothing is computed is the condition is false
it is easy while reading the code to see that it is only for debugging
I also used to have camlp4 macros, that would generate if statements from function applications, but it only works in projects where camlp4 is used, which I tend to avoid nowadays.
Note that, usually, I use not one debug flag, but many debug flags, one per module, and then meta-tags that will trigger debugging of several modules or orthogonal aspects. They are put in a hashtable as list of flags, and I can set them with either an argument or an environment variable.
I often use a debug function which prints value only when a debug flag is set to true:
let debug_flag = ref false
let debug fmt =
if !debug_flag then Printf.eprintf fmt
else Printf.ifprintf stderr fmt
I use a logging syntax extension:
http://toss.svn.sourceforge.net/viewvc/toss/trunk/Toss/caml_extensions/pa_log.ml?revision=1679&view=markup
You can also pass line number to the logging function (which is hard-coded to AuxIO.log in the source above) using Loc.start_line _loc (perhaps I'll add it).
Note that the conditional should be part of the syntax extension, this way it will not compute the arguments if it does not need to print them. Also, we have the flexible "printf" syntax.
Also, I use a command in Emacs:
(defun camldev-insert-log-entry ()
(interactive)
(insert "(* {{{ log entry *)
LOG 2 \"\";
(* }}} *)")
(goto-char (- (point) 12)))
together with `folding-mode'.

How do you define a constant in PLT Scheme?

How do I declare that a symbol will always stand for a particular value and cannot be changed throughout the execution of the program?
As far as I know, this isn't possible in Scheme. And, for all intents and purposes, it's not strictly necessary. Just define the value at the toplevel like a regular variable and then don't change it. To help you remember, you can adopt a convention for naming these kinds of constants - I've seen books where toplevel variables are defined with *stars* around their name.
In other languages, there is a danger that some library will override the definition you've created. However, Scheme's lexical scoping coupled with PLT's module system ensure this will never happen.
In PLT Scheme, you write your definitions in your own module -- and if your own code is not using `set!', then the binding can never change. In fact, the compiler uses this to perform various optimizations, so this is not just a convention.
You could define a macro that evaluates to the constant, which would protect you against simple uses of set!
(define-syntax constant
(syntax-rules ()
((_) 25)))
Then you just use (constant) everywhere, which is no more typing than *constant *
A really hackish answer that I thought of was to define a reader macro that returns your constant:
#lang racket
(current-readtable
(make-readtable (current-readtable)
#\k 'dispatch-macro (lambda (a b c d e f) 5)))
#k ;; <-- is read as 5
It would then be impossible to redefine this (without changing your reader macro):
(set! #k 6) ;; <-- error, 5 is not an identifier

Resources